Index: ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc |
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc |
index 64f7c42cd374489465d7a8ad63b6bae7ec3fdd64..b2d301d018fa10517f237b79cc941248451eede1 100644 |
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc |
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc |
@@ -20,8 +20,13 @@ |
#include "ui/views/test/views_test_base.h" |
#include "ui/views/test/widget_test.h" |
#include "ui/views/widget/widget.h" |
+#include "ui/views/window/dialog_delegate.h" |
#include "ui/wm/public/dispatcher_client.h" |
+#if defined(OS_WIN) |
+#include "ui/views/win/hwnd_util.h" |
+#endif |
+ |
namespace views { |
namespace test { |
@@ -504,5 +509,128 @@ TEST_F(DesktopAuraWidgetTest, CloseWidgetDuringMouseReleased) { |
RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_RELEASED); |
} |
+// Provides functionality to create a window modal dialog. |
+class ModalDialogDelegate : public DialogDelegateView { |
+ public: |
+ ModalDialogDelegate() {} |
+ ~ModalDialogDelegate() override {} |
+ |
+ // WidgetDelegate overrides. |
+ ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_WINDOW; } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate); |
+}; |
+ |
+// This test verifies that whether mouse events when a modal dialog is |
+// displayed are eaten or recieved by the dialog. |
+TEST_F(WidgetTest, WindowMouseModalityTest) { |
+ // Create a top level widget. |
+ Widget top_level_widget; |
+ Widget::InitParams init_params = |
+ CreateParams(Widget::InitParams::TYPE_WINDOW); |
+ init_params.show_state = ui::SHOW_STATE_NORMAL; |
+ gfx::Rect initial_bounds(0, 0, 500, 500); |
+ init_params.bounds = initial_bounds; |
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
+ init_params.native_widget = |
+ new PlatformDesktopNativeWidget(&top_level_widget); |
+ top_level_widget.Init(init_params); |
+ top_level_widget.Show(); |
+ EXPECT_TRUE(top_level_widget.IsVisible()); |
+ |
+ // Create a view and validate that a mouse moves makes it to the view. |
+ EventCountView* widget_view = new EventCountView(); |
+ widget_view->SetBounds(0, 0, 10, 10); |
+ top_level_widget.GetRootView()->AddChildView(widget_view); |
+ |
+ gfx::Point cursor_location_main(5, 5); |
+ ui::MouseEvent move_main(ui::ET_MOUSE_MOVED, cursor_location_main, |
+ cursor_location_main, ui::EventTimeForNow(), |
+ ui::EF_NONE, ui::EF_NONE); |
+ ui::EventDispatchDetails details = |
+ GetEventProcessor(&top_level_widget)->OnEventFromSource(&move_main); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ |
+ EXPECT_EQ(1, widget_view->GetEventCount(ui::ET_MOUSE_ENTERED)); |
+ widget_view->ResetCounts(); |
+ |
+ // Create a modal dialog and validate that a mouse down message makes it to |
+ // the main view within the dialog. |
+ |
+ // This instance will be destroyed when the dialog is destroyed. |
+ ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate; |
+ |
+ Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget( |
+ dialog_delegate, NULL, top_level_widget.GetNativeView()); |
+ modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200)); |
+ EventCountView* dialog_widget_view = new EventCountView(); |
+ dialog_widget_view->SetBounds(0, 0, 50, 50); |
+ modal_dialog_widget->GetRootView()->AddChildView(dialog_widget_view); |
+ modal_dialog_widget->Show(); |
+ EXPECT_TRUE(modal_dialog_widget->IsVisible()); |
+ |
+ gfx::Point cursor_location_dialog(100, 100); |
+ ui::MouseEvent mouse_down_dialog( |
+ ui::ET_MOUSE_PRESSED, cursor_location_dialog, cursor_location_dialog, |
+ ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); |
+ details = GetEventProcessor(&top_level_widget)->OnEventFromSource( |
+ &mouse_down_dialog); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ EXPECT_EQ(1, dialog_widget_view->GetEventCount(ui::ET_MOUSE_PRESSED)); |
+ |
+ // Send a mouse move message to the main window. It should not be received by |
+ // the main window as the modal dialog is still active. |
+ gfx::Point cursor_location_main2(6, 6); |
+ ui::MouseEvent mouse_down_main(ui::ET_MOUSE_MOVED, cursor_location_main2, |
+ cursor_location_main2, ui::EventTimeForNow(), |
+ ui::EF_NONE, ui::EF_NONE); |
+ details = GetEventProcessor(&top_level_widget)->OnEventFromSource( |
+ &mouse_down_main); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ EXPECT_EQ(0, widget_view->GetEventCount(ui::ET_MOUSE_MOVED)); |
+ |
+ modal_dialog_widget->CloseNow(); |
+ top_level_widget.CloseNow(); |
+} |
+ |
+#if defined(OS_WIN) |
+// Tests whether we can activate the top level widget when a modal dialog is |
+// active. |
+TEST_F(WidgetTest, WindowModalityActivationTest) { |
+ TestDesktopWidgetDelegate widget_delegate; |
+ widget_delegate.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW)); |
+ |
+ Widget* top_level_widget = widget_delegate.GetWidget(); |
+ top_level_widget->Show(); |
+ EXPECT_TRUE(top_level_widget->IsVisible()); |
+ |
+ HWND win32_window = views::HWNDForWidget(top_level_widget); |
+ EXPECT_TRUE(::IsWindow(win32_window)); |
+ |
+ // This instance will be destroyed when the dialog is destroyed. |
+ ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate; |
+ |
+ // We should be able to activate the window even if the WidgetDelegate |
+ // says no, when a modal dialog is active. |
+ widget_delegate.set_can_activate(false); |
+ |
+ Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget( |
+ dialog_delegate, NULL, top_level_widget->GetNativeView()); |
+ modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200)); |
+ modal_dialog_widget->Show(); |
+ EXPECT_TRUE(modal_dialog_widget->IsVisible()); |
+ |
+ LRESULT activate_result = ::SendMessage( |
+ win32_window, |
+ WM_MOUSEACTIVATE, |
+ reinterpret_cast<WPARAM>(win32_window), |
+ MAKELPARAM(WM_LBUTTONDOWN, HTCLIENT)); |
+ EXPECT_EQ(activate_result, MA_ACTIVATE); |
+ |
+ modal_dialog_widget->CloseNow(); |
+} |
+#endif // defined(OS_WIN) |
+ |
} // namespace test |
} // namespace views |