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