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