1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/controls/menu/menu_controller.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/run_loop.h"
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/aura/scoped_window_targeter.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/aura/window.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/events/event_targeter.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/events/platform/platform_event_source.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/controls/menu/menu_item_view.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/views/test/views_test_base.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/wm/public/dispatcher_client.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_WIN)
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/message_loop/message_pump_dispatcher.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#elif defined(USE_X11)
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <X11/Xlib.h>
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#undef Bool
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#undef None
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/events/test/events_test_utils_x11.h"
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/events/x/device_data_manager_x11.h"
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#elif defined(USE_OZONE)
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/events/event.h"
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace views {
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class TestMenuItemView : public MenuItemView {
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestMenuItemView() : MenuItemView(NULL) {}
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~TestMenuItemView() {}
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestMenuItemView);
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class TestPlatformEventSource : public ui::PlatformEventSource {
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  TestPlatformEventSource() {
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(USE_X11)
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ui::DeviceDataManagerX11::CreateInstance();
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~TestPlatformEventSource() {}
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  uint32_t Dispatch(const ui::PlatformEvent& event) {
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return DispatchEvent(event);
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestPlatformEventSource);
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class TestNullTargeter : public ui::EventTargeter {
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestNullTargeter() {}
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~TestNullTargeter() {}
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                              ui::Event* event) OVERRIDE {
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return NULL;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestNullTargeter);
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class TestDispatcherClient : public aura::client::DispatcherClient {
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestDispatcherClient() : dispatcher_(NULL) {}
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~TestDispatcherClient() {}
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessagePumpDispatcher* dispatcher() {
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return dispatcher_;
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // aura::client::DispatcherClient:
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual void PrepareNestedLoopClosures(
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::MessagePumpDispatcher* dispatcher,
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Closure* run_closure,
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Closure* quit_closure) OVERRIDE {
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<base::RunLoop> run_loop(new base::RunLoop());
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *quit_closure = run_loop->QuitClosure();
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *run_closure = base::Bind(&TestDispatcherClient::RunNestedDispatcher,
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              base::Unretained(this),
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              base::Passed(&run_loop),
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              dispatcher);
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void RunNestedDispatcher(scoped_ptr<base::RunLoop> run_loop,
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           base::MessagePumpDispatcher* dispatcher) {
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::AutoReset<base::MessagePumpDispatcher*> reset_dispatcher(&dispatcher_,
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                                   dispatcher);
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoop::ScopedNestableTaskAllower allow(loop);
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run_loop->Run();
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessagePumpDispatcher* dispatcher_;
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestDispatcherClient);
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class MenuControllerTest : public ViewsTestBase {
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MenuControllerTest() : controller_(NULL) {}
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~MenuControllerTest() {
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ResetMenuController();
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Dispatches |count| number of items, each in a separate iteration of the
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // message-loop, by posting a task.
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void Step3_DispatchEvents(int count) {
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoop::ScopedNestableTaskAllower allow(loop);
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    controller_->exit_type_ = MenuController::EXIT_ALL;
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DispatchEvent();
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (count) {
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::MessageLoop::current()->PostTask(
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          FROM_HERE,
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::Bind(&MenuControllerTest::Step3_DispatchEvents,
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     base::Unretained(this),
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     count - 1));
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      EXPECT_TRUE(run_loop_->running());
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      run_loop_->Quit();
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Runs a nested message-loop that does not involve the menu itself.
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void Step2_RunNestedLoop() {
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoop::ScopedNestableTaskAllower allow(loop);
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoop::current()->PostTask(
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE,
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&MenuControllerTest::Step3_DispatchEvents,
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   base::Unretained(this),
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   3));
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run_loop_.reset(new base::RunLoop());
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run_loop_->Run();
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void Step1_RunMenu() {
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    base::MessageLoop::current()->PostTask(
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE,
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&MenuControllerTest::Step2_RunNestedLoop,
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   base::Unretained(this)));
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<Widget> owner(CreateOwnerWidget());
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    RunMenu(owner.get());
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<Widget> CreateOwnerWidget() {
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<Widget> widget(new Widget);
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    widget->Init(params);
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    widget->Show();
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    aura::client::SetDispatcherClient(
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        widget->GetNativeWindow()->GetRootWindow(), &dispatcher_client_);
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return widget.Pass();
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void RunMenu(views::Widget* owner) {
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView);
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ResetMenuController();
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    controller_ = new MenuController(NULL, true, NULL);
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    controller_->owner_ = owner;
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    controller_->showing_ = true;
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    controller_->SetSelection(menu_item.get(),
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              MenuController::SELECTION_UPDATE_IMMEDIATELY);
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    controller_->RunMessageLoop(false);
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(USE_X11)
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void DispatchEscapeAndExpect(MenuController::ExitType exit_type) {
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ui::ScopedXI2Event key_event;
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    key_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0);
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    event_source_.Dispatch(key_event);
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    EXPECT_EQ(exit_type, controller_->exit_type());
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    controller_->exit_type_ = MenuController::EXIT_ALL;
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DispatchEvent();
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void DispatchEvent() {
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(USE_X11)
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    XEvent xevent;
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    memset(&xevent, 0, sizeof(xevent));
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    event_source_.Dispatch(&xevent);
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#elif defined(OS_WIN)
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MSG msg;
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    memset(&msg, 0, sizeof(MSG));
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    dispatcher_client_.dispatcher()->Dispatch(msg);
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#elif defined(USE_OZONE)
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ui::KeyEvent event(' ', ui::VKEY_SPACE, ui::EF_NONE);
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    event_source_.Dispatch(&event);
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#error Unsupported platform
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void ResetMenuController() {
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (controller_) {
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // These properties are faked by RunMenu for the purposes of testing and
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // need to be undone before we call the destructor.
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      controller_->owner_ = NULL;
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      controller_->showing_ = false;
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      delete controller_;
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      controller_ = NULL;
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // A weak pointer to the MenuController owned by this class.
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MenuController* controller_;
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<base::RunLoop> run_loop_;
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestPlatformEventSource event_source_;
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TestDispatcherClient dispatcher_client_;
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MenuControllerTest);
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(MenuControllerTest, Basic) {
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::MessageLoop::ScopedNestableTaskAllower allow_nested(
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::MessageLoop::current());
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  message_loop()->PostTask(
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      FROM_HERE,
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&MenuControllerTest::Step1_RunMenu, base::Unretained(this)));
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_LINUX) && defined(USE_X11)
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Tests that an event targeter which blocks events will be honored by the menu
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// event dispatcher.
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(MenuControllerTest, EventTargeter) {
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  {
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Verify that the menu handles the escape key under normal circumstances.
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<Widget> owner(CreateOwnerWidget());
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    message_loop()->PostTask(
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE,
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&MenuControllerTest::DispatchEscapeAndExpect,
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   base::Unretained(this),
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   MenuController::EXIT_OUTERMOST));
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    RunMenu(owner.get());
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  {
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // With the NULL targeter instantiated and assigned we expect the menu to
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // not handle the key event.
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<Widget> owner(CreateOwnerWidget());
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    aura::ScopedWindowTargeter scoped_targeter(
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        owner->GetNativeWindow()->GetRootWindow(),
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        scoped_ptr<ui::EventTargeter>(new TestNullTargeter));
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    message_loop()->PostTask(
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        FROM_HERE,
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        base::Bind(&MenuControllerTest::DispatchEscapeAndExpect,
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   base::Unretained(this),
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   MenuController::EXIT_NONE));
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    RunMenu(owner.get());
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace views
273