Home | History | Annotate | Download | only in widget
      1 // Copyright (c) 2013 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/command_line.h"
      8 #include "base/path_service.h"
      9 #include "base/run_loop.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "ui/base/resource/resource_bundle.h"
     13 #include "ui/base/ui_base_paths.h"
     14 #include "ui/base/ui_base_switches.h"
     15 #include "ui/events/event_processor.h"
     16 #include "ui/events/test/event_generator.h"
     17 #include "ui/gfx/native_widget_types.h"
     18 #include "ui/gl/gl_surface.h"
     19 #include "ui/views/controls/textfield/textfield.h"
     20 #include "ui/views/controls/textfield/textfield_test_api.h"
     21 #include "ui/views/focus/focus_manager.h"
     22 #include "ui/views/test/focus_manager_test.h"
     23 #include "ui/views/test/widget_test.h"
     24 #include "ui/views/touchui/touch_selection_controller_impl.h"
     25 #include "ui/views/widget/widget.h"
     26 #include "ui/views/window/dialog_delegate.h"
     27 #include "ui/wm/public/activation_client.h"
     28 
     29 #if defined(OS_WIN)
     30 #include "ui/aura/window.h"
     31 #include "ui/aura/window_tree_host.h"
     32 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
     33 #include "ui/views/win/hwnd_util.h"
     34 #endif
     35 
     36 namespace views {
     37 namespace test {
     38 
     39 namespace {
     40 
     41 // A View that closes the Widget and exits the current message-loop when it
     42 // receives a mouse-release event.
     43 class ExitLoopOnRelease : public View {
     44  public:
     45   ExitLoopOnRelease() {}
     46   virtual ~ExitLoopOnRelease() {}
     47 
     48  private:
     49   // Overridden from View:
     50   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE {
     51     GetWidget()->Close();
     52     base::MessageLoop::current()->QuitNow();
     53   }
     54 
     55   DISALLOW_COPY_AND_ASSIGN(ExitLoopOnRelease);
     56 };
     57 
     58 // A view that does a capture on ui::ET_GESTURE_TAP_DOWN events.
     59 class GestureCaptureView : public View {
     60  public:
     61   GestureCaptureView() {}
     62   virtual ~GestureCaptureView() {}
     63 
     64  private:
     65   // Overridden from View:
     66   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
     67     if (event->type() == ui::ET_GESTURE_TAP_DOWN) {
     68       GetWidget()->SetCapture(this);
     69       event->StopPropagation();
     70     }
     71   }
     72 
     73   DISALLOW_COPY_AND_ASSIGN(GestureCaptureView);
     74 };
     75 
     76 // A view that always processes all mouse events.
     77 class MouseView : public View {
     78  public:
     79   MouseView()
     80       : View(),
     81         entered_(0),
     82         exited_(0),
     83         pressed_(0) {
     84   }
     85   virtual ~MouseView() {}
     86 
     87   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
     88     pressed_++;
     89     return true;
     90   }
     91 
     92   virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE {
     93     entered_++;
     94   }
     95 
     96   virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE {
     97     exited_++;
     98   }
     99 
    100   // Return the number of OnMouseEntered calls and reset the counter.
    101   int EnteredCalls() {
    102     int i = entered_;
    103     entered_ = 0;
    104     return i;
    105   }
    106 
    107   // Return the number of OnMouseExited calls and reset the counter.
    108   int ExitedCalls() {
    109     int i = exited_;
    110     exited_ = 0;
    111     return i;
    112   }
    113 
    114   int pressed() const { return pressed_; }
    115 
    116  private:
    117   int entered_;
    118   int exited_;
    119 
    120   int pressed_;
    121 
    122   DISALLOW_COPY_AND_ASSIGN(MouseView);
    123 };
    124 
    125 // A View that shows a different widget, sets capture on that widget, and
    126 // initiates a nested message-loop when it receives a mouse-press event.
    127 class NestedLoopCaptureView : public View {
    128  public:
    129   explicit NestedLoopCaptureView(Widget* widget) : widget_(widget) {}
    130   virtual ~NestedLoopCaptureView() {}
    131 
    132  private:
    133   // Overridden from View:
    134   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
    135     // Start a nested loop.
    136     widget_->Show();
    137     widget_->SetCapture(widget_->GetContentsView());
    138     EXPECT_TRUE(widget_->HasCapture());
    139 
    140     base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
    141     base::MessageLoop::ScopedNestableTaskAllower allow(loop);
    142 
    143     base::RunLoop run_loop;
    144     run_loop.Run();
    145     return true;
    146   }
    147 
    148   Widget* widget_;
    149 
    150   DISALLOW_COPY_AND_ASSIGN(NestedLoopCaptureView);
    151 };
    152 
    153 }  // namespace
    154 
    155 class WidgetTestInteractive : public WidgetTest {
    156  public:
    157   WidgetTestInteractive() {}
    158   virtual ~WidgetTestInteractive() {}
    159 
    160   virtual void SetUp() OVERRIDE {
    161     gfx::GLSurface::InitializeOneOffForTests();
    162     ui::RegisterPathProvider();
    163     base::FilePath ui_test_pak_path;
    164     ASSERT_TRUE(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
    165     ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
    166     WidgetTest::SetUp();
    167   }
    168 
    169  protected:
    170   static void ShowQuickMenuImmediately(
    171       TouchSelectionControllerImpl* controller) {
    172     DCHECK(controller);
    173     if (controller->context_menu_timer_.IsRunning()) {
    174       controller->context_menu_timer_.Stop();
    175 // TODO(tapted): Enable this when porting ui/views/touchui to Mac.
    176 #if !defined(OS_MACOSX)
    177       controller->ContextMenuTimerFired();
    178 #endif
    179     }
    180   }
    181 
    182   static bool IsQuickMenuVisible(TouchSelectionControllerImpl* controller) {
    183     DCHECK(controller);
    184     return controller->context_menu_ && controller->context_menu_->visible();
    185   }
    186 };
    187 
    188 #if defined(OS_WIN)
    189 // Tests whether activation and focus change works correctly in Windows.
    190 // We test the following:-
    191 // 1. If the active aura window is correctly set when a top level widget is
    192 //    created.
    193 // 2. If the active aura window in widget 1 created above, is set to NULL when
    194 //    another top level widget is created and focused.
    195 // 3. On focusing the native platform window for widget 1, the active aura
    196 //    window for widget 1 should be set and that for widget 2 should reset.
    197 // TODO(ananta): Discuss with erg on how to write this test for linux x11 aura.
    198 TEST_F(WidgetTestInteractive, DesktopNativeWidgetAuraActivationAndFocusTest) {
    199   // Create widget 1 and expect the active window to be its window.
    200   View* contents_view1 = new View;
    201   contents_view1->SetFocusable(true);
    202   Widget widget1;
    203   Widget::InitParams init_params =
    204       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    205   init_params.bounds = gfx::Rect(0, 0, 200, 200);
    206   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    207   init_params.native_widget = new DesktopNativeWidgetAura(&widget1);
    208   widget1.Init(init_params);
    209   widget1.SetContentsView(contents_view1);
    210   widget1.Show();
    211   aura::Window* root_window1= widget1.GetNativeView()->GetRootWindow();
    212   contents_view1->RequestFocus();
    213 
    214   EXPECT_TRUE(root_window1 != NULL);
    215   aura::client::ActivationClient* activation_client1 =
    216       aura::client::GetActivationClient(root_window1);
    217   EXPECT_TRUE(activation_client1 != NULL);
    218   EXPECT_EQ(activation_client1->GetActiveWindow(), widget1.GetNativeView());
    219 
    220   // Create widget 2 and expect the active window to be its window.
    221   View* contents_view2 = new View;
    222   Widget widget2;
    223   Widget::InitParams init_params2 =
    224       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    225   init_params2.bounds = gfx::Rect(0, 0, 200, 200);
    226   init_params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    227   init_params2.native_widget = new DesktopNativeWidgetAura(&widget2);
    228   widget2.Init(init_params2);
    229   widget2.SetContentsView(contents_view2);
    230   widget2.Show();
    231   aura::Window* root_window2 = widget2.GetNativeView()->GetRootWindow();
    232   contents_view2->RequestFocus();
    233   ::SetActiveWindow(
    234       root_window2->GetHost()->GetAcceleratedWidget());
    235 
    236   aura::client::ActivationClient* activation_client2 =
    237       aura::client::GetActivationClient(root_window2);
    238   EXPECT_TRUE(activation_client2 != NULL);
    239   EXPECT_EQ(activation_client2->GetActiveWindow(), widget2.GetNativeView());
    240   EXPECT_EQ(activation_client1->GetActiveWindow(),
    241             reinterpret_cast<aura::Window*>(NULL));
    242 
    243   // Now set focus back to widget 1 and expect the active window to be its
    244   // window.
    245   contents_view1->RequestFocus();
    246   ::SetActiveWindow(
    247       root_window1->GetHost()->GetAcceleratedWidget());
    248   EXPECT_EQ(activation_client2->GetActiveWindow(),
    249             reinterpret_cast<aura::Window*>(NULL));
    250   EXPECT_EQ(activation_client1->GetActiveWindow(), widget1.GetNativeView());
    251 }
    252 #endif  // defined(OS_WIN)
    253 
    254 TEST_F(WidgetTestInteractive, CaptureAutoReset) {
    255   Widget* toplevel = CreateTopLevelFramelessPlatformWidget();
    256   View* container = new View;
    257   toplevel->SetContentsView(container);
    258 
    259   EXPECT_FALSE(toplevel->HasCapture());
    260   toplevel->SetCapture(NULL);
    261   EXPECT_TRUE(toplevel->HasCapture());
    262 
    263   // By default, mouse release removes capture.
    264   gfx::Point click_location(45, 15);
    265   ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location,
    266                          ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
    267   toplevel->OnMouseEvent(&release);
    268   EXPECT_FALSE(toplevel->HasCapture());
    269 
    270   // Now a mouse release shouldn't remove capture.
    271   toplevel->set_auto_release_capture(false);
    272   toplevel->SetCapture(NULL);
    273   EXPECT_TRUE(toplevel->HasCapture());
    274   toplevel->OnMouseEvent(&release);
    275   EXPECT_TRUE(toplevel->HasCapture());
    276   toplevel->ReleaseCapture();
    277   EXPECT_FALSE(toplevel->HasCapture());
    278 
    279   toplevel->Close();
    280   RunPendingMessages();
    281 }
    282 
    283 TEST_F(WidgetTestInteractive, ResetCaptureOnGestureEnd) {
    284   Widget* toplevel = CreateTopLevelFramelessPlatformWidget();
    285   View* container = new View;
    286   toplevel->SetContentsView(container);
    287 
    288   View* gesture = new GestureCaptureView;
    289   gesture->SetBounds(0, 0, 30, 30);
    290   container->AddChildView(gesture);
    291 
    292   MouseView* mouse = new MouseView;
    293   mouse->SetBounds(30, 0, 30, 30);
    294   container->AddChildView(mouse);
    295 
    296   toplevel->SetSize(gfx::Size(100, 100));
    297   toplevel->Show();
    298 
    299   // Start a gesture on |gesture|.
    300   ui::GestureEvent tap_down(15,
    301                             15,
    302                             0,
    303                             base::TimeDelta(),
    304                             ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
    305   ui::GestureEvent end(15,
    306                        15,
    307                        0,
    308                        base::TimeDelta(),
    309                        ui::GestureEventDetails(ui::ET_GESTURE_END));
    310   toplevel->OnGestureEvent(&tap_down);
    311 
    312   // Now try to click on |mouse|. Since |gesture| will have capture, |mouse|
    313   // will not receive the event.
    314   gfx::Point click_location(45, 15);
    315 
    316   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
    317                        ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
    318   ui::MouseEvent release(ui::ET_MOUSE_RELEASED, click_location, click_location,
    319                          ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
    320 
    321   EXPECT_TRUE(toplevel->HasCapture());
    322 
    323   toplevel->OnMouseEvent(&press);
    324   toplevel->OnMouseEvent(&release);
    325   EXPECT_EQ(0, mouse->pressed());
    326 
    327   EXPECT_FALSE(toplevel->HasCapture());
    328 
    329   // The end of the gesture should release the capture, and pressing on |mouse|
    330   // should now reach |mouse|.
    331   toplevel->OnGestureEvent(&end);
    332   toplevel->OnMouseEvent(&press);
    333   toplevel->OnMouseEvent(&release);
    334   EXPECT_EQ(1, mouse->pressed());
    335 
    336   toplevel->Close();
    337   RunPendingMessages();
    338 }
    339 
    340 // Checks that if a mouse-press triggers a capture on a different widget (which
    341 // consumes the mouse-release event), then the target of the press does not have
    342 // capture.
    343 TEST_F(WidgetTestInteractive, DisableCaptureWidgetFromMousePress) {
    344   // The test creates two widgets: |first| and |second|.
    345   // The View in |first| makes |second| visible, sets capture on it, and starts
    346   // a nested loop (like a menu does). The View in |second| terminates the
    347   // nested loop and closes the widget.
    348   // The test sends a mouse-press event to |first|, and posts a task to send a
    349   // release event to |second|, to make sure that the release event is
    350   // dispatched after the nested loop starts.
    351 
    352   Widget* first = CreateTopLevelFramelessPlatformWidget();
    353   Widget* second = CreateTopLevelFramelessPlatformWidget();
    354 
    355   View* container = new NestedLoopCaptureView(second);
    356   first->SetContentsView(container);
    357 
    358   second->SetContentsView(new ExitLoopOnRelease());
    359 
    360   first->SetSize(gfx::Size(100, 100));
    361   first->Show();
    362 
    363   gfx::Point location(20, 20);
    364   base::MessageLoop::current()->PostTask(FROM_HERE,
    365       base::Bind(&Widget::OnMouseEvent,
    366                  base::Unretained(second),
    367                  base::Owned(new ui::MouseEvent(ui::ET_MOUSE_RELEASED,
    368                                                 location,
    369                                                 location,
    370                                                 ui::EF_LEFT_MOUSE_BUTTON,
    371                                                 ui::EF_LEFT_MOUSE_BUTTON))));
    372   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, location, location,
    373                        ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
    374   first->OnMouseEvent(&press);
    375   EXPECT_FALSE(first->HasCapture());
    376   first->Close();
    377   RunPendingMessages();
    378 }
    379 
    380 // Tests some grab/ungrab events.
    381 // TODO(estade): can this be enabled now that this is an interactive ui test?
    382 TEST_F(WidgetTestInteractive, DISABLED_GrabUngrab) {
    383   Widget* toplevel = CreateTopLevelPlatformWidget();
    384   Widget* child1 = CreateChildNativeWidgetWithParent(toplevel);
    385   Widget* child2 = CreateChildNativeWidgetWithParent(toplevel);
    386 
    387   toplevel->SetBounds(gfx::Rect(0, 0, 500, 500));
    388 
    389   child1->SetBounds(gfx::Rect(10, 10, 300, 300));
    390   View* view = new MouseView();
    391   view->SetBounds(0, 0, 300, 300);
    392   child1->GetRootView()->AddChildView(view);
    393 
    394   child2->SetBounds(gfx::Rect(200, 10, 200, 200));
    395   view = new MouseView();
    396   view->SetBounds(0, 0, 200, 200);
    397   child2->GetRootView()->AddChildView(view);
    398 
    399   toplevel->Show();
    400   RunPendingMessages();
    401 
    402   // Click on child1
    403   gfx::Point p1(45, 45);
    404   ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1,
    405                          ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
    406   toplevel->OnMouseEvent(&pressed);
    407 
    408   EXPECT_TRUE(toplevel->HasCapture());
    409   EXPECT_TRUE(child1->HasCapture());
    410   EXPECT_FALSE(child2->HasCapture());
    411 
    412   ui::MouseEvent released(ui::ET_MOUSE_RELEASED, p1, p1,
    413                           ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
    414   toplevel->OnMouseEvent(&released);
    415 
    416   EXPECT_FALSE(toplevel->HasCapture());
    417   EXPECT_FALSE(child1->HasCapture());
    418   EXPECT_FALSE(child2->HasCapture());
    419 
    420   RunPendingMessages();
    421 
    422   // Click on child2
    423   gfx::Point p2(315, 45);
    424   ui::MouseEvent pressed2(ui::ET_MOUSE_PRESSED, p2, p2,
    425                           ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
    426   toplevel->OnMouseEvent(&pressed2);
    427   EXPECT_TRUE(pressed2.handled());
    428   EXPECT_TRUE(toplevel->HasCapture());
    429   EXPECT_TRUE(child2->HasCapture());
    430   EXPECT_FALSE(child1->HasCapture());
    431 
    432   ui::MouseEvent released2(ui::ET_MOUSE_RELEASED, p2, p2,
    433                            ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
    434   toplevel->OnMouseEvent(&released2);
    435   EXPECT_FALSE(toplevel->HasCapture());
    436   EXPECT_FALSE(child1->HasCapture());
    437   EXPECT_FALSE(child2->HasCapture());
    438 
    439   toplevel->CloseNow();
    440 }
    441 
    442 // Tests mouse move outside of the window into the "resize controller" and back
    443 // will still generate an OnMouseEntered and OnMouseExited event..
    444 TEST_F(WidgetTestInteractive, CheckResizeControllerEvents) {
    445   Widget* toplevel = CreateTopLevelPlatformWidget();
    446 
    447   toplevel->SetBounds(gfx::Rect(0, 0, 100, 100));
    448 
    449   MouseView* view = new MouseView();
    450   view->SetBounds(90, 90, 10, 10);
    451   toplevel->GetRootView()->AddChildView(view);
    452 
    453   toplevel->Show();
    454   RunPendingMessages();
    455 
    456   // Move to an outside position.
    457   gfx::Point p1(200, 200);
    458   ui::MouseEvent moved_out(ui::ET_MOUSE_MOVED, p1, p1, ui::EF_NONE,
    459                            ui::EF_NONE);
    460   toplevel->OnMouseEvent(&moved_out);
    461   EXPECT_EQ(0, view->EnteredCalls());
    462   EXPECT_EQ(0, view->ExitedCalls());
    463 
    464   // Move onto the active view.
    465   gfx::Point p2(95, 95);
    466   ui::MouseEvent moved_over(ui::ET_MOUSE_MOVED, p2, p2, ui::EF_NONE,
    467                             ui::EF_NONE);
    468   toplevel->OnMouseEvent(&moved_over);
    469   EXPECT_EQ(1, view->EnteredCalls());
    470   EXPECT_EQ(0, view->ExitedCalls());
    471 
    472   // Move onto the outer resizing border.
    473   gfx::Point p3(102, 95);
    474   ui::MouseEvent moved_resizer(ui::ET_MOUSE_MOVED, p3, p3, ui::EF_NONE,
    475                                ui::EF_NONE);
    476   toplevel->OnMouseEvent(&moved_resizer);
    477   EXPECT_EQ(0, view->EnteredCalls());
    478   EXPECT_EQ(1, view->ExitedCalls());
    479 
    480   // Move onto the view again.
    481   toplevel->OnMouseEvent(&moved_over);
    482   EXPECT_EQ(1, view->EnteredCalls());
    483   EXPECT_EQ(0, view->ExitedCalls());
    484 
    485   RunPendingMessages();
    486 
    487   toplevel->CloseNow();
    488 }
    489 
    490 // Test view focus restoration when a widget is deactivated and re-activated.
    491 TEST_F(WidgetTestInteractive, ViewFocusOnWidgetActivationChanges) {
    492   Widget* widget1 = CreateTopLevelPlatformWidget();
    493   View* view1 = new View;
    494   view1->SetFocusable(true);
    495   widget1->GetContentsView()->AddChildView(view1);
    496 
    497   Widget* widget2 = CreateTopLevelPlatformWidget();
    498   View* view2a = new View;
    499   View* view2b = new View;
    500   view2a->SetFocusable(true);
    501   view2b->SetFocusable(true);
    502   widget2->GetContentsView()->AddChildView(view2a);
    503   widget2->GetContentsView()->AddChildView(view2b);
    504 
    505   widget1->Show();
    506   EXPECT_TRUE(widget1->IsActive());
    507   view1->RequestFocus();
    508   EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView());
    509 
    510   widget2->Show();
    511   EXPECT_TRUE(widget2->IsActive());
    512   EXPECT_FALSE(widget1->IsActive());
    513   EXPECT_EQ(NULL, widget1->GetFocusManager()->GetFocusedView());
    514   view2a->RequestFocus();
    515   EXPECT_EQ(view2a, widget2->GetFocusManager()->GetFocusedView());
    516   view2b->RequestFocus();
    517   EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView());
    518 
    519   widget1->Activate();
    520   EXPECT_TRUE(widget1->IsActive());
    521   EXPECT_EQ(view1, widget1->GetFocusManager()->GetFocusedView());
    522   EXPECT_FALSE(widget2->IsActive());
    523   EXPECT_EQ(NULL, widget2->GetFocusManager()->GetFocusedView());
    524 
    525   widget2->Activate();
    526   EXPECT_TRUE(widget2->IsActive());
    527   EXPECT_EQ(view2b, widget2->GetFocusManager()->GetFocusedView());
    528   EXPECT_FALSE(widget1->IsActive());
    529   EXPECT_EQ(NULL, widget1->GetFocusManager()->GetFocusedView());
    530 
    531   widget1->CloseNow();
    532   widget2->CloseNow();
    533 }
    534 
    535 #if defined(OS_WIN)
    536 
    537 // Test view focus retention when a widget's HWND is disabled and re-enabled.
    538 TEST_F(WidgetTestInteractive, ViewFocusOnHWNDEnabledChanges) {
    539   Widget* widget = CreateTopLevelFramelessPlatformWidget();
    540   widget->SetContentsView(new View);
    541   for (size_t i = 0; i < 2; ++i) {
    542     widget->GetContentsView()->AddChildView(new View);
    543     widget->GetContentsView()->child_at(i)->SetFocusable(true);
    544   }
    545 
    546   widget->Show();
    547   const HWND hwnd = HWNDForWidget(widget);
    548   EXPECT_TRUE(::IsWindow(hwnd));
    549   EXPECT_TRUE(::IsWindowEnabled(hwnd));
    550   EXPECT_EQ(hwnd, ::GetActiveWindow());
    551 
    552   for (int i = 0; i < widget->GetContentsView()->child_count(); ++i) {
    553     SCOPED_TRACE(base::StringPrintf("Child view %d", i));
    554     View* view = widget->GetContentsView()->child_at(i);
    555 
    556     view->RequestFocus();
    557     EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
    558     EXPECT_FALSE(::EnableWindow(hwnd, FALSE));
    559     EXPECT_FALSE(::IsWindowEnabled(hwnd));
    560 
    561     // Oddly, disabling the HWND leaves it active with the focus unchanged.
    562     EXPECT_EQ(hwnd, ::GetActiveWindow());
    563     EXPECT_TRUE(widget->IsActive());
    564     EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
    565 
    566     EXPECT_TRUE(::EnableWindow(hwnd, TRUE));
    567     EXPECT_TRUE(::IsWindowEnabled(hwnd));
    568     EXPECT_EQ(hwnd, ::GetActiveWindow());
    569     EXPECT_TRUE(widget->IsActive());
    570     EXPECT_EQ(view, widget->GetFocusManager()->GetFocusedView());
    571   }
    572 
    573   widget->CloseNow();
    574 }
    575 
    576 // This class subclasses the Widget class to listen for activation change
    577 // notifications and provides accessors to return information as to whether
    578 // the widget is active. We need this to ensure that users of the widget
    579 // class activate the widget only when the underlying window becomes really
    580 // active. Previously we would activate the widget in the WM_NCACTIVATE
    581 // message which is incorrect because APIs like FlashWindowEx flash the
    582 // window caption by sending fake WM_NCACTIVATE messages.
    583 class WidgetActivationTest : public Widget {
    584  public:
    585   WidgetActivationTest()
    586       : active_(false) {}
    587 
    588   virtual ~WidgetActivationTest() {}
    589 
    590   virtual void OnNativeWidgetActivationChanged(bool active) OVERRIDE {
    591     active_ = active;
    592   }
    593 
    594   bool active() const { return active_; }
    595 
    596  private:
    597   bool active_;
    598 
    599   DISALLOW_COPY_AND_ASSIGN(WidgetActivationTest);
    600 };
    601 
    602 // Tests whether the widget only becomes active when the underlying window
    603 // is really active.
    604 TEST_F(WidgetTestInteractive, WidgetNotActivatedOnFakeActivationMessages) {
    605   WidgetActivationTest widget1;
    606   Widget::InitParams init_params =
    607       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    608   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    609   init_params.native_widget = new DesktopNativeWidgetAura(&widget1);
    610   init_params.bounds = gfx::Rect(0, 0, 200, 200);
    611   widget1.Init(init_params);
    612   widget1.Show();
    613   EXPECT_EQ(true, widget1.active());
    614 
    615   WidgetActivationTest widget2;
    616   init_params.native_widget = new DesktopNativeWidgetAura(&widget2);
    617   widget2.Init(init_params);
    618   widget2.Show();
    619   EXPECT_EQ(true, widget2.active());
    620   EXPECT_EQ(false, widget1.active());
    621 
    622   HWND win32_native_window1 = HWNDForWidget(&widget1);
    623   EXPECT_TRUE(::IsWindow(win32_native_window1));
    624 
    625   ::SendMessage(win32_native_window1, WM_NCACTIVATE, 1, 0);
    626   EXPECT_EQ(false, widget1.active());
    627   EXPECT_EQ(true, widget2.active());
    628 
    629   ::SetActiveWindow(win32_native_window1);
    630   EXPECT_EQ(true, widget1.active());
    631   EXPECT_EQ(false, widget2.active());
    632 }
    633 #endif  // defined(OS_WIN)
    634 
    635 #if !defined(OS_CHROMEOS)
    636 // Provides functionality to create a window modal dialog.
    637 class ModalDialogDelegate : public DialogDelegateView {
    638  public:
    639   explicit ModalDialogDelegate(ui::ModalType type) : type_(type) {}
    640   virtual ~ModalDialogDelegate() {}
    641 
    642   // WidgetDelegate overrides.
    643   virtual ui::ModalType GetModalType() const OVERRIDE {
    644     return type_;
    645   }
    646 
    647  private:
    648   ui::ModalType type_;
    649 
    650   DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate);
    651 };
    652 
    653 // Tests whether the focused window is set correctly when a modal window is
    654 // created and destroyed. When it is destroyed it should focus the owner window.
    655 TEST_F(WidgetTestInteractive, WindowModalWindowDestroyedActivationTest) {
    656   TestWidgetFocusChangeListener focus_listener;
    657   WidgetFocusManager::GetInstance()->AddFocusChangeListener(&focus_listener);
    658   const std::vector<NativeViewPair>& focus_changes =
    659       focus_listener.focus_changes();
    660 
    661   // Create a top level widget.
    662   Widget top_level_widget;
    663   Widget::InitParams init_params =
    664       CreateParams(Widget::InitParams::TYPE_WINDOW);
    665   init_params.show_state = ui::SHOW_STATE_NORMAL;
    666   gfx::Rect initial_bounds(0, 0, 500, 500);
    667   init_params.bounds = initial_bounds;
    668   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    669   init_params.native_widget =
    670       new PlatformDesktopNativeWidget(&top_level_widget);
    671   top_level_widget.Init(init_params);
    672   top_level_widget.Show();
    673 
    674   gfx::NativeView top_level_native_view = top_level_widget.GetNativeView();
    675   EXPECT_EQ(1u, focus_changes.size());
    676   EXPECT_EQ(NativeViewPair(NULL, top_level_native_view), focus_changes[0]);
    677 
    678   // Create a modal dialog.
    679   // This instance will be destroyed when the dialog is destroyed.
    680   ModalDialogDelegate* dialog_delegate =
    681       new ModalDialogDelegate(ui::MODAL_TYPE_WINDOW);
    682 
    683   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
    684       dialog_delegate, NULL, top_level_widget.GetNativeView());
    685   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
    686   modal_dialog_widget->Show();
    687 
    688   gfx::NativeView modal_native_view = modal_dialog_widget->GetNativeView();
    689   EXPECT_EQ(3u, focus_changes.size());
    690   EXPECT_EQ(NativeViewPair(top_level_native_view, modal_native_view),
    691             focus_changes[1]);
    692   EXPECT_EQ(NativeViewPair(top_level_native_view, modal_native_view),
    693             focus_changes[2]);
    694 
    695   modal_dialog_widget->CloseNow();
    696 
    697   EXPECT_EQ(5u, focus_changes.size());
    698   EXPECT_EQ(NativeViewPair(modal_native_view, top_level_native_view),
    699             focus_changes[3]);
    700   EXPECT_EQ(NativeViewPair(modal_native_view, top_level_native_view),
    701             focus_changes[4]);
    702 
    703   top_level_widget.CloseNow();
    704   WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(&focus_listener);
    705 }
    706 
    707 // Test that when opening a system-modal window, capture is released.
    708 TEST_F(WidgetTestInteractive, SystemModalWindowReleasesCapture) {
    709   TestWidgetFocusChangeListener focus_listener;
    710   WidgetFocusManager::GetInstance()->AddFocusChangeListener(&focus_listener);
    711 
    712   // Create a top level widget.
    713   Widget top_level_widget;
    714   Widget::InitParams init_params =
    715       CreateParams(Widget::InitParams::TYPE_WINDOW);
    716   init_params.show_state = ui::SHOW_STATE_NORMAL;
    717   gfx::Rect initial_bounds(0, 0, 500, 500);
    718   init_params.bounds = initial_bounds;
    719   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    720   init_params.native_widget =
    721       new PlatformDesktopNativeWidget(&top_level_widget);
    722   top_level_widget.Init(init_params);
    723   top_level_widget.Show();
    724 
    725   EXPECT_EQ(top_level_widget.GetNativeView(),
    726             focus_listener.focus_changes().back().second);;
    727 
    728   EXPECT_FALSE(top_level_widget.HasCapture());
    729   top_level_widget.SetCapture(NULL);
    730   EXPECT_TRUE(top_level_widget.HasCapture());
    731 
    732   // Create a modal dialog.
    733   ModalDialogDelegate* dialog_delegate =
    734       new ModalDialogDelegate(ui::MODAL_TYPE_SYSTEM);
    735 
    736   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
    737       dialog_delegate, NULL, top_level_widget.GetNativeView());
    738   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
    739   modal_dialog_widget->Show();
    740 
    741   EXPECT_FALSE(top_level_widget.HasCapture());
    742 
    743   modal_dialog_widget->CloseNow();
    744   top_level_widget.CloseNow();
    745   WidgetFocusManager::GetInstance()->RemoveFocusChangeListener(&focus_listener);
    746 }
    747 
    748 #endif  // !defined(OS_CHROMEOS)
    749 
    750 TEST_F(WidgetTestInteractive, CanActivateFlagIsHonored) {
    751   Widget widget;
    752   Widget::InitParams init_params =
    753       CreateParams(Widget::InitParams::TYPE_WINDOW);
    754   init_params.bounds = gfx::Rect(0, 0, 200, 200);
    755   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    756   init_params.activatable = Widget::InitParams::ACTIVATABLE_NO;
    757 #if !defined(OS_CHROMEOS)
    758   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
    759 #endif  // !defined(OS_CHROMEOS)
    760   widget.Init(init_params);
    761 
    762   widget.Show();
    763   EXPECT_FALSE(widget.IsActive());
    764 }
    765 
    766 // Test that touch selection quick menu is not activated when opened.
    767 TEST_F(WidgetTestInteractive, TouchSelectionQuickMenuIsNotActivated) {
    768   CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableTouchEditing);
    769 #if defined(OS_WIN)
    770   views_delegate().set_use_desktop_native_widgets(true);
    771 #endif  // !defined(OS_WIN)
    772 
    773   Widget widget;
    774   Widget::InitParams init_params =
    775       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    776   init_params.bounds = gfx::Rect(0, 0, 200, 200);
    777   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    778   widget.Init(init_params);
    779 
    780   Textfield* textfield = new Textfield;
    781   textfield->SetBounds(0, 0, 200, 20);
    782   textfield->SetText(base::ASCIIToUTF16("some text"));
    783   widget.GetRootView()->AddChildView(textfield);
    784 
    785   widget.Show();
    786   textfield->RequestFocus();
    787   textfield->SelectAll(true);
    788   TextfieldTestApi textfield_test_api(textfield);
    789 
    790   RunPendingMessages();
    791 
    792   ui::test::EventGenerator generator(widget.GetNativeWindow());
    793   generator.GestureTapAt(gfx::Point(10, 10));
    794   ShowQuickMenuImmediately(static_cast<TouchSelectionControllerImpl*>(
    795       textfield_test_api.touch_selection_controller()));
    796 
    797   EXPECT_TRUE(textfield->HasFocus());
    798   EXPECT_TRUE(widget.IsActive());
    799   EXPECT_TRUE(IsQuickMenuVisible(static_cast<TouchSelectionControllerImpl*>(
    800       textfield_test_api.touch_selection_controller())));
    801 }
    802 
    803 TEST_F(WidgetTestInteractive, DisableViewDoesNotActivateWidget) {
    804 #if defined(OS_WIN)
    805   views_delegate().set_use_desktop_native_widgets(true);
    806 #endif  // !defined(OS_WIN)
    807 
    808   // Create first widget and view, activate the widget, and focus the view.
    809   Widget widget1;
    810   Widget::InitParams params1 = CreateParams(Widget::InitParams::TYPE_POPUP);
    811   params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    812   params1.activatable = Widget::InitParams::ACTIVATABLE_YES;
    813   widget1.Init(params1);
    814 
    815   View* view1 = new View();
    816   view1->SetFocusable(true);
    817   widget1.GetRootView()->AddChildView(view1);
    818 
    819   widget1.Activate();
    820   EXPECT_TRUE(widget1.IsActive());
    821 
    822   FocusManager* focus_manager1 = widget1.GetFocusManager();
    823   ASSERT_TRUE(focus_manager1);
    824   focus_manager1->SetFocusedView(view1);
    825   EXPECT_EQ(view1, focus_manager1->GetFocusedView());
    826 
    827   // Create second widget and view, activate the widget, and focus the view.
    828   Widget widget2;
    829   Widget::InitParams params2 = CreateParams(Widget::InitParams::TYPE_POPUP);
    830   params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    831   params2.activatable = Widget::InitParams::ACTIVATABLE_YES;
    832   widget2.Init(params2);
    833 
    834   View* view2 = new View();
    835   view2->SetFocusable(true);
    836   widget2.GetRootView()->AddChildView(view2);
    837 
    838   widget2.Activate();
    839   EXPECT_TRUE(widget2.IsActive());
    840   EXPECT_FALSE(widget1.IsActive());
    841 
    842   FocusManager* focus_manager2 = widget2.GetFocusManager();
    843   ASSERT_TRUE(focus_manager2);
    844   focus_manager2->SetFocusedView(view2);
    845   EXPECT_EQ(view2, focus_manager2->GetFocusedView());
    846 
    847   // Disable the first view and make sure it loses focus, but its widget is not
    848   // activated.
    849   view1->SetEnabled(false);
    850   EXPECT_NE(view1, focus_manager1->GetFocusedView());
    851   EXPECT_FALSE(widget1.IsActive());
    852   EXPECT_TRUE(widget2.IsActive());
    853 }
    854 
    855 namespace {
    856 
    857 // Used to veirfy OnMouseCaptureLost() has been invoked.
    858 class CaptureLostTrackingWidget : public Widget {
    859  public:
    860   CaptureLostTrackingWidget() : got_capture_lost_(false) {}
    861   virtual ~CaptureLostTrackingWidget() {}
    862 
    863   bool GetAndClearGotCaptureLost() {
    864     bool value = got_capture_lost_;
    865     got_capture_lost_ = false;
    866     return value;
    867   }
    868 
    869   // Widget:
    870   virtual void OnMouseCaptureLost() OVERRIDE {
    871     got_capture_lost_ = true;
    872     Widget::OnMouseCaptureLost();
    873   }
    874 
    875  private:
    876   bool got_capture_lost_;
    877 
    878   DISALLOW_COPY_AND_ASSIGN(CaptureLostTrackingWidget);
    879 };
    880 
    881 }  // namespace
    882 
    883 class WidgetCaptureTest : public ViewsTestBase {
    884  public:
    885   WidgetCaptureTest() {
    886   }
    887 
    888   virtual ~WidgetCaptureTest() {
    889   }
    890 
    891   virtual void SetUp() OVERRIDE {
    892     gfx::GLSurface::InitializeOneOffForTests();
    893     ui::RegisterPathProvider();
    894     base::FilePath ui_test_pak_path;
    895     ASSERT_TRUE(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
    896     ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
    897     ViewsTestBase::SetUp();
    898   }
    899 
    900   // Verifies Widget::SetCapture() results in updating native capture along with
    901   // invoking the right Widget function.
    902   void TestCapture(bool use_desktop_native_widget) {
    903     CaptureLostTrackingWidget widget1;
    904     Widget::InitParams params1 =
    905         CreateParams(views::Widget::InitParams::TYPE_WINDOW);
    906     params1.native_widget = CreateNativeWidget(use_desktop_native_widget,
    907                                                &widget1);
    908     params1.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    909     widget1.Init(params1);
    910     widget1.Show();
    911 
    912     CaptureLostTrackingWidget widget2;
    913     Widget::InitParams params2 =
    914         CreateParams(views::Widget::InitParams::TYPE_WINDOW);
    915     params2.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    916     params2.native_widget = CreateNativeWidget(use_desktop_native_widget,
    917                                                &widget2);
    918     widget2.Init(params2);
    919     widget2.Show();
    920 
    921     // Set capture to widget2 and verity it gets it.
    922     widget2.SetCapture(widget2.GetRootView());
    923     EXPECT_FALSE(widget1.HasCapture());
    924     EXPECT_TRUE(widget2.HasCapture());
    925     EXPECT_FALSE(widget1.GetAndClearGotCaptureLost());
    926     EXPECT_FALSE(widget2.GetAndClearGotCaptureLost());
    927 
    928     // Set capture to widget1 and verify it gets it.
    929     widget1.SetCapture(widget1.GetRootView());
    930     EXPECT_TRUE(widget1.HasCapture());
    931     EXPECT_FALSE(widget2.HasCapture());
    932     EXPECT_FALSE(widget1.GetAndClearGotCaptureLost());
    933     EXPECT_TRUE(widget2.GetAndClearGotCaptureLost());
    934 
    935     // Release and verify no one has it.
    936     widget1.ReleaseCapture();
    937     EXPECT_FALSE(widget1.HasCapture());
    938     EXPECT_FALSE(widget2.HasCapture());
    939     EXPECT_TRUE(widget1.GetAndClearGotCaptureLost());
    940     EXPECT_FALSE(widget2.GetAndClearGotCaptureLost());
    941   }
    942 
    943   NativeWidget* CreateNativeWidget(bool create_desktop_native_widget,
    944                                    Widget* widget) {
    945 #if !defined(OS_CHROMEOS)
    946     if (create_desktop_native_widget)
    947       return new PlatformDesktopNativeWidget(widget);
    948 #endif
    949     return NULL;
    950   }
    951 
    952  private:
    953   DISALLOW_COPY_AND_ASSIGN(WidgetCaptureTest);
    954 };
    955 
    956 // See description in TestCapture().
    957 TEST_F(WidgetCaptureTest, Capture) {
    958   TestCapture(false);
    959 }
    960 
    961 #if !defined(OS_CHROMEOS)
    962 // See description in TestCapture(). Creates DesktopNativeWidget.
    963 TEST_F(WidgetCaptureTest, CaptureDesktopNativeWidget) {
    964   TestCapture(true);
    965 }
    966 #endif
    967 
    968 // Test that no state is set if capture fails.
    969 TEST_F(WidgetCaptureTest, FailedCaptureRequestIsNoop) {
    970   Widget widget;
    971   Widget::InitParams params =
    972       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    973   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    974   params.bounds = gfx::Rect(400, 400);
    975   widget.Init(params);
    976 
    977   MouseView* mouse_view1 = new MouseView;
    978   MouseView* mouse_view2 = new MouseView;
    979   View* contents_view = new View;
    980   contents_view->AddChildView(mouse_view1);
    981   contents_view->AddChildView(mouse_view2);
    982   widget.SetContentsView(contents_view);
    983 
    984   mouse_view1->SetBounds(0, 0, 200, 400);
    985   mouse_view2->SetBounds(200, 0, 200, 400);
    986 
    987   // Setting capture should fail because |widget| is not visible.
    988   widget.SetCapture(mouse_view1);
    989   EXPECT_FALSE(widget.HasCapture());
    990 
    991   widget.Show();
    992   ui::test::EventGenerator generator(GetContext(), widget.GetNativeWindow());
    993   generator.set_current_location(gfx::Point(300, 10));
    994   generator.PressLeftButton();
    995 
    996   EXPECT_FALSE(mouse_view1->pressed());
    997   EXPECT_TRUE(mouse_view2->pressed());
    998 }
    999 
   1000 #if !defined(OS_CHROMEOS) && !defined(OS_WIN)
   1001 // Test that a synthetic mouse exit is sent to the widget which was handling
   1002 // mouse events when a different widget grabs capture.
   1003 // TODO(pkotwicz): Make test pass on CrOS and Windows.
   1004 TEST_F(WidgetCaptureTest, MouseExitOnCaptureGrab) {
   1005   Widget widget1;
   1006   Widget::InitParams params1 =
   1007       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
   1008   params1.native_widget = CreateNativeWidget(true, &widget1);
   1009   params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1010   widget1.Init(params1);
   1011   MouseView* mouse_view1 = new MouseView;
   1012   widget1.SetContentsView(mouse_view1);
   1013   widget1.Show();
   1014   widget1.SetBounds(gfx::Rect(300, 300));
   1015 
   1016   Widget widget2;
   1017   Widget::InitParams params2 =
   1018       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
   1019   params2.native_widget = CreateNativeWidget(true, &widget2);
   1020   params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1021   widget2.Init(params2);
   1022   widget2.Show();
   1023   widget2.SetBounds(gfx::Rect(400, 0, 300, 300));
   1024 
   1025   ui::test::EventGenerator generator(widget1.GetNativeWindow());
   1026   generator.set_current_location(gfx::Point(100, 100));
   1027   generator.MoveMouseBy(0, 0);
   1028 
   1029   EXPECT_EQ(1, mouse_view1->EnteredCalls());
   1030   EXPECT_EQ(0, mouse_view1->ExitedCalls());
   1031 
   1032   widget2.SetCapture(NULL);
   1033   EXPECT_EQ(0, mouse_view1->EnteredCalls());
   1034   // Grabbing native capture on Windows generates a ui::ET_MOUSE_EXITED event
   1035   // in addition to the one generated by Chrome.
   1036   EXPECT_LT(0, mouse_view1->ExitedCalls());
   1037 }
   1038 #endif  // !defined(OS_CHROMEOS)
   1039 
   1040 namespace {
   1041 
   1042 // Widget observer which grabs capture when the widget is activated.
   1043 class CaptureOnActivationObserver : public WidgetObserver {
   1044  public:
   1045   CaptureOnActivationObserver() {
   1046   }
   1047   virtual ~CaptureOnActivationObserver() {
   1048   }
   1049 
   1050   // WidgetObserver:
   1051   virtual void OnWidgetActivationChanged(Widget* widget, bool active) OVERRIDE {
   1052     if (active)
   1053       widget->SetCapture(NULL);
   1054   }
   1055 
   1056  private:
   1057   DISALLOW_COPY_AND_ASSIGN(CaptureOnActivationObserver);
   1058 };
   1059 
   1060 }  // namespace
   1061 
   1062 // Test that setting capture on widget activation of a non-toplevel widget
   1063 // (e.g. a bubble on Linux) succeeds.
   1064 TEST_F(WidgetCaptureTest, SetCaptureToNonToplevel) {
   1065   Widget toplevel;
   1066   Widget::InitParams toplevel_params =
   1067       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
   1068   toplevel_params.native_widget = CreateNativeWidget(true, &toplevel);
   1069   toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1070   toplevel.Init(toplevel_params);
   1071   toplevel.Show();
   1072 
   1073   Widget* child = new Widget;
   1074   Widget::InitParams child_params =
   1075       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
   1076   child_params.parent = toplevel.GetNativeView();
   1077   child_params.context = toplevel.GetNativeWindow();
   1078   child->Init(child_params);
   1079 
   1080   CaptureOnActivationObserver observer;
   1081   child->AddObserver(&observer);
   1082   child->Show();
   1083 
   1084   EXPECT_TRUE(child->HasCapture());
   1085 }
   1086 
   1087 
   1088 #if defined(OS_WIN)
   1089 namespace {
   1090 
   1091 // Used to verify OnMouseEvent() has been invoked.
   1092 class MouseEventTrackingWidget : public Widget {
   1093  public:
   1094   MouseEventTrackingWidget() : got_mouse_event_(false) {}
   1095   virtual ~MouseEventTrackingWidget() {}
   1096 
   1097   bool GetAndClearGotMouseEvent() {
   1098     bool value = got_mouse_event_;
   1099     got_mouse_event_ = false;
   1100     return value;
   1101   }
   1102 
   1103   // Widget:
   1104   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
   1105     got_mouse_event_ = true;
   1106     Widget::OnMouseEvent(event);
   1107   }
   1108 
   1109  private:
   1110   bool got_mouse_event_;
   1111 
   1112   DISALLOW_COPY_AND_ASSIGN(MouseEventTrackingWidget);
   1113 };
   1114 
   1115 }  // namespace
   1116 
   1117 // Verifies if a mouse event is received on a widget that doesn't have capture
   1118 // on Windows that it is correctly processed by the widget that doesn't have
   1119 // capture. This behavior is not desired on OSes other than Windows.
   1120 TEST_F(WidgetCaptureTest, MouseEventDispatchedToRightWindow) {
   1121   MouseEventTrackingWidget widget1;
   1122   Widget::InitParams params1 =
   1123       CreateParams(views::Widget::InitParams::TYPE_WINDOW);
   1124   params1.native_widget = new DesktopNativeWidgetAura(&widget1);
   1125   params1.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1126   widget1.Init(params1);
   1127   widget1.Show();
   1128 
   1129   MouseEventTrackingWidget widget2;
   1130   Widget::InitParams params2 =
   1131       CreateParams(views::Widget::InitParams::TYPE_WINDOW);
   1132   params2.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1133   params2.native_widget = new DesktopNativeWidgetAura(&widget2);
   1134   widget2.Init(params2);
   1135   widget2.Show();
   1136 
   1137   // Set capture to widget2 and verity it gets it.
   1138   widget2.SetCapture(widget2.GetRootView());
   1139   EXPECT_FALSE(widget1.HasCapture());
   1140   EXPECT_TRUE(widget2.HasCapture());
   1141 
   1142   widget1.GetAndClearGotMouseEvent();
   1143   widget2.GetAndClearGotMouseEvent();
   1144   // Send a mouse event to the RootWindow associated with |widget1|. Even though
   1145   // |widget2| has capture, |widget1| should still get the event.
   1146   ui::MouseEvent mouse_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(),
   1147                              ui::EF_NONE, ui::EF_NONE);
   1148   ui::EventDispatchDetails details = widget1.GetNativeWindow()->
   1149       GetHost()->event_processor()->OnEventFromSource(&mouse_event);
   1150   ASSERT_FALSE(details.dispatcher_destroyed);
   1151   EXPECT_TRUE(widget1.GetAndClearGotMouseEvent());
   1152   EXPECT_FALSE(widget2.GetAndClearGotMouseEvent());
   1153 }
   1154 #endif  // defined(OS_WIN)
   1155 
   1156 }  // namespace test
   1157 }  // namespace views
   1158