Index: ui/views/controls/menu/menu_controller_unittest.cc |
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc |
index 7aa23a317f5567796374d48308f376f97ab516ae..dc089c68b0e706d7da5f89aa1d3ed5bd4c77dc7d 100644 |
--- a/ui/views/controls/menu/menu_controller_unittest.cc |
+++ b/ui/views/controls/menu/menu_controller_unittest.cc |
@@ -5,8 +5,11 @@ |
#include "ui/views/controls/menu/menu_controller.h" |
#include "base/run_loop.h" |
+#include "ui/aura/scoped_window_targeter.h" |
#include "ui/aura/window.h" |
+#include "ui/events/event_targeter.h" |
#include "ui/events/platform/platform_event_source.h" |
+#include "ui/views/controls/menu/menu_item_view.h" |
#include "ui/views/test/views_test_base.h" |
#include "ui/wm/public/dispatcher_client.h" |
@@ -16,12 +19,22 @@ |
#include <X11/Xlib.h> |
#undef Bool |
#undef None |
+#include "ui/events/test/events_test_utils_x11.h" |
#endif |
namespace views { |
namespace { |
+class TestMenuItemView : public MenuItemView { |
+ public: |
+ TestMenuItemView() : MenuItemView(NULL) {} |
+ virtual ~TestMenuItemView() {} |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(TestMenuItemView); |
+}; |
+ |
class TestPlatformEventSource : public ui::PlatformEventSource { |
public: |
TestPlatformEventSource() {} |
@@ -35,6 +48,20 @@ class TestPlatformEventSource : public ui::PlatformEventSource { |
DISALLOW_COPY_AND_ASSIGN(TestPlatformEventSource); |
}; |
+class TestNullTargeter : public ui::EventTargeter { |
+ public: |
+ TestNullTargeter() {} |
+ virtual ~TestNullTargeter() {} |
+ |
+ virtual ui::EventTarget* FindTargetForEvent(ui::EventTarget* root, |
+ ui::Event* event) OVERRIDE { |
+ return NULL; |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(TestNullTargeter); |
+}; |
+ |
class TestDispatcherClient : public aura::client::DispatcherClient { |
public: |
TestDispatcherClient() : dispatcher_(NULL) {} |
@@ -79,16 +106,7 @@ class MenuControllerTest : public ViewsTestBase { |
base::MessageLoop::ScopedNestableTaskAllower allow(loop); |
controller_->exit_type_ = MenuController::EXIT_ALL; |
-#if defined(USE_X11) |
- XEvent xevent; |
- memset(&xevent, 0, sizeof(xevent)); |
- event_source_.Dispatch(&xevent); |
-#else |
- MSG msg; |
- memset(&msg, 0, sizeof(MSG)); |
- dispatcher_client_.dispatcher()->Dispatch(msg); |
-#endif |
- |
+ DispatchEvent(); |
if (count) { |
base::MessageLoop::current()->PostTask( |
FROM_HERE, |
@@ -115,24 +133,59 @@ class MenuControllerTest : public ViewsTestBase { |
} |
void Step1_RunMenu() { |
- Widget widget; |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&MenuControllerTest::Step2_RunNestedLoop, |
+ base::Unretained(this))); |
+ scoped_ptr<Widget> owner(CreateOwnerWidget()); |
+ RunMenu(owner.get()); |
+ } |
+ |
+ scoped_ptr<Widget> CreateOwnerWidget() { |
+ scoped_ptr<Widget> widget(new Widget); |
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
- widget.Init(params); |
- widget.Show(); |
+ widget->Init(params); |
+ widget->Show(); |
- aura::client::SetDispatcherClient(widget.GetNativeWindow()->GetRootWindow(), |
- &dispatcher_client_); |
+ aura::client::SetDispatcherClient( |
+ widget->GetNativeWindow()->GetRootWindow(), &dispatcher_client_); |
+ return widget.Pass(); |
+ } |
+ void RunMenu(views::Widget* owner) { |
+ scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView); |
controller_ = new MenuController(NULL, true, NULL); |
- controller_->owner_ = &widget; |
- base::MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&MenuControllerTest::Step2_RunNestedLoop, |
- base::Unretained(this))); |
+ controller_->owner_ = owner; |
+ controller_->showing_ = true; |
+ controller_->SetSelection(menu_item.get(), |
+ MenuController::SELECTION_UPDATE_IMMEDIATELY); |
controller_->RunMessageLoop(false); |
} |
+#if defined(USE_X11) |
+ void DispatchEscapeAndExpect(MenuController::ExitType exit_type) { |
+ ui::ScopedXI2Event key_event; |
+ key_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0); |
+ event_source_.Dispatch(key_event); |
+ EXPECT_EQ(exit_type, controller_->exit_type()); |
+ controller_->exit_type_ = MenuController::EXIT_ALL; |
+ DispatchEvent(); |
+ } |
+#endif |
+ |
+ void DispatchEvent() { |
+#if defined(USE_X11) |
+ XEvent xevent; |
+ memset(&xevent, 0, sizeof(xevent)); |
+ event_source_.Dispatch(&xevent); |
+#else |
+ MSG msg; |
+ memset(&msg, 0, sizeof(MSG)); |
+ dispatcher_client_.dispatcher()->Dispatch(msg); |
+#endif |
+ } |
+ |
private: |
MenuController* controller_; |
scoped_ptr<base::RunLoop> run_loop_; |
@@ -150,4 +203,36 @@ TEST_F(MenuControllerTest, Basic) { |
base::Bind(&MenuControllerTest::Step1_RunMenu, base::Unretained(this))); |
} |
+#if defined(OS_LINUX) && defined(USE_X11) |
+// Tests that an event targeter which blocks events will be honored by the menu |
+// event dispatcher. |
+TEST_F(MenuControllerTest, EventTargeter) { |
+ { |
+ // Verify that the menu handles the escape key under normal circumstances. |
+ scoped_ptr<Widget> owner(CreateOwnerWidget()); |
+ message_loop()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&MenuControllerTest::DispatchEscapeAndExpect, |
+ base::Unretained(this), |
+ MenuController::EXIT_OUTERMOST)); |
+ RunMenu(owner.get()); |
+ } |
+ |
+ { |
+ // With the NULL targeter instantiated and assigned we expect the menu to |
+ // not handle the key event. |
+ scoped_ptr<Widget> owner(CreateOwnerWidget()); |
+ aura::ScopedWindowTargeter scoped_targeter( |
+ owner->GetNativeWindow()->GetRootWindow(), |
+ scoped_ptr<ui::EventTargeter>(new TestNullTargeter)); |
+ message_loop()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&MenuControllerTest::DispatchEscapeAndExpect, |
+ base::Unretained(this), |
+ MenuController::EXIT_NONE)); |
+ RunMenu(owner.get()); |
+ } |
+} |
+#endif |
+ |
} // namespace views |