- add sources.
[platform/framework/web/crosswalk.git] / src / ui / views / widget / widget_unittest.cc
1 // Copyright (c) 2012 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 <algorithm>
6 #include <set>
7
8 #include "base/basictypes.h"
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/gfx/native_widget_types.h"
17 #include "ui/gfx/point.h"
18 #include "ui/views/bubble/bubble_delegate.h"
19 #include "ui/views/controls/textfield/textfield.h"
20 #include "ui/views/test/test_views_delegate.h"
21 #include "ui/views/test/widget_test.h"
22 #include "ui/views/views_delegate.h"
23 #include "ui/views/widget/native_widget_delegate.h"
24 #include "ui/views/widget/root_view.h"
25 #include "ui/views/window/dialog_delegate.h"
26 #include "ui/views/window/native_frame_view.h"
27
28 #if defined(USE_AURA)
29 #include "ui/aura/client/aura_constants.h"
30 #include "ui/aura/client/window_tree_client.h"
31 #include "ui/aura/root_window.h"
32 #include "ui/aura/test/test_window_delegate.h"
33 #include "ui/aura/window.h"
34 #include "ui/views/widget/native_widget_aura.h"
35 #if !defined(OS_CHROMEOS)
36 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
37 #endif
38 #elif defined(OS_WIN)
39 #include "ui/views/widget/native_widget_win.h"
40 #endif
41
42 #if defined(OS_WIN)
43 #include "ui/views/win/hwnd_util.h"
44 #endif
45
46 namespace views {
47 namespace test {
48
49 // A view that keeps track of the events it receives, but consumes no events.
50 class EventCountView : public View {
51  public:
52   EventCountView() {}
53   virtual ~EventCountView() {}
54
55   int GetEventCount(ui::EventType type) {
56     return event_count_[type];
57   }
58
59   void ResetCounts() {
60     event_count_.clear();
61   }
62
63  protected:
64   // Overridden from ui::EventHandler:
65   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
66     RecordEvent(*event);
67   }
68   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
69     RecordEvent(*event);
70   }
71   virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
72     RecordEvent(*event);
73   }
74   virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
75     RecordEvent(*event);
76   }
77   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
78     RecordEvent(*event);
79   }
80
81  private:
82   void RecordEvent(const ui::Event& event) {
83     ++event_count_[event.type()];
84   }
85
86   std::map<ui::EventType, int> event_count_;
87
88   DISALLOW_COPY_AND_ASSIGN(EventCountView);
89 };
90
91 // A view that keeps track of the events it receives, and consumes all scroll
92 // gesture events.
93 class ScrollableEventCountView : public EventCountView {
94  public:
95   ScrollableEventCountView() {}
96   virtual ~ScrollableEventCountView() {}
97
98  private:
99   // Overridden from ui::EventHandler:
100   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
101     EventCountView::OnGestureEvent(event);
102     switch (event->type()) {
103       case ui::ET_GESTURE_SCROLL_BEGIN:
104       case ui::ET_GESTURE_SCROLL_UPDATE:
105       case ui::ET_GESTURE_SCROLL_END:
106       case ui::ET_SCROLL_FLING_START:
107         event->SetHandled();
108         break;
109       default:
110         break;
111     }
112   }
113
114   DISALLOW_COPY_AND_ASSIGN(ScrollableEventCountView);
115 };
116
117 // A view that implements GetMinimumSize.
118 class MinimumSizeFrameView : public NativeFrameView {
119  public:
120   explicit MinimumSizeFrameView(Widget* frame): NativeFrameView(frame) {}
121   virtual ~MinimumSizeFrameView() {}
122
123  private:
124   // Overridden from View:
125   virtual gfx::Size GetMinimumSize() OVERRIDE {
126     return gfx::Size(300, 400);
127   }
128
129   DISALLOW_COPY_AND_ASSIGN(MinimumSizeFrameView);
130 };
131
132 // An event handler that simply keeps a count of the different types of events
133 // it receives.
134 class EventCountHandler : public ui::EventHandler {
135  public:
136   EventCountHandler() {}
137   virtual ~EventCountHandler() {}
138
139   int GetEventCount(ui::EventType type) {
140     return event_count_[type];
141   }
142
143   void ResetCounts() {
144     event_count_.clear();
145   }
146
147  protected:
148   // Overridden from ui::EventHandler:
149   virtual void OnEvent(ui::Event* event) OVERRIDE {
150     RecordEvent(*event);
151     ui::EventHandler::OnEvent(event);
152   }
153
154  private:
155   void RecordEvent(const ui::Event& event) {
156     ++event_count_[event.type()];
157   }
158
159   std::map<ui::EventType, int> event_count_;
160
161   DISALLOW_COPY_AND_ASSIGN(EventCountHandler);
162 };
163
164 ui::WindowShowState GetWidgetShowState(const Widget* widget) {
165   // Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement
166   // because the former is implemented on all platforms but the latter is not.
167   return widget->IsFullscreen() ? ui::SHOW_STATE_FULLSCREEN :
168       widget->IsMaximized() ? ui::SHOW_STATE_MAXIMIZED :
169       widget->IsMinimized() ? ui::SHOW_STATE_MINIMIZED :
170                               ui::SHOW_STATE_NORMAL;
171 }
172
173 TEST_F(WidgetTest, WidgetInitParams) {
174   ASSERT_FALSE(views_delegate().UseTransparentWindows());
175
176   // Widgets are not transparent by default.
177   Widget::InitParams init1;
178   EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init1.opacity);
179
180   // Non-window widgets are not transparent either.
181   Widget::InitParams init2(Widget::InitParams::TYPE_MENU);
182   EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init2.opacity);
183
184   // A ViewsDelegate can set windows transparent by default.
185   views_delegate().SetUseTransparentWindows(true);
186   Widget::InitParams init3;
187   EXPECT_EQ(Widget::InitParams::TRANSLUCENT_WINDOW, init3.opacity);
188
189   // Non-window widgets stay opaque.
190   Widget::InitParams init4(Widget::InitParams::TYPE_MENU);
191   EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init4.opacity);
192 }
193
194 ////////////////////////////////////////////////////////////////////////////////
195 // Widget::GetTopLevelWidget tests.
196
197 TEST_F(WidgetTest, GetTopLevelWidget_Native) {
198   // Create a hierarchy of native widgets.
199   Widget* toplevel = CreateTopLevelPlatformWidget();
200   gfx::NativeView parent = toplevel->GetNativeView();
201   Widget* child = CreateChildPlatformWidget(parent);
202
203   EXPECT_EQ(toplevel, toplevel->GetTopLevelWidget());
204   EXPECT_EQ(toplevel, child->GetTopLevelWidget());
205
206   toplevel->CloseNow();
207   // |child| should be automatically destroyed with |toplevel|.
208 }
209
210 // Test if a focus manager and an inputmethod work without CHECK failure
211 // when window activation changes.
212 TEST_F(WidgetTest, ChangeActivation) {
213   Widget* top1 = CreateTopLevelPlatformWidget();
214   // CreateInputMethod before activated
215   top1->GetInputMethod();
216   top1->Show();
217   RunPendingMessages();
218
219   Widget* top2 = CreateTopLevelPlatformWidget();
220   top2->Show();
221   RunPendingMessages();
222
223   top1->Activate();
224   RunPendingMessages();
225
226   // Create InputMethod after deactivated.
227   top2->GetInputMethod();
228   top2->Activate();
229   RunPendingMessages();
230
231   top1->Activate();
232   RunPendingMessages();
233
234   top1->CloseNow();
235   top2->CloseNow();
236 }
237
238 // Tests visibility of child widgets.
239 TEST_F(WidgetTest, Visibility) {
240   Widget* toplevel = CreateTopLevelPlatformWidget();
241   gfx::NativeView parent = toplevel->GetNativeView();
242   Widget* child = CreateChildPlatformWidget(parent);
243
244   EXPECT_FALSE(toplevel->IsVisible());
245   EXPECT_FALSE(child->IsVisible());
246
247   child->Show();
248
249   EXPECT_FALSE(toplevel->IsVisible());
250   EXPECT_FALSE(child->IsVisible());
251
252   toplevel->Show();
253
254   EXPECT_TRUE(toplevel->IsVisible());
255   EXPECT_TRUE(child->IsVisible());
256
257   toplevel->CloseNow();
258   // |child| should be automatically destroyed with |toplevel|.
259 }
260
261 #if defined(OS_WIN) && !defined(USE_AURA)
262 // On Windows, it is possible to have child window that are TYPE_POPUP.  Unlike
263 // regular child windows, these should be created as hidden and must be shown
264 // explicitly.
265 TEST_F(WidgetTest, Visibility_ChildPopup) {
266   Widget* toplevel = CreateTopLevelPlatformWidget();
267   Widget* child_popup = CreateChildPopupPlatformWidget(
268       toplevel->GetNativeView());
269
270   EXPECT_FALSE(toplevel->IsVisible());
271   EXPECT_FALSE(child_popup->IsVisible());
272
273   toplevel->Show();
274
275   EXPECT_TRUE(toplevel->IsVisible());
276   EXPECT_FALSE(child_popup->IsVisible());
277
278   child_popup->Show();
279
280   EXPECT_TRUE(child_popup->IsVisible());
281
282   toplevel->CloseNow();
283   // |child_popup| should be automatically destroyed with |toplevel|.
284 }
285 #endif
286
287 ////////////////////////////////////////////////////////////////////////////////
288 // Widget ownership tests.
289 //
290 // Tests various permutations of Widget ownership specified in the
291 // InitParams::Ownership param.
292
293 // A WidgetTest that supplies a toplevel widget for NativeWidget to parent to.
294 class WidgetOwnershipTest : public WidgetTest {
295  public:
296   WidgetOwnershipTest() {}
297   virtual ~WidgetOwnershipTest() {}
298
299   virtual void SetUp() {
300     WidgetTest::SetUp();
301     desktop_widget_ = CreateTopLevelPlatformWidget();
302   }
303
304   virtual void TearDown() {
305     desktop_widget_->CloseNow();
306     WidgetTest::TearDown();
307   }
308
309  private:
310   Widget* desktop_widget_;
311
312   DISALLOW_COPY_AND_ASSIGN(WidgetOwnershipTest);
313 };
314
315 // A bag of state to monitor destructions.
316 struct OwnershipTestState {
317   OwnershipTestState() : widget_deleted(false), native_widget_deleted(false) {}
318
319   bool widget_deleted;
320   bool native_widget_deleted;
321 };
322
323 // A platform NativeWidget subclass that updates a bag of state when it is
324 // destroyed.
325 class OwnershipTestNativeWidget : public NativeWidgetPlatform {
326  public:
327   OwnershipTestNativeWidget(internal::NativeWidgetDelegate* delegate,
328                             OwnershipTestState* state)
329       : NativeWidgetPlatform(delegate),
330         state_(state) {
331   }
332   virtual ~OwnershipTestNativeWidget() {
333     state_->native_widget_deleted = true;
334   }
335
336  private:
337   OwnershipTestState* state_;
338
339   DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidget);
340 };
341
342 // A views NativeWidget subclass that updates a bag of state when it is
343 // destroyed.
344 class OwnershipTestNativeWidgetPlatform : public NativeWidgetPlatformForTest {
345  public:
346   OwnershipTestNativeWidgetPlatform(internal::NativeWidgetDelegate* delegate,
347                                     OwnershipTestState* state)
348       : NativeWidgetPlatformForTest(delegate),
349         state_(state) {
350   }
351   virtual ~OwnershipTestNativeWidgetPlatform() {
352     state_->native_widget_deleted = true;
353   }
354
355  private:
356   OwnershipTestState* state_;
357
358   DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetPlatform);
359 };
360
361 // A Widget subclass that updates a bag of state when it is destroyed.
362 class OwnershipTestWidget : public Widget {
363  public:
364   explicit OwnershipTestWidget(OwnershipTestState* state) : state_(state) {}
365   virtual ~OwnershipTestWidget() {
366     state_->widget_deleted = true;
367   }
368
369  private:
370   OwnershipTestState* state_;
371
372   DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget);
373 };
374
375 // Widget owns its NativeWidget, part 1: NativeWidget is a platform-native
376 // widget.
377 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) {
378   OwnershipTestState state;
379
380   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
381   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
382   params.native_widget =
383       new OwnershipTestNativeWidgetPlatform(widget.get(), &state);
384   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
385   widget->Init(params);
386
387   // Now delete the Widget, which should delete the NativeWidget.
388   widget.reset();
389
390   EXPECT_TRUE(state.widget_deleted);
391   EXPECT_TRUE(state.native_widget_deleted);
392
393   // TODO(beng): write test for this ownership scenario and the NativeWidget
394   //             being deleted out from under the Widget.
395 }
396
397 // Widget owns its NativeWidget, part 2: NativeWidget is a NativeWidget.
398 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) {
399   OwnershipTestState state;
400
401   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
402   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
403   params.native_widget =
404       new OwnershipTestNativeWidgetPlatform(widget.get(), &state);
405   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
406   widget->Init(params);
407
408   // Now delete the Widget, which should delete the NativeWidget.
409   widget.reset();
410
411   EXPECT_TRUE(state.widget_deleted);
412   EXPECT_TRUE(state.native_widget_deleted);
413
414   // TODO(beng): write test for this ownership scenario and the NativeWidget
415   //             being deleted out from under the Widget.
416 }
417
418 // Widget owns its NativeWidget, part 3: NativeWidget is a NativeWidget,
419 // destroy the parent view.
420 TEST_F(WidgetOwnershipTest,
421        Ownership_WidgetOwnsViewsNativeWidget_DestroyParentView) {
422   OwnershipTestState state;
423
424   Widget* toplevel = CreateTopLevelPlatformWidget();
425
426   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
427   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
428   params.native_widget =
429       new OwnershipTestNativeWidgetPlatform(widget.get(), &state);
430   params.parent = toplevel->GetNativeView();
431   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
432   widget->Init(params);
433
434   // Now close the toplevel, which deletes the view hierarchy.
435   toplevel->CloseNow();
436
437   RunPendingMessages();
438
439   // This shouldn't delete the widget because it shouldn't be deleted
440   // from the native side.
441   EXPECT_FALSE(state.widget_deleted);
442   EXPECT_FALSE(state.native_widget_deleted);
443
444   // Now delete it explicitly.
445   widget.reset();
446
447   EXPECT_TRUE(state.widget_deleted);
448   EXPECT_TRUE(state.native_widget_deleted);
449 }
450
451 // NativeWidget owns its Widget, part 1: NativeWidget is a platform-native
452 // widget.
453 TEST_F(WidgetOwnershipTest, Ownership_PlatformNativeWidgetOwnsWidget) {
454   OwnershipTestState state;
455
456   Widget* widget = new OwnershipTestWidget(&state);
457   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
458   params.native_widget =
459       new OwnershipTestNativeWidgetPlatform(widget, &state);
460   widget->Init(params);
461
462   // Now destroy the native widget.
463   widget->CloseNow();
464
465   EXPECT_TRUE(state.widget_deleted);
466   EXPECT_TRUE(state.native_widget_deleted);
467 }
468
469 // NativeWidget owns its Widget, part 2: NativeWidget is a NativeWidget.
470 TEST_F(WidgetOwnershipTest, Ownership_ViewsNativeWidgetOwnsWidget) {
471   OwnershipTestState state;
472
473   Widget* toplevel = CreateTopLevelPlatformWidget();
474
475   Widget* widget = new OwnershipTestWidget(&state);
476   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
477   params.native_widget =
478       new OwnershipTestNativeWidgetPlatform(widget, &state);
479   params.parent = toplevel->GetNativeView();
480   widget->Init(params);
481
482   // Now destroy the native widget. This is achieved by closing the toplevel.
483   toplevel->CloseNow();
484
485   // The NativeWidget won't be deleted until after a return to the message loop
486   // so we have to run pending messages before testing the destruction status.
487   RunPendingMessages();
488
489   EXPECT_TRUE(state.widget_deleted);
490   EXPECT_TRUE(state.native_widget_deleted);
491 }
492
493 // NativeWidget owns its Widget, part 3: NativeWidget is a platform-native
494 // widget, destroyed out from under it by the OS.
495 TEST_F(WidgetOwnershipTest,
496        Ownership_PlatformNativeWidgetOwnsWidget_NativeDestroy) {
497   OwnershipTestState state;
498
499   Widget* widget = new OwnershipTestWidget(&state);
500   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
501   params.native_widget =
502       new OwnershipTestNativeWidgetPlatform(widget, &state);
503   widget->Init(params);
504
505   // Now simulate a destroy of the platform native widget from the OS:
506 #if defined(USE_AURA)
507   delete widget->GetNativeView();
508 #elif defined(OS_WIN)
509   DestroyWindow(widget->GetNativeView());
510 #endif
511
512   EXPECT_TRUE(state.widget_deleted);
513   EXPECT_TRUE(state.native_widget_deleted);
514 }
515
516 // NativeWidget owns its Widget, part 4: NativeWidget is a NativeWidget,
517 // destroyed by the view hierarchy that contains it.
518 TEST_F(WidgetOwnershipTest,
519        Ownership_ViewsNativeWidgetOwnsWidget_NativeDestroy) {
520   OwnershipTestState state;
521
522   Widget* toplevel = CreateTopLevelPlatformWidget();
523
524   Widget* widget = new OwnershipTestWidget(&state);
525   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
526   params.native_widget =
527       new OwnershipTestNativeWidgetPlatform(widget, &state);
528   params.parent = toplevel->GetNativeView();
529   widget->Init(params);
530
531   // Destroy the widget (achieved by closing the toplevel).
532   toplevel->CloseNow();
533
534   // The NativeWidget won't be deleted until after a return to the message loop
535   // so we have to run pending messages before testing the destruction status.
536   RunPendingMessages();
537
538   EXPECT_TRUE(state.widget_deleted);
539   EXPECT_TRUE(state.native_widget_deleted);
540 }
541
542 // NativeWidget owns its Widget, part 5: NativeWidget is a NativeWidget,
543 // we close it directly.
544 TEST_F(WidgetOwnershipTest,
545        Ownership_ViewsNativeWidgetOwnsWidget_Close) {
546   OwnershipTestState state;
547
548   Widget* toplevel = CreateTopLevelPlatformWidget();
549
550   Widget* widget = new OwnershipTestWidget(&state);
551   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
552   params.native_widget =
553       new OwnershipTestNativeWidgetPlatform(widget, &state);
554   params.parent = toplevel->GetNativeView();
555   widget->Init(params);
556
557   // Destroy the widget.
558   widget->Close();
559   toplevel->CloseNow();
560
561   // The NativeWidget won't be deleted until after a return to the message loop
562   // so we have to run pending messages before testing the destruction status.
563   RunPendingMessages();
564
565   EXPECT_TRUE(state.widget_deleted);
566   EXPECT_TRUE(state.native_widget_deleted);
567 }
568
569 // Widget owns its NativeWidget and has a WidgetDelegateView as its contents.
570 TEST_F(WidgetOwnershipTest,
571        Ownership_WidgetOwnsNativeWidgetWithWithWidgetDelegateView) {
572   OwnershipTestState state;
573
574   WidgetDelegateView* delegate_view = new WidgetDelegateView;
575
576   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
577   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
578   params.native_widget =
579       new OwnershipTestNativeWidgetPlatform(widget.get(), &state);
580   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
581   params.delegate = delegate_view;
582   widget->Init(params);
583   widget->SetContentsView(delegate_view);
584
585   // Now delete the Widget. There should be no crash or use-after-free.
586   widget.reset();
587
588   EXPECT_TRUE(state.widget_deleted);
589   EXPECT_TRUE(state.native_widget_deleted);
590 }
591
592 ////////////////////////////////////////////////////////////////////////////////
593 // Test to verify using various Widget methods doesn't crash when the underlying
594 // NativeView is destroyed.
595 //
596 class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
597  public:
598   WidgetWithDestroyedNativeViewTest() {}
599   virtual ~WidgetWithDestroyedNativeViewTest() {}
600
601   void InvokeWidgetMethods(Widget* widget) {
602     widget->GetNativeView();
603     widget->GetNativeWindow();
604     ui::Accelerator accelerator;
605     widget->GetAccelerator(0, &accelerator);
606     widget->GetTopLevelWidget();
607     widget->GetWindowBoundsInScreen();
608     widget->GetClientAreaBoundsInScreen();
609     widget->SetBounds(gfx::Rect(0, 0, 100, 80));
610     widget->SetSize(gfx::Size(10, 11));
611     widget->SetBoundsConstrained(gfx::Rect(0, 0, 120, 140));
612     widget->SetVisibilityChangedAnimationsEnabled(false);
613     widget->StackAtTop();
614     widget->IsClosed();
615     widget->Close();
616     widget->Show();
617     widget->Hide();
618     widget->Activate();
619     widget->Deactivate();
620     widget->IsActive();
621     widget->DisableInactiveRendering();
622     widget->SetAlwaysOnTop(true);
623     widget->IsAlwaysOnTop();
624     widget->Maximize();
625     widget->Minimize();
626     widget->Restore();
627     widget->IsMaximized();
628     widget->IsFullscreen();
629     widget->SetOpacity(0);
630     widget->SetUseDragFrame(true);
631     widget->FlashFrame(true);
632     widget->IsVisible();
633     widget->GetThemeProvider();
634     widget->GetNativeTheme();
635     widget->GetFocusManager();
636     widget->GetInputMethod();
637     widget->SchedulePaintInRect(gfx::Rect(0, 0, 1, 2));
638     widget->IsMouseEventsEnabled();
639     widget->SetNativeWindowProperty("xx", widget);
640     widget->GetNativeWindowProperty("xx");
641     widget->GetFocusTraversable();
642     widget->GetLayer();
643     widget->ReorderNativeViews();
644     widget->SetCapture(widget->GetRootView());
645     widget->ReleaseCapture();
646     widget->HasCapture();
647     widget->GetWorkAreaBoundsInScreen();
648     // These three crash with NativeWidgetWin, so I'm assuming we don't need
649     // them to work for the other NativeWidget impls.
650     // widget->CenterWindow(gfx::Size(50, 60));
651     // widget->GetRestoredBounds();
652     // widget->ShowInactive();
653   }
654
655  private:
656   DISALLOW_COPY_AND_ASSIGN(WidgetWithDestroyedNativeViewTest);
657 };
658
659 TEST_F(WidgetWithDestroyedNativeViewTest, Test) {
660   {
661     Widget widget;
662     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
663     params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
664     widget.Init(params);
665     widget.Show();
666
667     widget.native_widget_private()->CloseNow();
668     InvokeWidgetMethods(&widget);
669   }
670 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
671   {
672     Widget widget;
673     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
674     params.native_widget = new DesktopNativeWidgetAura(&widget);
675     params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
676     widget.Init(params);
677     widget.Show();
678
679     widget.native_widget_private()->CloseNow();
680     InvokeWidgetMethods(&widget);
681   }
682 #endif
683 }
684
685 ////////////////////////////////////////////////////////////////////////////////
686 // Widget observer tests.
687 //
688
689 class WidgetObserverTest : public WidgetTest, public WidgetObserver {
690  public:
691   WidgetObserverTest()
692       : active_(NULL),
693         widget_closed_(NULL),
694         widget_activated_(NULL),
695         widget_shown_(NULL),
696         widget_hidden_(NULL),
697         widget_bounds_changed_(NULL) {
698   }
699
700   virtual ~WidgetObserverTest() {}
701
702   // Overridden from WidgetObserver:
703   virtual void OnWidgetDestroying(Widget* widget) OVERRIDE {
704     if (active_ == widget)
705       active_ = NULL;
706     widget_closed_ = widget;
707   }
708
709   virtual void OnWidgetActivationChanged(Widget* widget,
710                                          bool active) OVERRIDE {
711     if (active) {
712       if (widget_activated_)
713         widget_activated_->Deactivate();
714       widget_activated_ = widget;
715       active_ = widget;
716     } else {
717       if (widget_activated_ == widget)
718         widget_activated_ = NULL;
719       widget_deactivated_ = widget;
720     }
721   }
722
723   virtual void OnWidgetVisibilityChanged(Widget* widget,
724                                          bool visible) OVERRIDE {
725     if (visible)
726       widget_shown_ = widget;
727     else
728       widget_hidden_ = widget;
729   }
730
731   virtual void OnWidgetBoundsChanged(Widget* widget,
732                                      const gfx::Rect& new_bounds) OVERRIDE {
733     widget_bounds_changed_ = widget;
734   }
735
736   void reset() {
737     active_ = NULL;
738     widget_closed_ = NULL;
739     widget_activated_ = NULL;
740     widget_deactivated_ = NULL;
741     widget_shown_ = NULL;
742     widget_hidden_ = NULL;
743     widget_bounds_changed_ = NULL;
744   }
745
746   Widget* NewWidget() {
747     Widget* widget = CreateTopLevelNativeWidget();
748     widget->AddObserver(this);
749     return widget;
750   }
751
752   const Widget* active() const { return active_; }
753   const Widget* widget_closed() const { return widget_closed_; }
754   const Widget* widget_activated() const { return widget_activated_; }
755   const Widget* widget_deactivated() const { return widget_deactivated_; }
756   const Widget* widget_shown() const { return widget_shown_; }
757   const Widget* widget_hidden() const { return widget_hidden_; }
758   const Widget* widget_bounds_changed() const { return widget_bounds_changed_; }
759
760  private:
761   Widget* active_;
762
763   Widget* widget_closed_;
764   Widget* widget_activated_;
765   Widget* widget_deactivated_;
766   Widget* widget_shown_;
767   Widget* widget_hidden_;
768   Widget* widget_bounds_changed_;
769 };
770
771 TEST_F(WidgetObserverTest, DISABLED_ActivationChange) {
772   Widget* toplevel = CreateTopLevelPlatformWidget();
773
774   Widget* toplevel1 = NewWidget();
775   Widget* toplevel2 = NewWidget();
776
777   toplevel1->Show();
778   toplevel2->Show();
779
780   reset();
781
782   toplevel1->Activate();
783
784   RunPendingMessages();
785   EXPECT_EQ(toplevel1, widget_activated());
786
787   toplevel2->Activate();
788   RunPendingMessages();
789   EXPECT_EQ(toplevel1, widget_deactivated());
790   EXPECT_EQ(toplevel2, widget_activated());
791   EXPECT_EQ(toplevel2, active());
792
793   toplevel->CloseNow();
794 }
795
796 TEST_F(WidgetObserverTest, DISABLED_VisibilityChange) {
797   Widget* toplevel = CreateTopLevelPlatformWidget();
798
799   Widget* child1 = NewWidget();
800   Widget* child2 = NewWidget();
801
802   toplevel->Show();
803   child1->Show();
804   child2->Show();
805
806   reset();
807
808   child1->Hide();
809   EXPECT_EQ(child1, widget_hidden());
810
811   child2->Hide();
812   EXPECT_EQ(child2, widget_hidden());
813
814   child1->Show();
815   EXPECT_EQ(child1, widget_shown());
816
817   child2->Show();
818   EXPECT_EQ(child2, widget_shown());
819
820   toplevel->CloseNow();
821 }
822
823 TEST_F(WidgetObserverTest, DestroyBubble) {
824   Widget* anchor = CreateTopLevelPlatformWidget();
825   anchor->Show();
826
827   BubbleDelegateView* bubble_delegate =
828       new BubbleDelegateView(anchor->client_view(), BubbleBorder::NONE);
829   Widget* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate));
830   bubble_widget->Show();
831   bubble_widget->CloseNow();
832
833   anchor->Hide();
834   anchor->CloseNow();
835 }
836
837 TEST_F(WidgetObserverTest, WidgetBoundsChanged) {
838   Widget* child1 = NewWidget();
839   Widget* child2 = NewWidget();
840
841   child1->OnNativeWidgetMove();
842   EXPECT_EQ(child1, widget_bounds_changed());
843
844   child2->OnNativeWidgetMove();
845   EXPECT_EQ(child2, widget_bounds_changed());
846
847   child1->OnNativeWidgetSizeChanged(gfx::Size());
848   EXPECT_EQ(child1, widget_bounds_changed());
849
850   child2->OnNativeWidgetSizeChanged(gfx::Size());
851   EXPECT_EQ(child2, widget_bounds_changed());
852 }
853
854 #if !defined(USE_AURA) && defined(OS_WIN)
855 // Aura needs shell to maximize/fullscreen window.
856 // NativeWidgetGtk doesn't implement GetRestoredBounds.
857 TEST_F(WidgetTest, GetRestoredBounds) {
858   Widget* toplevel = CreateTopLevelPlatformWidget();
859   EXPECT_EQ(toplevel->GetWindowBoundsInScreen().ToString(),
860             toplevel->GetRestoredBounds().ToString());
861   toplevel->Show();
862   toplevel->Maximize();
863   RunPendingMessages();
864   EXPECT_NE(toplevel->GetWindowBoundsInScreen().ToString(),
865             toplevel->GetRestoredBounds().ToString());
866   EXPECT_GT(toplevel->GetRestoredBounds().width(), 0);
867   EXPECT_GT(toplevel->GetRestoredBounds().height(), 0);
868
869   toplevel->Restore();
870   RunPendingMessages();
871   EXPECT_EQ(toplevel->GetWindowBoundsInScreen().ToString(),
872             toplevel->GetRestoredBounds().ToString());
873
874   toplevel->SetFullscreen(true);
875   RunPendingMessages();
876   EXPECT_NE(toplevel->GetWindowBoundsInScreen().ToString(),
877             toplevel->GetRestoredBounds().ToString());
878   EXPECT_GT(toplevel->GetRestoredBounds().width(), 0);
879   EXPECT_GT(toplevel->GetRestoredBounds().height(), 0);
880 }
881 #endif
882
883 // Test that window state is not changed after getting out of full screen.
884 TEST_F(WidgetTest, ExitFullscreenRestoreState) {
885   Widget* toplevel = CreateTopLevelPlatformWidget();
886
887   toplevel->Show();
888   RunPendingMessages();
889
890   // This should be a normal state window.
891   EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
892
893   toplevel->SetFullscreen(true);
894   while (GetWidgetShowState(toplevel) != ui::SHOW_STATE_FULLSCREEN)
895     RunPendingMessages();
896   toplevel->SetFullscreen(false);
897   while (GetWidgetShowState(toplevel) == ui::SHOW_STATE_FULLSCREEN)
898     RunPendingMessages();
899
900   // And it should still be in normal state after getting out of full screen.
901   EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
902
903   // Now, make it maximized.
904   toplevel->Maximize();
905   while (GetWidgetShowState(toplevel) != ui::SHOW_STATE_MAXIMIZED)
906     RunPendingMessages();
907
908   toplevel->SetFullscreen(true);
909   while (GetWidgetShowState(toplevel) != ui::SHOW_STATE_FULLSCREEN)
910     RunPendingMessages();
911   toplevel->SetFullscreen(false);
912   while (GetWidgetShowState(toplevel) == ui::SHOW_STATE_FULLSCREEN)
913     RunPendingMessages();
914
915   // And it stays maximized after getting out of full screen.
916   EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel));
917
918   // Clean up.
919   toplevel->Close();
920   RunPendingMessages();
921 }
922
923 #if defined(USE_AURA)
924 // The key-event propagation from Widget happens differently on aura and
925 // non-aura systems because of the difference in IME. So this test works only on
926 // aura.
927 TEST_F(WidgetTest, KeyboardInputEvent) {
928   Widget* toplevel = CreateTopLevelPlatformWidget();
929   View* container = toplevel->client_view();
930
931   Textfield* textfield = new Textfield();
932   textfield->SetText(ASCIIToUTF16("some text"));
933   container->AddChildView(textfield);
934   toplevel->Show();
935   textfield->RequestFocus();
936
937   // The press gets handled. The release doesn't have an effect.
938   ui::KeyEvent backspace_p(ui::ET_KEY_PRESSED, ui::VKEY_DELETE, 0, false);
939   toplevel->OnKeyEvent(&backspace_p);
940   EXPECT_TRUE(backspace_p.stopped_propagation());
941   ui::KeyEvent backspace_r(ui::ET_KEY_RELEASED, ui::VKEY_DELETE, 0, false);
942   toplevel->OnKeyEvent(&backspace_r);
943   EXPECT_FALSE(backspace_r.handled());
944
945   toplevel->Close();
946 }
947
948 // Verifies bubbles result in a focus lost when shown.
949 // TODO(msw): this tests relies on focus, it needs to be in
950 // interactive_ui_tests.
951 TEST_F(WidgetTest, DISABLED_FocusChangesOnBubble) {
952   // Create a widget, show and activate it and focus the contents view.
953   View* contents_view = new View;
954   contents_view->set_focusable(true);
955   Widget widget;
956   Widget::InitParams init_params =
957       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
958   init_params.bounds = gfx::Rect(0, 0, 200, 200);
959   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
960 #if !defined(OS_CHROMEOS)
961   init_params.native_widget = new DesktopNativeWidgetAura(&widget);
962 #endif
963   widget.Init(init_params);
964   widget.SetContentsView(contents_view);
965   widget.Show();
966   widget.Activate();
967   contents_view->RequestFocus();
968   EXPECT_TRUE(contents_view->HasFocus());
969
970   // Show a bubble.
971   BubbleDelegateView* bubble_delegate_view =
972       new BubbleDelegateView(contents_view, BubbleBorder::TOP_LEFT);
973   bubble_delegate_view->set_focusable(true);
974   BubbleDelegateView::CreateBubble(bubble_delegate_view)->Show();
975   bubble_delegate_view->RequestFocus();
976
977   // |contents_view_| should no longer have focus.
978   EXPECT_FALSE(contents_view->HasFocus());
979   EXPECT_TRUE(bubble_delegate_view->HasFocus());
980
981   bubble_delegate_view->GetWidget()->CloseNow();
982
983   // Closing the bubble should result in focus going back to the contents view.
984   EXPECT_TRUE(contents_view->HasFocus());
985 }
986
987 // Desktop native widget Aura tests are for non Chrome OS platforms.
988 #if !defined(OS_CHROMEOS)
989 // Test to ensure that after minimize, view width is set to zero.
990 TEST_F(WidgetTest, TestViewWidthAfterMinimizingWidget) {
991   // Create a widget.
992   Widget widget;
993   Widget::InitParams init_params =
994       CreateParams(Widget::InitParams::TYPE_WINDOW);
995   init_params.show_state = ui::SHOW_STATE_NORMAL;
996   gfx::Rect initial_bounds(0, 0, 300, 400);
997   init_params.bounds = initial_bounds;
998   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
999   init_params.native_widget = new DesktopNativeWidgetAura(&widget);
1000   widget.Init(init_params);
1001   NonClientView* non_client_view = widget.non_client_view();
1002   NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
1003   non_client_view->SetFrameView(frame_view);
1004   widget.Show();
1005   widget.Minimize();
1006   EXPECT_EQ(0, frame_view->width());
1007 }
1008
1009 // This class validates whether paints are received for a visible Widget.
1010 // To achieve this it overrides the Show and Close methods on the Widget class
1011 // and sets state whether subsequent paints are expected.
1012 class DesktopAuraTestValidPaintWidget : public views::Widget {
1013  public:
1014   DesktopAuraTestValidPaintWidget()
1015     : expect_paint_(true),
1016       received_paint_while_hidden_(false) {
1017   }
1018
1019   virtual ~DesktopAuraTestValidPaintWidget() {
1020   }
1021
1022   virtual void Show() OVERRIDE {
1023     expect_paint_ = true;
1024     views::Widget::Show();
1025   }
1026
1027   virtual void Close() OVERRIDE {
1028     expect_paint_ = false;
1029     views::Widget::Close();
1030   }
1031
1032   void Hide() {
1033     expect_paint_ = false;
1034     views::Widget::Hide();
1035   }
1036
1037   virtual void OnNativeWidgetPaint(gfx::Canvas* canvas) OVERRIDE {
1038     EXPECT_TRUE(expect_paint_);
1039     if (!expect_paint_)
1040       received_paint_while_hidden_ = true;
1041     views::Widget::OnNativeWidgetPaint(canvas);
1042   }
1043
1044   bool received_paint_while_hidden() const {
1045     return received_paint_while_hidden_;
1046   }
1047
1048  private:
1049   bool expect_paint_;
1050   bool received_paint_while_hidden_;
1051 };
1052
1053 TEST_F(WidgetTest, DesktopNativeWidgetAuraNoPaintAfterCloseTest) {
1054   View* contents_view = new View;
1055   contents_view->set_focusable(true);
1056   DesktopAuraTestValidPaintWidget widget;
1057   Widget::InitParams init_params =
1058       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1059   init_params.bounds = gfx::Rect(0, 0, 200, 200);
1060   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1061   init_params.native_widget = new DesktopNativeWidgetAura(&widget);
1062   widget.Init(init_params);
1063   widget.SetContentsView(contents_view);
1064   widget.Show();
1065   widget.Activate();
1066   RunPendingMessages();
1067   widget.SchedulePaintInRect(init_params.bounds);
1068   widget.Close();
1069   RunPendingMessages();
1070   EXPECT_FALSE(widget.received_paint_while_hidden());
1071 }
1072
1073 TEST_F(WidgetTest, DesktopNativeWidgetAuraNoPaintAfterHideTest) {
1074   View* contents_view = new View;
1075   contents_view->set_focusable(true);
1076   DesktopAuraTestValidPaintWidget widget;
1077   Widget::InitParams init_params =
1078       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1079   init_params.bounds = gfx::Rect(0, 0, 200, 200);
1080   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1081   init_params.native_widget = new DesktopNativeWidgetAura(&widget);
1082   widget.Init(init_params);
1083   widget.SetContentsView(contents_view);
1084   widget.Show();
1085   widget.Activate();
1086   RunPendingMessages();
1087   widget.SchedulePaintInRect(init_params.bounds);
1088   widget.Hide();
1089   RunPendingMessages();
1090   EXPECT_FALSE(widget.received_paint_while_hidden());
1091   widget.Close();
1092 }
1093
1094 // This class provides functionality to create fullscreen and top level popup
1095 // windows. It additionally tests whether the destruction of these windows
1096 // occurs correctly in desktop AURA without crashing.
1097 // It provides facilities to test the following cases:-
1098 // 1. Child window destroyed which should lead to the destruction of the
1099 //    parent.
1100 // 2. Parent window destroyed which should lead to the child being destroyed.
1101 class DesktopAuraTopLevelWindowTest
1102     : public views::TestViewsDelegate,
1103       public aura::WindowObserver {
1104  public:
1105   DesktopAuraTopLevelWindowTest()
1106       : top_level_widget_(NULL),
1107         owned_window_(NULL),
1108         owner_destroyed_(false),
1109         owned_window_destroyed_(false) {}
1110
1111   virtual ~DesktopAuraTopLevelWindowTest() {
1112     EXPECT_TRUE(owner_destroyed_);
1113     EXPECT_TRUE(owned_window_destroyed_);
1114     top_level_widget_ = NULL;
1115     owned_window_ = NULL;
1116   }
1117
1118   // views::TestViewsDelegate overrides.
1119   virtual void OnBeforeWidgetInit(
1120       Widget::InitParams* params,
1121       internal::NativeWidgetDelegate* delegate) OVERRIDE {
1122     if (!params->native_widget)
1123       params->native_widget = new views::DesktopNativeWidgetAura(delegate);
1124   }
1125
1126   void CreateTopLevelWindow(const gfx::Rect& bounds, bool fullscreen) {
1127     Widget::InitParams init_params;
1128     init_params.type = Widget::InitParams::TYPE_WINDOW;
1129     init_params.bounds = bounds;
1130     init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1131     init_params.layer_type = ui::LAYER_NOT_DRAWN;
1132     init_params.accept_events = fullscreen;
1133
1134     widget_.Init(init_params);
1135
1136     owned_window_ = new aura::Window(&child_window_delegate_);
1137     owned_window_->SetType(aura::client::WINDOW_TYPE_NORMAL);
1138     owned_window_->SetName("TestTopLevelWindow");
1139     if (fullscreen) {
1140       owned_window_->SetProperty(aura::client::kShowStateKey,
1141                                  ui::SHOW_STATE_FULLSCREEN);
1142     } else {
1143       owned_window_->SetType(aura::client::WINDOW_TYPE_MENU);
1144     }
1145     owned_window_->Init(ui::LAYER_TEXTURED);
1146     aura::client::ParentWindowWithContext(
1147         owned_window_,
1148         widget_.GetNativeView()->GetRootWindow(),
1149         gfx::Rect(0, 0, 1900, 1600));
1150     owned_window_->Show();
1151     owned_window_->AddObserver(this);
1152
1153     ASSERT_TRUE(owned_window_->parent() != NULL);
1154     owned_window_->parent()->AddObserver(this);
1155
1156     top_level_widget_ =
1157         views::Widget::GetWidgetForNativeView(owned_window_->parent());
1158     ASSERT_TRUE(top_level_widget_ != NULL);
1159   }
1160
1161   void DestroyOwnedWindow() {
1162     ASSERT_TRUE(owned_window_ != NULL);
1163     delete owned_window_;
1164   }
1165
1166   void DestroyOwnerWindow() {
1167     ASSERT_TRUE(top_level_widget_ != NULL);
1168     top_level_widget_->CloseNow();
1169   }
1170
1171   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
1172     window->RemoveObserver(this);
1173     if (window == owned_window_) {
1174       owned_window_destroyed_ = true;
1175     } else if (window == top_level_widget_->GetNativeView()) {
1176       owner_destroyed_ = true;
1177     } else {
1178       ADD_FAILURE() << "Unexpected window destroyed callback: " << window;
1179     }
1180   }
1181
1182  private:
1183   views::Widget widget_;
1184   views::Widget* top_level_widget_;
1185   aura::Window* owned_window_;
1186   bool owner_destroyed_;
1187   bool owned_window_destroyed_;
1188   aura::test::TestWindowDelegate child_window_delegate_;
1189
1190   DISALLOW_COPY_AND_ASSIGN(DesktopAuraTopLevelWindowTest);
1191 };
1192
1193 TEST_F(WidgetTest, DesktopAuraFullscreenWindowDestroyedBeforeOwnerTest) {
1194   ViewsDelegate::views_delegate = NULL;
1195   DesktopAuraTopLevelWindowTest fullscreen_window;
1196   ASSERT_NO_FATAL_FAILURE(fullscreen_window.CreateTopLevelWindow(
1197       gfx::Rect(0, 0, 200, 200), true));
1198
1199   RunPendingMessages();
1200   ASSERT_NO_FATAL_FAILURE(fullscreen_window.DestroyOwnedWindow());
1201   RunPendingMessages();
1202 }
1203
1204 TEST_F(WidgetTest, DesktopAuraFullscreenWindowOwnerDestroyed) {
1205   ViewsDelegate::views_delegate = NULL;
1206
1207   DesktopAuraTopLevelWindowTest fullscreen_window;
1208   ASSERT_NO_FATAL_FAILURE(fullscreen_window.CreateTopLevelWindow(
1209       gfx::Rect(0, 0, 200, 200), true));
1210
1211   RunPendingMessages();
1212   ASSERT_NO_FATAL_FAILURE(fullscreen_window.DestroyOwnerWindow());
1213   RunPendingMessages();
1214 }
1215
1216 // TODO(erg): Disabled on desktop linux until http://crbug.com/288988 is fixed.
1217 #if !defined(OS_LINUX)
1218 TEST_F(WidgetTest, DesktopAuraTopLevelOwnedPopupTest) {
1219   ViewsDelegate::views_delegate = NULL;
1220   DesktopAuraTopLevelWindowTest popup_window;
1221   ASSERT_NO_FATAL_FAILURE(popup_window.CreateTopLevelWindow(
1222       gfx::Rect(0, 0, 200, 200), false));
1223
1224   RunPendingMessages();
1225   ASSERT_NO_FATAL_FAILURE(popup_window.DestroyOwnedWindow());
1226   RunPendingMessages();
1227 }
1228 #endif
1229
1230 // Test to ensure that the aura Window's visiblity state is set to visible if
1231 // the underlying widget is hidden and then shown.
1232 TEST_F(WidgetTest, TestWindowVisibilityAfterHide) {
1233   // Create a widget.
1234   Widget widget;
1235   Widget::InitParams init_params =
1236       CreateParams(Widget::InitParams::TYPE_WINDOW);
1237   init_params.show_state = ui::SHOW_STATE_NORMAL;
1238   gfx::Rect initial_bounds(0, 0, 300, 400);
1239   init_params.bounds = initial_bounds;
1240   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1241   init_params.native_widget = new DesktopNativeWidgetAura(&widget);
1242   widget.Init(init_params);
1243   NonClientView* non_client_view = widget.non_client_view();
1244   NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
1245   non_client_view->SetFrameView(frame_view);
1246
1247   widget.Hide();
1248   EXPECT_FALSE(widget.GetNativeView()->IsVisible());
1249   widget.Show();
1250   EXPECT_TRUE(widget.GetNativeView()->IsVisible());
1251 }
1252
1253 // The following code verifies we can correctly destroy a Widget from a mouse
1254 // enter/exit. We could test move/drag/enter/exit but in general we don't run
1255 // nested message loops from such events, nor has the code ever really dealt
1256 // with this situation.
1257
1258 // Class that closes the widget (which ends up deleting it immediately) when the
1259 // appropriate event is received.
1260 class CloseWidgetView : public View {
1261  public:
1262   explicit CloseWidgetView(ui::EventType event_type)
1263       : event_type_(event_type) {
1264   }
1265
1266   // View overrides:
1267   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
1268     if (!CloseWidget(event))
1269       View::OnMousePressed(event);
1270     return true;
1271   }
1272   virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE {
1273     if (!CloseWidget(event))
1274       View::OnMouseDragged(event);
1275     return true;
1276   }
1277   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE {
1278     if (!CloseWidget(event))
1279       View::OnMouseReleased(event);
1280   }
1281   virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE {
1282     if (!CloseWidget(event))
1283       View::OnMouseMoved(event);
1284   }
1285   virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
1286     if (!CloseWidget(event))
1287       View::OnMouseEntered(event);
1288   }
1289
1290  private:
1291   bool CloseWidget(const ui::LocatedEvent& event) {
1292     if (event.type() == event_type_) {
1293       // Go through NativeWidgetPrivate to simulate what happens if the OS
1294       // deletes the NativeWindow out from under us.
1295       GetWidget()->native_widget_private()->CloseNow();
1296       return true;
1297     }
1298     return false;
1299   }
1300
1301   const ui::EventType event_type_;
1302
1303   DISALLOW_COPY_AND_ASSIGN(CloseWidgetView);
1304 };
1305
1306 // Generates two moves (first generates enter, second real move), a press, drag
1307 // and release stopping at |last_event_type|.
1308 void GenerateMouseEvents(Widget* widget, ui::EventType last_event_type) {
1309   const gfx::Rect screen_bounds(widget->GetWindowBoundsInScreen());
1310   ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, screen_bounds.CenterPoint(),
1311                             screen_bounds.CenterPoint(), 0);
1312   aura::RootWindowHostDelegate* rwhd =
1313       widget->GetNativeWindow()->GetDispatcher()->AsRootWindowHostDelegate();
1314   rwhd->OnHostMouseEvent(&move_event);
1315   if (last_event_type == ui::ET_MOUSE_ENTERED)
1316     return;
1317   rwhd->OnHostMouseEvent(&move_event);
1318   if (last_event_type == ui::ET_MOUSE_MOVED)
1319     return;
1320
1321   ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, screen_bounds.CenterPoint(),
1322                              screen_bounds.CenterPoint(), 0);
1323   rwhd->OnHostMouseEvent(&press_event);
1324   if (last_event_type == ui::ET_MOUSE_PRESSED)
1325     return;
1326
1327   gfx::Point end_point(screen_bounds.CenterPoint());
1328   end_point.Offset(1, 1);
1329   ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, end_point, end_point, 0);
1330   rwhd->OnHostMouseEvent(&drag_event);
1331   if (last_event_type == ui::ET_MOUSE_DRAGGED)
1332     return;
1333
1334   ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, end_point, end_point, 0);
1335   rwhd->OnHostMouseEvent(&release_event);
1336 }
1337
1338 // Creates a widget and invokes GenerateMouseEvents() with |last_event_type|.
1339 void RunCloseWidgetDuringDispatchTest(WidgetTest* test,
1340                                       ui::EventType last_event_type) {
1341   // |widget| is deleted by CloseWidgetView.
1342   Widget* widget = new Widget;
1343   Widget::InitParams params =
1344       test->CreateParams(Widget::InitParams::TYPE_POPUP);
1345   params.native_widget = new DesktopNativeWidgetAura(widget);
1346   params.bounds = gfx::Rect(0, 0, 50, 100);
1347   widget->Init(params);
1348   widget->SetContentsView(new CloseWidgetView(last_event_type));
1349   widget->Show();
1350   GenerateMouseEvents(widget, last_event_type);
1351 }
1352
1353 // Verifies deleting the widget from a mouse pressed event doesn't crash.
1354 TEST_F(WidgetTest, CloseWidgetDuringMousePress) {
1355   RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_PRESSED);
1356 }
1357
1358 // Verifies deleting the widget from a mouse released event doesn't crash.
1359 TEST_F(WidgetTest, CloseWidgetDuringMouseReleased) {
1360   RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_RELEASED);
1361 }
1362
1363 #endif  // !defined(OS_CHROMEOS)
1364
1365 // Tests that wheel events generated from scroll events are targetted to the
1366 // views under the cursor when the focused view does not processed them.
1367 TEST_F(WidgetTest, WheelEventsFromScrollEventTarget) {
1368   EventCountView* cursor_view = new EventCountView;
1369   cursor_view->SetBounds(60, 0, 50, 40);
1370
1371   Widget* widget = CreateTopLevelPlatformWidget();
1372   widget->GetRootView()->AddChildView(cursor_view);
1373
1374   // Generate a scroll event on the cursor view.
1375   ui::ScrollEvent scroll(ui::ET_SCROLL,
1376                          gfx::Point(65, 5),
1377                          ui::EventTimeForNow(),
1378                          0,
1379                          0, 20,
1380                          0, 20,
1381                          2);
1382   widget->OnScrollEvent(&scroll);
1383
1384   EXPECT_EQ(1, cursor_view->GetEventCount(ui::ET_SCROLL));
1385   EXPECT_EQ(1, cursor_view->GetEventCount(ui::ET_MOUSEWHEEL));
1386
1387   cursor_view->ResetCounts();
1388
1389   ui::ScrollEvent scroll2(ui::ET_SCROLL,
1390                           gfx::Point(5, 5),
1391                           ui::EventTimeForNow(),
1392                           0,
1393                           0, 20,
1394                           0, 20,
1395                           2);
1396   widget->OnScrollEvent(&scroll2);
1397
1398   EXPECT_EQ(0, cursor_view->GetEventCount(ui::ET_SCROLL));
1399   EXPECT_EQ(0, cursor_view->GetEventCount(ui::ET_MOUSEWHEEL));
1400
1401   widget->CloseNow();
1402 }
1403
1404 #endif  // defined(USE_AURA)
1405
1406 // Tests that if a scroll-begin gesture is not handled, then subsequent scroll
1407 // events are not dispatched to any view.
1408 TEST_F(WidgetTest, GestureScrollEventDispatching) {
1409   EventCountView* noscroll_view = new EventCountView;
1410   EventCountView* scroll_view = new ScrollableEventCountView;
1411
1412   noscroll_view->SetBounds(0, 0, 50, 40);
1413   scroll_view->SetBounds(60, 0, 40, 40);
1414
1415   Widget* widget = CreateTopLevelPlatformWidget();
1416   widget->GetRootView()->AddChildView(noscroll_view);
1417   widget->GetRootView()->AddChildView(scroll_view);
1418
1419   {
1420     ui::GestureEvent begin(ui::ET_GESTURE_SCROLL_BEGIN,
1421         5, 5, 0, base::TimeDelta(),
1422         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0),
1423         1);
1424     widget->OnGestureEvent(&begin);
1425     ui::GestureEvent update(ui::ET_GESTURE_SCROLL_UPDATE,
1426         25, 15, 0, base::TimeDelta(),
1427         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 20, 10),
1428         1);
1429     widget->OnGestureEvent(&update);
1430     ui::GestureEvent end(ui::ET_GESTURE_SCROLL_END,
1431         25, 15, 0, base::TimeDelta(),
1432         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END, 0, 0),
1433         1);
1434     widget->OnGestureEvent(&end);
1435
1436     EXPECT_EQ(1, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
1437     EXPECT_EQ(0, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
1438     EXPECT_EQ(0, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END));
1439   }
1440
1441   {
1442     ui::GestureEvent begin(ui::ET_GESTURE_SCROLL_BEGIN,
1443         65, 5, 0, base::TimeDelta(),
1444         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0),
1445         1);
1446     widget->OnGestureEvent(&begin);
1447     ui::GestureEvent update(ui::ET_GESTURE_SCROLL_UPDATE,
1448         85, 15, 0, base::TimeDelta(),
1449         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 20, 10),
1450         1);
1451     widget->OnGestureEvent(&update);
1452     ui::GestureEvent end(ui::ET_GESTURE_SCROLL_END,
1453         85, 15, 0, base::TimeDelta(),
1454         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END, 0, 0),
1455         1);
1456     widget->OnGestureEvent(&end);
1457
1458     EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
1459     EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
1460     EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END));
1461   }
1462
1463   widget->CloseNow();
1464 }
1465
1466 // Tests that event-handlers installed on the RootView get triggered correctly.
1467 TEST_F(WidgetTest, EventHandlersOnRootView) {
1468   Widget* widget = CreateTopLevelNativeWidget();
1469   View* root_view = widget->GetRootView();
1470
1471   EventCountView* view = new EventCountView;
1472   view->SetBounds(0, 0, 20, 20);
1473   root_view->AddChildView(view);
1474
1475   EventCountHandler h1;
1476   root_view->AddPreTargetHandler(&h1);
1477
1478   EventCountHandler h2;
1479   root_view->AddPostTargetHandler(&h2);
1480
1481   widget->SetBounds(gfx::Rect(0, 0, 100, 100));
1482   widget->Show();
1483
1484   ui::TouchEvent pressed(ui::ET_TOUCH_PRESSED,
1485                          gfx::Point(10, 10),
1486                          0, 0,
1487                          ui::EventTimeForNow(),
1488                          1.0, 0.0, 1.0, 0.0);
1489   widget->OnTouchEvent(&pressed);
1490   EXPECT_EQ(1, h1.GetEventCount(ui::ET_TOUCH_PRESSED));
1491   EXPECT_EQ(1, view->GetEventCount(ui::ET_TOUCH_PRESSED));
1492   EXPECT_EQ(1, h2.GetEventCount(ui::ET_TOUCH_PRESSED));
1493
1494   ui::GestureEvent begin(ui::ET_GESTURE_BEGIN,
1495       5, 5, 0, ui::EventTimeForNow(),
1496       ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0, 0), 1);
1497   ui::GestureEvent end(ui::ET_GESTURE_END,
1498       5, 5, 0, ui::EventTimeForNow(),
1499       ui::GestureEventDetails(ui::ET_GESTURE_END, 0, 0), 1);
1500   widget->OnGestureEvent(&begin);
1501   EXPECT_EQ(1, h1.GetEventCount(ui::ET_GESTURE_BEGIN));
1502   EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_BEGIN));
1503   EXPECT_EQ(1, h2.GetEventCount(ui::ET_GESTURE_BEGIN));
1504
1505   ui::TouchEvent released(ui::ET_TOUCH_RELEASED,
1506                           gfx::Point(10, 10),
1507                           0, 0,
1508                           ui::EventTimeForNow(),
1509                           1.0, 0.0, 1.0, 0.0);
1510   widget->OnTouchEvent(&released);
1511   EXPECT_EQ(1, h1.GetEventCount(ui::ET_TOUCH_RELEASED));
1512   EXPECT_EQ(1, view->GetEventCount(ui::ET_TOUCH_RELEASED));
1513   EXPECT_EQ(1, h2.GetEventCount(ui::ET_TOUCH_RELEASED));
1514
1515   widget->OnGestureEvent(&end);
1516   EXPECT_EQ(1, h1.GetEventCount(ui::ET_GESTURE_END));
1517   EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_END));
1518   EXPECT_EQ(1, h2.GetEventCount(ui::ET_GESTURE_END));
1519
1520   ui::ScrollEvent scroll(ui::ET_SCROLL,
1521                          gfx::Point(5, 5),
1522                          ui::EventTimeForNow(),
1523                          0,
1524                          0, 20,
1525                          0, 20,
1526                          2);
1527   widget->OnScrollEvent(&scroll);
1528   EXPECT_EQ(1, h1.GetEventCount(ui::ET_SCROLL));
1529   EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL));
1530   EXPECT_EQ(1, h2.GetEventCount(ui::ET_SCROLL));
1531
1532   widget->CloseNow();
1533 }
1534
1535 TEST_F(WidgetTest, SynthesizeMouseMoveEvent) {
1536   Widget* widget = CreateTopLevelNativeWidget();
1537   View* root_view = widget->GetRootView();
1538
1539   EventCountView* v1 = new EventCountView();
1540   v1->SetBounds(0, 0, 10, 10);
1541   root_view->AddChildView(v1);
1542   EventCountView* v2 = new EventCountView();
1543   v2->SetBounds(0, 10, 10, 10);
1544   root_view->AddChildView(v2);
1545
1546   gfx::Point cursor_location(5, 5);
1547   ui::MouseEvent move(ui::ET_MOUSE_MOVED, cursor_location, cursor_location,
1548                       ui::EF_NONE);
1549   widget->OnMouseEvent(&move);
1550
1551   EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_ENTERED));
1552   EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
1553
1554   delete v1;
1555   v2->SetBounds(0, 0, 10, 10);
1556   EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
1557
1558   widget->SynthesizeMouseMoveEvent();
1559   EXPECT_EQ(1, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
1560 }
1561
1562 // Used by SingleWindowClosing to count number of times WindowClosing() has
1563 // been invoked.
1564 class ClosingDelegate : public WidgetDelegate {
1565  public:
1566   ClosingDelegate() : count_(0), widget_(NULL) {}
1567
1568   int count() const { return count_; }
1569
1570   void set_widget(views::Widget* widget) { widget_ = widget; }
1571
1572   // WidgetDelegate overrides:
1573   virtual Widget* GetWidget() OVERRIDE { return widget_; }
1574   virtual const Widget* GetWidget() const OVERRIDE { return widget_; }
1575   virtual void WindowClosing() OVERRIDE {
1576     count_++;
1577   }
1578
1579  private:
1580   int count_;
1581   views::Widget* widget_;
1582
1583   DISALLOW_COPY_AND_ASSIGN(ClosingDelegate);
1584 };
1585
1586 // Verifies WindowClosing() is invoked correctly on the delegate when a Widget
1587 // is closed.
1588 TEST_F(WidgetTest, SingleWindowClosing) {
1589   scoped_ptr<ClosingDelegate> delegate(new ClosingDelegate());
1590   Widget* widget = new Widget();  // Destroyed by CloseNow() below.
1591   Widget::InitParams init_params =
1592       CreateParams(Widget::InitParams::TYPE_WINDOW);
1593   init_params.bounds = gfx::Rect(0, 0, 200, 200);
1594   init_params.delegate = delegate.get();
1595 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
1596   init_params.native_widget = new DesktopNativeWidgetAura(widget);
1597 #endif
1598   widget->Init(init_params);
1599   EXPECT_EQ(0, delegate->count());
1600   widget->CloseNow();
1601   EXPECT_EQ(1, delegate->count());
1602 }
1603
1604 // Used by SetTopLevelCorrectly to track calls to OnBeforeWidgetInit().
1605 class VerifyTopLevelDelegate : public TestViewsDelegate {
1606  public:
1607   VerifyTopLevelDelegate()
1608       : on_before_init_called_(false),
1609         is_top_level_(false) {
1610   }
1611
1612   bool on_before_init_called() const { return on_before_init_called_; }
1613   bool is_top_level() const { return is_top_level_; }
1614
1615   virtual void OnBeforeWidgetInit(
1616       Widget::InitParams* params,
1617       internal::NativeWidgetDelegate* delegate) OVERRIDE {
1618     on_before_init_called_ = true;
1619     is_top_level_ = params->top_level;
1620   }
1621
1622  private:
1623   bool on_before_init_called_;
1624   bool is_top_level_;
1625
1626   DISALLOW_COPY_AND_ASSIGN(VerifyTopLevelDelegate);
1627 };
1628
1629 // Verifies |top_level| is correctly passed to
1630 // ViewsDelegate::OnBeforeWidgetInit().
1631 TEST_F(WidgetTest, SetTopLevelCorrectly) {
1632   set_views_delegate(NULL);
1633   VerifyTopLevelDelegate* delegate = new VerifyTopLevelDelegate;
1634   set_views_delegate(delegate);  // ViewsTestBase takes ownership.
1635   scoped_ptr<Widget> widget(new Widget);
1636   Widget::InitParams params =
1637       CreateParams(views::Widget::InitParams::TYPE_POPUP);
1638   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1639   widget->Init(params);
1640   EXPECT_TRUE(delegate->on_before_init_called());
1641   EXPECT_TRUE(delegate->is_top_level());
1642 }
1643
1644 // A scumbag View that deletes its owning widget OnMousePressed.
1645 class WidgetDeleterView : public View {
1646  public:
1647   WidgetDeleterView() : View() {}
1648
1649   // Overridden from View.
1650   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
1651     delete GetWidget();
1652     return true;
1653   }
1654
1655  private:
1656   DISALLOW_COPY_AND_ASSIGN(WidgetDeleterView);
1657 };
1658
1659 TEST_F(WidgetTest, TestWidgetDeletedInOnMousePressed) {
1660   Widget* widget = new Widget;
1661   Widget::InitParams params =
1662       CreateParams(views::Widget::InitParams::TYPE_POPUP);
1663   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1664   widget->Init(params);
1665
1666   widget->SetContentsView(new WidgetDeleterView);
1667
1668   widget->SetSize(gfx::Size(100, 100));
1669   widget->Show();
1670
1671   gfx::Point click_location(45, 15);
1672   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
1673       ui::EF_LEFT_MOUSE_BUTTON);
1674   widget->OnMouseEvent(&press);
1675
1676   // Yay we did not crash!
1677 }
1678
1679 // See description of RunGetNativeThemeFromDestructor() for details.
1680 class GetNativeThemeFromDestructorView : public WidgetDelegateView {
1681  public:
1682   GetNativeThemeFromDestructorView() {}
1683   virtual ~GetNativeThemeFromDestructorView() {
1684     VerifyNativeTheme();
1685   }
1686
1687   virtual View* GetContentsView() OVERRIDE {
1688     return this;
1689   }
1690
1691  private:
1692   void VerifyNativeTheme() {
1693     ASSERT_TRUE(GetNativeTheme() != NULL);
1694   }
1695
1696   DISALLOW_COPY_AND_ASSIGN(GetNativeThemeFromDestructorView);
1697 };
1698
1699 // Verifies GetNativeTheme() from the destructor of a WidgetDelegateView doesn't
1700 // crash. |is_first_run| is true if this is the first call. A return value of
1701 // true indicates this should be run again with a value of false.
1702 // First run uses DesktopNativeWidgetAura (if possible). Second run doesn't.
1703 bool RunGetNativeThemeFromDestructor(const Widget::InitParams& in_params,
1704                                      bool is_first_run) {
1705   bool needs_second_run = false;
1706   // Destroyed by CloseNow() below.
1707   Widget* widget = new Widget;
1708   Widget::InitParams params(in_params);
1709   // Deletes itself when the Widget is destroyed.
1710   params.delegate = new GetNativeThemeFromDestructorView;
1711 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
1712   if (is_first_run) {
1713     params.native_widget = new DesktopNativeWidgetAura(widget);
1714     needs_second_run = true;
1715   }
1716 #endif
1717   widget->Init(params);
1718   widget->CloseNow();
1719   return needs_second_run;
1720 }
1721
1722 // See description of RunGetNativeThemeFromDestructor() for details.
1723 TEST_F(WidgetTest, GetNativeThemeFromDestructor) {
1724   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1725   if (RunGetNativeThemeFromDestructor(params, true))
1726     RunGetNativeThemeFromDestructor(params, false);
1727 }
1728
1729 // Used by HideCloseDestroy. Allows setting a boolean when the widget is
1730 // destroyed.
1731 class CloseDestroysWidget : public Widget {
1732  public:
1733   explicit CloseDestroysWidget(bool* destroyed)
1734       : destroyed_(destroyed) {
1735   }
1736
1737   virtual ~CloseDestroysWidget() {
1738     if (destroyed_) {
1739       *destroyed_ = true;
1740       base::MessageLoop::current()->QuitNow();
1741     }
1742   }
1743
1744   void Detach() { destroyed_ = NULL; }
1745
1746  private:
1747   // If non-null set to true from destructor.
1748   bool* destroyed_;
1749
1750   DISALLOW_COPY_AND_ASSIGN(CloseDestroysWidget);
1751 };
1752
1753 // Verifies Close() results in destroying.
1754 TEST_F(WidgetTest, CloseDestroys) {
1755   bool destroyed = false;
1756   CloseDestroysWidget* widget = new CloseDestroysWidget(&destroyed);
1757   Widget::InitParams params =
1758       CreateParams(views::Widget::InitParams::TYPE_MENU);
1759   params.opacity = Widget::InitParams::OPAQUE_WINDOW;
1760 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
1761   params.native_widget = new DesktopNativeWidgetAura(widget);
1762 #endif
1763   widget->Init(params);
1764   widget->Show();
1765   widget->Hide();
1766   widget->Close();
1767   // Run the message loop as Close() asynchronously deletes.
1768   RunPendingMessages();
1769   EXPECT_TRUE(destroyed);
1770   // Close() should destroy the widget. If not we'll cleanup to avoid leaks.
1771   if (!destroyed) {
1772     widget->Detach();
1773     widget->CloseNow();
1774   }
1775 }
1776
1777 // A view that consumes mouse-pressed event and gesture-tap-down events.
1778 class RootViewTestView : public View {
1779  public:
1780   RootViewTestView(): View() {}
1781
1782  private:
1783   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
1784     return true;
1785   }
1786
1787   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
1788     if (event->type() == ui::ET_GESTURE_TAP_DOWN)
1789       event->SetHandled();
1790   }
1791 };
1792
1793 // Checks if RootView::*_handler_ fields are unset when widget is hidden.
1794 // Fails on chromium.webkit Windows bot, see crbug.com/264872.
1795 #if defined(OS_WIN)
1796 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
1797     DISABLED_TestRootViewHandlersWhenHidden
1798 #else
1799 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
1800     TestRootViewHandlersWhenHidden
1801 #endif
1802 TEST_F(WidgetTest, MAYBE_DisableTestRootViewHandlersWhenHidden) {
1803   Widget* widget = CreateTopLevelNativeWidget();
1804   widget->SetBounds(gfx::Rect(0, 0, 300, 300));
1805   View* view = new RootViewTestView();
1806   view->SetBounds(0, 0, 300, 300);
1807   internal::RootView* root_view =
1808       static_cast<internal::RootView*>(widget->GetRootView());
1809   root_view->AddChildView(view);
1810
1811   // Check RootView::mouse_pressed_handler_.
1812   widget->Show();
1813   EXPECT_EQ(NULL, GetMousePressedHandler(root_view));
1814   gfx::Point click_location(45, 15);
1815   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
1816       ui::EF_LEFT_MOUSE_BUTTON);
1817   widget->OnMouseEvent(&press);
1818   EXPECT_EQ(view, GetMousePressedHandler(root_view));
1819   widget->Hide();
1820   EXPECT_EQ(NULL, GetMousePressedHandler(root_view));
1821
1822   // Check RootView::mouse_move_handler_.
1823   widget->Show();
1824   EXPECT_EQ(NULL, GetMouseMoveHandler(root_view));
1825   gfx::Point move_location(45, 15);
1826   ui::MouseEvent move(ui::ET_MOUSE_MOVED, move_location, move_location, 0);
1827   widget->OnMouseEvent(&move);
1828   EXPECT_EQ(view, GetMouseMoveHandler(root_view));
1829   widget->Hide();
1830   EXPECT_EQ(NULL, GetMouseMoveHandler(root_view));
1831
1832   // Check RootView::gesture_handler_.
1833   widget->Show();
1834   EXPECT_EQ(NULL, GetGestureHandler(root_view));
1835   ui::GestureEvent tap_down(
1836       ui::ET_GESTURE_TAP_DOWN,
1837       15,
1838       15,
1839       0,
1840       base::TimeDelta(),
1841       ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN, 0, 0),
1842       1);
1843   widget->OnGestureEvent(&tap_down);
1844   EXPECT_EQ(view, GetGestureHandler(root_view));
1845   widget->Hide();
1846   EXPECT_EQ(NULL, GetGestureHandler(root_view));
1847
1848   widget->Close();
1849 }
1850
1851 // Test the result of Widget::GetAllChildWidgets().
1852 TEST_F(WidgetTest, GetAllChildWidgets) {
1853   // Create the following widget hierarchy:
1854   //
1855   // toplevel
1856   // +-- w1
1857   //     +-- w11
1858   // +-- w2
1859   //     +-- w21
1860   //     +-- w22
1861   Widget* toplevel = CreateTopLevelPlatformWidget();
1862   Widget* w1 = CreateChildPlatformWidget(toplevel->GetNativeView());
1863   Widget* w11 = CreateChildPlatformWidget(w1->GetNativeView());
1864   Widget* w2 = CreateChildPlatformWidget(toplevel->GetNativeView());
1865   Widget* w21 = CreateChildPlatformWidget(w2->GetNativeView());
1866   Widget* w22 = CreateChildPlatformWidget(w2->GetNativeView());
1867
1868   std::set<Widget*> expected;
1869   expected.insert(toplevel);
1870   expected.insert(w1);
1871   expected.insert(w11);
1872   expected.insert(w2);
1873   expected.insert(w21);
1874   expected.insert(w22);
1875
1876   std::set<Widget*> widgets;
1877   Widget::GetAllChildWidgets(toplevel->GetNativeView(), &widgets);
1878
1879   EXPECT_EQ(expected.size(), widgets.size());
1880   EXPECT_TRUE(std::equal(expected.begin(), expected.end(), widgets.begin()));
1881 }
1882
1883 // Used by DestroyChildWidgetsInOrder. On destruction adds the supplied name to
1884 // a vector.
1885 class DestroyedTrackingView : public View {
1886  public:
1887   DestroyedTrackingView(const std::string& name,
1888                         std::vector<std::string>* add_to)
1889       : name_(name),
1890         add_to_(add_to) {
1891   }
1892
1893   virtual ~DestroyedTrackingView() {
1894     add_to_->push_back(name_);
1895   }
1896
1897  private:
1898   const std::string name_;
1899   std::vector<std::string>* add_to_;
1900
1901   DISALLOW_COPY_AND_ASSIGN(DestroyedTrackingView);
1902 };
1903
1904 class WidgetChildDestructionTest : public WidgetTest {
1905  public:
1906   WidgetChildDestructionTest() {}
1907
1908   // Creates a top level and a child, destroys the child and verifies the views
1909   // of the child are destroyed before the views of the parent.
1910   void RunDestroyChildWidgetsTest(bool top_level_has_desktop_native_widget_aura,
1911                                   bool child_has_desktop_native_widget_aura) {
1912     // When a View is destroyed its name is added here.
1913     std::vector<std::string> destroyed;
1914
1915     Widget* top_level = new Widget;
1916     Widget::InitParams params =
1917         CreateParams(views::Widget::InitParams::TYPE_WINDOW);
1918 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
1919     if (top_level_has_desktop_native_widget_aura)
1920       params.native_widget = new DesktopNativeWidgetAura(top_level);
1921 #endif
1922     top_level->Init(params);
1923     top_level->GetRootView()->AddChildView(
1924         new DestroyedTrackingView("parent", &destroyed));
1925     top_level->Show();
1926
1927     Widget* child = new Widget;
1928     Widget::InitParams child_params =
1929         CreateParams(views::Widget::InitParams::TYPE_POPUP);
1930     child_params.parent = top_level->GetNativeView();
1931 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
1932     if (child_has_desktop_native_widget_aura)
1933       child_params.native_widget = new DesktopNativeWidgetAura(child);
1934 #endif
1935     child->Init(child_params);
1936     child->GetRootView()->AddChildView(
1937         new DestroyedTrackingView("child", &destroyed));
1938     child->Show();
1939
1940     // Should trigger destruction of the child too.
1941     top_level->native_widget_private()->CloseNow();
1942
1943     // Child should be destroyed first.
1944     ASSERT_EQ(2u, destroyed.size());
1945     EXPECT_EQ("child", destroyed[0]);
1946     EXPECT_EQ("parent", destroyed[1]);
1947   }
1948
1949  private:
1950   DISALLOW_COPY_AND_ASSIGN(WidgetChildDestructionTest);
1951 };
1952
1953 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
1954 // See description of RunDestroyChildWidgetsTest(). Parent uses
1955 // DesktopNativeWidgetAura.
1956 TEST_F(WidgetChildDestructionTest,
1957        DestroyChildWidgetsInOrderWithDesktopNativeWidget) {
1958   RunDestroyChildWidgetsTest(true, false);
1959 }
1960
1961 // See description of RunDestroyChildWidgetsTest(). Both parent and child use
1962 // DesktopNativeWidgetAura.
1963 TEST_F(WidgetChildDestructionTest,
1964        DestroyChildWidgetsInOrderWithDesktopNativeWidgetForBoth) {
1965   RunDestroyChildWidgetsTest(true, true);
1966 }
1967 #endif
1968
1969 // See description of RunDestroyChildWidgetsTest().
1970 TEST_F(WidgetChildDestructionTest, DestroyChildWidgetsInOrder) {
1971   RunDestroyChildWidgetsTest(false, false);
1972 }
1973
1974 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
1975 // Provides functionality to create a window modal dialog.
1976 class ModalDialogDelegate : public DialogDelegateView {
1977  public:
1978   ModalDialogDelegate() {}
1979   virtual ~ModalDialogDelegate() {}
1980
1981   // WidgetDelegate overrides.
1982   virtual ui::ModalType GetModalType() const OVERRIDE {
1983     return ui::MODAL_TYPE_WINDOW;
1984   }
1985
1986  private:
1987   DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate);
1988 };
1989
1990 // This test verifies that whether mouse events when a modal dialog is
1991 // displayed are eaten or recieved by the dialog.
1992 TEST_F(WidgetTest, WindowMouseModalityTest) {
1993   // Create a top level widget.
1994   Widget top_level_widget;
1995   Widget::InitParams init_params =
1996       CreateParams(Widget::InitParams::TYPE_WINDOW);
1997   init_params.show_state = ui::SHOW_STATE_NORMAL;
1998   gfx::Rect initial_bounds(0, 0, 500, 500);
1999   init_params.bounds = initial_bounds;
2000   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2001   init_params.native_widget = new DesktopNativeWidgetAura(&top_level_widget);
2002   top_level_widget.Init(init_params);
2003   top_level_widget.Show();
2004   EXPECT_TRUE(top_level_widget.IsVisible());
2005
2006   // Create a view and validate that a mouse moves makes it to the view.
2007   EventCountView* widget_view = new EventCountView();
2008   widget_view->SetBounds(0, 0, 10, 10);
2009   top_level_widget.GetRootView()->AddChildView(widget_view);
2010
2011   gfx::Point cursor_location_main(5, 5);
2012   ui::MouseEvent move_main(ui::ET_MOUSE_MOVED,
2013                            cursor_location_main,
2014                            cursor_location_main,
2015                            ui::EF_NONE);
2016   top_level_widget.GetNativeView()->GetDispatcher()->
2017       AsRootWindowHostDelegate()->OnHostMouseEvent(&move_main);
2018
2019   EXPECT_EQ(1, widget_view->GetEventCount(ui::ET_MOUSE_ENTERED));
2020   widget_view->ResetCounts();
2021
2022   // Create a modal dialog and validate that a mouse down message makes it to
2023   // the main view within the dialog.
2024
2025   // This instance will be destroyed when the dialog is destroyed.
2026   ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
2027
2028   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
2029       dialog_delegate, NULL, top_level_widget.GetNativeWindow());
2030   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
2031   EventCountView* dialog_widget_view = new EventCountView();
2032   dialog_widget_view->SetBounds(0, 0, 50, 50);
2033   modal_dialog_widget->GetRootView()->AddChildView(dialog_widget_view);
2034   modal_dialog_widget->Show();
2035   EXPECT_TRUE(modal_dialog_widget->IsVisible());
2036
2037   gfx::Point cursor_location_dialog(100, 100);
2038   ui::MouseEvent mouse_down_dialog(ui::ET_MOUSE_PRESSED,
2039                                    cursor_location_dialog,
2040                                    cursor_location_dialog,
2041                                    ui::EF_NONE);
2042   top_level_widget.GetNativeView()->GetDispatcher()->
2043       AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse_down_dialog);
2044   EXPECT_EQ(1, dialog_widget_view->GetEventCount(ui::ET_MOUSE_PRESSED));
2045
2046   // Send a mouse move message to the main window. It should not be received by
2047   // the main window as the modal dialog is still active.
2048   gfx::Point cursor_location_main2(6, 6);
2049   ui::MouseEvent mouse_down_main(ui::ET_MOUSE_MOVED,
2050                                  cursor_location_main2,
2051                                  cursor_location_main2,
2052                                  ui::EF_NONE);
2053   top_level_widget.GetNativeView()->GetDispatcher()->
2054       AsRootWindowHostDelegate()->OnHostMouseEvent(&mouse_down_main);
2055   EXPECT_EQ(0, widget_view->GetEventCount(ui::ET_MOUSE_MOVED));
2056
2057   modal_dialog_widget->CloseNow();
2058   top_level_widget.CloseNow();
2059 }
2060
2061 #if defined(OS_WIN)
2062
2063 // Provides functionality to test widget activation via an activation flag
2064 // which can be set by an accessor.
2065 class ModalWindowTestWidgetDelegate : public WidgetDelegate {
2066  public:
2067   ModalWindowTestWidgetDelegate()
2068       : widget_(NULL),
2069         can_activate_(true) {}
2070
2071   virtual ~ModalWindowTestWidgetDelegate() {}
2072
2073   // Overridden from WidgetDelegate:
2074   virtual void DeleteDelegate() OVERRIDE {
2075     delete this;
2076   }
2077   virtual Widget* GetWidget() OVERRIDE {
2078     return widget_;
2079   }
2080   virtual const Widget* GetWidget() const OVERRIDE {
2081     return widget_;
2082   }
2083   virtual bool CanActivate() const OVERRIDE {
2084     return can_activate_;
2085   }
2086   virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE {
2087     return true;
2088   }
2089
2090   void set_can_activate(bool can_activate) {
2091     can_activate_ = can_activate;
2092   }
2093
2094   void set_widget(Widget* widget) {
2095     widget_ = widget;
2096   }
2097
2098  private:
2099   Widget* widget_;
2100   bool can_activate_;
2101
2102   DISALLOW_COPY_AND_ASSIGN(ModalWindowTestWidgetDelegate);
2103 };
2104
2105 // Tests whether we can activate the top level widget when a modal dialog is
2106 // active.
2107 TEST_F(WidgetTest, WindowModalityActivationTest) {
2108   // Destroyed when the top level widget created below is destroyed.
2109   ModalWindowTestWidgetDelegate* widget_delegate =
2110       new ModalWindowTestWidgetDelegate;
2111   // Create a top level widget.
2112   Widget top_level_widget;
2113   Widget::InitParams init_params =
2114       CreateParams(Widget::InitParams::TYPE_WINDOW);
2115   init_params.show_state = ui::SHOW_STATE_NORMAL;
2116   gfx::Rect initial_bounds(0, 0, 500, 500);
2117   init_params.bounds = initial_bounds;
2118   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2119   init_params.native_widget = new DesktopNativeWidgetAura(&top_level_widget);
2120   init_params.delegate = widget_delegate;
2121   top_level_widget.Init(init_params);
2122   widget_delegate->set_widget(&top_level_widget);
2123   top_level_widget.Show();
2124   EXPECT_TRUE(top_level_widget.IsVisible());
2125
2126   HWND win32_window = views::HWNDForWidget(&top_level_widget);
2127   EXPECT_TRUE(::IsWindow(win32_window));
2128
2129   // This instance will be destroyed when the dialog is destroyed.
2130   ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
2131
2132   // We should be able to activate the window even if the WidgetDelegate
2133   // says no, when a modal dialog is active.
2134   widget_delegate->set_can_activate(false);
2135
2136   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
2137       dialog_delegate, NULL, top_level_widget.GetNativeWindow());
2138   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
2139   modal_dialog_widget->Show();
2140   EXPECT_TRUE(modal_dialog_widget->IsVisible());
2141
2142   LRESULT activate_result = ::SendMessage(
2143       win32_window,
2144       WM_MOUSEACTIVATE,
2145       reinterpret_cast<WPARAM>(win32_window),
2146       MAKELPARAM(WM_LBUTTONDOWN, HTCLIENT));
2147   EXPECT_EQ(activate_result, MA_ACTIVATE);
2148
2149   modal_dialog_widget->CloseNow();
2150   top_level_widget.CloseNow();
2151 }
2152 #endif
2153 #endif
2154
2155 }  // namespace test
2156 }  // namespace views