| 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 dd67cfb85a5563e318bb1fe75b85057f2c83b199..28424c997acf45eb6043002b0eeb7599a13af02e 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,6 +19,7 @@
|
| #include <X11/Xlib.h>
|
| #undef Bool
|
| #undef None
|
| +#include "ui/events/test/events_test_utils_x11.h"
|
| #elif defined(USE_OZONE)
|
| #include "ui/events/event.h"
|
| #endif
|
| @@ -24,6 +28,15 @@ 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() {}
|
| @@ -37,6 +50,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) {}
|
| @@ -72,7 +99,9 @@ class TestDispatcherClient : public aura::client::DispatcherClient {
|
| class MenuControllerTest : public ViewsTestBase {
|
| public:
|
| MenuControllerTest() : controller_(NULL) {}
|
| - virtual ~MenuControllerTest() {}
|
| + virtual ~MenuControllerTest() {
|
| + ResetMenuController();
|
| + }
|
|
|
| // Dispatches |count| number of items, each in a separate iteration of the
|
| // message-loop, by posting a task.
|
| @@ -81,21 +110,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);
|
| -#elif defined(OS_WIN)
|
| - MSG msg;
|
| - memset(&msg, 0, sizeof(MSG));
|
| - dispatcher_client_.dispatcher()->Dispatch(msg);
|
| -#elif defined(USE_OZONE)
|
| - ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0, true);
|
| - dispatcher_client_.dispatcher()->Dispatch(&event);
|
| -#else
|
| -#error Unsupported platform
|
| -#endif
|
| -
|
| + DispatchEvent();
|
| if (count) {
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE,
|
| @@ -122,25 +137,78 @@ 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);
|
| + ResetMenuController();
|
| 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);
|
| +#elif defined(OS_WIN)
|
| + MSG msg;
|
| + memset(&msg, 0, sizeof(MSG));
|
| + dispatcher_client_.dispatcher()->Dispatch(msg);
|
| +#elif defined(USE_OZONE)
|
| + ui::KeyEvent event(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0, true);
|
| + dispatcher_client_.dispatcher()->Dispatch(&event);
|
| +#else
|
| +#error Unsupported platform
|
| +#endif
|
| + }
|
| +
|
| private:
|
| + void ResetMenuController() {
|
| + if (controller_) {
|
| + // These properties are faked by RunMenu for the purposes of testing and
|
| + // need to be undone before we call the destructor.
|
| + controller_->owner_ = NULL;
|
| + controller_->showing_ = false;
|
| + delete controller_;
|
| + controller_ = NULL;
|
| + }
|
| + }
|
| +
|
| + // A weak pointer to the MenuController owned by this class.
|
| MenuController* controller_;
|
| scoped_ptr<base::RunLoop> run_loop_;
|
| TestPlatformEventSource event_source_;
|
| @@ -157,4 +225,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
|
|
|