Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: ui/views/controls/menu/menu_controller_unittest.cc

Issue 284903002: Only dispatch menu events if they have a valid target. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/controls/menu/menu_controller.h" 5 #include "ui/views/controls/menu/menu_controller.h"
6 6
7 #include "base/run_loop.h" 7 #include "base/run_loop.h"
8 #include "ui/aura/scoped_window_targeter.h"
8 #include "ui/aura/window.h" 9 #include "ui/aura/window.h"
10 #include "ui/events/event_targeter.h"
9 #include "ui/events/platform/platform_event_source.h" 11 #include "ui/events/platform/platform_event_source.h"
12 #include "ui/views/controls/menu/menu_item_view.h"
10 #include "ui/views/test/views_test_base.h" 13 #include "ui/views/test/views_test_base.h"
11 #include "ui/wm/public/dispatcher_client.h" 14 #include "ui/wm/public/dispatcher_client.h"
12 15
13 #if defined(OS_WIN) 16 #if defined(OS_WIN)
14 #include "base/message_loop/message_pump_dispatcher.h" 17 #include "base/message_loop/message_pump_dispatcher.h"
15 #elif defined(USE_X11) 18 #elif defined(USE_X11)
16 #include <X11/Xlib.h> 19 #include <X11/Xlib.h>
17 #undef Bool 20 #undef Bool
18 #undef None 21 #undef None
22 #include "ui/events/test/events_test_utils_x11.h"
19 #endif 23 #endif
20 24
21 namespace views { 25 namespace views {
22 26
23 namespace { 27 namespace {
24 28
29 class TestMenuItemView : public MenuItemView {
30 public:
31 TestMenuItemView() : MenuItemView(NULL) {}
32 virtual ~TestMenuItemView() {}
33
34 private:
35 DISALLOW_COPY_AND_ASSIGN(TestMenuItemView);
36 };
37
25 class TestPlatformEventSource : public ui::PlatformEventSource { 38 class TestPlatformEventSource : public ui::PlatformEventSource {
26 public: 39 public:
27 TestPlatformEventSource() {} 40 TestPlatformEventSource() {}
28 virtual ~TestPlatformEventSource() {} 41 virtual ~TestPlatformEventSource() {}
29 42
30 uint32_t Dispatch(const ui::PlatformEvent& event) { 43 uint32_t Dispatch(const ui::PlatformEvent& event) {
31 return DispatchEvent(event); 44 return DispatchEvent(event);
32 } 45 }
33 46
34 private: 47 private:
35 DISALLOW_COPY_AND_ASSIGN(TestPlatformEventSource); 48 DISALLOW_COPY_AND_ASSIGN(TestPlatformEventSource);
36 }; 49 };
37 50
51 class TestNullTargeter : public ui::EventTargeter {
52 public:
53 TestNullTargeter() {}
54 virtual ~TestNullTargeter() {}
55
56 virtual ui::EventTarget* FindTargetForEvent(ui::EventTarget* root,
57 ui::Event* event) OVERRIDE {
58 return NULL;
59 }
60
61 private:
62 DISALLOW_COPY_AND_ASSIGN(TestNullTargeter);
63 };
64
38 class TestDispatcherClient : public aura::client::DispatcherClient { 65 class TestDispatcherClient : public aura::client::DispatcherClient {
39 public: 66 public:
40 TestDispatcherClient() : dispatcher_(NULL) {} 67 TestDispatcherClient() : dispatcher_(NULL) {}
41 virtual ~TestDispatcherClient() {} 68 virtual ~TestDispatcherClient() {}
42 69
43 base::MessagePumpDispatcher* dispatcher() { 70 base::MessagePumpDispatcher* dispatcher() {
44 return dispatcher_; 71 return dispatcher_;
45 } 72 }
46 73
47 // aura::client::DispatcherClient: 74 // aura::client::DispatcherClient:
(...skipping 24 matching lines...) Expand all
72 MenuControllerTest() : controller_(NULL) {} 99 MenuControllerTest() : controller_(NULL) {}
73 virtual ~MenuControllerTest() {} 100 virtual ~MenuControllerTest() {}
74 101
75 // Dispatches |count| number of items, each in a separate iteration of the 102 // Dispatches |count| number of items, each in a separate iteration of the
76 // message-loop, by posting a task. 103 // message-loop, by posting a task.
77 void Step3_DispatchEvents(int count) { 104 void Step3_DispatchEvents(int count) {
78 base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); 105 base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
79 base::MessageLoop::ScopedNestableTaskAllower allow(loop); 106 base::MessageLoop::ScopedNestableTaskAllower allow(loop);
80 controller_->exit_type_ = MenuController::EXIT_ALL; 107 controller_->exit_type_ = MenuController::EXIT_ALL;
81 108
82 #if defined(USE_X11) 109 DispatchEvent();
83 XEvent xevent;
84 memset(&xevent, 0, sizeof(xevent));
85 event_source_.Dispatch(&xevent);
86 #else
87 MSG msg;
88 memset(&msg, 0, sizeof(MSG));
89 dispatcher_client_.dispatcher()->Dispatch(msg);
90 #endif
91
92 if (count) { 110 if (count) {
93 base::MessageLoop::current()->PostTask( 111 base::MessageLoop::current()->PostTask(
94 FROM_HERE, 112 FROM_HERE,
95 base::Bind(&MenuControllerTest::Step3_DispatchEvents, 113 base::Bind(&MenuControllerTest::Step3_DispatchEvents,
96 base::Unretained(this), 114 base::Unretained(this),
97 count - 1)); 115 count - 1));
98 } else { 116 } else {
99 EXPECT_TRUE(run_loop_->running()); 117 EXPECT_TRUE(run_loop_->running());
100 run_loop_->Quit(); 118 run_loop_->Quit();
101 } 119 }
102 } 120 }
103 121
104 // Runs a nested message-loop that does not involve the menu itself. 122 // Runs a nested message-loop that does not involve the menu itself.
105 void Step2_RunNestedLoop() { 123 void Step2_RunNestedLoop() {
106 base::MessageLoopForUI* loop = base::MessageLoopForUI::current(); 124 base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
107 base::MessageLoop::ScopedNestableTaskAllower allow(loop); 125 base::MessageLoop::ScopedNestableTaskAllower allow(loop);
108 base::MessageLoop::current()->PostTask( 126 base::MessageLoop::current()->PostTask(
109 FROM_HERE, 127 FROM_HERE,
110 base::Bind(&MenuControllerTest::Step3_DispatchEvents, 128 base::Bind(&MenuControllerTest::Step3_DispatchEvents,
111 base::Unretained(this), 129 base::Unretained(this),
112 3)); 130 3));
113 run_loop_.reset(new base::RunLoop()); 131 run_loop_.reset(new base::RunLoop());
114 run_loop_->Run(); 132 run_loop_->Run();
115 } 133 }
116 134
117 void Step1_RunMenu() { 135 void Step1_RunMenu() {
118 Widget widget;
119 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
120 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
121 widget.Init(params);
122 widget.Show();
123
124 aura::client::SetDispatcherClient(widget.GetNativeWindow()->GetRootWindow(),
125 &dispatcher_client_);
126
127 controller_ = new MenuController(NULL, true, NULL);
128 controller_->owner_ = &widget;
129 base::MessageLoop::current()->PostTask( 136 base::MessageLoop::current()->PostTask(
130 FROM_HERE, 137 FROM_HERE,
131 base::Bind(&MenuControllerTest::Step2_RunNestedLoop, 138 base::Bind(&MenuControllerTest::Step2_RunNestedLoop,
132 base::Unretained(this))); 139 base::Unretained(this)));
140 scoped_ptr<Widget> owner(CreateOwnerWidget());
141 RunMenu(owner.get());
142 }
143
144 scoped_ptr<Widget> CreateOwnerWidget() {
145 scoped_ptr<Widget> widget(new Widget);
146 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
147 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
148 widget->Init(params);
149 widget->Show();
150
151 aura::client::SetDispatcherClient(
152 widget->GetNativeWindow()->GetRootWindow(), &dispatcher_client_);
153 return widget.Pass();
154 }
155
156 void RunMenu(views::Widget* owner) {
157 scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView);
158 controller_ = new MenuController(NULL, true, NULL);
159 controller_->owner_ = owner;
160 controller_->showing_ = true;
161 controller_->SetSelection(menu_item.get(),
162 MenuController::SELECTION_UPDATE_IMMEDIATELY);
133 controller_->RunMessageLoop(false); 163 controller_->RunMessageLoop(false);
134 } 164 }
135 165
166 #if defined(USE_X11)
167 void DispatchEscapeAndExpect(MenuController::ExitType exit_type) {
168 ui::ScopedXI2Event key_event;
169 key_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0);
170 event_source_.Dispatch(key_event);
171 EXPECT_EQ(exit_type, controller_->exit_type());
172 controller_->exit_type_ = MenuController::EXIT_ALL;
173 DispatchEvent();
174 }
175 #endif
176
177 void DispatchEvent() {
178 #if defined(USE_X11)
179 XEvent xevent;
180 memset(&xevent, 0, sizeof(xevent));
181 event_source_.Dispatch(&xevent);
182 #else
183 MSG msg;
184 memset(&msg, 0, sizeof(MSG));
185 dispatcher_client_.dispatcher()->Dispatch(msg);
186 #endif
187 }
188
136 private: 189 private:
137 MenuController* controller_; 190 MenuController* controller_;
138 scoped_ptr<base::RunLoop> run_loop_; 191 scoped_ptr<base::RunLoop> run_loop_;
139 TestPlatformEventSource event_source_; 192 TestPlatformEventSource event_source_;
140 TestDispatcherClient dispatcher_client_; 193 TestDispatcherClient dispatcher_client_;
141 194
142 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest); 195 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest);
143 }; 196 };
144 197
145 TEST_F(MenuControllerTest, Basic) { 198 TEST_F(MenuControllerTest, Basic) {
146 base::MessageLoop::ScopedNestableTaskAllower allow_nested( 199 base::MessageLoop::ScopedNestableTaskAllower allow_nested(
147 base::MessageLoop::current()); 200 base::MessageLoop::current());
148 message_loop()->PostTask( 201 message_loop()->PostTask(
149 FROM_HERE, 202 FROM_HERE,
150 base::Bind(&MenuControllerTest::Step1_RunMenu, base::Unretained(this))); 203 base::Bind(&MenuControllerTest::Step1_RunMenu, base::Unretained(this)));
151 } 204 }
152 205
206 #if defined(OS_LINUX) && defined(USE_X11)
207 // Tests that an event targeter which blocks events will be honored by the menu
208 // event dispatcher.
209 TEST_F(MenuControllerTest, EventTargeter) {
210 {
211 // Verify that the menu handles the escape key under normal circumstances.
212 scoped_ptr<Widget> owner(CreateOwnerWidget());
213 message_loop()->PostTask(
214 FROM_HERE,
215 base::Bind(&MenuControllerTest::DispatchEscapeAndExpect,
216 base::Unretained(this),
217 MenuController::EXIT_OUTERMOST));
218 RunMenu(owner.get());
219 }
220
221 {
222 // With the NULL targeter instantiated and assigned we expect the menu to
223 // not handle the key event.
224 scoped_ptr<Widget> owner(CreateOwnerWidget());
225 aura::ScopedWindowTargeter scoped_targeter(
226 owner->GetNativeWindow()->GetRootWindow(),
227 scoped_ptr<ui::EventTargeter>(new TestNullTargeter));
228 message_loop()->PostTask(
229 FROM_HERE,
230 base::Bind(&MenuControllerTest::DispatchEscapeAndExpect,
231 base::Unretained(this),
232 MenuController::EXIT_NONE));
233 RunMenu(owner.get());
234 }
235 }
236 #endif
237
153 } // namespace views 238 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/menu/menu_controller.h ('k') | ui/views/controls/menu/menu_event_dispatcher_linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698