Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: ui/views/focus/focus_manager_unittest.cc

Issue 8642002: Enable FocusManager tests for Aura. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/logging.h"
6 #include "base/string16.h"
7 #include "base/string_number_conversions.h"
8 #include "base/utf_string_conversions.h" 5 #include "base/utf_string_conversions.h"
9 #include "third_party/skia/include/core/SkColor.h"
10 #include "ui/base/keycodes/keyboard_codes.h" 6 #include "ui/base/keycodes/keyboard_codes.h"
11 #include "ui/base/models/accelerator.h" 7 #include "ui/base/models/accelerator.h"
12 #include "ui/base/models/combobox_model.h"
13 #include "ui/gfx/rect.h"
14 #include "ui/views/focus/accelerator_handler.h" 8 #include "ui/views/focus/accelerator_handler.h"
15 #include "ui/views/focus/focus_manager_factory.h" 9 #include "ui/views/focus/focus_manager_factory.h"
16 #include "ui/views/test/views_test_base.h" 10 #include "ui/views/focus/focus_manager_test.h"
17 #include "ui/views/widget/root_view.h"
18 #include "ui/views/widget/widget.h" 11 #include "ui/views/widget/widget.h"
19 #include "ui/views/widget/widget_delegate.h" 12 #include "views/controls/button/text_button.h"
20 #include "ui/views/window/non_client_view.h" 13 #include "views/controls/textfield/textfield.h"
21 #include "views/background.h" 14
22 #include "views/border.h" 15 #if !defined(USE_AURA)
23 #include "views/controls/button/checkbox.h" 16 #include "views/controls/tabbed_pane/tabbed_pane.h"
24 #include "views/controls/button/radio_button.h"
25 #include "views/controls/combobox/combobox.h"
26 #include "views/controls/combobox/native_combobox_wrapper.h"
27 #include "views/controls/label.h"
28 #include "views/controls/link.h"
29 #include "views/controls/native/native_view_host.h"
30 #include "views/controls/scroll_view.h"
31 #include "views/controls/tabbed_pane/native_tabbed_pane_wrapper.h" 17 #include "views/controls/tabbed_pane/native_tabbed_pane_wrapper.h"
32 #include "views/controls/tabbed_pane/tabbed_pane.h" 18 #endif
33 #include "views/controls/textfield/textfield.h"
34 19
35 #if defined(OS_LINUX) 20 #if defined(OS_LINUX)
36 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h" 21 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
37 #endif 22 #endif
38 23
39 namespace {
40 const int kWindowWidth = 600;
41 const int kWindowHeight = 500;
42
43 int count = 1;
44
45 const int kTopCheckBoxID = count++; // 1
46 const int kLeftContainerID = count++;
47 const int kAppleLabelID = count++;
48 const int kAppleTextfieldID = count++;
49 const int kOrangeLabelID = count++; // 5
50 const int kOrangeTextfieldID = count++;
51 const int kBananaLabelID = count++;
52 const int kBananaTextfieldID = count++;
53 const int kKiwiLabelID = count++;
54 const int kKiwiTextfieldID = count++; // 10
55 const int kFruitButtonID = count++;
56 const int kFruitCheckBoxID = count++;
57 const int kComboboxID = count++;
58
59 const int kRightContainerID = count++;
60 const int kAsparagusButtonID = count++; // 15
61 const int kBroccoliButtonID = count++;
62 const int kCauliflowerButtonID = count++;
63
64 const int kInnerContainerID = count++;
65 const int kScrollViewID = count++;
66 const int kRosettaLinkID = count++; // 20
67 const int kStupeurEtTremblementLinkID = count++;
68 const int kDinerGameLinkID = count++;
69 const int kRidiculeLinkID = count++;
70 const int kClosetLinkID = count++;
71 const int kVisitingLinkID = count++; // 25
72 const int kAmelieLinkID = count++;
73 const int kJoyeuxNoelLinkID = count++;
74 const int kCampingLinkID = count++;
75 const int kBriceDeNiceLinkID = count++;
76 const int kTaxiLinkID = count++; // 30
77 const int kAsterixLinkID = count++;
78
79 const int kOKButtonID = count++;
80 const int kCancelButtonID = count++;
81 const int kHelpButtonID = count++;
82
83 const int kStyleContainerID = count++; // 35
84 const int kBoldCheckBoxID = count++;
85 const int kItalicCheckBoxID = count++;
86 const int kUnderlinedCheckBoxID = count++;
87 const int kStyleHelpLinkID = count++;
88 const int kStyleTextEditID = count++; // 40
89
90 const int kSearchContainerID = count++;
91 const int kSearchTextfieldID = count++;
92 const int kSearchButtonID = count++;
93 const int kHelpLinkID = count++;
94
95 const int kThumbnailContainerID = count++; // 45
96 const int kThumbnailStarID = count++;
97 const int kThumbnailSuperStarID = count++;
98
99 } // namespace
100
101 namespace views { 24 namespace views {
102 25
103 class FocusManagerTest : public ViewsTestBase, public WidgetDelegate {
104 public:
105 FocusManagerTest()
106 : window_(NULL),
107 content_view_(NULL),
108 focus_change_listener_(NULL) {
109 }
110
111 ~FocusManagerTest() {
112 }
113
114 virtual void SetUp() OVERRIDE {
115 ViewsTestBase::SetUp();
116 window_ = Widget::CreateWindowWithBounds(this, bounds());
117 InitContentView();
118 window_->Show();
119 }
120
121 virtual void TearDown() OVERRIDE {
122 if (focus_change_listener_)
123 GetFocusManager()->RemoveFocusChangeListener(focus_change_listener_);
124 window_->Close();
125
126 // Flush the message loop to make application verifiers happy.
127 RunPendingMessages();
128 ViewsTestBase::TearDown();
129 }
130
131 FocusManager* GetFocusManager() {
132 return window_->GetFocusManager();
133 }
134
135 void FocusNativeView(gfx::NativeView native_view) {
136 #if defined(USE_AURA)
137 NOTIMPLEMENTED();
138 #elif defined(OS_WIN)
139 ::SendMessage(native_view, WM_SETFOCUS, NULL, NULL);
140 #else
141 gint return_val;
142 GdkEventFocus event;
143 event.type = GDK_FOCUS_CHANGE;
144 event.window =
145 gtk_widget_get_root_window(GTK_WIDGET(window_->GetNativeWindow()));
146 event.send_event = TRUE;
147 event.in = TRUE;
148 gtk_signal_emit_by_name(GTK_OBJECT(native_view), "focus-in-event",
149 &event, &return_val);
150 #endif
151 }
152
153 // WidgetDelegate Implementation.
154 virtual View* GetContentsView() OVERRIDE {
155 if (!content_view_)
156 content_view_ = new View();
157 return content_view_;
158 }
159 virtual Widget* GetWidget() OVERRIDE {
160 return content_view_->GetWidget();
161 }
162 virtual const Widget* GetWidget() const OVERRIDE {
163 return content_view_->GetWidget();
164 }
165
166 virtual void InitContentView() {
167 }
168
169 protected:
170 virtual gfx::Rect bounds() {
171 return gfx::Rect(0, 0, 500, 500);
172 }
173
174 // Mocks activating/deactivating the window.
175 void SimulateActivateWindow() {
176 #if defined(USE_AURA)
177 NOTIMPLEMENTED();
178 #elif defined(OS_WIN)
179 ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
180 #else
181 gboolean result;
182 g_signal_emit_by_name(G_OBJECT(window_->GetNativeWindow()),
183 "focus_in_event", 0, &result);
184 #endif
185 }
186 void SimulateDeactivateWindow() {
187 #if defined(USE_AURA)
188 NOTIMPLEMENTED();
189 #elif defined(OS_WIN)
190 ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_INACTIVE, NULL);
191 #else
192 gboolean result;
193 g_signal_emit_by_name(G_OBJECT(window_->GetNativeWindow()),
194 "focus_out_event", 0, & result);
195 #endif
196 }
197
198 Widget* window_;
199 View* content_view_;
200
201 void AddFocusChangeListener(FocusChangeListener* listener) {
202 ASSERT_FALSE(focus_change_listener_);
203 focus_change_listener_ = listener;
204 GetFocusManager()->AddFocusChangeListener(listener);
205 }
206
207 #if defined(USE_AURA)
208 void PostKeyDown(ui::KeyboardCode key_code) {
209 NOTIMPLEMENTED();
210 }
211
212 void PostKeyUp(ui::KeyboardCode key_code) {
213 NOTIMPLEMENTED();
214 }
215 #elif defined(OS_WIN)
216 void PostKeyDown(ui::KeyboardCode key_code) {
217 ::PostMessage(window_->GetNativeWindow(), WM_KEYDOWN, key_code, 0);
218 }
219
220 void PostKeyUp(ui::KeyboardCode key_code) {
221 ::PostMessage(window_->GetNativeWindow(), WM_KEYUP, key_code, 0);
222 }
223 #elif defined(OS_LINUX)
224 void PostKeyDown(ui::KeyboardCode key_code) {
225 PostKeyEvent(key_code, true);
226 }
227
228 void PostKeyUp(ui::KeyboardCode key_code) {
229 PostKeyEvent(key_code, false);
230 }
231
232 void PostKeyEvent(ui::KeyboardCode key_code, bool pressed) {
233 int keyval = GdkKeyCodeForWindowsKeyCode(key_code, false);
234 GdkKeymapKey* keys;
235 gint n_keys;
236 gdk_keymap_get_entries_for_keyval(
237 gdk_keymap_get_default(),
238 keyval,
239 &keys,
240 &n_keys);
241 GdkEvent* event = gdk_event_new(pressed ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
242 GdkEventKey* key_event = reinterpret_cast<GdkEventKey*>(event);
243 int modifier = 0;
244 if (pressed)
245 key_event->state = modifier | GDK_KEY_PRESS_MASK;
246 else
247 key_event->state = modifier | GDK_KEY_RELEASE_MASK;
248
249 key_event->window = GTK_WIDGET(window_->GetNativeWindow())->window;
250 DCHECK(key_event->window != NULL);
251 g_object_ref(key_event->window);
252 key_event->send_event = true;
253 key_event->time = GDK_CURRENT_TIME;
254 key_event->keyval = keyval;
255 key_event->hardware_keycode = keys[0].keycode;
256 key_event->group = keys[0].group;
257
258 g_free(keys);
259
260 gdk_event_put(event);
261 gdk_event_free(event);
262 }
263 #endif
264
265 private:
266 FocusChangeListener* focus_change_listener_;
267
268 DISALLOW_COPY_AND_ASSIGN(FocusManagerTest);
269 };
270
271 // BorderView is a view containing a native window with its own view hierarchy.
272 // It is interesting to test focus traversal from a view hierarchy to an inner
273 // view hierarchy.
274 class BorderView : public NativeViewHost {
275 public:
276 explicit BorderView(View* child) : child_(child), widget_(NULL) {
277 DCHECK(child);
278 set_focusable(false);
279 }
280
281 virtual ~BorderView() {}
282
283 virtual internal::RootView* GetContentsRootView() {
284 return static_cast<internal::RootView*>(widget_->GetRootView());
285 }
286
287 virtual FocusTraversable* GetFocusTraversable() {
288 return static_cast<internal::RootView*>(widget_->GetRootView());
289 }
290
291 virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child) {
292 NativeViewHost::ViewHierarchyChanged(is_add, parent, child);
293
294 if (child == this && is_add) {
295 if (!widget_) {
296 widget_ = new Widget;
297 Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
298 #if defined(OS_WIN)
299 params.parent = parent->GetWidget()->GetNativeView();
300 #elif defined(TOOLKIT_USES_GTK)
301 params.parent = native_view();
302 #else
303 NOTREACHED();
304 #endif
305 widget_->Init(params);
306 widget_->SetFocusTraversableParentView(this);
307 widget_->SetContentsView(child_);
308 }
309
310 // We have been added to a view hierarchy, attach the native view.
311 Attach(widget_->GetNativeView());
312 // Also update the FocusTraversable parent so the focus traversal works.
313 static_cast<internal::RootView*>(widget_->GetRootView())->
314 SetFocusTraversableParent(GetWidget()->GetFocusTraversable());
315 }
316 }
317
318 private:
319 View* child_;
320 Widget* widget_;
321
322 DISALLOW_COPY_AND_ASSIGN(BorderView);
323 };
324
325 class DummyComboboxModel : public ui::ComboboxModel {
326 public:
327 virtual int GetItemCount() { return 10; }
328
329 virtual string16 GetItemAt(int index) {
330 return ASCIIToUTF16("Item ") + base::IntToString16(index);
331 }
332 };
333
334 // A View that can act as a pane.
335 class PaneView : public View, public FocusTraversable {
336 public:
337 PaneView() : focus_search_(NULL) {}
338
339 // If this method is called, this view will use GetPaneFocusTraversable to
340 // have this provided FocusSearch used instead of the default one, allowing
341 // you to trap focus within the pane.
342 void EnablePaneFocus(FocusSearch* focus_search) {
343 focus_search_ = focus_search;
344 }
345
346 // Overridden from views::View:
347 virtual FocusTraversable* GetPaneFocusTraversable() {
348 if (focus_search_)
349 return this;
350 else
351 return NULL;
352 }
353
354 // Overridden from views::FocusTraversable:
355 virtual views::FocusSearch* GetFocusSearch() {
356 return focus_search_;
357 }
358 virtual FocusTraversable* GetFocusTraversableParent() {
359 return NULL;
360 }
361 virtual View* GetFocusTraversableParentView() {
362 return NULL;
363 }
364
365 private:
366 FocusSearch* focus_search_;
367 };
368
369 class FocusTraversalTest : public FocusManagerTest {
370 public:
371 ~FocusTraversalTest();
372
373 virtual void InitContentView();
374
375 protected:
376 FocusTraversalTest();
377
378 virtual gfx::Rect bounds() {
379 return gfx::Rect(0, 0, 600, 460);
380 }
381
382 View* FindViewByID(int id) {
383 View* view = GetContentsView()->GetViewByID(id);
384 if (view)
385 return view;
386 if (style_tab_)
387 view = style_tab_->GetSelectedTab()->GetViewByID(id);
388 if (view)
389 return view;
390 view = search_border_view_->GetContentsRootView()->GetViewByID(id);
391 if (view)
392 return view;
393 return NULL;
394 }
395
396 protected:
397 TabbedPane* style_tab_;
398 BorderView* search_border_view_;
399 DummyComboboxModel combobox_model_;
400 PaneView* left_container_;
401 PaneView* right_container_;
402
403 DISALLOW_COPY_AND_ASSIGN(FocusTraversalTest);
404 };
405
406 ////////////////////////////////////////////////////////////////////////////////
407 // FocusTraversalTest
408 ////////////////////////////////////////////////////////////////////////////////
409
410 FocusTraversalTest::FocusTraversalTest()
411 : style_tab_(NULL),
412 search_border_view_(NULL) {
413 }
414
415 FocusTraversalTest::~FocusTraversalTest() {
416 }
417
418 void FocusTraversalTest::InitContentView() {
419 // Create a complicated view hierarchy with lots of control types for
420 // use by all of the focus traversal tests.
421 //
422 // Class name, ID, and asterisk next to focusable views:
423 //
424 // View
425 // Checkbox * kTopCheckBoxID
426 // PaneView kLeftContainerID
427 // Label kAppleLabelID
428 // Textfield * kAppleTextfieldID
429 // Label kOrangeLabelID
430 // Textfield * kOrangeTextfieldID
431 // Label kBananaLabelID
432 // Textfield * kBananaTextfieldID
433 // Label kKiwiLabelID
434 // Textfield * kKiwiTextfieldID
435 // NativeButton * kFruitButtonID
436 // Checkbox * kFruitCheckBoxID
437 // Combobox * kComboboxID
438 // PaneView kRightContainerID
439 // RadioButton * kAsparagusButtonID
440 // RadioButton * kBroccoliButtonID
441 // RadioButton * kCauliflowerButtonID
442 // View kInnerContainerID
443 // ScrollView kScrollViewID
444 // View
445 // Link * kRosettaLinkID
446 // Link * kStupeurEtTremblementLinkID
447 // Link * kDinerGameLinkID
448 // Link * kRidiculeLinkID
449 // Link * kClosetLinkID
450 // Link * kVisitingLinkID
451 // Link * kAmelieLinkID
452 // Link * kJoyeuxNoelLinkID
453 // Link * kCampingLinkID
454 // Link * kBriceDeNiceLinkID
455 // Link * kTaxiLinkID
456 // Link * kAsterixLinkID
457 // NativeButton * kOKButtonID
458 // NativeButton * kCancelButtonID
459 // NativeButton * kHelpButtonID
460 // TabbedPane * kStyleContainerID
461 // View
462 // Checkbox * kBoldCheckBoxID
463 // Checkbox * kItalicCheckBoxID
464 // Checkbox * kUnderlinedCheckBoxID
465 // Link * kStyleHelpLinkID
466 // Textfield * kStyleTextEditID
467 // Other
468 // BorderView kSearchContainerID
469 // View
470 // Textfield * kSearchTextfieldID
471 // NativeButton * kSearchButtonID
472 // Link * kHelpLinkID
473 // View * kThumbnailContainerID
474 // NativeButton * kThumbnailStarID
475 // NativeButton * kThumbnailSuperStarID
476
477 content_view_->set_background(
478 Background::CreateSolidBackground(SK_ColorWHITE));
479
480 Checkbox* cb = new Checkbox(ASCIIToUTF16("This is a checkbox"));
481 content_view_->AddChildView(cb);
482 // In this fast paced world, who really has time for non hard-coded layout?
483 cb->SetBounds(10, 10, 200, 20);
484 cb->set_id(kTopCheckBoxID);
485
486 left_container_ = new PaneView();
487 left_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
488 left_container_->set_background(
489 Background::CreateSolidBackground(240, 240, 240));
490 left_container_->set_id(kLeftContainerID);
491 content_view_->AddChildView(left_container_);
492 left_container_->SetBounds(10, 35, 250, 200);
493
494 int label_x = 5;
495 int label_width = 50;
496 int label_height = 15;
497 int text_field_width = 150;
498 int y = 10;
499 int gap_between_labels = 10;
500
501 Label* label = new Label(ASCIIToUTF16("Apple:"));
502 label->set_id(kAppleLabelID);
503 left_container_->AddChildView(label);
504 label->SetBounds(label_x, y, label_width, label_height);
505
506 Textfield* text_field = new Textfield();
507 text_field->set_id(kAppleTextfieldID);
508 left_container_->AddChildView(text_field);
509 text_field->SetBounds(label_x + label_width + 5, y,
510 text_field_width, label_height);
511
512 y += label_height + gap_between_labels;
513
514 label = new Label(ASCIIToUTF16("Orange:"));
515 label->set_id(kOrangeLabelID);
516 left_container_->AddChildView(label);
517 label->SetBounds(label_x, y, label_width, label_height);
518
519 text_field = new Textfield();
520 text_field->set_id(kOrangeTextfieldID);
521 left_container_->AddChildView(text_field);
522 text_field->SetBounds(label_x + label_width + 5, y,
523 text_field_width, label_height);
524
525 y += label_height + gap_between_labels;
526
527 label = new Label(ASCIIToUTF16("Banana:"));
528 label->set_id(kBananaLabelID);
529 left_container_->AddChildView(label);
530 label->SetBounds(label_x, y, label_width, label_height);
531
532 text_field = new Textfield();
533 text_field->set_id(kBananaTextfieldID);
534 left_container_->AddChildView(text_field);
535 text_field->SetBounds(label_x + label_width + 5, y,
536 text_field_width, label_height);
537
538 y += label_height + gap_between_labels;
539
540 label = new Label(ASCIIToUTF16("Kiwi:"));
541 label->set_id(kKiwiLabelID);
542 left_container_->AddChildView(label);
543 label->SetBounds(label_x, y, label_width, label_height);
544
545 text_field = new Textfield();
546 text_field->set_id(kKiwiTextfieldID);
547 left_container_->AddChildView(text_field);
548 text_field->SetBounds(label_x + label_width + 5, y,
549 text_field_width, label_height);
550
551 y += label_height + gap_between_labels;
552
553 NativeTextButton* button = new NativeTextButton(NULL,
554 ASCIIToUTF16("Click me"));
555 button->SetBounds(label_x, y + 10, 80, 30);
556 button->set_id(kFruitButtonID);
557 left_container_->AddChildView(button);
558 y += 40;
559
560 cb = new Checkbox(ASCIIToUTF16("This is another check box"));
561 cb->SetBounds(label_x + label_width + 5, y, 180, 20);
562 cb->set_id(kFruitCheckBoxID);
563 left_container_->AddChildView(cb);
564 y += 20;
565
566 Combobox* combobox = new Combobox(&combobox_model_);
567 combobox->SetBounds(label_x + label_width + 5, y, 150, 30);
568 combobox->set_id(kComboboxID);
569 left_container_->AddChildView(combobox);
570
571 right_container_ = new PaneView();
572 right_container_->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
573 right_container_->set_background(
574 Background::CreateSolidBackground(240, 240, 240));
575 right_container_->set_id(kRightContainerID);
576 content_view_->AddChildView(right_container_);
577 right_container_->SetBounds(270, 35, 300, 200);
578
579 y = 10;
580 int radio_button_height = 18;
581 int gap_between_radio_buttons = 10;
582 RadioButton* radio_button = new RadioButton(ASCIIToUTF16("Asparagus"), 1);
583 radio_button->set_id(kAsparagusButtonID);
584 right_container_->AddChildView(radio_button);
585 radio_button->SetBounds(5, y, 70, radio_button_height);
586 radio_button->SetGroup(1);
587 y += radio_button_height + gap_between_radio_buttons;
588 radio_button = new RadioButton(ASCIIToUTF16("Broccoli"), 1);
589 radio_button->set_id(kBroccoliButtonID);
590 right_container_->AddChildView(radio_button);
591 radio_button->SetBounds(5, y, 70, radio_button_height);
592 radio_button->SetGroup(1);
593 RadioButton* radio_button_to_check = radio_button;
594 y += radio_button_height + gap_between_radio_buttons;
595 radio_button = new RadioButton(ASCIIToUTF16("Cauliflower"), 1);
596 radio_button->set_id(kCauliflowerButtonID);
597 right_container_->AddChildView(radio_button);
598 radio_button->SetBounds(5, y, 70, radio_button_height);
599 radio_button->SetGroup(1);
600 y += radio_button_height + gap_between_radio_buttons;
601
602 View* inner_container = new View();
603 inner_container->set_border(Border::CreateSolidBorder(1, SK_ColorBLACK));
604 inner_container->set_background(
605 Background::CreateSolidBackground(230, 230, 230));
606 inner_container->set_id(kInnerContainerID);
607 right_container_->AddChildView(inner_container);
608 inner_container->SetBounds(100, 10, 150, 180);
609
610 ScrollView* scroll_view = new ScrollView();
611 scroll_view->set_id(kScrollViewID);
612 inner_container->AddChildView(scroll_view);
613 scroll_view->SetBounds(1, 1, 148, 178);
614
615 View* scroll_content = new View();
616 scroll_content->SetBounds(0, 0, 200, 200);
617 scroll_content->set_background(
618 Background::CreateSolidBackground(200, 200, 200));
619 scroll_view->SetContents(scroll_content);
620
621 static const char* const kTitles[] = {
622 "Rosetta", "Stupeur et tremblement", "The diner game",
623 "Ridicule", "Le placard", "Les Visiteurs", "Amelie",
624 "Joyeux Noel", "Camping", "Brice de Nice",
625 "Taxi", "Asterix"
626 };
627
628 static const int kIDs[] = {
629 kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
630 kRidiculeLinkID, kClosetLinkID, kVisitingLinkID, kAmelieLinkID,
631 kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
632 kTaxiLinkID, kAsterixLinkID
633 };
634
635 DCHECK(arraysize(kTitles) == arraysize(kIDs));
636
637 y = 5;
638 for (size_t i = 0; i < arraysize(kTitles); ++i) {
639 Link* link = new Link(ASCIIToUTF16(kTitles[i]));
640 link->SetHorizontalAlignment(Label::ALIGN_LEFT);
641 link->set_id(kIDs[i]);
642 scroll_content->AddChildView(link);
643 link->SetBounds(5, y, 300, 15);
644 y += 15;
645 }
646
647 y = 250;
648 int width = 60;
649 button = new NativeTextButton(NULL, ASCIIToUTF16("OK"));
650 button->set_id(kOKButtonID);
651 button->SetIsDefault(true);
652
653 content_view_->AddChildView(button);
654 button->SetBounds(150, y, width, 30);
655
656 button = new NativeTextButton(NULL, ASCIIToUTF16("Cancel"));
657 button->set_id(kCancelButtonID);
658 content_view_->AddChildView(button);
659 button->SetBounds(220, y, width, 30);
660
661 button = new NativeTextButton(NULL, ASCIIToUTF16("Help"));
662 button->set_id(kHelpButtonID);
663 content_view_->AddChildView(button);
664 button->SetBounds(290, y, width, 30);
665
666 y += 40;
667
668 // Left bottom box with style checkboxes.
669 View* contents = new View();
670 contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
671 cb = new Checkbox(ASCIIToUTF16("Bold"));
672 contents->AddChildView(cb);
673 cb->SetBounds(10, 10, 50, 20);
674 cb->set_id(kBoldCheckBoxID);
675
676 cb = new Checkbox(ASCIIToUTF16("Italic"));
677 contents->AddChildView(cb);
678 cb->SetBounds(70, 10, 50, 20);
679 cb->set_id(kItalicCheckBoxID);
680
681 cb = new Checkbox(ASCIIToUTF16("Underlined"));
682 contents->AddChildView(cb);
683 cb->SetBounds(130, 10, 70, 20);
684 cb->set_id(kUnderlinedCheckBoxID);
685
686 Link* link = new Link(ASCIIToUTF16("Help"));
687 contents->AddChildView(link);
688 link->SetBounds(10, 35, 70, 10);
689 link->set_id(kStyleHelpLinkID);
690
691 text_field = new Textfield();
692 contents->AddChildView(text_field);
693 text_field->SetBounds(10, 50, 100, 20);
694 text_field->set_id(kStyleTextEditID);
695
696 style_tab_ = new TabbedPane();
697 style_tab_->set_id(kStyleContainerID);
698 content_view_->AddChildView(style_tab_);
699 style_tab_->SetBounds(10, y, 210, 100);
700 style_tab_->AddTab(ASCIIToUTF16("Style"), contents);
701 style_tab_->AddTab(ASCIIToUTF16("Other"), new View());
702
703 // Right bottom box with search.
704 contents = new View();
705 contents->set_background(Background::CreateSolidBackground(SK_ColorWHITE));
706 text_field = new Textfield();
707 contents->AddChildView(text_field);
708 text_field->SetBounds(10, 10, 100, 20);
709 text_field->set_id(kSearchTextfieldID);
710
711 button = new NativeTextButton(NULL, ASCIIToUTF16("Search"));
712 contents->AddChildView(button);
713 button->SetBounds(112, 5, 60, 30);
714 button->set_id(kSearchButtonID);
715
716 link = new Link(ASCIIToUTF16("Help"));
717 link->SetHorizontalAlignment(Label::ALIGN_LEFT);
718 link->set_id(kHelpLinkID);
719 contents->AddChildView(link);
720 link->SetBounds(175, 10, 30, 20);
721
722 search_border_view_ = new BorderView(contents);
723 search_border_view_->set_id(kSearchContainerID);
724
725 content_view_->AddChildView(search_border_view_);
726 search_border_view_->SetBounds(300, y, 240, 50);
727
728 y += 60;
729
730 contents = new View();
731 contents->set_focusable(true);
732 contents->set_background(Background::CreateSolidBackground(SK_ColorBLUE));
733 contents->set_id(kThumbnailContainerID);
734 button = new NativeTextButton(NULL, ASCIIToUTF16("Star"));
735 contents->AddChildView(button);
736 button->SetBounds(5, 5, 50, 30);
737 button->set_id(kThumbnailStarID);
738 button = new NativeTextButton(NULL, ASCIIToUTF16("SuperStar"));
739 contents->AddChildView(button);
740 button->SetBounds(60, 5, 100, 30);
741 button->set_id(kThumbnailSuperStarID);
742
743 content_view_->AddChildView(contents);
744 contents->SetBounds(250, y, 200, 50);
745 // We can only call RadioButton::SetChecked() on the radio-button is part of
746 // the view hierarchy.
747 radio_button_to_check->SetChecked(true);
748 }
749
750 ////////////////////////////////////////////////////////////////////////////////
751 // The tests
752 ////////////////////////////////////////////////////////////////////////////////
753
754 enum FocusTestEventType { 26 enum FocusTestEventType {
755 ON_FOCUS = 0, 27 ON_FOCUS = 0,
756 ON_BLUR 28 ON_BLUR
757 }; 29 };
758 30
759 struct FocusTestEvent { 31 struct FocusTestEvent {
760 FocusTestEvent(FocusTestEventType type, int view_id) 32 FocusTestEvent(FocusTestEventType type, int view_id)
761 : type(type), 33 : type(type),
762 view_id(view_id) { 34 view_id(view_id) {
763 } 35 }
(...skipping 24 matching lines...) Expand all
788 60
789 // Tests that the appropriate Focus related methods are called when a View 61 // Tests that the appropriate Focus related methods are called when a View
790 // gets/loses focus. 62 // gets/loses focus.
791 TEST_F(FocusManagerTest, ViewFocusCallbacks) { 63 TEST_F(FocusManagerTest, ViewFocusCallbacks) {
792 std::vector<FocusTestEvent> event_list; 64 std::vector<FocusTestEvent> event_list;
793 const int kView1ID = 1; 65 const int kView1ID = 1;
794 const int kView2ID = 2; 66 const int kView2ID = 2;
795 67
796 SimpleTestView* view1 = new SimpleTestView(&event_list, kView1ID); 68 SimpleTestView* view1 = new SimpleTestView(&event_list, kView1ID);
797 SimpleTestView* view2 = new SimpleTestView(&event_list, kView2ID); 69 SimpleTestView* view2 = new SimpleTestView(&event_list, kView2ID);
798 content_view_->AddChildView(view1); 70 GetContentsView()->AddChildView(view1);
799 content_view_->AddChildView(view2); 71 GetContentsView()->AddChildView(view2);
800 72
801 view1->RequestFocus(); 73 view1->RequestFocus();
802 ASSERT_EQ(1, static_cast<int>(event_list.size())); 74 ASSERT_EQ(1, static_cast<int>(event_list.size()));
803 EXPECT_EQ(ON_FOCUS, event_list[0].type); 75 EXPECT_EQ(ON_FOCUS, event_list[0].type);
804 EXPECT_EQ(kView1ID, event_list[0].view_id); 76 EXPECT_EQ(kView1ID, event_list[0].view_id);
805 77
806 event_list.clear(); 78 event_list.clear();
807 view2->RequestFocus(); 79 view2->RequestFocus();
808 ASSERT_EQ(2, static_cast<int>(event_list.size())); 80 ASSERT_EQ(2, static_cast<int>(event_list.size()));
809 EXPECT_EQ(ON_BLUR, event_list[0].type); 81 EXPECT_EQ(ON_BLUR, event_list[0].type);
810 EXPECT_EQ(kView1ID, event_list[0].view_id); 82 EXPECT_EQ(kView1ID, event_list[0].view_id);
811 EXPECT_EQ(ON_FOCUS, event_list[1].type); 83 EXPECT_EQ(ON_FOCUS, event_list[1].type);
812 EXPECT_EQ(kView2ID, event_list[1].view_id); 84 EXPECT_EQ(kView2ID, event_list[1].view_id);
813 85
814 event_list.clear(); 86 event_list.clear();
815 GetFocusManager()->ClearFocus(); 87 GetFocusManager()->ClearFocus();
816 ASSERT_EQ(1, static_cast<int>(event_list.size())); 88 ASSERT_EQ(1, static_cast<int>(event_list.size()));
817 EXPECT_EQ(ON_BLUR, event_list[0].type); 89 EXPECT_EQ(ON_BLUR, event_list[0].type);
818 EXPECT_EQ(kView2ID, event_list[0].view_id); 90 EXPECT_EQ(kView2ID, event_list[0].view_id);
819 } 91 }
820 92
821 typedef std::pair<View*, View*> ViewPair;
822 class TestFocusChangeListener : public FocusChangeListener {
823 public:
824 virtual void OnWillChangeFocus(View* focused_before, View* focused_now) {
825 focus_changes_.push_back(ViewPair(focused_before, focused_now));
826 }
827 virtual void OnDidChangeFocus(View* focused_before, View* focused_now) {
828 }
829
830 const std::vector<ViewPair>& focus_changes() const { return focus_changes_; }
831 void ClearFocusChanges() { focus_changes_.clear(); }
832
833 private:
834 // A vector of which views lost/gained focus.
835 std::vector<ViewPair> focus_changes_;
836 };
837
838 TEST_F(FocusManagerTest, FocusChangeListener) { 93 TEST_F(FocusManagerTest, FocusChangeListener) {
839 View* view1 = new View(); 94 View* view1 = new View();
840 view1->set_focusable(true); 95 view1->set_focusable(true);
841 View* view2 = new View(); 96 View* view2 = new View();
842 view2->set_focusable(true); 97 view2->set_focusable(true);
843 content_view_->AddChildView(view1); 98 GetContentsView()->AddChildView(view1);
844 content_view_->AddChildView(view2); 99 GetContentsView()->AddChildView(view2);
845 100
846 TestFocusChangeListener listener; 101 TestFocusChangeListener listener;
847 AddFocusChangeListener(&listener); 102 AddFocusChangeListener(&listener);
848 103
849 // Visual Studio 2010 has problems converting NULL to the null pointer for 104 // Visual Studio 2010 has problems converting NULL to the null pointer for
850 // std::pair. See http://connect.microsoft.com/VisualStudio/feedback/details/ 520043/error-converting-from-null-to-a-pointer-type-in-std-pair 105 // std::pair. See http://connect.microsoft.com/VisualStudio/feedback/details/ 520043/error-converting-from-null-to-a-pointer-type-in-std-pair
851 // It will work if we pass nullptr. 106 // It will work if we pass nullptr.
852 #if defined(_MSC_VER) && _MSC_VER >= 1600 107 #if defined(_MSC_VER) && _MSC_VER >= 1600
853 views::View* null_view = nullptr; 108 views::View* null_view = nullptr;
854 #else 109 #else
855 views::View* null_view = NULL; 110 views::View* null_view = NULL;
856 #endif 111 #endif
857 112
858 view1->RequestFocus(); 113 view1->RequestFocus();
859 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); 114 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
860 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view1)); 115 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view1));
861 listener.ClearFocusChanges(); 116 listener.ClearFocusChanges();
862 117
863 view2->RequestFocus(); 118 view2->RequestFocus();
864 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); 119 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
865 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view1, view2)); 120 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view1, view2));
866 listener.ClearFocusChanges(); 121 listener.ClearFocusChanges();
867 122
868 GetFocusManager()->ClearFocus(); 123 GetFocusManager()->ClearFocus();
869 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); 124 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
870 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view2, null_view)); 125 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view2, null_view));
871 } 126 }
872 127
873 class TestNativeButton : public NativeTextButton { 128 #if !defined(USE_AURA)
874 public:
875 explicit TestNativeButton(const string16& text)
876 : NativeTextButton(NULL, text) {
877 };
878 virtual gfx::NativeView TestGetNativeControlView() {
879 return GetWidget()->GetNativeView();
880 }
881 };
882
883 class TestCheckbox : public Checkbox {
884 public:
885 explicit TestCheckbox(const string16& text) : Checkbox(text) {
886 };
887 virtual gfx::NativeView TestGetNativeControlView() {
888 return GetWidget()->GetNativeView();
889 }
890 };
891
892 class TestRadioButton : public RadioButton {
893 public:
894 explicit TestRadioButton(const string16& text)
895 : RadioButton(text, 1) {
896 }
897 virtual gfx::NativeView TestGetNativeControlView() {
898 return GetWidget()->GetNativeView();
899 }
900 };
901
902 class TestTextfield : public Textfield { 129 class TestTextfield : public Textfield {
903 public: 130 public:
904 TestTextfield() { } 131 TestTextfield() {}
905 virtual gfx::NativeView TestGetNativeControlView() { 132 virtual gfx::NativeView TestGetNativeControlView() {
906 return native_wrapper_->GetTestingHandle(); 133 return native_wrapper_->GetTestingHandle();
907 } 134 }
908 }; 135 };
909 136
910 class TestCombobox : public Combobox, public ui::ComboboxModel {
911 public:
912 TestCombobox() : Combobox(this) { }
913 virtual gfx::NativeView TestGetNativeControlView() {
914 return native_wrapper_->GetTestingHandle();
915 }
916 virtual int GetItemCount() {
917 return 10;
918 }
919 virtual string16 GetItemAt(int index) {
920 return ASCIIToUTF16("Hello combo");
921 }
922 };
923
924 class TestTabbedPane : public TabbedPane { 137 class TestTabbedPane : public TabbedPane {
925 public: 138 public:
926 TestTabbedPane() { } 139 TestTabbedPane() {}
927 virtual gfx::NativeView TestGetNativeControlView() { 140 virtual gfx::NativeView TestGetNativeControlView() {
928 return native_tabbed_pane_->GetTestingHandle(); 141 return native_tabbed_pane_->GetTestingHandle();
929 } 142 }
930 }; 143 };
931 144
932 #if !defined(TOUCH_UI) 145 // Tests that NativeControls do set the focused View appropriately on the
933 // TODO(oshima): replace TOUCH_UI with PURE_VIEWS
934
935 // Tests that NativeControls do set the focus View appropriately on the
936 // FocusManager. 146 // FocusManager.
937 TEST_F(FocusManagerTest, FAILS_FocusNativeControls) { 147 TEST_F(FocusManagerTest, FAILS_FocusNativeControls) {
938 TestTextfield* textfield = new TestTextfield(); 148 TestTextfield* textfield = new TestTextfield();
939 TestTabbedPane* tabbed_pane = new TestTabbedPane(); 149 TestTabbedPane* tabbed_pane = new TestTabbedPane();
940 TestTextfield* textfield2 = new TestTextfield(); 150 TestTextfield* textfield2 = new TestTextfield();
941 151
942 content_view_->AddChildView(textfield); 152 GetContentsView()->AddChildView(textfield);
943 content_view_->AddChildView(tabbed_pane); 153 GetContentsView()->AddChildView(tabbed_pane);
944 154
945 tabbed_pane->AddTab(ASCIIToUTF16("Awesome textfield"), textfield2); 155 tabbed_pane->AddTab(ASCIIToUTF16("Awesome textfield"), textfield2);
946 156
947 // Simulate the native view getting the native focus (such as by user click). 157 // Simulate the native view getting the native focus (such as by user click).
948 FocusNativeView(textfield->TestGetNativeControlView()); 158 GetWidget()->FocusNativeView(textfield->TestGetNativeControlView());
949 EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView()); 159 EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView());
950 160
951 FocusNativeView(tabbed_pane->TestGetNativeControlView()); 161 GetWidget()->FocusNativeView(tabbed_pane->TestGetNativeControlView());
952 EXPECT_EQ(tabbed_pane, GetFocusManager()->GetFocusedView()); 162 EXPECT_EQ(tabbed_pane, GetFocusManager()->GetFocusedView());
953 163
954 FocusNativeView(textfield2->TestGetNativeControlView()); 164 GetWidget()->FocusNativeView(textfield2->TestGetNativeControlView());
955 EXPECT_EQ(textfield2, GetFocusManager()->GetFocusedView()); 165 EXPECT_EQ(textfield2, GetFocusManager()->GetFocusedView());
956 } 166 }
957 #endif 167 #endif
958 168
959 // On linux, we don't store/restore focused view because gtk handles 169 // There is no tabbed pane in Aura.
960 // this (and pure views will be the same). 170 #if !defined(USE_AURA)
961 #if defined(OS_WIN)
962
963 // Test that when activating/deactivating the top window, the focus is stored/
964 // restored properly.
965 TEST_F(FocusManagerTest, FocusStoreRestore) {
966 // Simulate an activate, otherwise the deactivate isn't going to do anything.
967 SimulateActivateWindow();
968
969 NativeTextButton* button = new NativeTextButton(NULL,
970 ASCIIToUTF16("Press me"));
971 View* view = new View();
972 view->set_focusable(true);
973
974 content_view_->AddChildView(button);
975 button->SetBounds(10, 10, 200, 30);
976 content_view_->AddChildView(view);
977 RunPendingMessages();
978
979 TestFocusChangeListener listener;
980 AddFocusChangeListener(&listener);
981
982 view->RequestFocus();
983 RunPendingMessages();
984 // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
985
986 // Visual Studio 2010 has problems converting NULL to the null pointer for
987 // std::pair. See http://connect.microsoft.com/VisualStudio/feedback/details/ 520043/error-converting-from-null-to-a-pointer-type-in-std-pair
988 // It will work if we pass nullptr.
989 #if defined(_MSC_VER) && _MSC_VER >= 1600
990 views::View* null_view = nullptr;
991 #else
992 views::View* null_view = NULL;
993 #endif
994
995 // Deacivate the window, it should store its focus.
996 SimulateDeactivateWindow();
997 EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
998 ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
999 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
1000 EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(view, null_view));
1001 listener.ClearFocusChanges();
1002
1003 // Reactivate, focus should come-back to the previously focused view.
1004 SimulateActivateWindow();
1005 EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
1006 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
1007 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view));
1008 listener.ClearFocusChanges();
1009
1010 // Same test with a NativeControl.
1011 button->RequestFocus();
1012 SimulateDeactivateWindow();
1013 EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView());
1014 ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
1015 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view, button));
1016 EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(button, null_view));
1017 listener.ClearFocusChanges();
1018
1019 SimulateActivateWindow();
1020 EXPECT_EQ(button, GetFocusManager()->GetFocusedView());
1021 ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
1022 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, button));
1023 listener.ClearFocusChanges();
1024
1025 /*
1026 // Now test that while the window is inactive we can change the focused view
1027 // (we do that in several places).
1028 SimulateDeactivateWindow();
1029 // TODO: would have to mock the window being inactive (with a TestWidgetWin
1030 // that would return false on IsActive()).
1031 GetFocusManager()->SetFocusedView(view);
1032 ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL);
1033
1034 EXPECT_EQ(view, GetFocusManager()->GetFocusedView());
1035 ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size()));
1036 EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(button, null_view));
1037 EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(null_view, view));
1038 */
1039 }
1040 #endif
1041
1042 #if !defined(TOUCH_UI)
1043 // TODO(oshima): There is no tabbed pane in pure views. Replace it
1044 // with different implementation.
1045
1046 TEST_F(FocusManagerTest, ContainsView) { 171 TEST_F(FocusManagerTest, ContainsView) {
1047 View* view = new View(); 172 View* view = new View();
1048 scoped_ptr<View> detached_view(new View()); 173 scoped_ptr<View> detached_view(new View());
1049 TabbedPane* tabbed_pane = new TabbedPane(); 174 TabbedPane* tabbed_pane = new TabbedPane();
1050 TabbedPane* nested_tabbed_pane = new TabbedPane(); 175 TabbedPane* nested_tabbed_pane = new TabbedPane();
1051 NativeTextButton* tab_button = new NativeTextButton( 176 NativeTextButton* tab_button = new NativeTextButton(
1052 NULL, ASCIIToUTF16("tab button")); 177 NULL, ASCIIToUTF16("tab button"));
1053 178
1054 content_view_->AddChildView(view); 179 GetContentsView()->AddChildView(view);
1055 content_view_->AddChildView(tabbed_pane); 180 GetContentsView()->AddChildView(tabbed_pane);
1056 // Adding a View inside a TabbedPane to test the case of nested root view. 181 // Adding a View inside a TabbedPane to test the case of nested root view.
1057 182
1058 tabbed_pane->AddTab(ASCIIToUTF16("Awesome tab"), nested_tabbed_pane); 183 tabbed_pane->AddTab(ASCIIToUTF16("Awesome tab"), nested_tabbed_pane);
1059 nested_tabbed_pane->AddTab(ASCIIToUTF16("Awesomer tab"), tab_button); 184 nested_tabbed_pane->AddTab(ASCIIToUTF16("Awesomer tab"), tab_button);
1060 185
1061 EXPECT_TRUE(GetFocusManager()->ContainsView(view)); 186 EXPECT_TRUE(GetFocusManager()->ContainsView(view));
1062 EXPECT_TRUE(GetFocusManager()->ContainsView(tabbed_pane)); 187 EXPECT_TRUE(GetFocusManager()->ContainsView(tabbed_pane));
1063 EXPECT_TRUE(GetFocusManager()->ContainsView(nested_tabbed_pane)); 188 EXPECT_TRUE(GetFocusManager()->ContainsView(nested_tabbed_pane));
1064 EXPECT_TRUE(GetFocusManager()->ContainsView(tab_button)); 189 EXPECT_TRUE(GetFocusManager()->ContainsView(tab_button));
1065 EXPECT_FALSE(GetFocusManager()->ContainsView(detached_view.get())); 190 EXPECT_FALSE(GetFocusManager()->ContainsView(detached_view.get()));
1066 } 191 }
1067 #endif 192 #endif
1068 193
1069 TEST_F(FocusTraversalTest, NormalTraversal) {
1070 const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
1071 kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
1072 kFruitButtonID, kFruitCheckBoxID, kComboboxID, kBroccoliButtonID,
1073 kRosettaLinkID, kStupeurEtTremblementLinkID,
1074 kDinerGameLinkID, kRidiculeLinkID, kClosetLinkID, kVisitingLinkID,
1075 kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID,
1076 kTaxiLinkID, kAsterixLinkID, kOKButtonID, kCancelButtonID, kHelpButtonID,
1077 kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID,
1078 kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
1079 kSearchTextfieldID, kSearchButtonID, kHelpLinkID,
1080 kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID };
1081
1082 // Uncomment the following line if you want to test manually the UI of this
1083 // test.
1084 // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
1085
1086 // Let's traverse the whole focus hierarchy (several times, to make sure it
1087 // loops OK).
1088 GetFocusManager()->ClearFocus();
1089 for (int i = 0; i < 3; ++i) {
1090 for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
1091 GetFocusManager()->AdvanceFocus(false);
1092 View* focused_view = GetFocusManager()->GetFocusedView();
1093 EXPECT_TRUE(focused_view != NULL);
1094 if (focused_view)
1095 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
1096 }
1097 }
1098
1099 // Let's traverse in reverse order.
1100 GetFocusManager()->ClearFocus();
1101 for (int i = 0; i < 3; ++i) {
1102 for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
1103 GetFocusManager()->AdvanceFocus(true);
1104 View* focused_view = GetFocusManager()->GetFocusedView();
1105 EXPECT_TRUE(focused_view != NULL);
1106 if (focused_view)
1107 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
1108 }
1109 }
1110 }
1111
1112 TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) {
1113 const int kDisabledIDs[] = {
1114 kBananaTextfieldID, kFruitCheckBoxID, kComboboxID, kAsparagusButtonID,
1115 kCauliflowerButtonID, kClosetLinkID, kVisitingLinkID, kBriceDeNiceLinkID,
1116 kTaxiLinkID, kAsterixLinkID, kHelpButtonID, kBoldCheckBoxID,
1117 kSearchTextfieldID, kHelpLinkID };
1118
1119 const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID,
1120 kOrangeTextfieldID, kKiwiTextfieldID, kFruitButtonID, kBroccoliButtonID,
1121 kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID,
1122 kRidiculeLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID,
1123 kOKButtonID, kCancelButtonID, kStyleContainerID, kItalicCheckBoxID,
1124 kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID,
1125 kSearchButtonID, kThumbnailContainerID, kThumbnailStarID,
1126 kThumbnailSuperStarID };
1127
1128 // Let's disable some views.
1129 for (size_t i = 0; i < arraysize(kDisabledIDs); i++) {
1130 View* v = FindViewByID(kDisabledIDs[i]);
1131 ASSERT_TRUE(v != NULL);
1132 v->SetEnabled(false);
1133 }
1134
1135 // Uncomment the following line if you want to test manually the UI of this
1136 // test.
1137 // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
1138
1139 View* focused_view;
1140 // Let's do one traversal (several times, to make sure it loops ok).
1141 GetFocusManager()->ClearFocus();
1142 for (int i = 0; i < 3; ++i) {
1143 for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
1144 GetFocusManager()->AdvanceFocus(false);
1145 focused_view = GetFocusManager()->GetFocusedView();
1146 EXPECT_TRUE(focused_view != NULL);
1147 if (focused_view)
1148 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
1149 }
1150 }
1151
1152 // Same thing in reverse.
1153 GetFocusManager()->ClearFocus();
1154 for (int i = 0; i < 3; ++i) {
1155 for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
1156 GetFocusManager()->AdvanceFocus(true);
1157 focused_view = GetFocusManager()->GetFocusedView();
1158 EXPECT_TRUE(focused_view != NULL);
1159 if (focused_view)
1160 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
1161 }
1162 }
1163 }
1164
1165 TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) {
1166 const int kInvisibleIDs[] = { kTopCheckBoxID, kOKButtonID,
1167 kThumbnailContainerID };
1168
1169 const int kTraversalIDs[] = { kAppleTextfieldID, kOrangeTextfieldID,
1170 kBananaTextfieldID, kKiwiTextfieldID, kFruitButtonID, kFruitCheckBoxID,
1171 kComboboxID, kBroccoliButtonID, kRosettaLinkID,
1172 kStupeurEtTremblementLinkID, kDinerGameLinkID, kRidiculeLinkID,
1173 kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
1174 kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID,
1175 kCancelButtonID, kHelpButtonID, kStyleContainerID, kBoldCheckBoxID,
1176 kItalicCheckBoxID, kUnderlinedCheckBoxID, kStyleHelpLinkID,
1177 kStyleTextEditID, kSearchTextfieldID, kSearchButtonID, kHelpLinkID };
1178
1179
1180 // Let's make some views invisible.
1181 for (size_t i = 0; i < arraysize(kInvisibleIDs); i++) {
1182 View* v = FindViewByID(kInvisibleIDs[i]);
1183 ASSERT_TRUE(v != NULL);
1184 v->SetVisible(false);
1185 }
1186
1187 // Uncomment the following line if you want to test manually the UI of this
1188 // test.
1189 // MessageLoopForUI::current()->RunWithDispatcher(new AcceleratorHandler());
1190
1191 View* focused_view;
1192 // Let's do one traversal (several times, to make sure it loops ok).
1193 GetFocusManager()->ClearFocus();
1194 for (int i = 0; i < 3; ++i) {
1195 for (size_t j = 0; j < arraysize(kTraversalIDs); j++) {
1196 GetFocusManager()->AdvanceFocus(false);
1197 focused_view = GetFocusManager()->GetFocusedView();
1198 EXPECT_TRUE(focused_view != NULL);
1199 if (focused_view)
1200 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
1201 }
1202 }
1203
1204 // Same thing in reverse.
1205 GetFocusManager()->ClearFocus();
1206 for (int i = 0; i < 3; ++i) {
1207 for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) {
1208 GetFocusManager()->AdvanceFocus(true);
1209 focused_view = GetFocusManager()->GetFocusedView();
1210 EXPECT_TRUE(focused_view != NULL);
1211 if (focused_view)
1212 EXPECT_EQ(kTraversalIDs[j], focused_view->id());
1213 }
1214 }
1215 }
1216
1217 TEST_F(FocusTraversalTest, PaneTraversal) {
1218 // Tests trapping the traversal within a pane - useful for full
1219 // keyboard accessibility for toolbars.
1220
1221 // First test the left container.
1222 const int kLeftTraversalIDs[] = {
1223 kAppleTextfieldID,
1224 kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID,
1225 kFruitButtonID, kFruitCheckBoxID, kComboboxID };
1226
1227 FocusSearch focus_search_left(left_container_, true, false);
1228 left_container_->EnablePaneFocus(&focus_search_left);
1229 FindViewByID(kComboboxID)->RequestFocus();
1230
1231 // Traverse the focus hierarchy within the pane several times.
1232 for (int i = 0; i < 3; ++i) {
1233 for (size_t j = 0; j < arraysize(kLeftTraversalIDs); j++) {
1234 GetFocusManager()->AdvanceFocus(false);
1235 View* focused_view = GetFocusManager()->GetFocusedView();
1236 EXPECT_TRUE(focused_view != NULL);
1237 if (focused_view)
1238 EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
1239 }
1240 }
1241
1242 // Traverse in reverse order.
1243 FindViewByID(kAppleTextfieldID)->RequestFocus();
1244 for (int i = 0; i < 3; ++i) {
1245 for (int j = arraysize(kLeftTraversalIDs) - 1; j >= 0; --j) {
1246 GetFocusManager()->AdvanceFocus(true);
1247 View* focused_view = GetFocusManager()->GetFocusedView();
1248 EXPECT_TRUE(focused_view != NULL);
1249 if (focused_view)
1250 EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id());
1251 }
1252 }
1253
1254 // Now test the right container, but this time with accessibility mode.
1255 // Make some links not focusable, but mark one of them as
1256 // "accessibility focusable", so it should show up in the traversal.
1257 const int kRightTraversalIDs[] = {
1258 kBroccoliButtonID, kDinerGameLinkID, kRidiculeLinkID,
1259 kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID,
1260 kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID };
1261
1262 FocusSearch focus_search_right(right_container_, true, true);
1263 right_container_->EnablePaneFocus(&focus_search_right);
1264 FindViewByID(kRosettaLinkID)->set_focusable(false);
1265 FindViewByID(kStupeurEtTremblementLinkID)->set_focusable(false);
1266 FindViewByID(kDinerGameLinkID)->set_accessibility_focusable(true);
1267 FindViewByID(kDinerGameLinkID)->set_focusable(false);
1268 FindViewByID(kAsterixLinkID)->RequestFocus();
1269
1270 // Traverse the focus hierarchy within the pane several times.
1271 for (int i = 0; i < 3; ++i) {
1272 for (size_t j = 0; j < arraysize(kRightTraversalIDs); j++) {
1273 GetFocusManager()->AdvanceFocus(false);
1274 View* focused_view = GetFocusManager()->GetFocusedView();
1275 EXPECT_TRUE(focused_view != NULL);
1276 if (focused_view)
1277 EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
1278 }
1279 }
1280
1281 // Traverse in reverse order.
1282 FindViewByID(kBroccoliButtonID)->RequestFocus();
1283 for (int i = 0; i < 3; ++i) {
1284 for (int j = arraysize(kRightTraversalIDs) - 1; j >= 0; --j) {
1285 GetFocusManager()->AdvanceFocus(true);
1286 View* focused_view = GetFocusManager()->GetFocusedView();
1287 EXPECT_TRUE(focused_view != NULL);
1288 if (focused_view)
1289 EXPECT_EQ(kRightTraversalIDs[j], focused_view->id());
1290 }
1291 }
1292 }
1293
1294 // Counts accelerator calls. 194 // Counts accelerator calls.
1295 class TestAcceleratorTarget : public ui::AcceleratorTarget { 195 class TestAcceleratorTarget : public ui::AcceleratorTarget {
1296 public: 196 public:
1297 explicit TestAcceleratorTarget(bool process_accelerator) 197 explicit TestAcceleratorTarget(bool process_accelerator)
1298 : accelerator_count_(0), process_accelerator_(process_accelerator) {} 198 : accelerator_count_(0), process_accelerator_(process_accelerator) {}
1299 199
1300 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) { 200 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) {
1301 ++accelerator_count_; 201 ++accelerator_count_;
1302 return process_accelerator_; 202 return process_accelerator_;
1303 } 203 }
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1446 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); 346 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
1447 EXPECT_EQ(target.accelerator_count(), 1); 347 EXPECT_EQ(target.accelerator_count(), 1);
1448 EXPECT_EQ(NULL, 348 EXPECT_EQ(NULL,
1449 focus_manager->GetCurrentTargetForAccelerator(return_accelerator)); 349 focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
1450 350
1451 // Hitting the return key again; nothing should happen. 351 // Hitting the return key again; nothing should happen.
1452 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); 352 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
1453 EXPECT_EQ(target.accelerator_count(), 1); 353 EXPECT_EQ(target.accelerator_count(), 1);
1454 } 354 }
1455 355
1456 class MessageTrackingView : public View {
1457 public:
1458 MessageTrackingView() : accelerator_pressed_(false) {
1459 }
1460
1461 virtual bool OnKeyPressed(const KeyEvent& e) {
1462 keys_pressed_.push_back(e.key_code());
1463 return true;
1464 }
1465
1466 virtual bool OnKeyReleased(const KeyEvent& e) {
1467 keys_released_.push_back(e.key_code());
1468 return true;
1469 }
1470
1471 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) {
1472 accelerator_pressed_ = true;
1473 return true;
1474 }
1475
1476 void Reset() {
1477 accelerator_pressed_ = false;
1478 keys_pressed_.clear();
1479 keys_released_.clear();
1480 }
1481
1482 const std::vector<ui::KeyboardCode>& keys_pressed() const {
1483 return keys_pressed_;
1484 }
1485
1486 const std::vector<ui::KeyboardCode>& keys_released() const {
1487 return keys_released_;
1488 }
1489
1490 bool accelerator_pressed() const {
1491 return accelerator_pressed_;
1492 }
1493
1494 private:
1495 bool accelerator_pressed_;
1496 std::vector<ui::KeyboardCode> keys_pressed_;
1497 std::vector<ui::KeyboardCode> keys_released_;
1498
1499 DISALLOW_COPY_AND_ASSIGN(MessageTrackingView);
1500 };
1501
1502 #if defined(OS_WIN)
1503 // This test is now Windows only. Linux Views port does not handle accelerator
1504 // keys in AcceleratorHandler anymore. The logic has been moved into
1505 // NativeWidgetGtk::OnKeyEvent().
1506 // Tests that the keyup messages are eaten for accelerators.
1507 TEST_F(FocusManagerTest, IgnoreKeyupForAccelerators) {
1508 FocusManager* focus_manager = GetFocusManager();
1509 MessageTrackingView* mtv = new MessageTrackingView();
1510 mtv->AddAccelerator(ui::Accelerator(ui::VKEY_0, false, false, false));
1511 mtv->AddAccelerator(ui::Accelerator(ui::VKEY_1, false, false, false));
1512 content_view_->AddChildView(mtv);
1513 focus_manager->SetFocusedView(mtv);
1514
1515 // First send a non-accelerator key sequence.
1516 PostKeyDown(ui::VKEY_9);
1517 PostKeyUp(ui::VKEY_9);
1518 AcceleratorHandler accelerator_handler;
1519 MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
1520 MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
1521 // Make sure we get a key-up and key-down.
1522 ASSERT_EQ(1U, mtv->keys_pressed().size());
1523 EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
1524 ASSERT_EQ(1U, mtv->keys_released().size());
1525 EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
1526 EXPECT_FALSE(mtv->accelerator_pressed());
1527 mtv->Reset();
1528
1529 // Same thing with repeat and more than one key at once.
1530 PostKeyDown(ui::VKEY_9);
1531 PostKeyDown(ui::VKEY_9);
1532 PostKeyDown(ui::VKEY_8);
1533 PostKeyDown(ui::VKEY_9);
1534 PostKeyDown(ui::VKEY_7);
1535 PostKeyUp(ui::VKEY_9);
1536 PostKeyUp(ui::VKEY_7);
1537 PostKeyUp(ui::VKEY_8);
1538 MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
1539 MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
1540 // Make sure we get a key-up and key-down.
1541 ASSERT_EQ(5U, mtv->keys_pressed().size());
1542 EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[0]);
1543 EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[1]);
1544 EXPECT_EQ(ui::VKEY_8, mtv->keys_pressed()[2]);
1545 EXPECT_EQ(ui::VKEY_9, mtv->keys_pressed()[3]);
1546 EXPECT_EQ(ui::VKEY_7, mtv->keys_pressed()[4]);
1547 ASSERT_EQ(3U, mtv->keys_released().size());
1548 EXPECT_EQ(ui::VKEY_9, mtv->keys_released()[0]);
1549 EXPECT_EQ(ui::VKEY_7, mtv->keys_released()[1]);
1550 EXPECT_EQ(ui::VKEY_8, mtv->keys_released()[2]);
1551 EXPECT_FALSE(mtv->accelerator_pressed());
1552 mtv->Reset();
1553
1554 // Now send an accelerator key sequence.
1555 PostKeyDown(ui::VKEY_0);
1556 PostKeyUp(ui::VKEY_0);
1557 MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
1558 MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
1559 EXPECT_TRUE(mtv->keys_pressed().empty());
1560 EXPECT_TRUE(mtv->keys_released().empty());
1561 EXPECT_TRUE(mtv->accelerator_pressed());
1562 mtv->Reset();
1563
1564 // Same thing with repeat and more than one key at once.
1565 PostKeyDown(ui::VKEY_0);
1566 PostKeyDown(ui::VKEY_1);
1567 PostKeyDown(ui::VKEY_1);
1568 PostKeyDown(ui::VKEY_0);
1569 PostKeyDown(ui::VKEY_0);
1570 PostKeyUp(ui::VKEY_1);
1571 PostKeyUp(ui::VKEY_0);
1572 MessageLoopForUI::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
1573 MessageLoopForUI::current()->RunWithDispatcher(&accelerator_handler);
1574 EXPECT_TRUE(mtv->keys_pressed().empty());
1575 EXPECT_TRUE(mtv->keys_released().empty());
1576 EXPECT_TRUE(mtv->accelerator_pressed());
1577 mtv->Reset();
1578 }
1579 #endif
1580
1581 #if defined(OS_WIN) && !defined(USE_AURA)
1582 // Test that the focus manager is created successfully for the first view
1583 // window parented to a native dialog.
1584 TEST_F(FocusManagerTest, CreationForNativeRoot) {
1585 // Create a window class.
1586 WNDCLASSEX class_ex;
1587 memset(&class_ex, 0, sizeof(class_ex));
1588 class_ex.cbSize = sizeof(WNDCLASSEX);
1589 class_ex.lpfnWndProc = &DefWindowProc;
1590 class_ex.lpszClassName = L"TestWindow";
1591 ATOM atom = RegisterClassEx(&class_ex);
1592 ASSERT_TRUE(atom);
1593
1594 // Create a native dialog window.
1595 HWND hwnd = CreateWindowEx(0, class_ex.lpszClassName, NULL,
1596 WS_OVERLAPPEDWINDOW, 0, 0, 200, 200,
1597 NULL, NULL, NULL, NULL);
1598 ASSERT_TRUE(hwnd);
1599
1600 // Create a view window parented to native dialog.
1601 scoped_ptr<Widget> widget1(new Widget);
1602 Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
1603 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1604 params.parent = hwnd;
1605 params.bounds = gfx::Rect(0, 0, 100, 100);
1606 params.top_level = true; // This is top level in views hierarchy.
1607 widget1->Init(params);
1608
1609 // Get the focus manager directly from the first window. Should exist
1610 // because the first window is the root widget.
1611 views::FocusManager* focus_manager1 = widget1->GetFocusManager();
1612 EXPECT_TRUE(focus_manager1);
1613
1614 // Create another view window parented to the first view window.
1615 scoped_ptr<Widget> widget2(new Widget);
1616 params.parent = widget1->GetNativeView();
1617 params.top_level = false; // This is child widget.
1618 widget2->Init(params);
1619
1620 // Access the shared focus manager directly from the second window.
1621 views::FocusManager* focus_manager2 = widget2->GetFocusManager();
1622 EXPECT_EQ(focus_manager2, focus_manager1);
1623
1624 // Access the shared focus manager indirectly from the first window handle.
1625 gfx::NativeWindow native_window = widget1->GetNativeWindow();
1626 views::Widget* widget =
1627 views::Widget::GetWidgetForNativeWindow(native_window);
1628 EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
1629
1630 // Access the shared focus manager indirectly from the second window handle.
1631 native_window = widget2->GetNativeWindow();
1632 widget = views::Widget::GetWidgetForNativeWindow(native_window);
1633 EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
1634
1635 // Access the shared focus manager indirectly from the first view handle.
1636 gfx::NativeView native_view = widget1->GetNativeView();
1637 widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
1638 EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
1639
1640 // Access the shared focus manager indirectly from the second view handle.
1641 native_view = widget2->GetNativeView();
1642 widget = views::Widget::GetTopLevelWidgetForNativeView(native_view);
1643 EXPECT_EQ(widget->GetFocusManager(), focus_manager1);
1644
1645 DestroyWindow(hwnd);
1646 }
1647 #endif
1648
1649 class FocusManagerDtorTest : public FocusManagerTest { 356 class FocusManagerDtorTest : public FocusManagerTest {
1650 protected: 357 protected:
1651 typedef std::vector<std::string> DtorTrackVector; 358 typedef std::vector<std::string> DtorTrackVector;
1652 359
1653 class FocusManagerDtorTracked : public FocusManager { 360 class FocusManagerDtorTracked : public FocusManager {
1654 public: 361 public:
1655 FocusManagerDtorTracked(Widget* widget, DtorTrackVector* dtor_tracker) 362 FocusManagerDtorTracked(Widget* widget, DtorTrackVector* dtor_tracker)
1656 : FocusManager(widget), 363 : FocusManager(widget),
1657 dtor_tracker_(dtor_tracker) { 364 dtor_tracker_(dtor_tracker) {
1658 } 365 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1706 dtor_tracker_->push_back("WindowDtorTracked"); 413 dtor_tracker_->push_back("WindowDtorTracked");
1707 } 414 }
1708 415
1709 DtorTrackVector* dtor_tracker_; 416 DtorTrackVector* dtor_tracker_;
1710 }; 417 };
1711 418
1712 virtual void SetUp() { 419 virtual void SetUp() {
1713 ViewsTestBase::SetUp(); 420 ViewsTestBase::SetUp();
1714 FocusManagerFactory::Install(new TestFocusManagerFactory(&dtor_tracker_)); 421 FocusManagerFactory::Install(new TestFocusManagerFactory(&dtor_tracker_));
1715 // Create WindowDtorTracked that uses FocusManagerDtorTracked. 422 // Create WindowDtorTracked that uses FocusManagerDtorTracked.
1716 window_ = new WindowDtorTracked(&dtor_tracker_); 423 Widget* widget = new WindowDtorTracked(&dtor_tracker_);
1717 Widget::InitParams params; 424 Widget::InitParams params;
1718 params.delegate = this; 425 params.delegate = this;
1719 params.bounds = gfx::Rect(0, 0, 100, 100); 426 params.bounds = gfx::Rect(0, 0, 100, 100);
1720 window_->Init(params); 427 widget->Init(params);
1721 428
1722 tracked_focus_manager_ = 429 tracked_focus_manager_ =
1723 static_cast<FocusManagerDtorTracked*>(GetFocusManager()); 430 static_cast<FocusManagerDtorTracked*>(GetFocusManager());
1724 window_->Show(); 431 widget->Show();
1725 } 432 }
1726 433
1727 virtual void TearDown() { 434 virtual void TearDown() {
1728 if (window_) {
1729 window_->Close();
1730 RunPendingMessages();
1731 }
1732 FocusManagerFactory::Install(NULL); 435 FocusManagerFactory::Install(NULL);
1733 ViewsTestBase::TearDown(); 436 ViewsTestBase::TearDown();
1734 } 437 }
1735 438
1736 FocusManager* tracked_focus_manager_; 439 FocusManager* tracked_focus_manager_;
1737 DtorTrackVector dtor_tracker_; 440 DtorTrackVector dtor_tracker_;
1738 }; 441 };
1739 442
443 #if !defined(USE_AURA)
1740 TEST_F(FocusManagerDtorTest, FocusManagerDestructedLast) { 444 TEST_F(FocusManagerDtorTest, FocusManagerDestructedLast) {
1741 // Setup views hierarchy. 445 // Setup views hierarchy.
1742 TabbedPane* tabbed_pane = new TabbedPane(); 446 TabbedPane* tabbed_pane = new TabbedPane();
1743 content_view_->AddChildView(tabbed_pane); 447 GetContentsView()->AddChildView(tabbed_pane);
1744 448
1745 NativeButtonDtorTracked* button = new NativeButtonDtorTracked( 449 NativeButtonDtorTracked* button = new NativeButtonDtorTracked(
1746 ASCIIToUTF16("button"), &dtor_tracker_); 450 ASCIIToUTF16("button"), &dtor_tracker_);
1747 tabbed_pane->AddTab(ASCIIToUTF16("Awesome tab"), button); 451 tabbed_pane->AddTab(ASCIIToUTF16("Awesome tab"), button);
1748 452
1749 // Close the window. 453 // Close the window.
1750 window_->Close(); 454 GetWidget()->Close();
1751 RunPendingMessages(); 455 RunPendingMessages();
1752 456
1753 // Test window, button and focus manager should all be destructed. 457 // Test window, button and focus manager should all be destructed.
1754 ASSERT_EQ(3, static_cast<int>(dtor_tracker_.size())); 458 ASSERT_EQ(3, static_cast<int>(dtor_tracker_.size()));
1755 459
1756 // Focus manager should be the last one to destruct. 460 // Focus manager should be the last one to destruct.
1757 ASSERT_STREQ("FocusManagerDtorTracked", dtor_tracker_[2].c_str()); 461 ASSERT_STREQ("FocusManagerDtorTracked", dtor_tracker_[2].c_str());
1758
1759 // Clear window_ so that we don't try to close it again.
1760 window_ = NULL;
1761 } 462 }
463 #endif
1762 464
1763 } // namespace views 465 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698