Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / ui / views / widget / widget_interactive_uitest.cc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/basictypes.h"
6 #include "base/bind.h"
7 #include "base/command_line.h"
8 #include "base/path_service.h"
9 #include "base/run_loop.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "ui/base/resource/resource_bundle.h"
13 #include "ui/base/ui_base_paths.h"
14 #include "ui/base/ui_base_switches.h"
15 #include "ui/events/event_processor.h"
16 #include "ui/events/test/event_generator.h"
17 #include "ui/gfx/native_widget_types.h"
18 #include "ui/gl/gl_surface.h"
19 #include "ui/views/controls/textfield/textfield.h"
20 #include "ui/views/controls/textfield/textfield_test_api.h"
21 #include "ui/views/focus/focus_manager.h"
22 #include "ui/views/test/focus_manager_test.h"
23 #include "ui/views/test/widget_test.h"
24 #include "ui/views/touchui/touch_selection_controller_impl.h"
25 #include "ui/views/widget/widget.h"
26 #include "ui/views/window/dialog_delegate.h"
27 #include "ui/wm/public/activation_client.h"
28
29 #if defined(OS_WIN)
30 #include "ui/aura/window.h"
31 #include "ui/aura/window_tree_host.h"
32 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
33 #include "ui/views/win/hwnd_util.h"
34 #endif
35
36 namespace views {
37 namespace test {
38
39 namespace {
40
41 // A View that closes the Widget and exits the current message-loop when it
42 // receives a mouse-release event.
43 class ExitLoopOnRelease : public View {
44  public:
45   ExitLoopOnRelease() {}
46   ~ExitLoopOnRelease() override {}
47
48  private:
49   // Overridden from View:
50   void OnMouseReleased(const ui::MouseEvent& event) override {
51     GetWidget()->Close();
52     base::MessageLoop::current()->QuitNow();
53   }
54
55   DISALLOW_COPY_AND_ASSIGN(ExitLoopOnRelease);
56 };
57
58 // A view that does a capture on ui::ET_GESTURE_TAP_DOWN events.
59 class GestureCaptureView : public View {
60  public:
61   GestureCaptureView() {}
62   ~GestureCaptureView() override {}
63
64  private:
65   // Overridden from View:
66   void OnGestureEvent(ui::GestureEvent* event) override {
67     if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
68       GetWidget()->SetCapture(this);
69       event->StopPropagation();
70     }
71   }
72
73   DISALLOW_COPY_AND_ASSIGN(GestureCaptureView);
74 };
75
76 // A view that always processes all mouse events.
77 class MouseView : public View {
78  public:
79   MouseView()
80       : View(),
81         entered_(0),
82         exited_(0),
83         pressed_(0) {
84   }
85   ~MouseView() override {}
86
87   bool OnMousePressed(const ui::MouseEvent& event) override {
88     pressed_++;
89     return true;
90   }
91
92   void OnMouseEntered(const ui::MouseEvent& event) override { entered_++; }
93
94   void OnMouseExited(const ui::MouseEvent& event) override { exited_++; }
95
96   // Return the number of OnMouseEntered calls and reset the counter.
97   int EnteredCalls() {
98     int i = entered_;
99     entered_ = 0;
100     return i;
101   }
102
103   // Return the number of OnMouseExited calls and reset the counter.
104   int ExitedCalls() {
105     int i = exited_;
106     exited_ = 0;
107     return i;
108   }
109
110   int pressed() const { return pressed_; }
111
112  private:
113   int entered_;
114   int exited_;
115
116   int pressed_;
117
118   DISALLOW_COPY_AND_ASSIGN(MouseView);
119 };
120
121 // A View that shows a different widget, sets capture on that widget, and
122 // initiates a nested message-loop when it receives a mouse-press event.
123 class NestedLoopCaptureView : public View {
124  public:
125   explicit NestedLoopCaptureView(Widget* widget) : widget_(widget) {}
126   ~NestedLoopCaptureView() override {}
127
128  private:
129   // Overridden from View:
130   bool OnMousePressed(const ui::MouseEvent& event) override {
131     // Start a nested loop.
132     widget_->Show();
133     widget_->SetCapture(widget_->GetContentsView());
134     EXPECT_TRUE(widget_->HasCapture());
135
136     base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
137     base::MessageLoop::ScopedNestableTaskAllower allow(loop);
138
139     base::RunLoop run_loop;
140     run_loop.Run();
141     return true;
142   }
143
144   Widget* widget_;
145
146   DISALLOW_COPY_AND_ASSIGN(NestedLoopCaptureView);
147 };
148
149 }  // namespace
150
151 class WidgetTestInteractive : public WidgetTest {
152  public:
153   WidgetTestInteractive() {}
154   ~WidgetTestInteractive() override {}
155
156   void SetUp() override {
157     gfx::GLSurface::InitializeOneOffForTests();
158     ui::RegisterPathProvider();
159     base::FilePath ui_test_pak_path;
160     ASSERT_TRUE(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
161     ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
162     WidgetTest::SetUp();
163   }
164
165  protected:
166   static void ShowQuickMenuImmediately(
167       TouchSelectionControllerImpl* controller) {
168     DCHECK(controller);
169     if (controller->context_menu_timer_.IsRunning()) {
170       controller->context_menu_timer_.Stop();
171 // TODO(tapted): Enable this when porting ui/views/touchui to Mac.
172 #if !defined(OS_MACOSX)
173       controller->ContextMenuTimerFired();
174 #endif
175     }
176   }
177
178   static bool IsQuickMenuVisible(TouchSelectionControllerImpl* controller) {
179     DCHECK(controller);
180     return controller->context_menu_ && controller->context_menu_->visible();
181   }
182 };
183
184 #if defined(OS_WIN)
185 // Tests whether activation and focus change works correctly in Windows.
186 // We test the following:-
187 // 1. If the active aura window is correctly set when a top level widget is
188 //    created.
189 // 2. If the active aura window in widget 1 created above, is set to NULL when
190 //    another top level widget is created and focused.
191 // 3. On focusing the native platform window for widget 1, the active aura
192 //    window for widget 1 should be set and that for widget 2 should reset.
193 // TODO(ananta): Discuss with erg on how to write this test for linux x11 aura.
194 TEST_F(WidgetTestInteractive, DesktopNativeWidgetAuraActivationAndFocusTest) {
195   // Create widget 1 and expect the active window to be its window.
196   View* contents_view1 = new View;
197   contents_view1->SetFocusable(true);
198   Widget widget1;
199   Widget::InitParams init_params =
200       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
201   init_params.bounds = gfx::Rect(0, 0, 200, 200);
202   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
203   init_params.native_widget = new DesktopNativeWidgetAura(&widget1);
204   widget1.Init(init_params);
205   widget1.SetContentsView(contents_view1);
206   widget1.Show();
207   aura::Window* root_window1= widget1.GetNativeView()->GetRootWindow();
208   contents_view1->RequestFocus();
209
210   EXPECT_TRUE(root_window1 != NULL);
211   aura::client::ActivationClient* activation_client1 =
212       aura::client::GetActivationClient(root_window1);
213   EXPECT_TRUE(activation_client1 != NULL);
214   EXPECT_EQ(activation_client1->GetActiveWindow(), widget1.GetNativeView());
215
216   // Create widget 2 and expect the active window to be its window.
217   View* contents_view2 = new View;
218   Widget widget2;
219   Widget::InitParams init_params2 =
220       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
221   init_params2.bounds = gfx::Rect(0, 0, 200, 200);
222   init_params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
223   init_params2.native_widget = new DesktopNativeWidgetAura(&widget2);
224   widget2.Init(init_params2);
225   widget2.SetContentsView(contents_view2);
226   widget2.Show();
227   aura::Window* root_window2 = widget2.GetNativeView()->GetRootWindow();
228   contents_view2->RequestFocus();
229   ::SetActiveWindow(
230       root_window2->GetHost()->GetAcceleratedWidget());
231
232   aura::client::ActivationClient* activation_client2 =
233       aura::client::GetActivationClient(root_window2);
234   EXPECT_TRUE(activation_client2 != NULL);
235   EXPECT_EQ(activation_client2->GetActiveWindow(), widget2.GetNativeView());
236   EXPECT_EQ(activation_client1->GetActiveWindow(),
237             reinterpret_cast<aura::Window*>(NULL));
238
239   // Now set focus back to widget 1 and expect the active window to be its
240   // window.
241   contents_view1->RequestFocus();
242   ::SetActiveWindow(
243       root_window1->GetHost()->GetAcceleratedWidget());
244   EXPECT_EQ(activation_client2->GetActiveWindow(),
245             reinterpret_cast<aura::Window*>(NULL));
246   EXPECT_EQ(activation_client1->GetActiveWindow(), widget1.GetNativeView());
247 }
248 #endif  // defined(OS_WIN)
249
250 TEST_F(WidgetTestInteractive, CaptureAutoReset) {
251   Widget* toplevel = CreateTopLevelFramelessPlatformWidget();
252   View* container = new View;
253   toplevel->SetContentsView(container);
254
255   EXPECT_FALSE(toplevel->HasCapture());
256   toplevel->SetCapture(NULL);
257   EXPECT_TRUE(toplevel->HasCapture());
258
259   // By default, mouse release removes capture.
260   gfx::Point click_location(45, 15);
261   ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location,
262                          ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
263   toplevel->OnMouseEvent(&release);
264   EXPECT_FALSE(toplevel->HasCapture());
265
266   // Now a mouse release shouldn't remove capture.
267   toplevel->set_auto_release_capture(false);
268   toplevel->SetCapture(NULL);
269   EXPECT_TRUE(toplevel->HasCapture());
270   toplevel->OnMouseEvent(&release);
271   EXPECT_TRUE(toplevel->HasCapture());
272   toplevel->ReleaseCapture();
273   EXPECT_FALSE(toplevel->HasCapture());
274
275   toplevel->Close();
276   RunPendingMessages();
277 }
278
279 TEST_F(WidgetTestInteractive, ResetCaptureOnGestureEnd) {
280   Widget* toplevel = CreateTopLevelFramelessPlatformWidget();
281   View* container = new View;
282   toplevel->SetContentsView(container);
283
284   View* gesture = new GestureCaptureView;
285   gesture->SetBounds(0, 0, 30, 30);
286   container->AddChildView(gesture);
287
288   MouseView* mouse = new MouseView;
289   mouse->SetBounds(30, 0, 30, 30);
290   container->AddChildView(mouse);
291
292   toplevel->SetSize(gfx::Size(100, 100));
293   toplevel->Show();
294
295   // Start a gesture on |gesture|.
296   ui::GestureEvent tap_down(15,
297                             15,
298                             0,
299                             base::TimeDelta(),
300                             ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
301   ui::GestureEvent end(15,
302                        15,
303                        0,
304                        base::TimeDelta(),
305                        ui::GestureEventDetails(ui::ET_GESTURE_END));
306   toplevel->OnGestureEvent(&tap_down);
307
308   // Now try to click on |mouse|. Since |gesture| will have capture, |mouse|
309   // will not receive the event.
310   gfx::Point click_location(45, 15);
311
312   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
313                        ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
314   ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location,
315                          ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
316
317   EXPECT_TRUE(toplevel->HasCapture());
318
319   toplevel->OnMouseEvent(&press);
320   toplevel->OnMouseEvent(&release);
321   EXPECT_EQ(0, mouse->pressed());
322
323   EXPECT_FALSE(toplevel->HasCapture());
324
325   // The end of the gesture should release the capture, and pressing on |mouse|
326   // should now reach |mouse|.
327   toplevel->OnGestureEvent(&end);
328   toplevel->OnMouseEvent(&press);
329   toplevel->OnMouseEvent(&release);
330   EXPECT_EQ(1, mouse->pressed());
331
332   toplevel->Close();
333   RunPendingMessages();
334 }
335
336 // Checks that if a mouse-press triggers a capture on a different widget (which
337 // consumes the mouse-release event), then the target of the press does not have
338 // capture.
339 TEST_F(WidgetTestInteractive, DisableCaptureWidgetFromMousePress) {
340   // The test creates two widgets: |first| and |second|.
341   // The View in |first| makes |second| visible, sets capture on it, and starts
342   // a nested loop (like a menu does). The View in |second| terminates the
343   // nested loop and closes the widget.
344   // The test sends a mouse-press event to |first|, and posts a task to send a
345   // release event to |second|, to make sure that the release event is
346   // dispatched after the nested loop starts.
347
348   Widget* first = CreateTopLevelFramelessPlatformWidget();
349   Widget* second = CreateTopLevelFramelessPlatformWidget();
350
351   View* container = new NestedLoopCaptureView(second);
352   first->SetContentsView(container);
353
354   second->SetContentsView(new ExitLoopOnRelease());
355
356   first->SetSize(gfx::Size(100, 100));
357   first->Show();
358
359   gfx::Point location(20, 20);
360   base::MessageLoop::current()->PostTask(FROM_HERE,
361       base::Bind(&Widget::OnMouseEvent,
362                  base::Unretained(second),
363                  base::Owned(new ui::MouseEvent(ui::ET_MOUSE_RELEASED,
364                                                 location,
365                                                 location,
366                                                 ui::EF_LEFT_MOUSE_BUTTON,
367                                                 ui::EF_LEFT_MOUSE_BUTTON))));
368   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location,
369                        ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
370   first->OnMouseEvent(&press);
371   EXPECT_FALSE(first->HasCapture());
372   first->Close();
373   RunPendingMessages();
374 }
375
376 // Tests some grab/ungrab events.
377 // TODO(estade): can this be enabled now that this is an interactive ui test?
378 TEST_F(WidgetTestInteractive, DISABLED_GrabUngrab) {
379   Widget* toplevel = CreateTopLevelPlatformWidget();
380   Widget* child1 = CreateChildNativeWidgetWithParent(toplevel);
381   Widget* child2 = CreateChildNativeWidgetWithParent(toplevel);
382
383   toplevel->SetBounds(gfx::Rect(0, 0, 500, 500));
384
385   child1->SetBounds(gfx::Rect(10, 10, 300, 300));
386   View* view = new MouseView();
387   view->SetBounds(0, 0, 300, 300);
388   child1->GetRootView()->AddChildView(view);
389
390   child2->SetBounds(gfx::Rect(200, 10, 200, 200));
391   view = new MouseView();
392   view->SetBounds(0, 0, 200, 200);
393   child2->GetRootView()->AddChildView(view);
394
395   toplevel->Show();
396   RunPendingMessages();
397
398   // Click on child1
399   gfx::Point p1(45, 45);
400   ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1,
401                          ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
402   toplevel->OnMouseEvent(&pressed);
403
404   EXPECT_TRUE(toplevel->HasCapture());
405   EXPECT_TRUE(child1->HasCapture());
406   EXPECT_FALSE(child2->HasCapture());
407
408   ui::MouseEvent released(ui::ET_MOUSE_RELEASED, p1, p1,
409                           ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
410   toplevel->OnMouseEvent(&released);
411
412   EXPECT_FALSE(toplevel->HasCapture());
413   EXPECT_FALSE(child1->HasCapture());
414   EXPECT_FALSE(child2->HasCapture());
415
416   RunPendingMessages();
417
418   // Click on child2
419   gfx::Point p2(315, 45);
420   ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED, p2, p2,
421                           ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
422   toplevel->OnMouseEvent(&pressed2);
423   EXPECT_TRUE(pressed2.handled());
424   EXPECT_TRUE(toplevel->HasCapture());
425   EXPECT_TRUE(child2->HasCapture());
426   EXPECT_FALSE(child1->HasCapture());
427
428   ui::MouseEvent released2(ui::ET_MOUSE_RELEASED, p2, p2,
429                            ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
430   toplevel->OnMouseEvent(&released2);
431   EXPECT_FALSE(toplevel->HasCapture());
432   EXPECT_FALSE(child1->HasCapture());
433   EXPECT_FALSE(child2->HasCapture());
434
435   toplevel->CloseNow();
436 }
437
438 // Tests mouse move outside of the window into the "resize controller" and back
439 // will still generate an OnMouseEntered and OnMouseExited event..
440 TEST_F(WidgetTestInteractive, CheckResizeControllerEvents) {
441   Widget* toplevel = CreateTopLevelPlatformWidget();
442
443   toplevel->SetBounds(gfx::Rect(0, 0, 100, 100));
444
445   MouseView* view = new MouseView();
446   view->SetBounds(90, 90, 10, 10);
447   toplevel->GetRootView()->AddChildView(view);
448
449   toplevel->Show();
450   RunPendingMessages();
451
452   // Move to an outside position.
453   gfx::Point p1(200, 200);
454   ui::MouseEvent moved_out(ui::ET_MOUSE_MOVED, p1, p1, ui::EF_NONE,
455                            ui::EF_NONE);
456   toplevel->OnMouseEvent(&moved_out);
457   EXPECT_EQ(0, view->EnteredCalls());
458   EXPECT_EQ(0, view->ExitedCalls());
459
460   // Move onto the active view.
461   gfx::Point p2(95, 95);
462   ui::MouseEvent moved_over(ui::ET_MOUSE_MOVED, p2, p2, ui::EF_NONE,
463                             ui::EF_NONE);
464   toplevel->OnMouseEvent(&moved_over);
465   EXPECT_EQ(1, view->EnteredCalls());
466   EXPECT_EQ(0, view->ExitedCalls());
467
468   // Move onto the outer resizing border.
469   gfx::Point p3(102, 95);
470   ui::MouseEvent moved_resizer(ui::ET_MOUSE_MOVED, p3, p3, ui::EF_NONE,
471                                ui::EF_NONE);
472   toplevel->OnMouseEvent(&moved_resizer);
473   EXPECT_EQ(0, view->EnteredCalls());
474   EXPECT_EQ(1, view->ExitedCalls());
475
476   // Move onto the view again.
477   toplevel->OnMouseEvent(&moved_over);
478   EXPECT_EQ(1, view->EnteredCalls());
479   EXPECT_EQ(0, view->ExitedCalls());
480
481   RunPendingMessages();
482
483   toplevel->CloseNow();
484 }
485
486 // Test view focus restoration when a widget is deactivated and re-activated.
487 TEST_F(WidgetTestInteractive, ViewFocusOnWidgetActivationChanges) {
488   Widget* widget1 = CreateTopLevelPlatformWidget();
489   View* view1 = new View;
490   view1->SetFocusable(true);
491   widget1->GetContentsView()->AddChildView(view1);
492
493   Widget* widget2 = CreateTopLevelPlatformWidget();
494   View* view2a = new View;
495   View* view2b = new View;
496   view2a->SetFocusable(true);
497   view2b->SetFocusable(true);
498   widget2->GetContentsView()->AddChildView(view2a);
499   widget2->GetContentsView()->AddChildView(view2b);
500
501   widget1->Show();
502   EXPECT_TRUE(widget1->IsActive());
503   view1->RequestFocus();
504   EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView());
505
506   widget2->Show();
507   EXPECT_TRUE(widget2->IsActive());
508   EXPECT_FALSE(widget1->IsActive());
509   EXPECT_EQ(NULL, widget1->GetFocusManager()->GetFocusedView());
510   view2a->RequestFocus();
511   EXPECT_EQ(view2a, widget2->GetFocusManager()->GetFocusedView());
512   view2b->RequestFocus();
513   EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView());
514
515   widget1->Activate();
516   EXPECT_TRUE(widget1->IsActive());
517   EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView());
518   EXPECT_FALSE(widget2->IsActive());
519   EXPECT_EQ(NULL, widget2->GetFocusManager()->GetFocusedView());
520
521   widget2->Activate();
522   EXPECT_TRUE(widget2->IsActive());
523   EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView());
524   EXPECT_FALSE(widget1->IsActive());
525   EXPECT_EQ(NULL, widget1->GetFocusManager()->GetFocusedView());
526
527   widget1->CloseNow();
528   widget2->CloseNow();
529 }
530
531 #if defined(OS_WIN)
532
533 // Test view focus retention when a widget's HWND is disabled and re-enabled.
534 TEST_F(WidgetTestInteractive, ViewFocusOnHWNDEnabledChanges) {
535   Widget* widget = CreateTopLevelFramelessPlatformWidget();
536   widget->SetContentsView(new View);
537   for (size_t i = 0; i < 2; ++i) {
538     widget->GetContentsView()->AddChildView(new View);
539     widget->GetContentsView()->child_at(i)->SetFocusable(true);
540   }
541
542   widget->Show();
543   const HWND hwnd = HWNDForWidget(widget);
544   EXPECT_TRUE(::IsWindow(hwnd));
545   EXPECT_TRUE(::IsWindowEnabled(hwnd));
546   EXPECT_EQ(hwnd, ::GetActiveWindow());
547
548   for (int i = 0; i < widget->GetContentsView()->child_count(); ++i) {
549     SCOPED_TRACE(base::StringPrintf("Child view %d", i));
550     View* view = widget->GetContentsView()->child_at(i);
551
552     view->RequestFocus();
553     EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
554     EXPECT_FALSE(::EnableWindow(hwnd, FALSE));
555     EXPECT_FALSE(::IsWindowEnabled(hwnd));
556
557     // Oddly, disabling the HWND leaves it active with the focus unchanged.
558     EXPECT_EQ(hwnd, ::GetActiveWindow());
559     EXPECT_TRUE(widget->IsActive());
560     EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
561
562     EXPECT_TRUE(::EnableWindow(hwnd, TRUE));
563     EXPECT_TRUE(::IsWindowEnabled(hwnd));
564     EXPECT_EQ(hwnd, ::GetActiveWindow());
565     EXPECT_TRUE(widget->IsActive());
566     EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
567   }
568
569   widget->CloseNow();
570 }
571
572 // This class subclasses the Widget class to listen for activation change
573 // notifications and provides accessors to return information as to whether
574 // the widget is active. We need this to ensure that users of the widget
575 // class activate the widget only when the underlying window becomes really
576 // active. Previously we would activate the widget in the WM_NCACTIVATE
577 // message which is incorrect because APIs like FlashWindowEx flash the
578 // window caption by sending fake WM_NCACTIVATE messages.
579 class WidgetActivationTest : public Widget {
580  public:
581   WidgetActivationTest()
582       : active_(false) {}
583
584   virtual ~WidgetActivationTest() {}
585
586   virtual void OnNativeWidgetActivationChanged(bool active) override {
587     active_ = active;
588   }
589
590   bool active() const { return active_; }
591
592  private:
593   bool active_;
594
595   DISALLOW_COPY_AND_ASSIGN(WidgetActivationTest);
596 };
597
598 // Tests whether the widget only becomes active when the underlying window
599 // is really active.
600 TEST_F(WidgetTestInteractive, WidgetNotActivatedOnFakeActivationMessages) {
601   WidgetActivationTest widget1;
602   Widget::InitParams init_params =
603       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
604   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
605   init_params.native_widget = new DesktopNativeWidgetAura(&widget1);
606   init_params.bounds = gfx::Rect(0, 0, 200, 200);
607   widget1.Init(init_params);
608   widget1.Show();
609   EXPECT_EQ(true, widget1.active());
610
611   WidgetActivationTest widget2;
612   init_params.native_widget = new DesktopNativeWidgetAura(&widget2);
613   widget2.Init(init_params);
614   widget2.Show();
615   EXPECT_EQ(true, widget2.active());
616   EXPECT_EQ(false, widget1.active());
617
618   HWND win32_native_window1 = HWNDForWidget(&widget1);
619   EXPECT_TRUE(::IsWindow(win32_native_window1));
620
621   ::SendMessage(win32_native_window1, WM_NCACTIVATE, 1, 0);
622   EXPECT_EQ(false, widget1.active());
623   EXPECT_EQ(true, widget2.active());
624
625   ::SetActiveWindow(win32_native_window1);
626   EXPECT_EQ(true, widget1.active());
627   EXPECT_EQ(false, widget2.active());
628 }
629 #endif  // defined(OS_WIN)
630
631 #if !defined(OS_CHROMEOS)
632 // Provides functionality to create a window modal dialog.
633 class ModalDialogDelegate : public DialogDelegateView {
634  public:
635   explicit ModalDialogDelegate(ui::ModalType type) : type_(type) {}
636   ~ModalDialogDelegate() override {}
637
638   // WidgetDelegate overrides.
639   ui::ModalType GetModalType() const override { return type_; }
640
641  private:
642   ui::ModalType type_;
643
644   DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate);
645 };
646
647 // Tests whether the focused window is set correctly when a modal window is
648 // created and destroyed. When it is destroyed it should focus the owner window.
649 TEST_F(WidgetTestInteractive, WindowModalWindowDestroyedActivationTest) {
650   TestWidgetFocusChangeListener focus_listener;
651   WidgetFocusManager::GetInstance()->AddFocusChangeListener(&focus_listener);
652   const std::vector<NativeViewPair>& focus_changes =
653       focus_listener.focus_changes();
654
655   // Create a top level widget.
656   Widget top_level_widget;
657   Widget::InitParams init_params =
658       CreateParams(Widget::InitParams::TYPE_WINDOW);
659   init_params.show_state = ui::SHOW_STATE_NORMAL;
660   gfx::Rect initial_bounds(0, 0, 500, 500);
661   init_params.bounds = initial_bounds;
662   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
663   init_params.native_widget =
664       new PlatformDesktopNativeWidget(&top_level_widget);
665   top_level_widget.Init(init_params);
666   top_level_widget.Show();
667
668   gfx::NativeView top_level_native_view = top_level_widget.GetNativeView();
669   EXPECT_EQ(1u, focus_changes.size());
670   EXPECT_EQ(NativeViewPair(NULL, top_level_native_view), focus_changes[0]);
671
672   // Create a modal dialog.
673   // This instance will be destroyed when the dialog is destroyed.
674   ModalDialogDelegate* dialog_delegate =
675       new ModalDialogDelegate(ui::MODAL_TYPE_WINDOW);
676
677   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
678       dialog_delegate, NULL, top_level_widget.GetNativeView());
679   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
680   modal_dialog_widget->Show();
681
682   gfx::NativeView modal_native_view = modal_dialog_widget->GetNativeView();
683   EXPECT_EQ(3u, focus_changes.size());
684   EXPECT_EQ(NativeViewPair(top_level_native_view, modal_native_view),
685             focus_changes[1]);
686   EXPECT_EQ(NativeViewPair(top_level_native_view, modal_native_view),
687             focus_changes[2]);
688
689   modal_dialog_widget->CloseNow();
690
691   EXPECT_EQ(5u, focus_changes.size());
692   EXPECT_EQ(NativeViewPair(modal_native_view, top_level_native_view),
693             focus_changes[3]);
694   EXPECT_EQ(NativeViewPair(modal_native_view, top_level_native_view),
695             focus_changes[4]);
696
697   top_level_widget.CloseNow();
698   WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(&focus_listener);
699 }
700
701 // Test that when opening a system-modal window, capture is released.
702 TEST_F(WidgetTestInteractive, SystemModalWindowReleasesCapture) {
703   TestWidgetFocusChangeListener focus_listener;
704   WidgetFocusManager::GetInstance()->AddFocusChangeListener(&focus_listener);
705
706   // Create a top level widget.
707   Widget top_level_widget;
708   Widget::InitParams init_params =
709       CreateParams(Widget::InitParams::TYPE_WINDOW);
710   init_params.show_state = ui::SHOW_STATE_NORMAL;
711   gfx::Rect initial_bounds(0, 0, 500, 500);
712   init_params.bounds = initial_bounds;
713   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
714   init_params.native_widget =
715       new PlatformDesktopNativeWidget(&top_level_widget);
716   top_level_widget.Init(init_params);
717   top_level_widget.Show();
718
719   EXPECT_EQ(top_level_widget.GetNativeView(),
720             focus_listener.focus_changes().back().second);;
721
722   EXPECT_FALSE(top_level_widget.HasCapture());
723   top_level_widget.SetCapture(NULL);
724   EXPECT_TRUE(top_level_widget.HasCapture());
725
726   // Create a modal dialog.
727   ModalDialogDelegate* dialog_delegate =
728       new ModalDialogDelegate(ui::MODAL_TYPE_SYSTEM);
729
730   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
731       dialog_delegate, NULL, top_level_widget.GetNativeView());
732   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
733   modal_dialog_widget->Show();
734
735   EXPECT_FALSE(top_level_widget.HasCapture());
736
737   modal_dialog_widget->CloseNow();
738   top_level_widget.CloseNow();
739   WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(&focus_listener);
740 }
741
742 #endif  // !defined(OS_CHROMEOS)
743
744 TEST_F(WidgetTestInteractive, CanActivateFlagIsHonored) {
745   Widget widget;
746   Widget::InitParams init_params =
747       CreateParams(Widget::InitParams::TYPE_WINDOW);
748   init_params.bounds = gfx::Rect(0, 0, 200, 200);
749   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
750   init_params.activatable = Widget::InitParams::ACTIVATABLE_NO;
751 #if !defined(OS_CHROMEOS)
752   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
753 #endif  // !defined(OS_CHROMEOS)
754   widget.Init(init_params);
755
756   widget.Show();
757   EXPECT_FALSE(widget.IsActive());
758 }
759
760 // Test that touch selection quick menu is not activated when opened.
761 TEST_F(WidgetTestInteractive, TouchSelectionQuickMenuIsNotActivated) {
762   CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing);
763 #if defined(OS_WIN)
764   views_delegate().set_use_desktop_native_widgets(true);
765 #endif  // !defined(OS_WIN)
766
767   Widget widget;
768   Widget::InitParams init_params =
769       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
770   init_params.bounds = gfx::Rect(0, 0, 200, 200);
771   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
772   widget.Init(init_params);
773
774   Textfield* textfield = new Textfield;
775   textfield->SetBounds(0, 0, 200, 20);
776   textfield->SetText(base::ASCIIToUTF16("some text"));
777   widget.GetRootView()->AddChildView(textfield);
778
779   widget.Show();
780   textfield->RequestFocus();
781   textfield->SelectAll(true);
782   TextfieldTestApi textfield_test_api(textfield);
783
784   RunPendingMessages();
785
786   ui::test::EventGenerator generator(widget.GetNativeWindow());
787   generator.GestureTapAt(gfx::Point(10, 10));
788   ShowQuickMenuImmediately(static_cast<TouchSelectionControllerImpl*>(
789       textfield_test_api.touch_selection_controller()));
790
791   EXPECT_TRUE(textfield->HasFocus());
792   EXPECT_TRUE(widget.IsActive());
793   EXPECT_TRUE(IsQuickMenuVisible(static_cast<TouchSelectionControllerImpl*>(
794       textfield_test_api.touch_selection_controller())));
795 }
796
797 TEST_F(WidgetTestInteractive, DisableViewDoesNotActivateWidget) {
798 #if defined(OS_WIN)
799   views_delegate().set_use_desktop_native_widgets(true);
800 #endif  // !defined(OS_WIN)
801
802   // Create first widget and view, activate the widget, and focus the view.
803   Widget widget1;
804   Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_POPUP);
805   params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
806   params1.activatable = Widget::InitParams::ACTIVATABLE_YES;
807   widget1.Init(params1);
808
809   View* view1 = new View();
810   view1->SetFocusable(true);
811   widget1.GetRootView()->AddChildView(view1);
812
813   widget1.Activate();
814   EXPECT_TRUE(widget1.IsActive());
815
816   FocusManager* focus_manager1 = widget1.GetFocusManager();
817   ASSERT_TRUE(focus_manager1);
818   focus_manager1->SetFocusedView(view1);
819   EXPECT_EQ(view1, focus_manager1->GetFocusedView());
820
821   // Create second widget and view, activate the widget, and focus the view.
822   Widget widget2;
823   Widget::InitParams params2 = CreateParams(Widget::InitParams::TYPE_POPUP);
824   params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
825   params2.activatable = Widget::InitParams::ACTIVATABLE_YES;
826   widget2.Init(params2);
827
828   View* view2 = new View();
829   view2->SetFocusable(true);
830   widget2.GetRootView()->AddChildView(view2);
831
832   widget2.Activate();
833   EXPECT_TRUE(widget2.IsActive());
834   EXPECT_FALSE(widget1.IsActive());
835
836   FocusManager* focus_manager2 = widget2.GetFocusManager();
837   ASSERT_TRUE(focus_manager2);
838   focus_manager2->SetFocusedView(view2);
839   EXPECT_EQ(view2, focus_manager2->GetFocusedView());
840
841   // Disable the first view and make sure it loses focus, but its widget is not
842   // activated.
843   view1->SetEnabled(false);
844   EXPECT_NE(view1, focus_manager1->GetFocusedView());
845   EXPECT_FALSE(widget1.IsActive());
846   EXPECT_TRUE(widget2.IsActive());
847 }
848
849 namespace {
850
851 // Used to veirfy OnMouseCaptureLost() has been invoked.
852 class CaptureLostTrackingWidget : public Widget {
853  public:
854   CaptureLostTrackingWidget() : got_capture_lost_(false) {}
855   ~CaptureLostTrackingWidget() override {}
856
857   bool GetAndClearGotCaptureLost() {
858     bool value = got_capture_lost_;
859     got_capture_lost_ = false;
860     return value;
861   }
862
863   // Widget:
864   void OnMouseCaptureLost() override {
865     got_capture_lost_ = true;
866     Widget::OnMouseCaptureLost();
867   }
868
869  private:
870   bool got_capture_lost_;
871
872   DISALLOW_COPY_AND_ASSIGN(CaptureLostTrackingWidget);
873 };
874
875 }  // namespace
876
877 class WidgetCaptureTest : public ViewsTestBase {
878  public:
879   WidgetCaptureTest() {
880   }
881
882   ~WidgetCaptureTest() override {}
883
884   void SetUp() override {
885     gfx::GLSurface::InitializeOneOffForTests();
886     ui::RegisterPathProvider();
887     base::FilePath ui_test_pak_path;
888     ASSERT_TRUE(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
889     ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
890     ViewsTestBase::SetUp();
891   }
892
893   // Verifies Widget::SetCapture() results in updating native capture along with
894   // invoking the right Widget function.
895   void TestCapture(bool use_desktop_native_widget) {
896     CaptureLostTrackingWidget widget1;
897     Widget::InitParams params1 =
898         CreateParams(views::Widget::InitParams::TYPE_WINDOW);
899     params1.native_widget = CreateNativeWidget(use_desktop_native_widget,
900                                                &widget1);
901     params1.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
902     widget1.Init(params1);
903     widget1.Show();
904
905     CaptureLostTrackingWidget widget2;
906     Widget::InitParams params2 =
907         CreateParams(views::Widget::InitParams::TYPE_WINDOW);
908     params2.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
909     params2.native_widget = CreateNativeWidget(use_desktop_native_widget,
910                                                &widget2);
911     widget2.Init(params2);
912     widget2.Show();
913
914     // Set capture to widget2 and verity it gets it.
915     widget2.SetCapture(widget2.GetRootView());
916     EXPECT_FALSE(widget1.HasCapture());
917     EXPECT_TRUE(widget2.HasCapture());
918     EXPECT_FALSE(widget1.GetAndClearGotCaptureLost());
919     EXPECT_FALSE(widget2.GetAndClearGotCaptureLost());
920
921     // Set capture to widget1 and verify it gets it.
922     widget1.SetCapture(widget1.GetRootView());
923     EXPECT_TRUE(widget1.HasCapture());
924     EXPECT_FALSE(widget2.HasCapture());
925     EXPECT_FALSE(widget1.GetAndClearGotCaptureLost());
926     EXPECT_TRUE(widget2.GetAndClearGotCaptureLost());
927
928     // Release and verify no one has it.
929     widget1.ReleaseCapture();
930     EXPECT_FALSE(widget1.HasCapture());
931     EXPECT_FALSE(widget2.HasCapture());
932     EXPECT_TRUE(widget1.GetAndClearGotCaptureLost());
933     EXPECT_FALSE(widget2.GetAndClearGotCaptureLost());
934   }
935
936   NativeWidget* CreateNativeWidget(bool create_desktop_native_widget,
937                                    Widget* widget) {
938 #if !defined(OS_CHROMEOS)
939     if (create_desktop_native_widget)
940       return new PlatformDesktopNativeWidget(widget);
941 #endif
942     return NULL;
943   }
944
945  private:
946   DISALLOW_COPY_AND_ASSIGN(WidgetCaptureTest);
947 };
948
949 // See description in TestCapture().
950 TEST_F(WidgetCaptureTest, Capture) {
951   TestCapture(false);
952 }
953
954 #if !defined(OS_CHROMEOS)
955 // See description in TestCapture(). Creates DesktopNativeWidget.
956 TEST_F(WidgetCaptureTest, CaptureDesktopNativeWidget) {
957   TestCapture(true);
958 }
959 #endif
960
961 // Test that no state is set if capture fails.
962 TEST_F(WidgetCaptureTest, FailedCaptureRequestIsNoop) {
963   Widget widget;
964   Widget::InitParams params =
965       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
966   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
967   params.bounds = gfx::Rect(400, 400);
968   widget.Init(params);
969
970   MouseView* mouse_view1 = new MouseView;
971   MouseView* mouse_view2 = new MouseView;
972   View* contents_view = new View;
973   contents_view->AddChildView(mouse_view1);
974   contents_view->AddChildView(mouse_view2);
975   widget.SetContentsView(contents_view);
976
977   mouse_view1->SetBounds(0, 0, 200, 400);
978   mouse_view2->SetBounds(200, 0, 200, 400);
979
980   // Setting capture should fail because |widget| is not visible.
981   widget.SetCapture(mouse_view1);
982   EXPECT_FALSE(widget.HasCapture());
983
984   widget.Show();
985   ui::test::EventGenerator generator(GetContext(), widget.GetNativeWindow());
986   generator.set_current_location(gfx::Point(300, 10));
987   generator.PressLeftButton();
988
989   EXPECT_FALSE(mouse_view1->pressed());
990   EXPECT_TRUE(mouse_view2->pressed());
991 }
992
993 #if !defined(OS_CHROMEOS) && !defined(OS_WIN)
994 // Test that a synthetic mouse exit is sent to the widget which was handling
995 // mouse events when a different widget grabs capture.
996 // TODO(pkotwicz): Make test pass on CrOS and Windows.
997 TEST_F(WidgetCaptureTest, MouseExitOnCaptureGrab) {
998   Widget widget1;
999   Widget::InitParams params1 =
1000       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1001   params1.native_widget = CreateNativeWidget(true, &widget1);
1002   params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1003   widget1.Init(params1);
1004   MouseView* mouse_view1 = new MouseView;
1005   widget1.SetContentsView(mouse_view1);
1006   widget1.Show();
1007   widget1.SetBounds(gfx::Rect(300, 300));
1008
1009   Widget widget2;
1010   Widget::InitParams params2 =
1011       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1012   params2.native_widget = CreateNativeWidget(true, &widget2);
1013   params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1014   widget2.Init(params2);
1015   widget2.Show();
1016   widget2.SetBounds(gfx::Rect(400, 0, 300, 300));
1017
1018   ui::test::EventGenerator generator(widget1.GetNativeWindow());
1019   generator.set_current_location(gfx::Point(100, 100));
1020   generator.MoveMouseBy(0, 0);
1021
1022   EXPECT_EQ(1, mouse_view1->EnteredCalls());
1023   EXPECT_EQ(0, mouse_view1->ExitedCalls());
1024
1025   widget2.SetCapture(NULL);
1026   EXPECT_EQ(0, mouse_view1->EnteredCalls());
1027   // Grabbing native capture on Windows generates a ui::ET_MOUSE_EXITED event
1028   // in addition to the one generated by Chrome.
1029   EXPECT_LT(0, mouse_view1->ExitedCalls());
1030 }
1031 #endif  // !defined(OS_CHROMEOS)
1032
1033 namespace {
1034
1035 // Widget observer which grabs capture when the widget is activated.
1036 class CaptureOnActivationObserver : public WidgetObserver {
1037  public:
1038   CaptureOnActivationObserver() {
1039   }
1040   ~CaptureOnActivationObserver() override {}
1041
1042   // WidgetObserver:
1043   void OnWidgetActivationChanged(Widget* widget, bool active) override {
1044     if (active)
1045       widget->SetCapture(NULL);
1046   }
1047
1048  private:
1049   DISALLOW_COPY_AND_ASSIGN(CaptureOnActivationObserver);
1050 };
1051
1052 }  // namespace
1053
1054 // Test that setting capture on widget activation of a non-toplevel widget
1055 // (e.g. a bubble on Linux) succeeds.
1056 TEST_F(WidgetCaptureTest, SetCaptureToNonToplevel) {
1057   Widget toplevel;
1058   Widget::InitParams toplevel_params =
1059       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1060   toplevel_params.native_widget = CreateNativeWidget(true, &toplevel);
1061   toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1062   toplevel.Init(toplevel_params);
1063   toplevel.Show();
1064
1065   Widget* child = new Widget;
1066   Widget::InitParams child_params =
1067       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1068   child_params.parent = toplevel.GetNativeView();
1069   child_params.context = toplevel.GetNativeWindow();
1070   child->Init(child_params);
1071
1072   CaptureOnActivationObserver observer;
1073   child->AddObserver(&observer);
1074   child->Show();
1075
1076   EXPECT_TRUE(child->HasCapture());
1077 }
1078
1079
1080 #if defined(OS_WIN)
1081 namespace {
1082
1083 // Used to verify OnMouseEvent() has been invoked.
1084 class MouseEventTrackingWidget : public Widget {
1085  public:
1086   MouseEventTrackingWidget() : got_mouse_event_(false) {}
1087   virtual ~MouseEventTrackingWidget() {}
1088
1089   bool GetAndClearGotMouseEvent() {
1090     bool value = got_mouse_event_;
1091     got_mouse_event_ = false;
1092     return value;
1093   }
1094
1095   // Widget:
1096   virtual void OnMouseEvent(ui::MouseEvent* event) override {
1097     got_mouse_event_ = true;
1098     Widget::OnMouseEvent(event);
1099   }
1100
1101  private:
1102   bool got_mouse_event_;
1103
1104   DISALLOW_COPY_AND_ASSIGN(MouseEventTrackingWidget);
1105 };
1106
1107 }  // namespace
1108
1109 // Verifies if a mouse event is received on a widget that doesn't have capture
1110 // on Windows that it is correctly processed by the widget that doesn't have
1111 // capture. This behavior is not desired on OSes other than Windows.
1112 TEST_F(WidgetCaptureTest, MouseEventDispatchedToRightWindow) {
1113   MouseEventTrackingWidget widget1;
1114   Widget::InitParams params1 =
1115       CreateParams(views::Widget::InitParams::TYPE_WINDOW);
1116   params1.native_widget = new DesktopNativeWidgetAura(&widget1);
1117   params1.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1118   widget1.Init(params1);
1119   widget1.Show();
1120
1121   MouseEventTrackingWidget widget2;
1122   Widget::InitParams params2 =
1123       CreateParams(views::Widget::InitParams::TYPE_WINDOW);
1124   params2.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1125   params2.native_widget = new DesktopNativeWidgetAura(&widget2);
1126   widget2.Init(params2);
1127   widget2.Show();
1128
1129   // Set capture to widget2 and verity it gets it.
1130   widget2.SetCapture(widget2.GetRootView());
1131   EXPECT_FALSE(widget1.HasCapture());
1132   EXPECT_TRUE(widget2.HasCapture());
1133
1134   widget1.GetAndClearGotMouseEvent();
1135   widget2.GetAndClearGotMouseEvent();
1136   // Send a mouse event to the RootWindow associated with |widget1|. Even though
1137   // |widget2| has capture, |widget1| should still get the event.
1138   ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(),
1139                              ui::EF_NONE, ui::EF_NONE);
1140   ui::EventDispatchDetails details = widget1.GetNativeWindow()->
1141       GetHost()->event_processor()->OnEventFromSource(&mouse_event);
1142   ASSERT_FALSE(details.dispatcher_destroyed);
1143   EXPECT_TRUE(widget1.GetAndClearGotMouseEvent());
1144   EXPECT_FALSE(widget2.GetAndClearGotMouseEvent());
1145 }
1146 #endif  // defined(OS_WIN)
1147
1148 }  // namespace test
1149 }  // namespace views