• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/hit_test.h"
16 #include "ui/compositor/layer_animation_observer.h"
17 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
18 #include "ui/compositor/scoped_layer_animation_settings.h"
19 #include "ui/events/event_processor.h"
20 #include "ui/events/event_utils.h"
21 #include "ui/events/test/event_generator.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 namespace {
43 
44 // TODO(tdanderson): This utility function is used in different unittest
45 //                   files. Move to a common location to avoid
46 //                   repeated code.
ConvertPointFromWidgetToView(View * view,const gfx::Point & p)47 gfx::Point ConvertPointFromWidgetToView(View* view, const gfx::Point& p) {
48   gfx::Point tmp(p);
49   View::ConvertPointToTarget(view->GetWidget()->GetRootView(), view, &tmp);
50   return tmp;
51 }
52 
53 }  // namespace
54 
55 // A view that keeps track of the events it receives, optionally consuming them.
56 class EventCountView : public View {
57  public:
58   // Whether to call SetHandled() on events as they are received. For some event
59   // types, this will allow EventCountView to receives future events in the
60   // event sequence, such as a drag.
61   enum HandleMode {
62     PROPAGATE_EVENTS,
63     CONSUME_EVENTS
64   };
65 
EventCountView()66   EventCountView()
67       : last_flags_(0),
68         handle_mode_(PROPAGATE_EVENTS) {}
69 
~EventCountView()70   virtual ~EventCountView() {}
71 
GetEventCount(ui::EventType type)72   int GetEventCount(ui::EventType type) {
73     return event_count_[type];
74   }
75 
ResetCounts()76   void ResetCounts() {
77     event_count_.clear();
78   }
79 
last_flags() const80   int last_flags() const {
81     return last_flags_;
82   }
83 
set_handle_mode(HandleMode handle_mode)84   void set_handle_mode(HandleMode handle_mode) {
85     handle_mode_ = handle_mode;
86   }
87 
88  protected:
89   // Overridden from View:
OnMouseMoved(const ui::MouseEvent & event)90   virtual void OnMouseMoved(const ui::MouseEvent& event) OVERRIDE {
91     // MouseMove events are not re-dispatched from the RootView.
92     ++event_count_[ui::ET_MOUSE_MOVED];
93     last_flags_ = 0;
94   }
95 
96   // Overridden from ui::EventHandler:
OnKeyEvent(ui::KeyEvent * event)97   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
98     RecordEvent(event);
99   }
OnMouseEvent(ui::MouseEvent * event)100   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
101     RecordEvent(event);
102   }
OnScrollEvent(ui::ScrollEvent * event)103   virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
104     RecordEvent(event);
105   }
OnGestureEvent(ui::GestureEvent * event)106   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
107     RecordEvent(event);
108   }
109 
110  private:
RecordEvent(ui::Event * event)111   void RecordEvent(ui::Event* event) {
112     ++event_count_[event->type()];
113     last_flags_ = event->flags();
114     if (handle_mode_ == CONSUME_EVENTS)
115       event->SetHandled();
116   }
117 
118   std::map<ui::EventType, int> event_count_;
119   int last_flags_;
120   HandleMode handle_mode_;
121 
122   DISALLOW_COPY_AND_ASSIGN(EventCountView);
123 };
124 
125 // A view that keeps track of the events it receives, and consumes all scroll
126 // gesture events and ui::ET_SCROLL events.
127 class ScrollableEventCountView : public EventCountView {
128  public:
ScrollableEventCountView()129   ScrollableEventCountView() {}
~ScrollableEventCountView()130   virtual ~ScrollableEventCountView() {}
131 
132  private:
133   // Overridden from ui::EventHandler:
OnGestureEvent(ui::GestureEvent * event)134   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
135     EventCountView::OnGestureEvent(event);
136     switch (event->type()) {
137       case ui::ET_GESTURE_SCROLL_BEGIN:
138       case ui::ET_GESTURE_SCROLL_UPDATE:
139       case ui::ET_GESTURE_SCROLL_END:
140       case ui::ET_SCROLL_FLING_START:
141         event->SetHandled();
142         break;
143       default:
144         break;
145     }
146   }
147 
OnScrollEvent(ui::ScrollEvent * event)148   virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
149     EventCountView::OnScrollEvent(event);
150     if (event->type() == ui::ET_SCROLL)
151       event->SetHandled();
152   }
153 
154   DISALLOW_COPY_AND_ASSIGN(ScrollableEventCountView);
155 };
156 
157 // A view that implements GetMinimumSize.
158 class MinimumSizeFrameView : public NativeFrameView {
159  public:
MinimumSizeFrameView(Widget * frame)160   explicit MinimumSizeFrameView(Widget* frame): NativeFrameView(frame) {}
~MinimumSizeFrameView()161   virtual ~MinimumSizeFrameView() {}
162 
163  private:
164   // Overridden from View:
GetMinimumSize() const165   virtual gfx::Size GetMinimumSize() const OVERRIDE {
166     return gfx::Size(300, 400);
167   }
168 
169   DISALLOW_COPY_AND_ASSIGN(MinimumSizeFrameView);
170 };
171 
172 // An event handler that simply keeps a count of the different types of events
173 // it receives.
174 class EventCountHandler : public ui::EventHandler {
175  public:
EventCountHandler()176   EventCountHandler() {}
~EventCountHandler()177   virtual ~EventCountHandler() {}
178 
GetEventCount(ui::EventType type)179   int GetEventCount(ui::EventType type) {
180     return event_count_[type];
181   }
182 
ResetCounts()183   void ResetCounts() {
184     event_count_.clear();
185   }
186 
187  protected:
188   // Overridden from ui::EventHandler:
OnEvent(ui::Event * event)189   virtual void OnEvent(ui::Event* event) OVERRIDE {
190     RecordEvent(*event);
191     ui::EventHandler::OnEvent(event);
192   }
193 
194  private:
RecordEvent(const ui::Event & event)195   void RecordEvent(const ui::Event& event) {
196     ++event_count_[event.type()];
197   }
198 
199   std::map<ui::EventType, int> event_count_;
200 
201   DISALLOW_COPY_AND_ASSIGN(EventCountHandler);
202 };
203 
204 // Class that closes the widget (which ends up deleting it immediately) when the
205 // appropriate event is received.
206 class CloseWidgetView : public View {
207  public:
CloseWidgetView(ui::EventType event_type)208   explicit CloseWidgetView(ui::EventType event_type)
209       : event_type_(event_type) {
210   }
211 
212   // ui::EventHandler override:
OnEvent(ui::Event * event)213   virtual void OnEvent(ui::Event* event) OVERRIDE {
214     if (event->type() == event_type_) {
215       // Go through NativeWidgetPrivate to simulate what happens if the OS
216       // deletes the NativeWindow out from under us.
217       GetWidget()->native_widget_private()->CloseNow();
218     } else {
219       View::OnEvent(event);
220       if (!event->IsTouchEvent())
221         event->SetHandled();
222     }
223   }
224 
225  private:
226   const ui::EventType event_type_;
227 
228   DISALLOW_COPY_AND_ASSIGN(CloseWidgetView);
229 };
230 
GetWidgetShowState(const Widget * widget)231 ui::WindowShowState GetWidgetShowState(const Widget* widget) {
232   // Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement
233   // because the former is implemented on all platforms but the latter is not.
234   return widget->IsFullscreen() ? ui::SHOW_STATE_FULLSCREEN :
235       widget->IsMaximized() ? ui::SHOW_STATE_MAXIMIZED :
236       widget->IsMinimized() ? ui::SHOW_STATE_MINIMIZED :
237       widget->IsActive() ? ui::SHOW_STATE_NORMAL :
238                            ui::SHOW_STATE_INACTIVE;
239 }
240 
TEST_F(WidgetTest,WidgetInitParams)241 TEST_F(WidgetTest, WidgetInitParams) {
242   // Widgets are not transparent by default.
243   Widget::InitParams init1;
244   EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init1.opacity);
245 }
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 // Widget::GetTopLevelWidget tests.
249 
TEST_F(WidgetTest,GetTopLevelWidget_Native)250 TEST_F(WidgetTest, GetTopLevelWidget_Native) {
251   // Create a hierarchy of native widgets.
252   Widget* toplevel = CreateTopLevelPlatformWidget();
253   gfx::NativeView parent = toplevel->GetNativeView();
254   Widget* child = CreateChildPlatformWidget(parent);
255 
256   EXPECT_EQ(toplevel, toplevel->GetTopLevelWidget());
257   EXPECT_EQ(toplevel, child->GetTopLevelWidget());
258 
259   toplevel->CloseNow();
260   // |child| should be automatically destroyed with |toplevel|.
261 }
262 
263 // Test if a focus manager and an inputmethod work without CHECK failure
264 // when window activation changes.
TEST_F(WidgetTest,ChangeActivation)265 TEST_F(WidgetTest, ChangeActivation) {
266   Widget* top1 = CreateTopLevelPlatformWidget();
267   // CreateInputMethod before activated
268   top1->GetInputMethod();
269   top1->Show();
270   RunPendingMessages();
271 
272   Widget* top2 = CreateTopLevelPlatformWidget();
273   top2->Show();
274   RunPendingMessages();
275 
276   top1->Activate();
277   RunPendingMessages();
278 
279   // Create InputMethod after deactivated.
280   top2->GetInputMethod();
281   top2->Activate();
282   RunPendingMessages();
283 
284   top1->Activate();
285   RunPendingMessages();
286 
287   top1->CloseNow();
288   top2->CloseNow();
289 }
290 
291 // Tests visibility of child widgets.
TEST_F(WidgetTest,Visibility)292 TEST_F(WidgetTest, Visibility) {
293   Widget* toplevel = CreateTopLevelPlatformWidget();
294   gfx::NativeView parent = toplevel->GetNativeView();
295   Widget* child = CreateChildPlatformWidget(parent);
296 
297   EXPECT_FALSE(toplevel->IsVisible());
298   EXPECT_FALSE(child->IsVisible());
299 
300   child->Show();
301 
302   EXPECT_FALSE(toplevel->IsVisible());
303   EXPECT_FALSE(child->IsVisible());
304 
305   toplevel->Show();
306 
307   EXPECT_TRUE(toplevel->IsVisible());
308   EXPECT_TRUE(child->IsVisible());
309 
310   toplevel->CloseNow();
311   // |child| should be automatically destroyed with |toplevel|.
312 }
313 
314 ////////////////////////////////////////////////////////////////////////////////
315 // Widget ownership tests.
316 //
317 // Tests various permutations of Widget ownership specified in the
318 // InitParams::Ownership param.
319 
320 // A WidgetTest that supplies a toplevel widget for NativeWidget to parent to.
321 class WidgetOwnershipTest : public WidgetTest {
322  public:
WidgetOwnershipTest()323   WidgetOwnershipTest() {}
~WidgetOwnershipTest()324   virtual ~WidgetOwnershipTest() {}
325 
SetUp()326   virtual void SetUp() {
327     WidgetTest::SetUp();
328     desktop_widget_ = CreateTopLevelPlatformWidget();
329   }
330 
TearDown()331   virtual void TearDown() {
332     desktop_widget_->CloseNow();
333     WidgetTest::TearDown();
334   }
335 
336  private:
337   Widget* desktop_widget_;
338 
339   DISALLOW_COPY_AND_ASSIGN(WidgetOwnershipTest);
340 };
341 
342 // A bag of state to monitor destructions.
343 struct OwnershipTestState {
OwnershipTestStateviews::test::OwnershipTestState344   OwnershipTestState() : widget_deleted(false), native_widget_deleted(false) {}
345 
346   bool widget_deleted;
347   bool native_widget_deleted;
348 };
349 
350 // A platform NativeWidget subclass that updates a bag of state when it is
351 // destroyed.
352 class OwnershipTestNativeWidget : public PlatformNativeWidget {
353  public:
OwnershipTestNativeWidget(internal::NativeWidgetDelegate * delegate,OwnershipTestState * state)354   OwnershipTestNativeWidget(internal::NativeWidgetDelegate* delegate,
355                             OwnershipTestState* state)
356       : PlatformNativeWidget(delegate),
357         state_(state) {
358   }
~OwnershipTestNativeWidget()359   virtual ~OwnershipTestNativeWidget() {
360     state_->native_widget_deleted = true;
361   }
362 
363  private:
364   OwnershipTestState* state_;
365 
366   DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidget);
367 };
368 
369 // A views NativeWidget subclass that updates a bag of state when it is
370 // destroyed.
371 class OwnershipTestNativeWidgetAura : public NativeWidgetCapture {
372  public:
OwnershipTestNativeWidgetAura(internal::NativeWidgetDelegate * delegate,OwnershipTestState * state)373   OwnershipTestNativeWidgetAura(internal::NativeWidgetDelegate* delegate,
374                                 OwnershipTestState* state)
375       : NativeWidgetCapture(delegate),
376         state_(state) {
377   }
~OwnershipTestNativeWidgetAura()378   virtual ~OwnershipTestNativeWidgetAura() {
379     state_->native_widget_deleted = true;
380   }
381 
382  private:
383   OwnershipTestState* state_;
384 
385   DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetAura);
386 };
387 
388 // A Widget subclass that updates a bag of state when it is destroyed.
389 class OwnershipTestWidget : public Widget {
390  public:
OwnershipTestWidget(OwnershipTestState * state)391   explicit OwnershipTestWidget(OwnershipTestState* state) : state_(state) {}
~OwnershipTestWidget()392   virtual ~OwnershipTestWidget() {
393     state_->widget_deleted = true;
394   }
395 
396  private:
397   OwnershipTestState* state_;
398 
399   DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget);
400 };
401 
402 // Widget owns its NativeWidget, part 1: NativeWidget is a platform-native
403 // widget.
TEST_F(WidgetOwnershipTest,Ownership_WidgetOwnsPlatformNativeWidget)404 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) {
405   OwnershipTestState state;
406 
407   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
408   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
409   params.native_widget =
410       new OwnershipTestNativeWidgetAura(widget.get(), &state);
411   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
412   widget->Init(params);
413 
414   // Now delete the Widget, which should delete the NativeWidget.
415   widget.reset();
416 
417   EXPECT_TRUE(state.widget_deleted);
418   EXPECT_TRUE(state.native_widget_deleted);
419 
420   // TODO(beng): write test for this ownership scenario and the NativeWidget
421   //             being deleted out from under the Widget.
422 }
423 
424 // Widget owns its NativeWidget, part 2: NativeWidget is a NativeWidget.
TEST_F(WidgetOwnershipTest,Ownership_WidgetOwnsViewsNativeWidget)425 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) {
426   OwnershipTestState state;
427 
428   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
429   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
430   params.native_widget =
431       new OwnershipTestNativeWidgetAura(widget.get(), &state);
432   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
433   widget->Init(params);
434 
435   // Now delete the Widget, which should delete the NativeWidget.
436   widget.reset();
437 
438   EXPECT_TRUE(state.widget_deleted);
439   EXPECT_TRUE(state.native_widget_deleted);
440 
441   // TODO(beng): write test for this ownership scenario and the NativeWidget
442   //             being deleted out from under the Widget.
443 }
444 
445 // Widget owns its NativeWidget, part 3: NativeWidget is a NativeWidget,
446 // destroy the parent view.
TEST_F(WidgetOwnershipTest,Ownership_WidgetOwnsViewsNativeWidget_DestroyParentView)447 TEST_F(WidgetOwnershipTest,
448        Ownership_WidgetOwnsViewsNativeWidget_DestroyParentView) {
449   OwnershipTestState state;
450 
451   Widget* toplevel = CreateTopLevelPlatformWidget();
452 
453   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
454   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
455   params.native_widget =
456       new OwnershipTestNativeWidgetAura(widget.get(), &state);
457   params.parent = toplevel->GetNativeView();
458   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
459   widget->Init(params);
460 
461   // Now close the toplevel, which deletes the view hierarchy.
462   toplevel->CloseNow();
463 
464   RunPendingMessages();
465 
466   // This shouldn't delete the widget because it shouldn't be deleted
467   // from the native side.
468   EXPECT_FALSE(state.widget_deleted);
469   EXPECT_FALSE(state.native_widget_deleted);
470 
471   // Now delete it explicitly.
472   widget.reset();
473 
474   EXPECT_TRUE(state.widget_deleted);
475   EXPECT_TRUE(state.native_widget_deleted);
476 }
477 
478 // NativeWidget owns its Widget, part 1: NativeWidget is a platform-native
479 // widget.
TEST_F(WidgetOwnershipTest,Ownership_PlatformNativeWidgetOwnsWidget)480 TEST_F(WidgetOwnershipTest, Ownership_PlatformNativeWidgetOwnsWidget) {
481   OwnershipTestState state;
482 
483   Widget* widget = new OwnershipTestWidget(&state);
484   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
485   params.native_widget =
486       new OwnershipTestNativeWidgetAura(widget, &state);
487   widget->Init(params);
488 
489   // Now destroy the native widget.
490   widget->CloseNow();
491 
492   EXPECT_TRUE(state.widget_deleted);
493   EXPECT_TRUE(state.native_widget_deleted);
494 }
495 
496 // NativeWidget owns its Widget, part 2: NativeWidget is a NativeWidget.
TEST_F(WidgetOwnershipTest,Ownership_ViewsNativeWidgetOwnsWidget)497 TEST_F(WidgetOwnershipTest, Ownership_ViewsNativeWidgetOwnsWidget) {
498   OwnershipTestState state;
499 
500   Widget* toplevel = CreateTopLevelPlatformWidget();
501 
502   Widget* widget = new OwnershipTestWidget(&state);
503   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
504   params.native_widget =
505       new OwnershipTestNativeWidgetAura(widget, &state);
506   params.parent = toplevel->GetNativeView();
507   widget->Init(params);
508 
509   // Now destroy the native widget. This is achieved by closing the toplevel.
510   toplevel->CloseNow();
511 
512   // The NativeWidget won't be deleted until after a return to the message loop
513   // so we have to run pending messages before testing the destruction status.
514   RunPendingMessages();
515 
516   EXPECT_TRUE(state.widget_deleted);
517   EXPECT_TRUE(state.native_widget_deleted);
518 }
519 
520 // NativeWidget owns its Widget, part 3: NativeWidget is a platform-native
521 // widget, destroyed out from under it by the OS.
TEST_F(WidgetOwnershipTest,Ownership_PlatformNativeWidgetOwnsWidget_NativeDestroy)522 TEST_F(WidgetOwnershipTest,
523        Ownership_PlatformNativeWidgetOwnsWidget_NativeDestroy) {
524   OwnershipTestState state;
525 
526   Widget* widget = new OwnershipTestWidget(&state);
527   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
528   params.native_widget =
529       new OwnershipTestNativeWidgetAura(widget, &state);
530   widget->Init(params);
531 
532   // Now simulate a destroy of the platform native widget from the OS:
533   SimulateNativeDestroy(widget);
534 
535   EXPECT_TRUE(state.widget_deleted);
536   EXPECT_TRUE(state.native_widget_deleted);
537 }
538 
539 // NativeWidget owns its Widget, part 4: NativeWidget is a NativeWidget,
540 // destroyed by the view hierarchy that contains it.
TEST_F(WidgetOwnershipTest,Ownership_ViewsNativeWidgetOwnsWidget_NativeDestroy)541 TEST_F(WidgetOwnershipTest,
542        Ownership_ViewsNativeWidgetOwnsWidget_NativeDestroy) {
543   OwnershipTestState state;
544 
545   Widget* toplevel = CreateTopLevelPlatformWidget();
546 
547   Widget* widget = new OwnershipTestWidget(&state);
548   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
549   params.native_widget =
550       new OwnershipTestNativeWidgetAura(widget, &state);
551   params.parent = toplevel->GetNativeView();
552   widget->Init(params);
553 
554   // Destroy the widget (achieved by closing the toplevel).
555   toplevel->CloseNow();
556 
557   // The NativeWidget won't be deleted until after a return to the message loop
558   // so we have to run pending messages before testing the destruction status.
559   RunPendingMessages();
560 
561   EXPECT_TRUE(state.widget_deleted);
562   EXPECT_TRUE(state.native_widget_deleted);
563 }
564 
565 // NativeWidget owns its Widget, part 5: NativeWidget is a NativeWidget,
566 // we close it directly.
TEST_F(WidgetOwnershipTest,Ownership_ViewsNativeWidgetOwnsWidget_Close)567 TEST_F(WidgetOwnershipTest,
568        Ownership_ViewsNativeWidgetOwnsWidget_Close) {
569   OwnershipTestState state;
570 
571   Widget* toplevel = CreateTopLevelPlatformWidget();
572 
573   Widget* widget = new OwnershipTestWidget(&state);
574   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
575   params.native_widget =
576       new OwnershipTestNativeWidgetAura(widget, &state);
577   params.parent = toplevel->GetNativeView();
578   widget->Init(params);
579 
580   // Destroy the widget.
581   widget->Close();
582   toplevel->CloseNow();
583 
584   // The NativeWidget won't be deleted until after a return to the message loop
585   // so we have to run pending messages before testing the destruction status.
586   RunPendingMessages();
587 
588   EXPECT_TRUE(state.widget_deleted);
589   EXPECT_TRUE(state.native_widget_deleted);
590 }
591 
592 // Widget owns its NativeWidget and has a WidgetDelegateView as its contents.
TEST_F(WidgetOwnershipTest,Ownership_WidgetOwnsNativeWidgetWithWithWidgetDelegateView)593 TEST_F(WidgetOwnershipTest,
594        Ownership_WidgetOwnsNativeWidgetWithWithWidgetDelegateView) {
595   OwnershipTestState state;
596 
597   WidgetDelegateView* delegate_view = new WidgetDelegateView;
598 
599   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
600   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
601   params.native_widget =
602       new OwnershipTestNativeWidgetAura(widget.get(), &state);
603   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
604   params.delegate = delegate_view;
605   widget->Init(params);
606   widget->SetContentsView(delegate_view);
607 
608   // Now delete the Widget. There should be no crash or use-after-free.
609   widget.reset();
610 
611   EXPECT_TRUE(state.widget_deleted);
612   EXPECT_TRUE(state.native_widget_deleted);
613 }
614 
615 ////////////////////////////////////////////////////////////////////////////////
616 // Test to verify using various Widget methods doesn't crash when the underlying
617 // NativeView is destroyed.
618 //
619 class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
620  public:
WidgetWithDestroyedNativeViewTest()621   WidgetWithDestroyedNativeViewTest() {}
~WidgetWithDestroyedNativeViewTest()622   virtual ~WidgetWithDestroyedNativeViewTest() {}
623 
InvokeWidgetMethods(Widget * widget)624   void InvokeWidgetMethods(Widget* widget) {
625     widget->GetNativeView();
626     widget->GetNativeWindow();
627     ui::Accelerator accelerator;
628     widget->GetAccelerator(0, &accelerator);
629     widget->GetTopLevelWidget();
630     widget->GetWindowBoundsInScreen();
631     widget->GetClientAreaBoundsInScreen();
632     widget->SetBounds(gfx::Rect(0, 0, 100, 80));
633     widget->SetSize(gfx::Size(10, 11));
634     widget->SetBoundsConstrained(gfx::Rect(0, 0, 120, 140));
635     widget->SetVisibilityChangedAnimationsEnabled(false);
636     widget->StackAtTop();
637     widget->IsClosed();
638     widget->Close();
639     widget->Hide();
640     widget->Activate();
641     widget->Deactivate();
642     widget->IsActive();
643     widget->DisableInactiveRendering();
644     widget->SetAlwaysOnTop(true);
645     widget->IsAlwaysOnTop();
646     widget->Maximize();
647     widget->Minimize();
648     widget->Restore();
649     widget->IsMaximized();
650     widget->IsFullscreen();
651     widget->SetOpacity(0);
652     widget->SetUseDragFrame(true);
653     widget->FlashFrame(true);
654     widget->IsVisible();
655     widget->GetThemeProvider();
656     widget->GetNativeTheme();
657     widget->GetFocusManager();
658     widget->GetInputMethod();
659     widget->SchedulePaintInRect(gfx::Rect(0, 0, 1, 2));
660     widget->IsMouseEventsEnabled();
661     widget->SetNativeWindowProperty("xx", widget);
662     widget->GetNativeWindowProperty("xx");
663     widget->GetFocusTraversable();
664     widget->GetLayer();
665     widget->ReorderNativeViews();
666     widget->SetCapture(widget->GetRootView());
667     widget->ReleaseCapture();
668     widget->HasCapture();
669     widget->GetWorkAreaBoundsInScreen();
670     widget->IsTranslucentWindowOpacitySupported();
671   }
672 
673  private:
674   DISALLOW_COPY_AND_ASSIGN(WidgetWithDestroyedNativeViewTest);
675 };
676 
TEST_F(WidgetWithDestroyedNativeViewTest,Test)677 TEST_F(WidgetWithDestroyedNativeViewTest, Test) {
678   {
679     Widget widget;
680     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
681     params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
682     widget.Init(params);
683     widget.Show();
684 
685     widget.native_widget_private()->CloseNow();
686     InvokeWidgetMethods(&widget);
687   }
688 #if !defined(OS_CHROMEOS)
689   {
690     Widget widget;
691     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
692     params.native_widget = new PlatformDesktopNativeWidget(&widget);
693     params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
694     widget.Init(params);
695     widget.Show();
696 
697     widget.native_widget_private()->CloseNow();
698     InvokeWidgetMethods(&widget);
699   }
700 #endif
701 }
702 
703 ////////////////////////////////////////////////////////////////////////////////
704 // Widget observer tests.
705 //
706 
707 class WidgetObserverTest : public WidgetTest, public WidgetObserver {
708  public:
WidgetObserverTest()709   WidgetObserverTest()
710       : active_(NULL),
711         widget_closed_(NULL),
712         widget_activated_(NULL),
713         widget_shown_(NULL),
714         widget_hidden_(NULL),
715         widget_bounds_changed_(NULL) {
716   }
717 
~WidgetObserverTest()718   virtual ~WidgetObserverTest() {}
719 
720   // Overridden from WidgetObserver:
OnWidgetDestroying(Widget * widget)721   virtual void OnWidgetDestroying(Widget* widget) OVERRIDE {
722     if (active_ == widget)
723       active_ = NULL;
724     widget_closed_ = widget;
725   }
726 
OnWidgetActivationChanged(Widget * widget,bool active)727   virtual void OnWidgetActivationChanged(Widget* widget,
728                                          bool active) OVERRIDE {
729     if (active) {
730       if (widget_activated_)
731         widget_activated_->Deactivate();
732       widget_activated_ = widget;
733       active_ = widget;
734     } else {
735       if (widget_activated_ == widget)
736         widget_activated_ = NULL;
737       widget_deactivated_ = widget;
738     }
739   }
740 
OnWidgetVisibilityChanged(Widget * widget,bool visible)741   virtual void OnWidgetVisibilityChanged(Widget* widget,
742                                          bool visible) OVERRIDE {
743     if (visible)
744       widget_shown_ = widget;
745     else
746       widget_hidden_ = widget;
747   }
748 
OnWidgetBoundsChanged(Widget * widget,const gfx::Rect & new_bounds)749   virtual void OnWidgetBoundsChanged(Widget* widget,
750                                      const gfx::Rect& new_bounds) OVERRIDE {
751     widget_bounds_changed_ = widget;
752   }
753 
reset()754   void reset() {
755     active_ = NULL;
756     widget_closed_ = NULL;
757     widget_activated_ = NULL;
758     widget_deactivated_ = NULL;
759     widget_shown_ = NULL;
760     widget_hidden_ = NULL;
761     widget_bounds_changed_ = NULL;
762   }
763 
NewWidget()764   Widget* NewWidget() {
765     Widget* widget = CreateTopLevelNativeWidget();
766     widget->AddObserver(this);
767     return widget;
768   }
769 
active() const770   const Widget* active() const { return active_; }
widget_closed() const771   const Widget* widget_closed() const { return widget_closed_; }
widget_activated() const772   const Widget* widget_activated() const { return widget_activated_; }
widget_deactivated() const773   const Widget* widget_deactivated() const { return widget_deactivated_; }
widget_shown() const774   const Widget* widget_shown() const { return widget_shown_; }
widget_hidden() const775   const Widget* widget_hidden() const { return widget_hidden_; }
widget_bounds_changed() const776   const Widget* widget_bounds_changed() const { return widget_bounds_changed_; }
777 
778  private:
779   Widget* active_;
780 
781   Widget* widget_closed_;
782   Widget* widget_activated_;
783   Widget* widget_deactivated_;
784   Widget* widget_shown_;
785   Widget* widget_hidden_;
786   Widget* widget_bounds_changed_;
787 };
788 
TEST_F(WidgetObserverTest,DISABLED_ActivationChange)789 TEST_F(WidgetObserverTest, DISABLED_ActivationChange) {
790   Widget* toplevel = CreateTopLevelPlatformWidget();
791 
792   Widget* toplevel1 = NewWidget();
793   Widget* toplevel2 = NewWidget();
794 
795   toplevel1->Show();
796   toplevel2->Show();
797 
798   reset();
799 
800   toplevel1->Activate();
801 
802   RunPendingMessages();
803   EXPECT_EQ(toplevel1, widget_activated());
804 
805   toplevel2->Activate();
806   RunPendingMessages();
807   EXPECT_EQ(toplevel1, widget_deactivated());
808   EXPECT_EQ(toplevel2, widget_activated());
809   EXPECT_EQ(toplevel2, active());
810 
811   toplevel->CloseNow();
812 }
813 
TEST_F(WidgetObserverTest,DISABLED_VisibilityChange)814 TEST_F(WidgetObserverTest, DISABLED_VisibilityChange) {
815   Widget* toplevel = CreateTopLevelPlatformWidget();
816 
817   Widget* child1 = NewWidget();
818   Widget* child2 = NewWidget();
819 
820   toplevel->Show();
821   child1->Show();
822   child2->Show();
823 
824   reset();
825 
826   child1->Hide();
827   EXPECT_EQ(child1, widget_hidden());
828 
829   child2->Hide();
830   EXPECT_EQ(child2, widget_hidden());
831 
832   child1->Show();
833   EXPECT_EQ(child1, widget_shown());
834 
835   child2->Show();
836   EXPECT_EQ(child2, widget_shown());
837 
838   toplevel->CloseNow();
839 }
840 
TEST_F(WidgetObserverTest,DestroyBubble)841 TEST_F(WidgetObserverTest, DestroyBubble) {
842   Widget* anchor = CreateTopLevelPlatformWidget();
843   anchor->Show();
844 
845   BubbleDelegateView* bubble_delegate =
846       new BubbleDelegateView(anchor->client_view(), BubbleBorder::NONE);
847   Widget* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate));
848   bubble_widget->Show();
849   bubble_widget->CloseNow();
850 
851   anchor->Hide();
852   anchor->CloseNow();
853 }
854 
TEST_F(WidgetObserverTest,WidgetBoundsChanged)855 TEST_F(WidgetObserverTest, WidgetBoundsChanged) {
856   Widget* child1 = NewWidget();
857   Widget* child2 = NewWidget();
858 
859   child1->OnNativeWidgetMove();
860   EXPECT_EQ(child1, widget_bounds_changed());
861 
862   child2->OnNativeWidgetMove();
863   EXPECT_EQ(child2, widget_bounds_changed());
864 
865   child1->OnNativeWidgetSizeChanged(gfx::Size());
866   EXPECT_EQ(child1, widget_bounds_changed());
867 
868   child2->OnNativeWidgetSizeChanged(gfx::Size());
869   EXPECT_EQ(child2, widget_bounds_changed());
870 }
871 
872 // Tests that SetBounds() and GetWindowBoundsInScreen() is symmetric when the
873 // widget is visible and not maximized or fullscreen.
TEST_F(WidgetTest,GetWindowBoundsInScreen)874 TEST_F(WidgetTest, GetWindowBoundsInScreen) {
875   // Choose test coordinates away from edges and dimensions that are "small"
876   // (but not too small) to ensure the OS doesn't try to adjust them.
877   const gfx::Rect kTestBounds(150, 150, 400, 300);
878   const gfx::Size kTestSize(200, 180);
879 
880   // First test a toplevel widget.
881   Widget* widget = CreateTopLevelPlatformWidget();
882   widget->Show();
883 
884   EXPECT_NE(kTestSize.ToString(),
885             widget->GetWindowBoundsInScreen().size().ToString());
886   widget->SetSize(kTestSize);
887   EXPECT_EQ(kTestSize.ToString(),
888             widget->GetWindowBoundsInScreen().size().ToString());
889 
890   EXPECT_NE(kTestBounds.ToString(),
891             widget->GetWindowBoundsInScreen().ToString());
892   widget->SetBounds(kTestBounds);
893   EXPECT_EQ(kTestBounds.ToString(),
894             widget->GetWindowBoundsInScreen().ToString());
895 
896   // Changing just the size should not change the origin.
897   widget->SetSize(kTestSize);
898   EXPECT_EQ(kTestBounds.origin().ToString(),
899             widget->GetWindowBoundsInScreen().origin().ToString());
900 
901   widget->CloseNow();
902 
903   // Same tests with a frameless window.
904   widget = CreateTopLevelFramelessPlatformWidget();
905   widget->Show();
906 
907   EXPECT_NE(kTestSize.ToString(),
908             widget->GetWindowBoundsInScreen().size().ToString());
909   widget->SetSize(kTestSize);
910   EXPECT_EQ(kTestSize.ToString(),
911             widget->GetWindowBoundsInScreen().size().ToString());
912 
913   EXPECT_NE(kTestBounds.ToString(),
914             widget->GetWindowBoundsInScreen().ToString());
915   widget->SetBounds(kTestBounds);
916   EXPECT_EQ(kTestBounds.ToString(),
917             widget->GetWindowBoundsInScreen().ToString());
918 
919   // For a frameless widget, the client bounds should also match.
920   EXPECT_EQ(kTestBounds.ToString(),
921             widget->GetClientAreaBoundsInScreen().ToString());
922 
923   // Verify origin is stable for a frameless window as well.
924   widget->SetSize(kTestSize);
925   EXPECT_EQ(kTestBounds.origin().ToString(),
926             widget->GetWindowBoundsInScreen().origin().ToString());
927 
928   widget->CloseNow();
929 }
930 
931 #if defined(false)
932 // Aura needs shell to maximize/fullscreen window.
933 // NativeWidgetGtk doesn't implement GetRestoredBounds.
TEST_F(WidgetTest,GetRestoredBounds)934 TEST_F(WidgetTest, GetRestoredBounds) {
935   Widget* toplevel = CreateTopLevelPlatformWidget();
936   EXPECT_EQ(toplevel->GetWindowBoundsInScreen().ToString(),
937             toplevel->GetRestoredBounds().ToString());
938   toplevel->Show();
939   toplevel->Maximize();
940   RunPendingMessages();
941   EXPECT_NE(toplevel->GetWindowBoundsInScreen().ToString(),
942             toplevel->GetRestoredBounds().ToString());
943   EXPECT_GT(toplevel->GetRestoredBounds().width(), 0);
944   EXPECT_GT(toplevel->GetRestoredBounds().height(), 0);
945 
946   toplevel->Restore();
947   RunPendingMessages();
948   EXPECT_EQ(toplevel->GetWindowBoundsInScreen().ToString(),
949             toplevel->GetRestoredBounds().ToString());
950 
951   toplevel->SetFullscreen(true);
952   RunPendingMessages();
953   EXPECT_NE(toplevel->GetWindowBoundsInScreen().ToString(),
954             toplevel->GetRestoredBounds().ToString());
955   EXPECT_GT(toplevel->GetRestoredBounds().width(), 0);
956   EXPECT_GT(toplevel->GetRestoredBounds().height(), 0);
957 }
958 #endif
959 
960 // Test that window state is not changed after getting out of full screen.
TEST_F(WidgetTest,ExitFullscreenRestoreState)961 TEST_F(WidgetTest, ExitFullscreenRestoreState) {
962   Widget* toplevel = CreateTopLevelPlatformWidget();
963 
964   toplevel->Show();
965   RunPendingMessages();
966 
967   // This should be a normal state window.
968   EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
969 
970   toplevel->SetFullscreen(true);
971   EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
972   toplevel->SetFullscreen(false);
973   EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
974 
975   // And it should still be in normal state after getting out of full screen.
976   EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
977 
978   // Now, make it maximized.
979   toplevel->Maximize();
980   EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel));
981 
982   toplevel->SetFullscreen(true);
983   EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
984   toplevel->SetFullscreen(false);
985   EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
986 
987   // And it stays maximized after getting out of full screen.
988   EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel));
989 
990   // Clean up.
991   toplevel->Close();
992   RunPendingMessages();
993 }
994 
995 // The key-event propagation from Widget happens differently on aura and
996 // non-aura systems because of the difference in IME. So this test works only on
997 // aura.
TEST_F(WidgetTest,KeyboardInputEvent)998 TEST_F(WidgetTest, KeyboardInputEvent) {
999   Widget* toplevel = CreateTopLevelPlatformWidget();
1000   View* container = toplevel->client_view();
1001 
1002   Textfield* textfield = new Textfield();
1003   textfield->SetText(base::ASCIIToUTF16("some text"));
1004   container->AddChildView(textfield);
1005   toplevel->Show();
1006   textfield->RequestFocus();
1007 
1008   // The press gets handled. The release doesn't have an effect.
1009   ui::KeyEvent backspace_p(ui::ET_KEY_PRESSED, ui::VKEY_DELETE, ui::EF_NONE);
1010   toplevel->OnKeyEvent(&backspace_p);
1011   EXPECT_TRUE(backspace_p.stopped_propagation());
1012   ui::KeyEvent backspace_r(ui::ET_KEY_RELEASED, ui::VKEY_DELETE, ui::EF_NONE);
1013   toplevel->OnKeyEvent(&backspace_r);
1014   EXPECT_FALSE(backspace_r.handled());
1015 
1016   toplevel->Close();
1017 }
1018 
1019 // Verifies bubbles result in a focus lost when shown.
1020 // TODO(msw): this tests relies on focus, it needs to be in
1021 // interactive_ui_tests.
TEST_F(WidgetTest,DISABLED_FocusChangesOnBubble)1022 TEST_F(WidgetTest, DISABLED_FocusChangesOnBubble) {
1023   // Create a widget, show and activate it and focus the contents view.
1024   View* contents_view = new View;
1025   contents_view->SetFocusable(true);
1026   Widget widget;
1027   Widget::InitParams init_params =
1028       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1029   init_params.bounds = gfx::Rect(0, 0, 200, 200);
1030   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1031 #if !defined(OS_CHROMEOS)
1032   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
1033 #endif
1034   widget.Init(init_params);
1035   widget.SetContentsView(contents_view);
1036   widget.Show();
1037   widget.Activate();
1038   contents_view->RequestFocus();
1039   EXPECT_TRUE(contents_view->HasFocus());
1040 
1041   // Show a bubble.
1042   BubbleDelegateView* bubble_delegate_view =
1043       new BubbleDelegateView(contents_view, BubbleBorder::TOP_LEFT);
1044   bubble_delegate_view->SetFocusable(true);
1045   BubbleDelegateView::CreateBubble(bubble_delegate_view)->Show();
1046   bubble_delegate_view->RequestFocus();
1047 
1048   // |contents_view_| should no longer have focus.
1049   EXPECT_FALSE(contents_view->HasFocus());
1050   EXPECT_TRUE(bubble_delegate_view->HasFocus());
1051 
1052   bubble_delegate_view->GetWidget()->CloseNow();
1053 
1054   // Closing the bubble should result in focus going back to the contents view.
1055   EXPECT_TRUE(contents_view->HasFocus());
1056 }
1057 
1058 class TestBubbleDelegateView : public BubbleDelegateView {
1059  public:
TestBubbleDelegateView(View * anchor)1060   TestBubbleDelegateView(View* anchor)
1061       : BubbleDelegateView(anchor, BubbleBorder::NONE),
1062         reset_controls_called_(false) {}
~TestBubbleDelegateView()1063   virtual ~TestBubbleDelegateView() {}
1064 
ShouldShowCloseButton() const1065   virtual bool ShouldShowCloseButton() const OVERRIDE {
1066     reset_controls_called_ = true;
1067     return true;
1068   }
1069 
1070   mutable bool reset_controls_called_;
1071 };
1072 
TEST_F(WidgetTest,BubbleControlsResetOnInit)1073 TEST_F(WidgetTest, BubbleControlsResetOnInit) {
1074   Widget* anchor = CreateTopLevelPlatformWidget();
1075   anchor->Show();
1076 
1077   TestBubbleDelegateView* bubble_delegate =
1078       new TestBubbleDelegateView(anchor->client_view());
1079   Widget* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate));
1080   EXPECT_TRUE(bubble_delegate->reset_controls_called_);
1081   bubble_widget->Show();
1082   bubble_widget->CloseNow();
1083 
1084   anchor->Hide();
1085   anchor->CloseNow();
1086 }
1087 
1088 // Desktop native widget Aura tests are for non Chrome OS platforms.
1089 #if !defined(OS_CHROMEOS)
1090 // Test to ensure that after minimize, view width is set to zero.
TEST_F(WidgetTest,TestViewWidthAfterMinimizingWidget)1091 TEST_F(WidgetTest, TestViewWidthAfterMinimizingWidget) {
1092   // Create a widget.
1093   Widget widget;
1094   Widget::InitParams init_params =
1095       CreateParams(Widget::InitParams::TYPE_WINDOW);
1096   init_params.show_state = ui::SHOW_STATE_NORMAL;
1097   gfx::Rect initial_bounds(0, 0, 300, 400);
1098   init_params.bounds = initial_bounds;
1099   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1100   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
1101   widget.Init(init_params);
1102   NonClientView* non_client_view = widget.non_client_view();
1103   NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
1104   non_client_view->SetFrameView(frame_view);
1105   widget.Show();
1106   widget.Minimize();
1107   EXPECT_EQ(0, frame_view->width());
1108 }
1109 
1110 // This class validates whether paints are received for a visible Widget.
1111 // To achieve this it overrides the Show and Close methods on the Widget class
1112 // and sets state whether subsequent paints are expected.
1113 class DesktopAuraTestValidPaintWidget : public views::Widget {
1114  public:
DesktopAuraTestValidPaintWidget()1115   DesktopAuraTestValidPaintWidget()
1116     : expect_paint_(true),
1117       received_paint_while_hidden_(false) {
1118   }
1119 
~DesktopAuraTestValidPaintWidget()1120   virtual ~DesktopAuraTestValidPaintWidget() {
1121   }
1122 
Show()1123   virtual void Show() OVERRIDE {
1124     expect_paint_ = true;
1125     views::Widget::Show();
1126   }
1127 
Close()1128   virtual void Close() OVERRIDE {
1129     expect_paint_ = false;
1130     views::Widget::Close();
1131   }
1132 
Hide()1133   void Hide() {
1134     expect_paint_ = false;
1135     views::Widget::Hide();
1136   }
1137 
OnNativeWidgetPaint(gfx::Canvas * canvas)1138   virtual void OnNativeWidgetPaint(gfx::Canvas* canvas) OVERRIDE {
1139     EXPECT_TRUE(expect_paint_);
1140     if (!expect_paint_)
1141       received_paint_while_hidden_ = true;
1142     views::Widget::OnNativeWidgetPaint(canvas);
1143   }
1144 
received_paint_while_hidden() const1145   bool received_paint_while_hidden() const {
1146     return received_paint_while_hidden_;
1147   }
1148 
1149  private:
1150   bool expect_paint_;
1151   bool received_paint_while_hidden_;
1152 };
1153 
TEST_F(WidgetTest,DesktopNativeWidgetNoPaintAfterCloseTest)1154 TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterCloseTest) {
1155   View* contents_view = new View;
1156   contents_view->SetFocusable(true);
1157   DesktopAuraTestValidPaintWidget widget;
1158   Widget::InitParams init_params =
1159       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1160   init_params.bounds = gfx::Rect(0, 0, 200, 200);
1161   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1162   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
1163   widget.Init(init_params);
1164   widget.SetContentsView(contents_view);
1165   widget.Show();
1166   widget.Activate();
1167   RunPendingMessages();
1168   widget.SchedulePaintInRect(init_params.bounds);
1169   widget.Close();
1170   RunPendingMessages();
1171   EXPECT_FALSE(widget.received_paint_while_hidden());
1172 }
1173 
TEST_F(WidgetTest,DesktopNativeWidgetNoPaintAfterHideTest)1174 TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterHideTest) {
1175   View* contents_view = new View;
1176   contents_view->SetFocusable(true);
1177   DesktopAuraTestValidPaintWidget widget;
1178   Widget::InitParams init_params =
1179       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
1180   init_params.bounds = gfx::Rect(0, 0, 200, 200);
1181   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1182   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
1183   widget.Init(init_params);
1184   widget.SetContentsView(contents_view);
1185   widget.Show();
1186   widget.Activate();
1187   RunPendingMessages();
1188   widget.SchedulePaintInRect(init_params.bounds);
1189   widget.Hide();
1190   RunPendingMessages();
1191   EXPECT_FALSE(widget.received_paint_while_hidden());
1192   widget.Close();
1193 }
1194 
1195 // Test to ensure that the aura Window's visiblity state is set to visible if
1196 // the underlying widget is hidden and then shown.
TEST_F(WidgetTest,TestWindowVisibilityAfterHide)1197 TEST_F(WidgetTest, TestWindowVisibilityAfterHide) {
1198   // Create a widget.
1199   Widget widget;
1200   Widget::InitParams init_params =
1201       CreateParams(Widget::InitParams::TYPE_WINDOW);
1202   init_params.show_state = ui::SHOW_STATE_NORMAL;
1203   gfx::Rect initial_bounds(0, 0, 300, 400);
1204   init_params.bounds = initial_bounds;
1205   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1206   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
1207   widget.Init(init_params);
1208   NonClientView* non_client_view = widget.non_client_view();
1209   NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
1210   non_client_view->SetFrameView(frame_view);
1211 
1212   widget.Hide();
1213   EXPECT_FALSE(IsNativeWindowVisible(widget.GetNativeWindow()));
1214   widget.Show();
1215   EXPECT_TRUE(IsNativeWindowVisible(widget.GetNativeWindow()));
1216 }
1217 
1218 // The following code verifies we can correctly destroy a Widget from a mouse
1219 // enter/exit. We could test move/drag/enter/exit but in general we don't run
1220 // nested message loops from such events, nor has the code ever really dealt
1221 // with this situation.
1222 
1223 // Generates two moves (first generates enter, second real move), a press, drag
1224 // and release stopping at |last_event_type|.
GenerateMouseEvents(Widget * widget,ui::EventType last_event_type)1225 void GenerateMouseEvents(Widget* widget, ui::EventType last_event_type) {
1226   const gfx::Rect screen_bounds(widget->GetWindowBoundsInScreen());
1227   ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, screen_bounds.CenterPoint(),
1228                             screen_bounds.CenterPoint(), 0, 0);
1229   ui::EventProcessor* dispatcher = WidgetTest::GetEventProcessor(widget);
1230   ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&move_event);
1231   if (last_event_type == ui::ET_MOUSE_ENTERED || details.dispatcher_destroyed)
1232     return;
1233   details = dispatcher->OnEventFromSource(&move_event);
1234   if (last_event_type == ui::ET_MOUSE_MOVED || details.dispatcher_destroyed)
1235     return;
1236 
1237   ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, screen_bounds.CenterPoint(),
1238                              screen_bounds.CenterPoint(), 0, 0);
1239   details = dispatcher->OnEventFromSource(&press_event);
1240   if (last_event_type == ui::ET_MOUSE_PRESSED || details.dispatcher_destroyed)
1241     return;
1242 
1243   gfx::Point end_point(screen_bounds.CenterPoint());
1244   end_point.Offset(1, 1);
1245   ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, end_point, end_point, 0, 0);
1246   details = dispatcher->OnEventFromSource(&drag_event);
1247   if (last_event_type == ui::ET_MOUSE_DRAGGED || details.dispatcher_destroyed)
1248     return;
1249 
1250   ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, end_point, end_point, 0,
1251                                0);
1252   details = dispatcher->OnEventFromSource(&release_event);
1253   if (details.dispatcher_destroyed)
1254     return;
1255 }
1256 
1257 // Creates a widget and invokes GenerateMouseEvents() with |last_event_type|.
RunCloseWidgetDuringDispatchTest(WidgetTest * test,ui::EventType last_event_type)1258 void RunCloseWidgetDuringDispatchTest(WidgetTest* test,
1259                                       ui::EventType last_event_type) {
1260   // |widget| is deleted by CloseWidgetView.
1261   Widget* widget = new Widget;
1262   Widget::InitParams params =
1263       test->CreateParams(Widget::InitParams::TYPE_POPUP);
1264   params.native_widget = new PlatformDesktopNativeWidget(widget);
1265   params.bounds = gfx::Rect(0, 0, 50, 100);
1266   widget->Init(params);
1267   widget->SetContentsView(new CloseWidgetView(last_event_type));
1268   widget->Show();
1269   GenerateMouseEvents(widget, last_event_type);
1270 }
1271 
1272 // Verifies deleting the widget from a mouse pressed event doesn't crash.
TEST_F(WidgetTest,CloseWidgetDuringMousePress)1273 TEST_F(WidgetTest, CloseWidgetDuringMousePress) {
1274   RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_PRESSED);
1275 }
1276 
1277 // Verifies deleting the widget from a mouse released event doesn't crash.
TEST_F(WidgetTest,CloseWidgetDuringMouseReleased)1278 TEST_F(WidgetTest, CloseWidgetDuringMouseReleased) {
1279   RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_RELEASED);
1280 }
1281 
1282 #endif  // !defined(OS_CHROMEOS)
1283 
1284 // Tests that wheel events generated from scroll events are targetted to the
1285 // views under the cursor when the focused view does not processed them.
TEST_F(WidgetTest,WheelEventsFromScrollEventTarget)1286 TEST_F(WidgetTest, WheelEventsFromScrollEventTarget) {
1287   EventCountView* cursor_view = new EventCountView;
1288   cursor_view->SetBounds(60, 0, 50, 40);
1289 
1290   Widget* widget = CreateTopLevelPlatformWidget();
1291   widget->GetRootView()->AddChildView(cursor_view);
1292 
1293   // Generate a scroll event on the cursor view.
1294   ui::ScrollEvent scroll(ui::ET_SCROLL,
1295                          gfx::Point(65, 5),
1296                          ui::EventTimeForNow(),
1297                          0,
1298                          0, 20,
1299                          0, 20,
1300                          2);
1301   widget->OnScrollEvent(&scroll);
1302 
1303   EXPECT_EQ(1, cursor_view->GetEventCount(ui::ET_SCROLL));
1304   EXPECT_EQ(1, cursor_view->GetEventCount(ui::ET_MOUSEWHEEL));
1305 
1306   cursor_view->ResetCounts();
1307 
1308   ui::ScrollEvent scroll2(ui::ET_SCROLL,
1309                           gfx::Point(5, 5),
1310                           ui::EventTimeForNow(),
1311                           0,
1312                           0, 20,
1313                           0, 20,
1314                           2);
1315   widget->OnScrollEvent(&scroll2);
1316 
1317   EXPECT_EQ(0, cursor_view->GetEventCount(ui::ET_SCROLL));
1318   EXPECT_EQ(0, cursor_view->GetEventCount(ui::ET_MOUSEWHEEL));
1319 
1320   widget->CloseNow();
1321 }
1322 
1323 // Tests that if a scroll-begin gesture is not handled, then subsequent scroll
1324 // events are not dispatched to any view.
TEST_F(WidgetTest,GestureScrollEventDispatching)1325 TEST_F(WidgetTest, GestureScrollEventDispatching) {
1326   EventCountView* noscroll_view = new EventCountView;
1327   EventCountView* scroll_view = new ScrollableEventCountView;
1328 
1329   noscroll_view->SetBounds(0, 0, 50, 40);
1330   scroll_view->SetBounds(60, 0, 40, 40);
1331 
1332   Widget* widget = CreateTopLevelPlatformWidget();
1333   widget->GetRootView()->AddChildView(noscroll_view);
1334   widget->GetRootView()->AddChildView(scroll_view);
1335 
1336   {
1337     ui::GestureEvent begin(
1338         5,
1339         5,
1340         0,
1341         base::TimeDelta(),
1342         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
1343     widget->OnGestureEvent(&begin);
1344     ui::GestureEvent update(
1345         25,
1346         15,
1347         0,
1348         base::TimeDelta(),
1349         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 20, 10));
1350     widget->OnGestureEvent(&update);
1351     ui::GestureEvent end(25,
1352                          15,
1353                          0,
1354                          base::TimeDelta(),
1355                          ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
1356     widget->OnGestureEvent(&end);
1357 
1358     EXPECT_EQ(1, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
1359     EXPECT_EQ(0, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
1360     EXPECT_EQ(0, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END));
1361   }
1362 
1363   {
1364     ui::GestureEvent begin(
1365         65,
1366         5,
1367         0,
1368         base::TimeDelta(),
1369         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
1370     widget->OnGestureEvent(&begin);
1371     ui::GestureEvent update(
1372         85,
1373         15,
1374         0,
1375         base::TimeDelta(),
1376         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 20, 10));
1377     widget->OnGestureEvent(&update);
1378     ui::GestureEvent end(85,
1379                          15,
1380                          0,
1381                          base::TimeDelta(),
1382                          ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
1383     widget->OnGestureEvent(&end);
1384 
1385     EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
1386     EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
1387     EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END));
1388   }
1389 
1390   widget->CloseNow();
1391 }
1392 
1393 // Tests that event-handlers installed on the RootView get triggered correctly.
1394 // TODO(tdanderson): Clean up this test as part of crbug.com/355680.
TEST_F(WidgetTest,EventHandlersOnRootView)1395 TEST_F(WidgetTest, EventHandlersOnRootView) {
1396   Widget* widget = CreateTopLevelNativeWidget();
1397   View* root_view = widget->GetRootView();
1398 
1399   scoped_ptr<EventCountView> view(new EventCountView());
1400   view->set_owned_by_client();
1401   view->SetBounds(0, 0, 20, 20);
1402   root_view->AddChildView(view.get());
1403 
1404   EventCountHandler h1;
1405   root_view->AddPreTargetHandler(&h1);
1406 
1407   EventCountHandler h2;
1408   root_view->AddPostTargetHandler(&h2);
1409 
1410   widget->SetBounds(gfx::Rect(0, 0, 100, 100));
1411   widget->Show();
1412 
1413   // Dispatch a ui::ET_SCROLL event. The event remains unhandled and should
1414   // bubble up the views hierarchy to be re-dispatched on the root view.
1415   ui::ScrollEvent scroll(ui::ET_SCROLL,
1416                          gfx::Point(5, 5),
1417                          ui::EventTimeForNow(),
1418                          0,
1419                          0, 20,
1420                          0, 20,
1421                          2);
1422   widget->OnScrollEvent(&scroll);
1423   EXPECT_EQ(2, h1.GetEventCount(ui::ET_SCROLL));
1424   EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL));
1425   EXPECT_EQ(2, h2.GetEventCount(ui::ET_SCROLL));
1426 
1427   // Unhandled scroll events are turned into wheel events and re-dispatched.
1428   EXPECT_EQ(1, h1.GetEventCount(ui::ET_MOUSEWHEEL));
1429   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSEWHEEL));
1430   EXPECT_EQ(1, h2.GetEventCount(ui::ET_MOUSEWHEEL));
1431 
1432   h1.ResetCounts();
1433   view->ResetCounts();
1434   h2.ResetCounts();
1435 
1436   // Dispatch a ui::ET_SCROLL_FLING_START event. The event remains unhandled and
1437   // should bubble up the views hierarchy to be re-dispatched on the root view.
1438   ui::ScrollEvent fling(ui::ET_SCROLL_FLING_START,
1439                         gfx::Point(5, 5),
1440                         ui::EventTimeForNow(),
1441                         0,
1442                         0, 20,
1443                         0, 20,
1444                         2);
1445   widget->OnScrollEvent(&fling);
1446   EXPECT_EQ(2, h1.GetEventCount(ui::ET_SCROLL_FLING_START));
1447   EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL_FLING_START));
1448   EXPECT_EQ(2, h2.GetEventCount(ui::ET_SCROLL_FLING_START));
1449 
1450   // Unhandled scroll events which are not of type ui::ET_SCROLL should not
1451   // be turned into wheel events and re-dispatched.
1452   EXPECT_EQ(0, h1.GetEventCount(ui::ET_MOUSEWHEEL));
1453   EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSEWHEEL));
1454   EXPECT_EQ(0, h2.GetEventCount(ui::ET_MOUSEWHEEL));
1455 
1456   h1.ResetCounts();
1457   view->ResetCounts();
1458   h2.ResetCounts();
1459 
1460   // Change the handle mode of |view| so that events are marked as handled at
1461   // the target phase.
1462   view->set_handle_mode(EventCountView::CONSUME_EVENTS);
1463 
1464   // Dispatch a ui::ET_GESTURE_TAP_DOWN and a ui::ET_GESTURE_TAP_CANCEL event.
1465   // The events are handled at the target phase and should not reach the
1466   // post-target handler.
1467   ui::GestureEvent tap_down(5,
1468                             5,
1469                             0,
1470                             ui::EventTimeForNow(),
1471                             ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
1472   widget->OnGestureEvent(&tap_down);
1473   EXPECT_EQ(1, h1.GetEventCount(ui::ET_GESTURE_TAP_DOWN));
1474   EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
1475   EXPECT_EQ(0, h2.GetEventCount(ui::ET_GESTURE_TAP_DOWN));
1476 
1477   ui::GestureEvent tap_cancel(
1478       5,
1479       5,
1480       0,
1481       ui::EventTimeForNow(),
1482       ui::GestureEventDetails(ui::ET_GESTURE_TAP_CANCEL));
1483   widget->OnGestureEvent(&tap_cancel);
1484   EXPECT_EQ(1, h1.GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
1485   EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
1486   EXPECT_EQ(0, h2.GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
1487 
1488   h1.ResetCounts();
1489   view->ResetCounts();
1490   h2.ResetCounts();
1491 
1492   // Dispatch a ui::ET_SCROLL event. The event is handled at the target phase
1493   // and should not reach the post-target handler.
1494   ui::ScrollEvent consumed_scroll(ui::ET_SCROLL,
1495                                   gfx::Point(5, 5),
1496                                   ui::EventTimeForNow(),
1497                                   0,
1498                                   0, 20,
1499                                   0, 20,
1500                                   2);
1501   widget->OnScrollEvent(&consumed_scroll);
1502   EXPECT_EQ(1, h1.GetEventCount(ui::ET_SCROLL));
1503   EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL));
1504   EXPECT_EQ(0, h2.GetEventCount(ui::ET_SCROLL));
1505 
1506   // Handled scroll events are not turned into wheel events and re-dispatched.
1507   EXPECT_EQ(0, h1.GetEventCount(ui::ET_MOUSEWHEEL));
1508   EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSEWHEEL));
1509   EXPECT_EQ(0, h2.GetEventCount(ui::ET_MOUSEWHEEL));
1510 
1511   widget->CloseNow();
1512 }
1513 
TEST_F(WidgetTest,SynthesizeMouseMoveEvent)1514 TEST_F(WidgetTest, SynthesizeMouseMoveEvent) {
1515   Widget* widget = CreateTopLevelNativeWidget();
1516   View* root_view = widget->GetRootView();
1517 
1518   EventCountView* v1 = new EventCountView();
1519   v1->SetBounds(0, 0, 10, 10);
1520   root_view->AddChildView(v1);
1521   EventCountView* v2 = new EventCountView();
1522   v2->SetBounds(0, 10, 10, 10);
1523   root_view->AddChildView(v2);
1524 
1525   gfx::Point cursor_location(5, 5);
1526   ui::MouseEvent move(ui::ET_MOUSE_MOVED, cursor_location, cursor_location,
1527                       ui::EF_NONE, ui::EF_NONE);
1528   widget->OnMouseEvent(&move);
1529 
1530   EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_ENTERED));
1531   EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
1532 
1533   delete v1;
1534   v2->SetBounds(0, 0, 10, 10);
1535   EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
1536 
1537   widget->SynthesizeMouseMoveEvent();
1538   EXPECT_EQ(1, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
1539 }
1540 
1541 namespace {
1542 
1543 // ui::EventHandler which handles all mouse press events.
1544 class MousePressEventConsumer : public ui::EventHandler {
1545  public:
MousePressEventConsumer()1546   explicit MousePressEventConsumer() {
1547   }
1548 
~MousePressEventConsumer()1549   virtual ~MousePressEventConsumer() {
1550   }
1551 
1552  private:
1553   // ui::EventHandler:
OnMouseEvent(ui::MouseEvent * event)1554   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1555     if (event->type() == ui::ET_MOUSE_PRESSED)
1556       event->SetHandled();
1557   }
1558 
1559   DISALLOW_COPY_AND_ASSIGN(MousePressEventConsumer);
1560 };
1561 
1562 }  // namespace
1563 
1564 // Test that mouse presses and mouse releases are dispatched normally when a
1565 // touch is down.
TEST_F(WidgetTest,MouseEventDispatchWhileTouchIsDown)1566 TEST_F(WidgetTest, MouseEventDispatchWhileTouchIsDown) {
1567   Widget* widget = CreateTopLevelNativeWidget();
1568   widget->Show();
1569   widget->SetSize(gfx::Size(300, 300));
1570 
1571   EventCountView* event_count_view = new EventCountView();
1572   event_count_view->SetBounds(0, 0, 300, 300);
1573   widget->GetRootView()->AddChildView(event_count_view);
1574 
1575   MousePressEventConsumer consumer;
1576   event_count_view->AddPostTargetHandler(&consumer);
1577 
1578   ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
1579   generator.PressTouch();
1580   generator.ClickLeftButton();
1581 
1582   EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED));
1583   EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_RELEASED));
1584 
1585   widget->CloseNow();
1586 }
1587 
1588 // Used by SingleWindowClosing to count number of times WindowClosing() has
1589 // been invoked.
1590 class ClosingDelegate : public WidgetDelegate {
1591  public:
ClosingDelegate()1592   ClosingDelegate() : count_(0), widget_(NULL) {}
1593 
count() const1594   int count() const { return count_; }
1595 
set_widget(views::Widget * widget)1596   void set_widget(views::Widget* widget) { widget_ = widget; }
1597 
1598   // WidgetDelegate overrides:
GetWidget()1599   virtual Widget* GetWidget() OVERRIDE { return widget_; }
GetWidget() const1600   virtual const Widget* GetWidget() const OVERRIDE { return widget_; }
WindowClosing()1601   virtual void WindowClosing() OVERRIDE {
1602     count_++;
1603   }
1604 
1605  private:
1606   int count_;
1607   views::Widget* widget_;
1608 
1609   DISALLOW_COPY_AND_ASSIGN(ClosingDelegate);
1610 };
1611 
1612 // Verifies WindowClosing() is invoked correctly on the delegate when a Widget
1613 // is closed.
TEST_F(WidgetTest,SingleWindowClosing)1614 TEST_F(WidgetTest, SingleWindowClosing) {
1615   scoped_ptr<ClosingDelegate> delegate(new ClosingDelegate());
1616   Widget* widget = new Widget();  // Destroyed by CloseNow() below.
1617   Widget::InitParams init_params =
1618       CreateParams(Widget::InitParams::TYPE_WINDOW);
1619   init_params.bounds = gfx::Rect(0, 0, 200, 200);
1620   init_params.delegate = delegate.get();
1621 #if !defined(OS_CHROMEOS)
1622   init_params.native_widget = new PlatformDesktopNativeWidget(widget);
1623 #endif
1624   widget->Init(init_params);
1625   EXPECT_EQ(0, delegate->count());
1626   widget->CloseNow();
1627   EXPECT_EQ(1, delegate->count());
1628 }
1629 
1630 class WidgetWindowTitleTest : public WidgetTest {
1631  protected:
RunTest(bool desktop_native_widget)1632   void RunTest(bool desktop_native_widget) {
1633     Widget* widget = new Widget();  // Destroyed by CloseNow() below.
1634     Widget::InitParams init_params =
1635         CreateParams(Widget::InitParams::TYPE_WINDOW);
1636     widget->Init(init_params);
1637 
1638 #if !defined(OS_CHROMEOS)
1639     if (desktop_native_widget)
1640       init_params.native_widget = new PlatformDesktopNativeWidget(widget);
1641 #else
1642     DCHECK(!desktop_native_widget)
1643         << "DesktopNativeWidget does not exist on non-Aura or on ChromeOS.";
1644 #endif
1645 
1646     internal::NativeWidgetPrivate* native_widget =
1647         widget->native_widget_private();
1648 
1649     base::string16 empty;
1650     base::string16 s1(base::UTF8ToUTF16("Title1"));
1651     base::string16 s2(base::UTF8ToUTF16("Title2"));
1652     base::string16 s3(base::UTF8ToUTF16("TitleLong"));
1653 
1654     // The widget starts with no title, setting empty should not change
1655     // anything.
1656     EXPECT_FALSE(native_widget->SetWindowTitle(empty));
1657     // Setting the title to something non-empty should cause a change.
1658     EXPECT_TRUE(native_widget->SetWindowTitle(s1));
1659     // Setting the title to something else with the same length should cause a
1660     // change.
1661     EXPECT_TRUE(native_widget->SetWindowTitle(s2));
1662     // Setting the title to something else with a different length should cause
1663     // a change.
1664     EXPECT_TRUE(native_widget->SetWindowTitle(s3));
1665     // Setting the title to the same thing twice should not cause a change.
1666     EXPECT_FALSE(native_widget->SetWindowTitle(s3));
1667 
1668     widget->CloseNow();
1669   }
1670 };
1671 
TEST_F(WidgetWindowTitleTest,SetWindowTitleChanged_NativeWidget)1672 TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_NativeWidget) {
1673   // Use the default NativeWidget.
1674   bool desktop_native_widget = false;
1675   RunTest(desktop_native_widget);
1676 }
1677 
1678 // DesktopNativeWidget does not exist on non-Aura or on ChromeOS.
1679 #if !defined(OS_CHROMEOS)
TEST_F(WidgetWindowTitleTest,SetWindowTitleChanged_DesktopNativeWidget)1680 TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_DesktopNativeWidget) {
1681   // Override to use a DesktopNativeWidget.
1682   bool desktop_native_widget = true;
1683   RunTest(desktop_native_widget);
1684 }
1685 #endif  // !OS_CHROMEOS
1686 
TEST_F(WidgetTest,WidgetDeleted_InOnMousePressed)1687 TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) {
1688   Widget* widget = new Widget;
1689   Widget::InitParams params =
1690       CreateParams(views::Widget::InitParams::TYPE_POPUP);
1691   widget->Init(params);
1692 
1693   widget->SetContentsView(new CloseWidgetView(ui::ET_MOUSE_PRESSED));
1694 
1695   widget->SetSize(gfx::Size(100, 100));
1696   widget->Show();
1697 
1698   ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
1699 
1700   WidgetDeletionObserver deletion_observer(widget);
1701   generator.ClickLeftButton();
1702   EXPECT_FALSE(deletion_observer.IsWidgetAlive());
1703 
1704   // Yay we did not crash!
1705 }
1706 
TEST_F(WidgetTest,WidgetDeleted_InDispatchGestureEvent)1707 TEST_F(WidgetTest, WidgetDeleted_InDispatchGestureEvent) {
1708   Widget* widget = new Widget;
1709   Widget::InitParams params =
1710       CreateParams(views::Widget::InitParams::TYPE_POPUP);
1711   widget->Init(params);
1712 
1713   widget->SetContentsView(new CloseWidgetView(ui::ET_GESTURE_TAP_DOWN));
1714 
1715   widget->SetSize(gfx::Size(100, 100));
1716   widget->Show();
1717 
1718   ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
1719 
1720   WidgetDeletionObserver deletion_observer(widget);
1721   generator.GestureTapAt(widget->GetWindowBoundsInScreen().CenterPoint());
1722   EXPECT_FALSE(deletion_observer.IsWidgetAlive());
1723 
1724   // Yay we did not crash!
1725 }
1726 
1727 // See description of RunGetNativeThemeFromDestructor() for details.
1728 class GetNativeThemeFromDestructorView : public WidgetDelegateView {
1729  public:
GetNativeThemeFromDestructorView()1730   GetNativeThemeFromDestructorView() {}
~GetNativeThemeFromDestructorView()1731   virtual ~GetNativeThemeFromDestructorView() {
1732     VerifyNativeTheme();
1733   }
1734 
GetContentsView()1735   virtual View* GetContentsView() OVERRIDE {
1736     return this;
1737   }
1738 
1739  private:
VerifyNativeTheme()1740   void VerifyNativeTheme() {
1741     ASSERT_TRUE(GetNativeTheme() != NULL);
1742   }
1743 
1744   DISALLOW_COPY_AND_ASSIGN(GetNativeThemeFromDestructorView);
1745 };
1746 
1747 // Verifies GetNativeTheme() from the destructor of a WidgetDelegateView doesn't
1748 // crash. |is_first_run| is true if this is the first call. A return value of
1749 // true indicates this should be run again with a value of false.
1750 // First run uses DesktopNativeWidgetAura (if possible). Second run doesn't.
RunGetNativeThemeFromDestructor(const Widget::InitParams & in_params,bool is_first_run)1751 bool RunGetNativeThemeFromDestructor(const Widget::InitParams& in_params,
1752                                      bool is_first_run) {
1753   bool needs_second_run = false;
1754   // Destroyed by CloseNow() below.
1755   Widget* widget = new Widget;
1756   Widget::InitParams params(in_params);
1757   // Deletes itself when the Widget is destroyed.
1758   params.delegate = new GetNativeThemeFromDestructorView;
1759 #if !defined(OS_CHROMEOS)
1760   if (is_first_run) {
1761     params.native_widget = new PlatformDesktopNativeWidget(widget);
1762     needs_second_run = true;
1763   }
1764 #endif
1765   widget->Init(params);
1766   widget->CloseNow();
1767   return needs_second_run;
1768 }
1769 
1770 // See description of RunGetNativeThemeFromDestructor() for details.
TEST_F(WidgetTest,GetNativeThemeFromDestructor)1771 TEST_F(WidgetTest, GetNativeThemeFromDestructor) {
1772   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1773   if (RunGetNativeThemeFromDestructor(params, true))
1774     RunGetNativeThemeFromDestructor(params, false);
1775 }
1776 
1777 // Used by HideCloseDestroy. Allows setting a boolean when the widget is
1778 // destroyed.
1779 class CloseDestroysWidget : public Widget {
1780  public:
CloseDestroysWidget(bool * destroyed)1781   explicit CloseDestroysWidget(bool* destroyed)
1782       : destroyed_(destroyed) {
1783   }
1784 
~CloseDestroysWidget()1785   virtual ~CloseDestroysWidget() {
1786     if (destroyed_) {
1787       *destroyed_ = true;
1788       base::MessageLoop::current()->QuitNow();
1789     }
1790   }
1791 
Detach()1792   void Detach() { destroyed_ = NULL; }
1793 
1794  private:
1795   // If non-null set to true from destructor.
1796   bool* destroyed_;
1797 
1798   DISALLOW_COPY_AND_ASSIGN(CloseDestroysWidget);
1799 };
1800 
1801 // An observer that registers that an animation has ended.
1802 class AnimationEndObserver : public ui::ImplicitAnimationObserver {
1803  public:
AnimationEndObserver()1804   AnimationEndObserver() : animation_completed_(false) {}
~AnimationEndObserver()1805   virtual ~AnimationEndObserver() {}
1806 
animation_completed() const1807   bool animation_completed() const { return animation_completed_; }
1808 
1809   // ui::ImplicitAnimationObserver:
OnImplicitAnimationsCompleted()1810   virtual void OnImplicitAnimationsCompleted() OVERRIDE {
1811     animation_completed_ = true;
1812   }
1813 
1814  private:
1815   bool animation_completed_;
1816 
1817   DISALLOW_COPY_AND_ASSIGN(AnimationEndObserver);
1818 };
1819 
1820 // An observer that registers the bounds of a widget on destruction.
1821 class WidgetBoundsObserver : public WidgetObserver {
1822  public:
WidgetBoundsObserver()1823   WidgetBoundsObserver() {}
~WidgetBoundsObserver()1824   virtual ~WidgetBoundsObserver() {}
1825 
bounds()1826   gfx::Rect bounds() { return bounds_; }
1827 
1828   // WidgetObserver:
OnWidgetDestroying(Widget * widget)1829   virtual void OnWidgetDestroying(Widget* widget) OVERRIDE {
1830     bounds_ = widget->GetWindowBoundsInScreen();
1831   }
1832 
1833  private:
1834   gfx::Rect bounds_;
1835 
1836   DISALLOW_COPY_AND_ASSIGN(WidgetBoundsObserver);
1837 };
1838 
1839 // Verifies Close() results in destroying.
TEST_F(WidgetTest,CloseDestroys)1840 TEST_F(WidgetTest, CloseDestroys) {
1841   bool destroyed = false;
1842   CloseDestroysWidget* widget = new CloseDestroysWidget(&destroyed);
1843   Widget::InitParams params =
1844       CreateParams(views::Widget::InitParams::TYPE_MENU);
1845   params.opacity = Widget::InitParams::OPAQUE_WINDOW;
1846 #if !defined(OS_CHROMEOS)
1847   params.native_widget = new PlatformDesktopNativeWidget(widget);
1848 #endif
1849   widget->Init(params);
1850   widget->Show();
1851   widget->Hide();
1852   widget->Close();
1853   EXPECT_FALSE(destroyed);
1854   // Run the message loop as Close() asynchronously deletes.
1855   base::RunLoop().Run();
1856   EXPECT_TRUE(destroyed);
1857   // Close() should destroy the widget. If not we'll cleanup to avoid leaks.
1858   if (!destroyed) {
1859     widget->Detach();
1860     widget->CloseNow();
1861   }
1862 }
1863 
1864 // Tests that killing a widget while animating it does not crash.
TEST_F(WidgetTest,CloseWidgetWhileAnimating)1865 TEST_F(WidgetTest, CloseWidgetWhileAnimating) {
1866   scoped_ptr<Widget> widget(new Widget);
1867   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1868   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1869   params.bounds = gfx::Rect(50, 50, 250, 250);
1870   widget->Init(params);
1871   AnimationEndObserver animation_observer;
1872   WidgetBoundsObserver widget_observer;
1873   gfx::Rect bounds(0, 0, 50, 50);
1874   {
1875     // Normal animations for tests have ZERO_DURATION, make sure we are actually
1876     // animating the movement.
1877     ui::ScopedAnimationDurationScaleMode animation_scale_mode(
1878         ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1879     ui::ScopedLayerAnimationSettings animation_settings(
1880         widget->GetLayer()->GetAnimator());
1881     animation_settings.AddObserver(&animation_observer);
1882     widget->AddObserver(&widget_observer);
1883     widget->Show();
1884 
1885     // Animate the bounds change.
1886     widget->SetBounds(bounds);
1887     widget.reset();
1888     EXPECT_FALSE(animation_observer.animation_completed());
1889   }
1890   EXPECT_TRUE(animation_observer.animation_completed());
1891   EXPECT_EQ(widget_observer.bounds(), bounds);
1892 }
1893 
1894 // A view that consumes mouse-pressed event and gesture-tap-down events.
1895 class RootViewTestView : public View {
1896  public:
RootViewTestView()1897   RootViewTestView(): View() {}
1898 
1899  private:
OnMousePressed(const ui::MouseEvent & event)1900   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
1901     return true;
1902   }
1903 
OnGestureEvent(ui::GestureEvent * event)1904   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
1905     if (event->type() == ui::ET_GESTURE_TAP_DOWN)
1906       event->SetHandled();
1907   }
1908 };
1909 
1910 // Checks if RootView::*_handler_ fields are unset when widget is hidden.
1911 // Fails on chromium.webkit Windows bot, see crbug.com/264872.
1912 #if defined(OS_WIN)
1913 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
1914     DISABLED_TestRootViewHandlersWhenHidden
1915 #else
1916 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
1917     TestRootViewHandlersWhenHidden
1918 #endif
TEST_F(WidgetTest,MAYBE_DisableTestRootViewHandlersWhenHidden)1919 TEST_F(WidgetTest, MAYBE_DisableTestRootViewHandlersWhenHidden) {
1920   Widget* widget = CreateTopLevelNativeWidget();
1921   widget->SetBounds(gfx::Rect(0, 0, 300, 300));
1922   View* view = new RootViewTestView();
1923   view->SetBounds(0, 0, 300, 300);
1924   internal::RootView* root_view =
1925       static_cast<internal::RootView*>(widget->GetRootView());
1926   root_view->AddChildView(view);
1927 
1928   // Check RootView::mouse_pressed_handler_.
1929   widget->Show();
1930   EXPECT_EQ(NULL, GetMousePressedHandler(root_view));
1931   gfx::Point click_location(45, 15);
1932   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
1933                        ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
1934   widget->OnMouseEvent(&press);
1935   EXPECT_EQ(view, GetMousePressedHandler(root_view));
1936   widget->Hide();
1937   EXPECT_EQ(NULL, GetMousePressedHandler(root_view));
1938 
1939   // Check RootView::mouse_move_handler_.
1940   widget->Show();
1941   EXPECT_EQ(NULL, GetMouseMoveHandler(root_view));
1942   gfx::Point move_location(45, 15);
1943   ui::MouseEvent move(ui::ET_MOUSE_MOVED, move_location, move_location, 0, 0);
1944   widget->OnMouseEvent(&move);
1945   EXPECT_EQ(view, GetMouseMoveHandler(root_view));
1946   widget->Hide();
1947   EXPECT_EQ(NULL, GetMouseMoveHandler(root_view));
1948 
1949   // Check RootView::gesture_handler_.
1950   widget->Show();
1951   EXPECT_EQ(NULL, GetGestureHandler(root_view));
1952   ui::GestureEvent tap_down(15,
1953                             15,
1954                             0,
1955                             base::TimeDelta(),
1956                             ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
1957   widget->OnGestureEvent(&tap_down);
1958   EXPECT_EQ(view, GetGestureHandler(root_view));
1959   widget->Hide();
1960   EXPECT_EQ(NULL, GetGestureHandler(root_view));
1961 
1962   widget->Close();
1963 }
1964 
1965 // Convenience to make constructing a GestureEvent simpler.
1966 class GestureEventForTest : public ui::GestureEvent {
1967  public:
GestureEventForTest(ui::EventType type,int x,int y)1968   GestureEventForTest(ui::EventType type, int x, int y)
1969       : GestureEvent(x,
1970                      y,
1971                      0,
1972                      base::TimeDelta(),
1973                      ui::GestureEventDetails(type)) {}
1974 
GestureEventForTest(ui::GestureEventDetails details,int x,int y)1975   GestureEventForTest(ui::GestureEventDetails details, int x, int y)
1976       : GestureEvent(x, y, 0, base::TimeDelta(), details) {}
1977 };
1978 
1979 // Tests that the |gesture_handler_| member in RootView is always NULL
1980 // after the dispatch of a ui::ET_GESTURE_END event corresponding to
1981 // the release of the final touch point on the screen and that
1982 // ui::ET_GESTURE_END events corresponding to the removal of any other touch
1983 // point are never dispatched to a view. Also verifies that
1984 // ui::ET_GESTURE_BEGIN is never dispatched to a view and does not change the
1985 // value of |gesture_handler_|.
TEST_F(WidgetTest,GestureBeginAndEndEvents)1986 TEST_F(WidgetTest, GestureBeginAndEndEvents) {
1987   Widget* widget = CreateTopLevelNativeWidget();
1988   widget->SetBounds(gfx::Rect(0, 0, 300, 300));
1989   EventCountView* view = new EventCountView();
1990   view->SetBounds(0, 0, 300, 300);
1991   internal::RootView* root_view =
1992       static_cast<internal::RootView*>(widget->GetRootView());
1993   root_view->AddChildView(view);
1994   widget->Show();
1995 
1996   // If no gesture handler is set, dispatching a ui::ET_GESTURE_END or
1997   // ui::ET_GESTURE_BEGIN event should not set the gesture handler and
1998   // the events should remain unhandled because the handle mode of |view|
1999   // indicates that events should not be consumed.
2000   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2001   GestureEventForTest end(ui::ET_GESTURE_END, 15, 15);
2002   widget->OnGestureEvent(&end);
2003   EXPECT_FALSE(end.handled());
2004   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2005 
2006   GestureEventForTest begin(ui::ET_GESTURE_BEGIN, 15, 15);
2007   widget->OnGestureEvent(&begin);
2008   EXPECT_FALSE(begin.handled());
2009   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2010 
2011   // Change the handle mode of |view| to indicate that it would like
2012   // to handle all events.
2013   view->set_handle_mode(EventCountView::CONSUME_EVENTS);
2014 
2015   // If no gesture handler is set, dispatching only a ui::ET_GESTURE_BEGIN
2016   // should not set the gesture handler and should not be marked as handled
2017   // because it is never dispatched.
2018   begin = GestureEventForTest(ui::ET_GESTURE_BEGIN, 15, 15);
2019   widget->OnGestureEvent(&begin);
2020   EXPECT_FALSE(begin.handled());
2021   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2022 
2023   // If no gesture handler is set, dispatching only a ui::ET_GESTURE_BEGIN
2024   // corresponding to a second touch point should not set the gesture handler
2025   // and should not be marked as handled because it is never dispatched.
2026   ui::GestureEventDetails details(ui::ET_GESTURE_END);
2027   details.set_touch_points(2);
2028   GestureEventForTest end_second_touch_point(details, 15, 15);
2029   widget->OnGestureEvent(&end_second_touch_point);
2030   EXPECT_FALSE(end_second_touch_point.handled());
2031   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2032 
2033   // If no gesture handler is set, dispatching only a ui::ET_GESTURE_END
2034   // event corresponding to the final touch point should not set the gesture
2035   // handler. Furthermore, it should not be marked as handled because it was
2036   // not dispatched (GESTURE_END events are only dispatched in cases where
2037   // a gesture handler is already set).
2038   end = GestureEventForTest(ui::ET_GESTURE_END, 15, 15);
2039   widget->OnGestureEvent(&end);
2040   EXPECT_FALSE(end.handled());
2041   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2042 
2043   // If the gesture handler has been set by a previous gesture, then it should
2044   // remain unchanged on a ui::ET_GESTURE_BEGIN or a ui::ET_GESTURE_END
2045   // corresponding to a second touch point. It should be reset to NULL by a
2046   // ui::ET_GESTURE_END corresponding to the final touch point.
2047   GestureEventForTest tap(ui::ET_GESTURE_TAP, 15, 15);
2048   widget->OnGestureEvent(&tap);
2049   EXPECT_TRUE(tap.handled());
2050   EXPECT_EQ(view, GetGestureHandler(root_view));
2051 
2052   begin = GestureEventForTest(ui::ET_GESTURE_BEGIN, 15, 15);
2053   widget->OnGestureEvent(&begin);
2054   EXPECT_FALSE(begin.handled());
2055   EXPECT_EQ(view, GetGestureHandler(root_view));
2056 
2057   end_second_touch_point = GestureEventForTest(details, 15, 15);
2058   widget->OnGestureEvent(&end_second_touch_point);
2059   EXPECT_FALSE(end_second_touch_point.handled());
2060   EXPECT_EQ(view, GetGestureHandler(root_view));
2061 
2062   end = GestureEventForTest(ui::ET_GESTURE_END, 15, 15);
2063   widget->OnGestureEvent(&end);
2064   EXPECT_TRUE(end.handled());
2065   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2066 
2067   // If the gesture handler has been set by a previous gesture, then
2068   // it should remain unchanged on a ui::ET_GESTURE_BEGIN or a
2069   // ui::ET_GESTURE_END corresponding to a second touch point and be reset
2070   // to NULL by a ui::ET_GESTURE_END corresponding to the final touch point,
2071   // even when the gesture handler has indicated that it would not like to
2072   // handle any further events.
2073   tap = GestureEventForTest(ui::ET_GESTURE_TAP, 15, 15);
2074   widget->OnGestureEvent(&tap);
2075   EXPECT_TRUE(tap.handled());
2076   EXPECT_EQ(view, GetGestureHandler(root_view));
2077 
2078   // Change the handle mode of |view| to indicate that it does not want
2079   // to handle any further events.
2080   view->set_handle_mode(EventCountView::PROPAGATE_EVENTS);
2081 
2082   begin = GestureEventForTest(ui::ET_GESTURE_BEGIN, 15, 15);
2083   widget->OnGestureEvent(&begin);
2084   EXPECT_FALSE(begin.handled());
2085   EXPECT_EQ(view, GetGestureHandler(root_view));
2086 
2087   end_second_touch_point = GestureEventForTest(details, 15, 15);
2088   widget->OnGestureEvent(&end_second_touch_point);
2089   EXPECT_FALSE(end_second_touch_point.handled());
2090   EXPECT_EQ(view, GetGestureHandler(root_view));
2091 
2092   end = GestureEventForTest(ui::ET_GESTURE_END, 15, 15);
2093   widget->OnGestureEvent(&end);
2094   EXPECT_FALSE(end.handled());
2095   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2096 
2097   widget->Close();
2098 }
2099 
2100 // Tests that a (non-scroll) gesture event is dispatched to the correct views
2101 // in a view hierarchy and that the default gesture handler in RootView is set
2102 // correctly.
TEST_F(WidgetTest,GestureEventDispatch)2103 TEST_F(WidgetTest, GestureEventDispatch) {
2104   Widget* widget = CreateTopLevelNativeWidget();
2105   widget->SetBounds(gfx::Rect(0, 0, 300, 300));
2106 
2107   // Define a hierarchy of four views (coordinates are in
2108   // their parent coordinate space).
2109   // v1 (0, 0, 300, 300)
2110   //   v2 (0, 0, 100, 100)
2111   //     v3 (0, 0, 50, 50)
2112   //       v4(0, 0, 10, 10)
2113   EventCountView* v1 = new EventCountView();
2114   v1->SetBounds(0, 0, 300, 300);
2115   EventCountView* v2 = new EventCountView();
2116   v2->SetBounds(0, 0, 100, 100);
2117   EventCountView* v3 = new EventCountView();
2118   v3->SetBounds(0, 0, 50, 50);
2119   EventCountView* v4 = new EventCountView();
2120   v4->SetBounds(0, 0, 10, 10);
2121   internal::RootView* root_view =
2122       static_cast<internal::RootView*>(widget->GetRootView());
2123   root_view->AddChildView(v1);
2124   v1->AddChildView(v2);
2125   v2->AddChildView(v3);
2126   v3->AddChildView(v4);
2127 
2128   widget->Show();
2129 
2130   // No gesture handler is set in the root view and none of the views in the
2131   // view hierarchy handle a ui::ET_GESTURE_TAP event. In this case the tap
2132   // event should be dispatched to all views in the hierarchy, the gesture
2133   // handler should remain unset, and the event should remain unhandled.
2134   GestureEventForTest tap(ui::ET_GESTURE_TAP, 5, 5);
2135   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2136   widget->OnGestureEvent(&tap);
2137   EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_TAP));
2138   EXPECT_EQ(1, v2->GetEventCount(ui::ET_GESTURE_TAP));
2139   EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP));
2140   EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
2141   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2142   EXPECT_FALSE(tap.handled());
2143 
2144   // No gesture handler is set in the root view and |v1|, |v2|, and |v3| all
2145   // handle a ui::ET_GESTURE_TAP event. In this case the tap event should be
2146   // dispatched to |v4| and |v3|, the gesture handler should be set to |v3|,
2147   // and the event should be marked as handled.
2148   v1->ResetCounts();
2149   v2->ResetCounts();
2150   v3->ResetCounts();
2151   v4->ResetCounts();
2152   v1->set_handle_mode(EventCountView::CONSUME_EVENTS);
2153   v2->set_handle_mode(EventCountView::CONSUME_EVENTS);
2154   v3->set_handle_mode(EventCountView::CONSUME_EVENTS);
2155   tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
2156   widget->OnGestureEvent(&tap);
2157   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
2158   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
2159   EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP));
2160   EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
2161   EXPECT_EQ(v3, GetGestureHandler(root_view));
2162   EXPECT_TRUE(tap.handled());
2163 
2164   // The gesture handler is set to |v3| and all views handle all gesture event
2165   // types. In this case subsequent gesture events should only be dispatched to
2166   // |v3| and marked as handled. The gesture handler should remain as |v3|.
2167   v1->ResetCounts();
2168   v2->ResetCounts();
2169   v3->ResetCounts();
2170   v4->ResetCounts();
2171   v4->set_handle_mode(EventCountView::CONSUME_EVENTS);
2172   tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
2173   widget->OnGestureEvent(&tap);
2174   EXPECT_TRUE(tap.handled());
2175   GestureEventForTest show_press(ui::ET_GESTURE_SHOW_PRESS, 5, 5);
2176   widget->OnGestureEvent(&show_press);
2177   tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
2178   widget->OnGestureEvent(&tap);
2179   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
2180   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
2181   EXPECT_EQ(2, v3->GetEventCount(ui::ET_GESTURE_TAP));
2182   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_TAP));
2183   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_SHOW_PRESS));
2184   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_SHOW_PRESS));
2185   EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_SHOW_PRESS));
2186   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SHOW_PRESS));
2187   EXPECT_TRUE(tap.handled());
2188   EXPECT_TRUE(show_press.handled());
2189   EXPECT_EQ(v3, GetGestureHandler(root_view));
2190 
2191   // The gesture handler is set to |v3|, but |v3| does not handle
2192   // ui::ET_GESTURE_TAP events. In this case a tap gesture should be dispatched
2193   // only to |v3|, but the event should remain unhandled. The gesture handler
2194   // should remain as |v3|.
2195   v1->ResetCounts();
2196   v2->ResetCounts();
2197   v3->ResetCounts();
2198   v4->ResetCounts();
2199   v3->set_handle_mode(EventCountView::PROPAGATE_EVENTS);
2200   tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
2201   widget->OnGestureEvent(&tap);
2202   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
2203   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
2204   EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP));
2205   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_TAP));
2206   EXPECT_FALSE(tap.handled());
2207   EXPECT_EQ(v3, GetGestureHandler(root_view));
2208 
2209   widget->Close();
2210 }
2211 
2212 // Tests that gesture scroll events will change the default gesture handler in
2213 // RootView if the current handler to which they are dispatched does not handle
2214 // gesture scroll events.
TEST_F(WidgetTest,ScrollGestureEventDispatch)2215 TEST_F(WidgetTest, ScrollGestureEventDispatch) {
2216   Widget* widget = CreateTopLevelNativeWidget();
2217   widget->SetBounds(gfx::Rect(0, 0, 300, 300));
2218 
2219   // Define a hierarchy of four views (coordinates are in
2220   // their parent coordinate space).
2221   // v1 (0, 0, 300, 300)
2222   //   v2 (0, 0, 100, 100)
2223   //     v3 (0, 0, 50, 50)
2224   //       v4(0, 0, 10, 10)
2225   EventCountView* v1 = new EventCountView();
2226   v1->SetBounds(0, 0, 300, 300);
2227   EventCountView* v2 = new EventCountView();
2228   v2->SetBounds(0, 0, 100, 100);
2229   EventCountView* v3 = new EventCountView();
2230   v3->SetBounds(0, 0, 50, 50);
2231   EventCountView* v4 = new EventCountView();
2232   v4->SetBounds(0, 0, 10, 10);
2233   internal::RootView* root_view =
2234       static_cast<internal::RootView*>(widget->GetRootView());
2235   root_view->AddChildView(v1);
2236   v1->AddChildView(v2);
2237   v2->AddChildView(v3);
2238   v3->AddChildView(v4);
2239 
2240   widget->Show();
2241 
2242   // Change the handle mode of |v3| to indicate that it would like to handle
2243   // gesture events.
2244   v3->set_handle_mode(EventCountView::CONSUME_EVENTS);
2245 
2246   // When no gesture handler is set, dispatching a ui::ET_GESTURE_TAP_DOWN
2247   // should bubble up the views hierarchy until it reaches the first view
2248   // that will handle it (|v3|) and then sets the handler to |v3|.
2249   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2250   GestureEventForTest tap_down(ui::ET_GESTURE_TAP_DOWN, 5, 5);
2251   widget->OnGestureEvent(&tap_down);
2252   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
2253   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
2254   EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
2255   EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP_DOWN));
2256   EXPECT_EQ(v3, GetGestureHandler(root_view));
2257   EXPECT_TRUE(tap_down.handled());
2258   v1->ResetCounts();
2259   v2->ResetCounts();
2260   v3->ResetCounts();
2261   v4->ResetCounts();
2262 
2263   // A ui::ET_GESTURE_TAP_CANCEL event should be dispatched to |v3| directly.
2264   GestureEventForTest tap_cancel(ui::ET_GESTURE_TAP_CANCEL, 5, 5);
2265   widget->OnGestureEvent(&tap_cancel);
2266   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
2267   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
2268   EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
2269   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_TAP_CANCEL));
2270   EXPECT_EQ(v3, GetGestureHandler(root_view));
2271   EXPECT_TRUE(tap_cancel.handled());
2272   v1->ResetCounts();
2273   v2->ResetCounts();
2274   v3->ResetCounts();
2275   v4->ResetCounts();
2276 
2277   // Change the handle mode of |v3| to indicate that it would no longer like
2278   // to handle events, and change the mode of |v1| to indicate that it would
2279   // like to handle events.
2280   v3->set_handle_mode(EventCountView::PROPAGATE_EVENTS);
2281   v1->set_handle_mode(EventCountView::CONSUME_EVENTS);
2282 
2283   // Dispatch a ui::ET_GESTURE_SCROLL_BEGIN event. Because the current gesture
2284   // handler (|v3|) does not handle scroll events, the event should bubble up
2285   // the views hierarchy until it reaches the first view that will handle
2286   // it (|v1|) and then sets the handler to |v1|.
2287   GestureEventForTest scroll_begin(ui::ET_GESTURE_SCROLL_BEGIN, 5, 5);
2288   widget->OnGestureEvent(&scroll_begin);
2289   EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
2290   EXPECT_EQ(1, v2->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
2291   EXPECT_EQ(1, v3->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
2292   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
2293   EXPECT_EQ(v1, GetGestureHandler(root_view));
2294   EXPECT_TRUE(scroll_begin.handled());
2295   v1->ResetCounts();
2296   v2->ResetCounts();
2297   v3->ResetCounts();
2298   v4->ResetCounts();
2299 
2300   // A ui::ET_GESTURE_SCROLL_UPDATE event should be dispatched to |v1|
2301   // directly.
2302   GestureEventForTest scroll_update(ui::ET_GESTURE_SCROLL_UPDATE, 5, 5);
2303   widget->OnGestureEvent(&scroll_update);
2304   EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
2305   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
2306   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
2307   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
2308   EXPECT_EQ(v1, GetGestureHandler(root_view));
2309   EXPECT_TRUE(scroll_update.handled());
2310   v1->ResetCounts();
2311   v2->ResetCounts();
2312   v3->ResetCounts();
2313   v4->ResetCounts();
2314 
2315   // A ui::ET_GESTURE_SCROLL_END event should be dispatched to |v1|
2316   // directly and should not reset the gesture handler.
2317   GestureEventForTest scroll_end(ui::ET_GESTURE_SCROLL_END, 5, 5);
2318   widget->OnGestureEvent(&scroll_end);
2319   EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_SCROLL_END));
2320   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_SCROLL_END));
2321   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_SCROLL_END));
2322   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_SCROLL_END));
2323   EXPECT_EQ(v1, GetGestureHandler(root_view));
2324   EXPECT_TRUE(scroll_end.handled());
2325   v1->ResetCounts();
2326   v2->ResetCounts();
2327   v3->ResetCounts();
2328   v4->ResetCounts();
2329 
2330   // A ui::ET_GESTURE_PINCH_BEGIN event (which is a non-scroll event) should
2331   // still be dispatched to |v1| directly.
2332   GestureEventForTest pinch_begin(ui::ET_GESTURE_PINCH_BEGIN, 5, 5);
2333   widget->OnGestureEvent(&pinch_begin);
2334   EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN));
2335   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN));
2336   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN));
2337   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_PINCH_BEGIN));
2338   EXPECT_EQ(v1, GetGestureHandler(root_view));
2339   EXPECT_TRUE(pinch_begin.handled());
2340   v1->ResetCounts();
2341   v2->ResetCounts();
2342   v3->ResetCounts();
2343   v4->ResetCounts();
2344 
2345   // A ui::ET_GESTURE_END event should be dispatched to |v1| and should
2346   // set the gesture handler to NULL.
2347   GestureEventForTest end(ui::ET_GESTURE_END, 5, 5);
2348   widget->OnGestureEvent(&end);
2349   EXPECT_EQ(1, v1->GetEventCount(ui::ET_GESTURE_END));
2350   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
2351   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
2352   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
2353   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2354   EXPECT_TRUE(end.handled());
2355 
2356   widget->Close();
2357 }
2358 
2359 // A class used in WidgetTest.GestureEventLocationWhileBubbling to verify
2360 // that when a gesture event bubbles up a View hierarchy, the location
2361 // of a gesture event seen by each View is in the local coordinate space
2362 // of that View.
2363 class GestureLocationView : public EventCountView {
2364  public:
GestureLocationView()2365   GestureLocationView() {}
~GestureLocationView()2366   virtual ~GestureLocationView() {}
2367 
set_expected_location(gfx::Point expected_location)2368   void set_expected_location(gfx::Point expected_location) {
2369     expected_location_ = expected_location;
2370   }
2371 
2372   // EventCountView:
OnGestureEvent(ui::GestureEvent * event)2373   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
2374     EventCountView::OnGestureEvent(event);
2375 
2376     // Verify that the location of |event| is in the local coordinate
2377     // space of |this|.
2378     EXPECT_EQ(expected_location_, event->location());
2379   }
2380 
2381  private:
2382   // The expected location of a gesture event dispatched to |this|.
2383   gfx::Point expected_location_;
2384 
2385   DISALLOW_COPY_AND_ASSIGN(GestureLocationView);
2386 };
2387 
2388 // Verifies that the location of a gesture event is always in the local
2389 // coordinate space of the View receiving the event while bubbling.
TEST_F(WidgetTest,GestureEventLocationWhileBubbling)2390 TEST_F(WidgetTest, GestureEventLocationWhileBubbling) {
2391   Widget* widget = CreateTopLevelNativeWidget();
2392   widget->SetBounds(gfx::Rect(0, 0, 300, 300));
2393 
2394   // Define a hierarchy of three views (coordinates shown below are in the
2395   // coordinate space of the root view, but the coordinates used for
2396   // SetBounds() are in their parent coordinate space).
2397   // v1 (50, 50, 150, 150)
2398   //   v2 (100, 70, 50, 80)
2399   //     v3 (120, 100, 10, 10)
2400   GestureLocationView* v1 = new GestureLocationView();
2401   v1->SetBounds(50, 50, 150, 150);
2402   GestureLocationView* v2 = new GestureLocationView();
2403   v2->SetBounds(50, 20, 50, 80);
2404   GestureLocationView* v3 = new GestureLocationView();
2405   v3->SetBounds(20, 30, 10, 10);
2406   internal::RootView* root_view =
2407       static_cast<internal::RootView*>(widget->GetRootView());
2408   root_view->AddChildView(v1);
2409   v1->AddChildView(v2);
2410   v2->AddChildView(v3);
2411 
2412   widget->Show();
2413 
2414   // Define a GESTURE_TAP event located at (125, 105) in root view coordinates.
2415   // This event is contained within all of |v1|, |v2|, and |v3|.
2416   gfx::Point location_in_root(125, 105);
2417   GestureEventForTest tap(
2418       ui::ET_GESTURE_TAP, location_in_root.x(), location_in_root.y());
2419 
2420   // Calculate the location of the event in the local coordinate spaces
2421   // of each of the views.
2422   gfx::Point location_in_v1(ConvertPointFromWidgetToView(v1, location_in_root));
2423   EXPECT_EQ(gfx::Point(75, 55), location_in_v1);
2424   gfx::Point location_in_v2(ConvertPointFromWidgetToView(v2, location_in_root));
2425   EXPECT_EQ(gfx::Point(25, 35), location_in_v2);
2426   gfx::Point location_in_v3(ConvertPointFromWidgetToView(v3, location_in_root));
2427   EXPECT_EQ(gfx::Point(5, 5), location_in_v3);
2428 
2429   // Dispatch the event. When each view receives the event, its location should
2430   // be in the local coordinate space of that view (see the check made by
2431   // GestureLocationView). After dispatch is complete the event's location
2432   // should be in the root coordinate space.
2433   v1->set_expected_location(location_in_v1);
2434   v2->set_expected_location(location_in_v2);
2435   v3->set_expected_location(location_in_v3);
2436   widget->OnGestureEvent(&tap);
2437   EXPECT_EQ(location_in_root, tap.location());
2438 
2439   // Verify that each view did in fact see the event.
2440   EventCountView* view1 = v1;
2441   EventCountView* view2 = v2;
2442   EventCountView* view3 = v3;
2443   EXPECT_EQ(1, view1->GetEventCount(ui::ET_GESTURE_TAP));
2444   EXPECT_EQ(1, view2->GetEventCount(ui::ET_GESTURE_TAP));
2445   EXPECT_EQ(1, view3->GetEventCount(ui::ET_GESTURE_TAP));
2446 
2447   widget->Close();
2448 }
2449 
2450 // Verifies that disabled views are permitted to be set as the default gesture
2451 // handler in RootView. Also verifies that gesture events targeted to a disabled
2452 // view are not actually dispatched to the view, but are still marked as
2453 // handled.
TEST_F(WidgetTest,DisabledGestureEventTarget)2454 TEST_F(WidgetTest, DisabledGestureEventTarget) {
2455   Widget* widget = CreateTopLevelNativeWidget();
2456   widget->SetBounds(gfx::Rect(0, 0, 300, 300));
2457 
2458   // Define a hierarchy of four views (coordinates are in
2459   // their parent coordinate space).
2460   // v1 (0, 0, 300, 300)
2461   //   v2 (0, 0, 100, 100)
2462   //     v3 (0, 0, 50, 50)
2463   //       v4(0, 0, 10, 10)
2464   EventCountView* v1 = new EventCountView();
2465   v1->SetBounds(0, 0, 300, 300);
2466   EventCountView* v2 = new EventCountView();
2467   v2->SetBounds(0, 0, 100, 100);
2468   EventCountView* v3 = new EventCountView();
2469   v3->SetBounds(0, 0, 50, 50);
2470   EventCountView* v4 = new EventCountView();
2471   v4->SetBounds(0, 0, 10, 10);
2472   internal::RootView* root_view =
2473       static_cast<internal::RootView*>(widget->GetRootView());
2474   root_view->AddChildView(v1);
2475   v1->AddChildView(v2);
2476   v2->AddChildView(v3);
2477   v3->AddChildView(v4);
2478 
2479   widget->Show();
2480 
2481   // |v1|, |v2|, and |v3| all handle gesture events but |v3| is marked as
2482   // disabled.
2483   v1->set_handle_mode(EventCountView::CONSUME_EVENTS);
2484   v2->set_handle_mode(EventCountView::CONSUME_EVENTS);
2485   v3->set_handle_mode(EventCountView::CONSUME_EVENTS);
2486   v3->SetEnabled(false);
2487 
2488   // No gesture handler is set in the root view, so it should remain unset
2489   // after a GESTURE_END. GESTURE_END events are not dispatched unless
2490   // a gesture handler is already set in the root view, so none of the
2491   // views should see this event and it should not be marked as handled.
2492   GestureEventForTest end(ui::ET_GESTURE_END, 5, 5);
2493   widget->OnGestureEvent(&end);
2494   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_END));
2495   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
2496   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
2497   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
2498   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2499   EXPECT_FALSE(end.handled());
2500   v1->ResetCounts();
2501   v2->ResetCounts();
2502   v3->ResetCounts();
2503   v4->ResetCounts();
2504 
2505   // No gesture handler is set in the root view. In this case the tap event
2506   // should be dispatched only to |v4|, the gesture handler should be set to
2507   // |v3|, and the event should be marked as handled.
2508   GestureEventForTest tap(ui::ET_GESTURE_TAP, 5, 5);
2509   widget->OnGestureEvent(&tap);
2510   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
2511   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
2512   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_TAP));
2513   EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
2514   EXPECT_EQ(v3, GetGestureHandler(root_view));
2515   EXPECT_TRUE(tap.handled());
2516   v1->ResetCounts();
2517   v2->ResetCounts();
2518   v3->ResetCounts();
2519   v4->ResetCounts();
2520 
2521   // A subsequent gesture event should be marked as handled but not dispatched.
2522   tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
2523   widget->OnGestureEvent(&tap);
2524   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
2525   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
2526   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_TAP));
2527   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_TAP));
2528   EXPECT_EQ(v3, GetGestureHandler(root_view));
2529   EXPECT_TRUE(tap.handled());
2530   v1->ResetCounts();
2531   v2->ResetCounts();
2532   v3->ResetCounts();
2533   v4->ResetCounts();
2534 
2535   // A GESTURE_END should reset the default gesture handler to NULL. It should
2536   // also not be dispatched to |v3| but still marked as handled.
2537   end = GestureEventForTest(ui::ET_GESTURE_END, 5, 5);
2538   widget->OnGestureEvent(&end);
2539   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_END));
2540   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
2541   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
2542   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
2543   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2544   EXPECT_TRUE(end.handled());
2545   v1->ResetCounts();
2546   v2->ResetCounts();
2547   v3->ResetCounts();
2548   v4->ResetCounts();
2549 
2550   // Change the handle mode of |v3| to indicate that it would no longer like
2551   // to handle events which are dispatched to it.
2552   v3->set_handle_mode(EventCountView::PROPAGATE_EVENTS);
2553 
2554   // No gesture handler is set in the root view. In this case the tap event
2555   // should be dispatched only to |v4| and the event should be marked as
2556   // handled. Furthermore, the gesture handler should be set to
2557   // |v3|; even though |v3| does not explicitly handle events, it is a
2558   // valid target for the tap event because it is disabled.
2559   tap = GestureEventForTest(ui::ET_GESTURE_TAP, 5, 5);
2560   widget->OnGestureEvent(&tap);
2561   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_TAP));
2562   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_TAP));
2563   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_TAP));
2564   EXPECT_EQ(1, v4->GetEventCount(ui::ET_GESTURE_TAP));
2565   EXPECT_EQ(v3, GetGestureHandler(root_view));
2566   EXPECT_TRUE(tap.handled());
2567   v1->ResetCounts();
2568   v2->ResetCounts();
2569   v3->ResetCounts();
2570   v4->ResetCounts();
2571 
2572   // A GESTURE_END should reset the default gesture handler to NULL. It should
2573   // also not be dispatched to |v3| but still marked as handled.
2574   end = GestureEventForTest(ui::ET_GESTURE_END, 5, 5);
2575   widget->OnGestureEvent(&end);
2576   EXPECT_EQ(0, v1->GetEventCount(ui::ET_GESTURE_END));
2577   EXPECT_EQ(0, v2->GetEventCount(ui::ET_GESTURE_END));
2578   EXPECT_EQ(0, v3->GetEventCount(ui::ET_GESTURE_END));
2579   EXPECT_EQ(0, v4->GetEventCount(ui::ET_GESTURE_END));
2580   EXPECT_EQ(NULL, GetGestureHandler(root_view));
2581   EXPECT_TRUE(end.handled());
2582 
2583   widget->Close();
2584 }
2585 
2586 // Test the result of Widget::GetAllChildWidgets().
TEST_F(WidgetTest,GetAllChildWidgets)2587 TEST_F(WidgetTest, GetAllChildWidgets) {
2588   // Create the following widget hierarchy:
2589   //
2590   // toplevel
2591   // +-- w1
2592   //     +-- w11
2593   // +-- w2
2594   //     +-- w21
2595   //     +-- w22
2596   Widget* toplevel = CreateTopLevelPlatformWidget();
2597   Widget* w1 = CreateChildPlatformWidget(toplevel->GetNativeView());
2598   Widget* w11 = CreateChildPlatformWidget(w1->GetNativeView());
2599   Widget* w2 = CreateChildPlatformWidget(toplevel->GetNativeView());
2600   Widget* w21 = CreateChildPlatformWidget(w2->GetNativeView());
2601   Widget* w22 = CreateChildPlatformWidget(w2->GetNativeView());
2602 
2603   std::set<Widget*> expected;
2604   expected.insert(toplevel);
2605   expected.insert(w1);
2606   expected.insert(w11);
2607   expected.insert(w2);
2608   expected.insert(w21);
2609   expected.insert(w22);
2610 
2611   std::set<Widget*> widgets;
2612   Widget::GetAllChildWidgets(toplevel->GetNativeView(), &widgets);
2613 
2614   EXPECT_EQ(expected.size(), widgets.size());
2615   EXPECT_TRUE(std::equal(expected.begin(), expected.end(), widgets.begin()));
2616 }
2617 
2618 // Used by DestroyChildWidgetsInOrder. On destruction adds the supplied name to
2619 // a vector.
2620 class DestroyedTrackingView : public View {
2621  public:
DestroyedTrackingView(const std::string & name,std::vector<std::string> * add_to)2622   DestroyedTrackingView(const std::string& name,
2623                         std::vector<std::string>* add_to)
2624       : name_(name),
2625         add_to_(add_to) {
2626   }
2627 
~DestroyedTrackingView()2628   virtual ~DestroyedTrackingView() {
2629     add_to_->push_back(name_);
2630   }
2631 
2632  private:
2633   const std::string name_;
2634   std::vector<std::string>* add_to_;
2635 
2636   DISALLOW_COPY_AND_ASSIGN(DestroyedTrackingView);
2637 };
2638 
2639 class WidgetChildDestructionTest : public WidgetTest {
2640  public:
WidgetChildDestructionTest()2641   WidgetChildDestructionTest() {}
2642 
2643   // Creates a top level and a child, destroys the child and verifies the views
2644   // of the child are destroyed before the views of the parent.
RunDestroyChildWidgetsTest(bool top_level_has_desktop_native_widget_aura,bool child_has_desktop_native_widget_aura)2645   void RunDestroyChildWidgetsTest(bool top_level_has_desktop_native_widget_aura,
2646                                   bool child_has_desktop_native_widget_aura) {
2647     // When a View is destroyed its name is added here.
2648     std::vector<std::string> destroyed;
2649 
2650     Widget* top_level = new Widget;
2651     Widget::InitParams params =
2652         CreateParams(views::Widget::InitParams::TYPE_WINDOW);
2653 #if !defined(OS_CHROMEOS)
2654     if (top_level_has_desktop_native_widget_aura)
2655       params.native_widget = new PlatformDesktopNativeWidget(top_level);
2656 #endif
2657     top_level->Init(params);
2658     top_level->GetRootView()->AddChildView(
2659         new DestroyedTrackingView("parent", &destroyed));
2660     top_level->Show();
2661 
2662     Widget* child = new Widget;
2663     Widget::InitParams child_params =
2664         CreateParams(views::Widget::InitParams::TYPE_POPUP);
2665     child_params.parent = top_level->GetNativeView();
2666 #if !defined(OS_CHROMEOS)
2667     if (child_has_desktop_native_widget_aura)
2668       child_params.native_widget = new PlatformDesktopNativeWidget(child);
2669 #endif
2670     child->Init(child_params);
2671     child->GetRootView()->AddChildView(
2672         new DestroyedTrackingView("child", &destroyed));
2673     child->Show();
2674 
2675     // Should trigger destruction of the child too.
2676     top_level->native_widget_private()->CloseNow();
2677 
2678     // Child should be destroyed first.
2679     ASSERT_EQ(2u, destroyed.size());
2680     EXPECT_EQ("child", destroyed[0]);
2681     EXPECT_EQ("parent", destroyed[1]);
2682   }
2683 
2684  private:
2685   DISALLOW_COPY_AND_ASSIGN(WidgetChildDestructionTest);
2686 };
2687 
2688 #if !defined(OS_CHROMEOS)
2689 // See description of RunDestroyChildWidgetsTest(). Parent uses
2690 // DesktopNativeWidgetAura.
TEST_F(WidgetChildDestructionTest,DestroyChildWidgetsInOrderWithDesktopNativeWidget)2691 TEST_F(WidgetChildDestructionTest,
2692        DestroyChildWidgetsInOrderWithDesktopNativeWidget) {
2693   RunDestroyChildWidgetsTest(true, false);
2694 }
2695 
2696 // See description of RunDestroyChildWidgetsTest(). Both parent and child use
2697 // DesktopNativeWidgetAura.
TEST_F(WidgetChildDestructionTest,DestroyChildWidgetsInOrderWithDesktopNativeWidgetForBoth)2698 TEST_F(WidgetChildDestructionTest,
2699        DestroyChildWidgetsInOrderWithDesktopNativeWidgetForBoth) {
2700   RunDestroyChildWidgetsTest(true, true);
2701 }
2702 #endif  // !defined(OS_CHROMEOS)
2703 
2704 // See description of RunDestroyChildWidgetsTest().
TEST_F(WidgetChildDestructionTest,DestroyChildWidgetsInOrder)2705 TEST_F(WidgetChildDestructionTest, DestroyChildWidgetsInOrder) {
2706   RunDestroyChildWidgetsTest(false, false);
2707 }
2708 
2709 #if !defined(OS_CHROMEOS)
2710 // Provides functionality to create a window modal dialog.
2711 class ModalDialogDelegate : public DialogDelegateView {
2712  public:
ModalDialogDelegate()2713   ModalDialogDelegate() {}
~ModalDialogDelegate()2714   virtual ~ModalDialogDelegate() {}
2715 
2716   // WidgetDelegate overrides.
GetModalType() const2717   virtual ui::ModalType GetModalType() const OVERRIDE {
2718     return ui::MODAL_TYPE_WINDOW;
2719   }
2720 
2721  private:
2722   DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate);
2723 };
2724 
2725 // This test verifies that whether mouse events when a modal dialog is
2726 // displayed are eaten or recieved by the dialog.
TEST_F(WidgetTest,WindowMouseModalityTest)2727 TEST_F(WidgetTest, WindowMouseModalityTest) {
2728   // Create a top level widget.
2729   Widget top_level_widget;
2730   Widget::InitParams init_params =
2731       CreateParams(Widget::InitParams::TYPE_WINDOW);
2732   init_params.show_state = ui::SHOW_STATE_NORMAL;
2733   gfx::Rect initial_bounds(0, 0, 500, 500);
2734   init_params.bounds = initial_bounds;
2735   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2736   init_params.native_widget =
2737       new PlatformDesktopNativeWidget(&top_level_widget);
2738   top_level_widget.Init(init_params);
2739   top_level_widget.Show();
2740   EXPECT_TRUE(top_level_widget.IsVisible());
2741 
2742   // Create a view and validate that a mouse moves makes it to the view.
2743   EventCountView* widget_view = new EventCountView();
2744   widget_view->SetBounds(0, 0, 10, 10);
2745   top_level_widget.GetRootView()->AddChildView(widget_view);
2746 
2747   gfx::Point cursor_location_main(5, 5);
2748   ui::MouseEvent move_main(ui::ET_MOUSE_MOVED,
2749                            cursor_location_main,
2750                            cursor_location_main,
2751                            ui::EF_NONE,
2752                            ui::EF_NONE);
2753   ui::EventDispatchDetails details =
2754       GetEventProcessor(&top_level_widget)->OnEventFromSource(&move_main);
2755   ASSERT_FALSE(details.dispatcher_destroyed);
2756 
2757   EXPECT_EQ(1, widget_view->GetEventCount(ui::ET_MOUSE_ENTERED));
2758   widget_view->ResetCounts();
2759 
2760   // Create a modal dialog and validate that a mouse down message makes it to
2761   // the main view within the dialog.
2762 
2763   // This instance will be destroyed when the dialog is destroyed.
2764   ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
2765 
2766   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
2767       dialog_delegate, NULL, top_level_widget.GetNativeView());
2768   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
2769   EventCountView* dialog_widget_view = new EventCountView();
2770   dialog_widget_view->SetBounds(0, 0, 50, 50);
2771   modal_dialog_widget->GetRootView()->AddChildView(dialog_widget_view);
2772   modal_dialog_widget->Show();
2773   EXPECT_TRUE(modal_dialog_widget->IsVisible());
2774 
2775   gfx::Point cursor_location_dialog(100, 100);
2776   ui::MouseEvent mouse_down_dialog(ui::ET_MOUSE_PRESSED,
2777                                    cursor_location_dialog,
2778                                    cursor_location_dialog,
2779                                    ui::EF_NONE,
2780                                    ui::EF_NONE);
2781   details = GetEventProcessor(&top_level_widget)->OnEventFromSource(
2782       &mouse_down_dialog);
2783   ASSERT_FALSE(details.dispatcher_destroyed);
2784   EXPECT_EQ(1, dialog_widget_view->GetEventCount(ui::ET_MOUSE_PRESSED));
2785 
2786   // Send a mouse move message to the main window. It should not be received by
2787   // the main window as the modal dialog is still active.
2788   gfx::Point cursor_location_main2(6, 6);
2789   ui::MouseEvent mouse_down_main(ui::ET_MOUSE_MOVED,
2790                                  cursor_location_main2,
2791                                  cursor_location_main2,
2792                                  ui::EF_NONE,
2793                                  ui::EF_NONE);
2794   details = GetEventProcessor(&top_level_widget)->OnEventFromSource(
2795       &mouse_down_main);
2796   ASSERT_FALSE(details.dispatcher_destroyed);
2797   EXPECT_EQ(0, widget_view->GetEventCount(ui::ET_MOUSE_MOVED));
2798 
2799   modal_dialog_widget->CloseNow();
2800   top_level_widget.CloseNow();
2801 }
2802 
2803 // Verifies nativeview visbility matches that of Widget visibility when
2804 // SetFullscreen is invoked.
TEST_F(WidgetTest,FullscreenStatePropagated)2805 TEST_F(WidgetTest, FullscreenStatePropagated) {
2806   Widget::InitParams init_params =
2807       CreateParams(Widget::InitParams::TYPE_WINDOW);
2808   init_params.show_state = ui::SHOW_STATE_NORMAL;
2809   init_params.bounds = gfx::Rect(0, 0, 500, 500);
2810   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2811 
2812   {
2813     Widget top_level_widget;
2814     top_level_widget.Init(init_params);
2815     top_level_widget.SetFullscreen(true);
2816     EXPECT_EQ(top_level_widget.IsVisible(),
2817               IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
2818     top_level_widget.CloseNow();
2819   }
2820 #if !defined(OS_CHROMEOS)
2821   {
2822     Widget top_level_widget;
2823     init_params.native_widget =
2824         new PlatformDesktopNativeWidget(&top_level_widget);
2825     top_level_widget.Init(init_params);
2826     top_level_widget.SetFullscreen(true);
2827     EXPECT_EQ(top_level_widget.IsVisible(),
2828               IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
2829     top_level_widget.CloseNow();
2830   }
2831 #endif
2832 }
2833 #if defined(OS_WIN)
2834 
2835 // Provides functionality to test widget activation via an activation flag
2836 // which can be set by an accessor.
2837 class ModalWindowTestWidgetDelegate : public WidgetDelegate {
2838  public:
ModalWindowTestWidgetDelegate()2839   ModalWindowTestWidgetDelegate()
2840       : widget_(NULL),
2841         can_activate_(true) {}
2842 
~ModalWindowTestWidgetDelegate()2843   virtual ~ModalWindowTestWidgetDelegate() {}
2844 
2845   // Overridden from WidgetDelegate:
DeleteDelegate()2846   virtual void DeleteDelegate() OVERRIDE {
2847     delete this;
2848   }
GetWidget()2849   virtual Widget* GetWidget() OVERRIDE {
2850     return widget_;
2851   }
GetWidget() const2852   virtual const Widget* GetWidget() const OVERRIDE {
2853     return widget_;
2854   }
CanActivate() const2855   virtual bool CanActivate() const OVERRIDE {
2856     return can_activate_;
2857   }
ShouldAdvanceFocusToTopLevelWidget() const2858   virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE {
2859     return true;
2860   }
2861 
set_can_activate(bool can_activate)2862   void set_can_activate(bool can_activate) {
2863     can_activate_ = can_activate;
2864   }
2865 
set_widget(Widget * widget)2866   void set_widget(Widget* widget) {
2867     widget_ = widget;
2868   }
2869 
2870  private:
2871   Widget* widget_;
2872   bool can_activate_;
2873 
2874   DISALLOW_COPY_AND_ASSIGN(ModalWindowTestWidgetDelegate);
2875 };
2876 
2877 // Tests whether we can activate the top level widget when a modal dialog is
2878 // active.
TEST_F(WidgetTest,WindowModalityActivationTest)2879 TEST_F(WidgetTest, WindowModalityActivationTest) {
2880   // Destroyed when the top level widget created below is destroyed.
2881   ModalWindowTestWidgetDelegate* widget_delegate =
2882       new ModalWindowTestWidgetDelegate;
2883   // Create a top level widget.
2884   Widget top_level_widget;
2885   Widget::InitParams init_params =
2886       CreateParams(Widget::InitParams::TYPE_WINDOW);
2887   init_params.show_state = ui::SHOW_STATE_NORMAL;
2888   gfx::Rect initial_bounds(0, 0, 500, 500);
2889   init_params.bounds = initial_bounds;
2890   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2891   init_params.native_widget = new DesktopNativeWidgetAura(&top_level_widget);
2892   init_params.delegate = widget_delegate;
2893   top_level_widget.Init(init_params);
2894   widget_delegate->set_widget(&top_level_widget);
2895   top_level_widget.Show();
2896   EXPECT_TRUE(top_level_widget.IsVisible());
2897 
2898   HWND win32_window = views::HWNDForWidget(&top_level_widget);
2899   EXPECT_TRUE(::IsWindow(win32_window));
2900 
2901   // This instance will be destroyed when the dialog is destroyed.
2902   ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
2903 
2904   // We should be able to activate the window even if the WidgetDelegate
2905   // says no, when a modal dialog is active.
2906   widget_delegate->set_can_activate(false);
2907 
2908   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
2909       dialog_delegate, NULL, top_level_widget.GetNativeWindow());
2910   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
2911   modal_dialog_widget->Show();
2912   EXPECT_TRUE(modal_dialog_widget->IsVisible());
2913 
2914   LRESULT activate_result = ::SendMessage(
2915       win32_window,
2916       WM_MOUSEACTIVATE,
2917       reinterpret_cast<WPARAM>(win32_window),
2918       MAKELPARAM(WM_LBUTTONDOWN, HTCLIENT));
2919   EXPECT_EQ(activate_result, MA_ACTIVATE);
2920 
2921   modal_dialog_widget->CloseNow();
2922   top_level_widget.CloseNow();
2923 }
2924 #endif  // defined(OS_WIN)
2925 #endif  // !defined(OS_CHROMEOS)
2926 
TEST_F(WidgetTest,ShowCreatesActiveWindow)2927 TEST_F(WidgetTest, ShowCreatesActiveWindow) {
2928   Widget* widget = CreateTopLevelPlatformWidget();
2929 
2930   widget->Show();
2931   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
2932 
2933   widget->CloseNow();
2934 }
2935 
2936 // OSX does not have a per-application "active" window such as provided by
2937 // ::GetActiveWindow() on Windows. There is only a system-wide "keyWindow" which
2938 // is updated asynchronously.
2939 #if defined(OS_MACOSX)
2940 #define MAYBE_ShowInactive DISABLED_ShowInactive
2941 #else
2942 #define MAYBE_ShowInactive ShowInactive
2943 #endif
TEST_F(WidgetTest,MAYBE_ShowInactive)2944 TEST_F(WidgetTest, MAYBE_ShowInactive) {
2945   Widget* widget = CreateTopLevelPlatformWidget();
2946 
2947   widget->ShowInactive();
2948   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_INACTIVE);
2949 
2950   widget->CloseNow();
2951 }
2952 
TEST_F(WidgetTest,InactiveBeforeShow)2953 TEST_F(WidgetTest, InactiveBeforeShow) {
2954   Widget* widget = CreateTopLevelPlatformWidget();
2955 
2956   EXPECT_FALSE(widget->IsActive());
2957   EXPECT_FALSE(widget->IsVisible());
2958 
2959   widget->Show();
2960 
2961   EXPECT_TRUE(widget->IsActive());
2962   EXPECT_TRUE(widget->IsVisible());
2963 
2964   widget->CloseNow();
2965 }
2966 
TEST_F(WidgetTest,ShowInactiveAfterShow)2967 TEST_F(WidgetTest, ShowInactiveAfterShow) {
2968   // Create 2 widgets to ensure window layering does not change.
2969   Widget* widget = CreateTopLevelPlatformWidget();
2970   Widget* widget2 = CreateTopLevelPlatformWidget();
2971 
2972   widget2->Show();
2973   EXPECT_FALSE(widget->IsActive());
2974   EXPECT_TRUE(widget2->IsVisible());
2975   EXPECT_TRUE(widget2->IsActive());
2976 
2977   widget->Show();
2978   EXPECT_TRUE(widget->IsActive());
2979   EXPECT_FALSE(widget2->IsActive());
2980   widget->ShowInactive();
2981   EXPECT_TRUE(widget->IsActive());
2982   EXPECT_FALSE(widget2->IsActive());
2983   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
2984 
2985   widget2->CloseNow();
2986   widget->CloseNow();
2987 }
2988 
TEST_F(WidgetTest,ShowAfterShowInactive)2989 TEST_F(WidgetTest, ShowAfterShowInactive) {
2990   Widget* widget = CreateTopLevelPlatformWidget();
2991 
2992   widget->ShowInactive();
2993   widget->Show();
2994   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
2995 
2996   widget->CloseNow();
2997 }
2998 
2999 #if !defined(OS_CHROMEOS)
TEST_F(WidgetTest,InactiveWidgetDoesNotGrabActivation)3000 TEST_F(WidgetTest, InactiveWidgetDoesNotGrabActivation) {
3001   Widget* widget = CreateTopLevelPlatformWidget();
3002   widget->Show();
3003   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
3004 
3005   Widget widget2;
3006   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
3007   params.native_widget = new PlatformDesktopNativeWidget(&widget2);
3008   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3009   widget2.Init(params);
3010   widget2.Show();
3011 
3012   EXPECT_EQ(GetWidgetShowState(&widget2), ui::SHOW_STATE_INACTIVE);
3013   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
3014 
3015   widget->CloseNow();
3016   widget2.CloseNow();
3017 }
3018 #endif  // !defined(OS_CHROMEOS)
3019 
3020 namespace {
3021 
3022 class FullscreenAwareFrame : public views::NonClientFrameView {
3023  public:
FullscreenAwareFrame(views::Widget * widget)3024   explicit FullscreenAwareFrame(views::Widget* widget)
3025       : widget_(widget), fullscreen_layout_called_(false) {}
~FullscreenAwareFrame()3026   virtual ~FullscreenAwareFrame() {}
3027 
3028   // views::NonClientFrameView overrides:
GetBoundsForClientView() const3029   virtual gfx::Rect GetBoundsForClientView() const OVERRIDE {
3030     return gfx::Rect();
3031   }
GetWindowBoundsForClientBounds(const gfx::Rect & client_bounds) const3032   virtual gfx::Rect GetWindowBoundsForClientBounds(
3033       const gfx::Rect& client_bounds) const OVERRIDE {
3034     return gfx::Rect();
3035   }
NonClientHitTest(const gfx::Point & point)3036   virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
3037     return HTNOWHERE;
3038   }
GetWindowMask(const gfx::Size & size,gfx::Path * window_mask)3039   virtual void GetWindowMask(const gfx::Size& size,
3040                              gfx::Path* window_mask) OVERRIDE {}
ResetWindowControls()3041   virtual void ResetWindowControls() OVERRIDE {}
UpdateWindowIcon()3042   virtual void UpdateWindowIcon() OVERRIDE {}
UpdateWindowTitle()3043   virtual void UpdateWindowTitle() OVERRIDE {}
SizeConstraintsChanged()3044   virtual void SizeConstraintsChanged() OVERRIDE {}
3045 
3046   // views::View overrides:
Layout()3047   virtual void Layout() OVERRIDE {
3048     if (widget_->IsFullscreen())
3049       fullscreen_layout_called_ = true;
3050   }
3051 
fullscreen_layout_called() const3052   bool fullscreen_layout_called() const { return fullscreen_layout_called_; }
3053 
3054  private:
3055   views::Widget* widget_;
3056   bool fullscreen_layout_called_;
3057 
3058   DISALLOW_COPY_AND_ASSIGN(FullscreenAwareFrame);
3059 };
3060 
3061 }  // namespace
3062 
3063 // Tests that frame Layout is called when a widget goes fullscreen without
3064 // changing its size or title.
TEST_F(WidgetTest,FullscreenFrameLayout)3065 TEST_F(WidgetTest, FullscreenFrameLayout) {
3066   Widget* widget = CreateTopLevelPlatformWidget();
3067   FullscreenAwareFrame* frame = new FullscreenAwareFrame(widget);
3068   widget->non_client_view()->SetFrameView(frame);  // Owns |frame|.
3069 
3070   widget->Maximize();
3071   RunPendingMessages();
3072 
3073   EXPECT_FALSE(frame->fullscreen_layout_called());
3074   widget->SetFullscreen(true);
3075   widget->Show();
3076   RunPendingMessages();
3077   EXPECT_TRUE(frame->fullscreen_layout_called());
3078 
3079   widget->CloseNow();
3080 }
3081 
3082 #if !defined(OS_CHROMEOS)
3083 namespace {
3084 
3085 // Trivial WidgetObserverTest that invokes Widget::IsActive() from
3086 // OnWindowDestroying.
3087 class IsActiveFromDestroyObserver : public WidgetObserver {
3088  public:
IsActiveFromDestroyObserver()3089   IsActiveFromDestroyObserver() {}
~IsActiveFromDestroyObserver()3090   virtual ~IsActiveFromDestroyObserver() {}
OnWidgetDestroying(Widget * widget)3091   virtual void OnWidgetDestroying(Widget* widget) OVERRIDE {
3092     widget->IsActive();
3093   }
3094 
3095  private:
3096   DISALLOW_COPY_AND_ASSIGN(IsActiveFromDestroyObserver);
3097 };
3098 
3099 }  // namespace
3100 
3101 // Verifies Widget::IsActive() invoked from
3102 // WidgetObserver::OnWidgetDestroying() in a child widget doesn't crash.
TEST_F(WidgetTest,IsActiveFromDestroy)3103 TEST_F(WidgetTest, IsActiveFromDestroy) {
3104   // Create two widgets, one a child of the other.
3105   IsActiveFromDestroyObserver observer;
3106   Widget parent_widget;
3107   Widget::InitParams parent_params =
3108       CreateParams(Widget::InitParams::TYPE_POPUP);
3109   parent_params.native_widget = new PlatformDesktopNativeWidget(&parent_widget);
3110   parent_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3111   parent_widget.Init(parent_params);
3112   parent_widget.Show();
3113 
3114   Widget child_widget;
3115   Widget::InitParams child_params =
3116       CreateParams(Widget::InitParams::TYPE_POPUP);
3117   child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3118   child_params.context = parent_widget.GetNativeWindow();
3119   child_widget.Init(child_params);
3120   child_widget.AddObserver(&observer);
3121   child_widget.Show();
3122 
3123   parent_widget.CloseNow();
3124 }
3125 #endif  // !defined(OS_CHROMEOS)
3126 
3127 // Tests that events propagate through from the dispatcher with the correct
3128 // event type, and that the different platforms behave the same.
TEST_F(WidgetTest,MouseEventTypesViaGenerator)3129 TEST_F(WidgetTest, MouseEventTypesViaGenerator) {
3130   EventCountView* view = new EventCountView;
3131   view->set_handle_mode(EventCountView::CONSUME_EVENTS);
3132   view->SetBounds(10, 10, 50, 40);
3133 
3134   Widget* widget = CreateTopLevelFramelessPlatformWidget();
3135   widget->GetRootView()->AddChildView(view);
3136 
3137   widget->SetBounds(gfx::Rect(0, 0, 100, 80));
3138   widget->Show();
3139 
3140   ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
3141   generator.set_current_location(gfx::Point(20, 20));
3142 
3143   generator.ClickLeftButton();
3144   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_PRESSED));
3145   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_RELEASED));
3146   EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, view->last_flags());
3147 
3148   generator.PressRightButton();
3149   EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_PRESSED));
3150   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_RELEASED));
3151   EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, view->last_flags());
3152 
3153   generator.ReleaseRightButton();
3154   EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_PRESSED));
3155   EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_RELEASED));
3156   EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, view->last_flags());
3157 
3158   // Test mouse move events.
3159   EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSE_MOVED));
3160   EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSE_ENTERED));
3161 
3162   // Move the mouse within the view (20, 20) -> (30, 30).
3163   generator.MoveMouseTo(gfx::Point(30, 30));
3164   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_MOVED));
3165   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_ENTERED));
3166   EXPECT_EQ(ui::EF_NONE, view->last_flags());
3167 
3168   // Move it again - entered count shouldn't change.
3169   generator.MoveMouseTo(gfx::Point(31, 31));
3170   EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_MOVED));
3171   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_ENTERED));
3172   EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSE_EXITED));
3173 
3174   // Move it off the view.
3175   generator.MoveMouseTo(gfx::Point(5, 5));
3176   EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_MOVED));
3177   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_ENTERED));
3178   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_EXITED));
3179 
3180   // Move it back on.
3181   generator.MoveMouseTo(gfx::Point(20, 20));
3182   EXPECT_EQ(3, view->GetEventCount(ui::ET_MOUSE_MOVED));
3183   EXPECT_EQ(2, view->GetEventCount(ui::ET_MOUSE_ENTERED));
3184   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_EXITED));
3185 
3186   // Drargging. Cover HasCapture() and NativeWidgetPrivate::IsMouseButtonDown().
3187   generator.DragMouseTo(gfx::Point(40, 40));
3188   EXPECT_EQ(3, view->GetEventCount(ui::ET_MOUSE_PRESSED));
3189   EXPECT_EQ(3, view->GetEventCount(ui::ET_MOUSE_RELEASED));
3190   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSE_DRAGGED));
3191   EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, view->last_flags());
3192 
3193   widget->CloseNow();
3194 }
3195 
3196 // Tests that the root view is correctly set up for Widget types that do not
3197 // require a non-client view, before any other views are added to the widget.
3198 // That is, before Widget::ReorderNativeViews() is called which, if called with
3199 // a root view not set, could cause the root view to get resized to the widget.
TEST_F(WidgetTest,NonClientWindowValidAfterInit)3200 TEST_F(WidgetTest, NonClientWindowValidAfterInit) {
3201   Widget* widget = CreateTopLevelFramelessPlatformWidget();
3202   View* root_view = widget->GetRootView();
3203 
3204   // Size the root view to exceed the widget bounds.
3205   const gfx::Rect test_rect(0, 0, 500, 500);
3206   root_view->SetBoundsRect(test_rect);
3207 
3208   EXPECT_NE(test_rect.size(), widget->GetWindowBoundsInScreen().size());
3209 
3210   EXPECT_EQ(test_rect, root_view->bounds());
3211   widget->ReorderNativeViews();
3212   EXPECT_EQ(test_rect, root_view->bounds());
3213 
3214   widget->CloseNow();
3215 }
3216 
3217 }  // namespace test
3218 }  // namespace views
3219