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
39namespace views {
40namespace test {
41
42namespace {
43
44// TODO(tdanderson): This utility function is used in different unittest
45//                   files. Move to a common location to avoid
46//                   repeated code.
47gfx::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.
56class 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
66  EventCountView()
67      : last_flags_(0),
68        handle_mode_(PROPAGATE_EVENTS) {}
69
70  virtual ~EventCountView() {}
71
72  int GetEventCount(ui::EventType type) {
73    return event_count_[type];
74  }
75
76  void ResetCounts() {
77    event_count_.clear();
78  }
79
80  int last_flags() const {
81    return last_flags_;
82  }
83
84  void set_handle_mode(HandleMode handle_mode) {
85    handle_mode_ = handle_mode;
86  }
87
88 protected:
89  // Overridden from View:
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:
97  virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
98    RecordEvent(event);
99  }
100  virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
101    RecordEvent(event);
102  }
103  virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
104    RecordEvent(event);
105  }
106  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
107    RecordEvent(event);
108  }
109
110 private:
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.
127class ScrollableEventCountView : public EventCountView {
128 public:
129  ScrollableEventCountView() {}
130  virtual ~ScrollableEventCountView() {}
131
132 private:
133  // Overridden from ui::EventHandler:
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
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.
158class MinimumSizeFrameView : public NativeFrameView {
159 public:
160  explicit MinimumSizeFrameView(Widget* frame): NativeFrameView(frame) {}
161  virtual ~MinimumSizeFrameView() {}
162
163 private:
164  // Overridden from View:
165  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.
174class EventCountHandler : public ui::EventHandler {
175 public:
176  EventCountHandler() {}
177  virtual ~EventCountHandler() {}
178
179  int GetEventCount(ui::EventType type) {
180    return event_count_[type];
181  }
182
183  void ResetCounts() {
184    event_count_.clear();
185  }
186
187 protected:
188  // Overridden from ui::EventHandler:
189  virtual void OnEvent(ui::Event* event) OVERRIDE {
190    RecordEvent(*event);
191    ui::EventHandler::OnEvent(event);
192  }
193
194 private:
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.
206class CloseWidgetView : public View {
207 public:
208  explicit CloseWidgetView(ui::EventType event_type)
209      : event_type_(event_type) {
210  }
211
212  // ui::EventHandler override:
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
231ui::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
241TEST_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
250TEST_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.
265TEST_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.
292TEST_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.
321class WidgetOwnershipTest : public WidgetTest {
322 public:
323  WidgetOwnershipTest() {}
324  virtual ~WidgetOwnershipTest() {}
325
326  virtual void SetUp() {
327    WidgetTest::SetUp();
328    desktop_widget_ = CreateTopLevelPlatformWidget();
329  }
330
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.
343struct OwnershipTestState {
344  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.
352class OwnershipTestNativeWidget : public PlatformNativeWidget {
353 public:
354  OwnershipTestNativeWidget(internal::NativeWidgetDelegate* delegate,
355                            OwnershipTestState* state)
356      : PlatformNativeWidget(delegate),
357        state_(state) {
358  }
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.
371class OwnershipTestNativeWidgetAura : public NativeWidgetCapture {
372 public:
373  OwnershipTestNativeWidgetAura(internal::NativeWidgetDelegate* delegate,
374                                OwnershipTestState* state)
375      : NativeWidgetCapture(delegate),
376        state_(state) {
377  }
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.
389class OwnershipTestWidget : public Widget {
390 public:
391  explicit OwnershipTestWidget(OwnershipTestState* state) : state_(state) {}
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.
404TEST_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.
425TEST_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.
447TEST_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.
480TEST_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.
497TEST_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.
522TEST_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.
541TEST_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.
567TEST_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.
593TEST_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//
619class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
620 public:
621  WidgetWithDestroyedNativeViewTest() {}
622  virtual ~WidgetWithDestroyedNativeViewTest() {}
623
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
677TEST_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
707class WidgetObserverTest : public WidgetTest, public WidgetObserver {
708 public:
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
718  virtual ~WidgetObserverTest() {}
719
720  // Overridden from WidgetObserver:
721  virtual void OnWidgetDestroying(Widget* widget) OVERRIDE {
722    if (active_ == widget)
723      active_ = NULL;
724    widget_closed_ = widget;
725  }
726
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
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
749  virtual void OnWidgetBoundsChanged(Widget* widget,
750                                     const gfx::Rect& new_bounds) OVERRIDE {
751    widget_bounds_changed_ = widget;
752  }
753
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
764  Widget* NewWidget() {
765    Widget* widget = CreateTopLevelNativeWidget();
766    widget->AddObserver(this);
767    return widget;
768  }
769
770  const Widget* active() const { return active_; }
771  const Widget* widget_closed() const { return widget_closed_; }
772  const Widget* widget_activated() const { return widget_activated_; }
773  const Widget* widget_deactivated() const { return widget_deactivated_; }
774  const Widget* widget_shown() const { return widget_shown_; }
775  const Widget* widget_hidden() const { return widget_hidden_; }
776  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
789TEST_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
814TEST_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
841TEST_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
855TEST_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.
874TEST_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.
934TEST_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.
961TEST_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.
998TEST_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.
1022TEST_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
1058class TestBubbleDelegateView : public BubbleDelegateView {
1059 public:
1060  TestBubbleDelegateView(View* anchor)
1061      : BubbleDelegateView(anchor, BubbleBorder::NONE),
1062        reset_controls_called_(false) {}
1063  virtual ~TestBubbleDelegateView() {}
1064
1065  virtual bool ShouldShowCloseButton() const OVERRIDE {
1066    reset_controls_called_ = true;
1067    return true;
1068  }
1069
1070  mutable bool reset_controls_called_;
1071};
1072
1073TEST_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.
1091TEST_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.
1113class DesktopAuraTestValidPaintWidget : public views::Widget {
1114 public:
1115  DesktopAuraTestValidPaintWidget()
1116    : expect_paint_(true),
1117      received_paint_while_hidden_(false) {
1118  }
1119
1120  virtual ~DesktopAuraTestValidPaintWidget() {
1121  }
1122
1123  virtual void Show() OVERRIDE {
1124    expect_paint_ = true;
1125    views::Widget::Show();
1126  }
1127
1128  virtual void Close() OVERRIDE {
1129    expect_paint_ = false;
1130    views::Widget::Close();
1131  }
1132
1133  void Hide() {
1134    expect_paint_ = false;
1135    views::Widget::Hide();
1136  }
1137
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
1145  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
1154TEST_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
1174TEST_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.
1197TEST_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|.
1225void 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|.
1258void 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.
1273TEST_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.
1278TEST_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.
1286TEST_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.
1325TEST_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.
1395TEST_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
1514TEST_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
1541namespace {
1542
1543// ui::EventHandler which handles all mouse press events.
1544class MousePressEventConsumer : public ui::EventHandler {
1545 public:
1546  explicit MousePressEventConsumer() {
1547  }
1548
1549  virtual ~MousePressEventConsumer() {
1550  }
1551
1552 private:
1553  // ui::EventHandler:
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.
1566TEST_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.
1590class ClosingDelegate : public WidgetDelegate {
1591 public:
1592  ClosingDelegate() : count_(0), widget_(NULL) {}
1593
1594  int count() const { return count_; }
1595
1596  void set_widget(views::Widget* widget) { widget_ = widget; }
1597
1598  // WidgetDelegate overrides:
1599  virtual Widget* GetWidget() OVERRIDE { return widget_; }
1600  virtual const Widget* GetWidget() const OVERRIDE { return widget_; }
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.
1614TEST_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
1630class WidgetWindowTitleTest : public WidgetTest {
1631 protected:
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
1672TEST_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)
1680TEST_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
1687TEST_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
1707TEST_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.
1728class GetNativeThemeFromDestructorView : public WidgetDelegateView {
1729 public:
1730  GetNativeThemeFromDestructorView() {}
1731  virtual ~GetNativeThemeFromDestructorView() {
1732    VerifyNativeTheme();
1733  }
1734
1735  virtual View* GetContentsView() OVERRIDE {
1736    return this;
1737  }
1738
1739 private:
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.
1751bool 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.
1771TEST_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.
1779class CloseDestroysWidget : public Widget {
1780 public:
1781  explicit CloseDestroysWidget(bool* destroyed)
1782      : destroyed_(destroyed) {
1783  }
1784
1785  virtual ~CloseDestroysWidget() {
1786    if (destroyed_) {
1787      *destroyed_ = true;
1788      base::MessageLoop::current()->QuitNow();
1789    }
1790  }
1791
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.
1802class AnimationEndObserver : public ui::ImplicitAnimationObserver {
1803 public:
1804  AnimationEndObserver() : animation_completed_(false) {}
1805  virtual ~AnimationEndObserver() {}
1806
1807  bool animation_completed() const { return animation_completed_; }
1808
1809  // ui::ImplicitAnimationObserver:
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.
1821class WidgetBoundsObserver : public WidgetObserver {
1822 public:
1823  WidgetBoundsObserver() {}
1824  virtual ~WidgetBoundsObserver() {}
1825
1826  gfx::Rect bounds() { return bounds_; }
1827
1828  // WidgetObserver:
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.
1840TEST_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.
1865TEST_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.
1895class RootViewTestView : public View {
1896 public:
1897  RootViewTestView(): View() {}
1898
1899 private:
1900  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
1901    return true;
1902  }
1903
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
1919TEST_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.
1966class GestureEventForTest : public ui::GestureEvent {
1967 public:
1968  GestureEventForTest(ui::EventType type, int x, int y)
1969      : GestureEvent(x,
1970                     y,
1971                     0,
1972                     base::TimeDelta(),
1973                     ui::GestureEventDetails(type)) {}
1974
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_|.
1986TEST_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.
2103TEST_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.
2215TEST_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.
2363class GestureLocationView : public EventCountView {
2364 public:
2365  GestureLocationView() {}
2366  virtual ~GestureLocationView() {}
2367
2368  void set_expected_location(gfx::Point expected_location) {
2369    expected_location_ = expected_location;
2370  }
2371
2372  // EventCountView:
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.
2390TEST_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.
2454TEST_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().
2587TEST_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.
2620class DestroyedTrackingView : public View {
2621 public:
2622  DestroyedTrackingView(const std::string& name,
2623                        std::vector<std::string>* add_to)
2624      : name_(name),
2625        add_to_(add_to) {
2626  }
2627
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
2639class WidgetChildDestructionTest : public WidgetTest {
2640 public:
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.
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.
2691TEST_F(WidgetChildDestructionTest,
2692       DestroyChildWidgetsInOrderWithDesktopNativeWidget) {
2693  RunDestroyChildWidgetsTest(true, false);
2694}
2695
2696// See description of RunDestroyChildWidgetsTest(). Both parent and child use
2697// DesktopNativeWidgetAura.
2698TEST_F(WidgetChildDestructionTest,
2699       DestroyChildWidgetsInOrderWithDesktopNativeWidgetForBoth) {
2700  RunDestroyChildWidgetsTest(true, true);
2701}
2702#endif  // !defined(OS_CHROMEOS)
2703
2704// See description of RunDestroyChildWidgetsTest().
2705TEST_F(WidgetChildDestructionTest, DestroyChildWidgetsInOrder) {
2706  RunDestroyChildWidgetsTest(false, false);
2707}
2708
2709#if !defined(OS_CHROMEOS)
2710// Provides functionality to create a window modal dialog.
2711class ModalDialogDelegate : public DialogDelegateView {
2712 public:
2713  ModalDialogDelegate() {}
2714  virtual ~ModalDialogDelegate() {}
2715
2716  // WidgetDelegate overrides.
2717  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.
2727TEST_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.
2805TEST_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.
2837class ModalWindowTestWidgetDelegate : public WidgetDelegate {
2838 public:
2839  ModalWindowTestWidgetDelegate()
2840      : widget_(NULL),
2841        can_activate_(true) {}
2842
2843  virtual ~ModalWindowTestWidgetDelegate() {}
2844
2845  // Overridden from WidgetDelegate:
2846  virtual void DeleteDelegate() OVERRIDE {
2847    delete this;
2848  }
2849  virtual Widget* GetWidget() OVERRIDE {
2850    return widget_;
2851  }
2852  virtual const Widget* GetWidget() const OVERRIDE {
2853    return widget_;
2854  }
2855  virtual bool CanActivate() const OVERRIDE {
2856    return can_activate_;
2857  }
2858  virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE {
2859    return true;
2860  }
2861
2862  void set_can_activate(bool can_activate) {
2863    can_activate_ = can_activate;
2864  }
2865
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.
2879TEST_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
2927TEST_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
2944TEST_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
2953TEST_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
2967TEST_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
2989TEST_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)
3000TEST_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
3020namespace {
3021
3022class FullscreenAwareFrame : public views::NonClientFrameView {
3023 public:
3024  explicit FullscreenAwareFrame(views::Widget* widget)
3025      : widget_(widget), fullscreen_layout_called_(false) {}
3026  virtual ~FullscreenAwareFrame() {}
3027
3028  // views::NonClientFrameView overrides:
3029  virtual gfx::Rect GetBoundsForClientView() const OVERRIDE {
3030    return gfx::Rect();
3031  }
3032  virtual gfx::Rect GetWindowBoundsForClientBounds(
3033      const gfx::Rect& client_bounds) const OVERRIDE {
3034    return gfx::Rect();
3035  }
3036  virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
3037    return HTNOWHERE;
3038  }
3039  virtual void GetWindowMask(const gfx::Size& size,
3040                             gfx::Path* window_mask) OVERRIDE {}
3041  virtual void ResetWindowControls() OVERRIDE {}
3042  virtual void UpdateWindowIcon() OVERRIDE {}
3043  virtual void UpdateWindowTitle() OVERRIDE {}
3044  virtual void SizeConstraintsChanged() OVERRIDE {}
3045
3046  // views::View overrides:
3047  virtual void Layout() OVERRIDE {
3048    if (widget_->IsFullscreen())
3049      fullscreen_layout_called_ = true;
3050  }
3051
3052  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.
3065TEST_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)
3083namespace {
3084
3085// Trivial WidgetObserverTest that invokes Widget::IsActive() from
3086// OnWindowDestroying.
3087class IsActiveFromDestroyObserver : public WidgetObserver {
3088 public:
3089  IsActiveFromDestroyObserver() {}
3090  virtual ~IsActiveFromDestroyObserver() {}
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.
3103TEST_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.
3129TEST_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.
3200TEST_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