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

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: Add test MenuControllerTest.EventTargeter 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_->SetSelection(menu_item.get(),
161 MenuController::SELECTION_UPDATE_IMMEDIATELY);
133 controller_->RunMessageLoop(false); 162 controller_->RunMessageLoop(false);
134 } 163 }
135 164
165 #if defined(USE_X11)
166 void DispatchEscapeAndExpect(uint32_t result) {
167 ui::ScopedXI2Event key_event;
168 key_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0);
169 EXPECT_EQ(result, event_source_.Dispatch(key_event));
170 controller_->exit_type_ = MenuController::EXIT_ALL;
171 DispatchEvent();
172 }
173 #endif
174
175 void DispatchEvent() {
176 #if defined(USE_X11)
177 XEvent xevent;
178 memset(&xevent, 0, sizeof(xevent));
179 event_source_.Dispatch(&xevent);
180 #else
181 MSG msg;
182 memset(&msg, 0, sizeof(MSG));
183 dispatcher_client_.dispatcher()->Dispatch(msg);
184 #endif
185 }
186
136 private: 187 private:
137 MenuController* controller_; 188 MenuController* controller_;
138 scoped_ptr<base::RunLoop> run_loop_; 189 scoped_ptr<base::RunLoop> run_loop_;
139 TestPlatformEventSource event_source_; 190 TestPlatformEventSource event_source_;
140 TestDispatcherClient dispatcher_client_; 191 TestDispatcherClient dispatcher_client_;
141 192
142 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest); 193 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest);
143 }; 194 };
144 195
145 TEST_F(MenuControllerTest, Basic) { 196 TEST_F(MenuControllerTest, Basic) {
146 base::MessageLoop::ScopedNestableTaskAllower allow_nested( 197 base::MessageLoop::ScopedNestableTaskAllower allow_nested(
147 base::MessageLoop::current()); 198 base::MessageLoop::current());
148 message_loop()->PostTask( 199 message_loop()->PostTask(
149 FROM_HERE, 200 FROM_HERE,
150 base::Bind(&MenuControllerTest::Step1_RunMenu, base::Unretained(this))); 201 base::Bind(&MenuControllerTest::Step1_RunMenu, base::Unretained(this)));
151 } 202 }
152 203
204 #if defined(OS_LINUX) and defined(USE_X11)
sadrul 2014/05/15 21:53:01 Does this test not work on chromeos?
flackr 2014/05/15 22:13:01 OS_LINUX is true on chromeos, I was matching the p
205 // Tests that an event targeter which blocks events will be honored by the menu
206 // event dispatcher.
207 TEST_F(MenuControllerTest, EventTargeter) {
208 {
209 // Verify that the menu handles the escape key under normal circumstances.
210 scoped_ptr<Widget> owner(CreateOwnerWidget());
211 message_loop()->PostTask(
212 FROM_HERE,
213 base::Bind(&MenuControllerTest::DispatchEscapeAndExpect,
214 base::Unretained(this),
215 ui::POST_DISPATCH_QUIT_LOOP));
sadrul 2014/05/15 21:53:01 Hm. I removed this recently (https://codereview.ch
flackr 2014/05/15 22:13:01 Done.
216 RunMenu(owner.get());
217 }
218
219 {
220 // With the NULL targeter instantiated and assigned we expect the menu to
221 // not handle the key event.
222 scoped_ptr<Widget> owner(CreateOwnerWidget());
223 aura::ScopedWindowTargeter scoped_targeter(
224 owner->GetNativeWindow()->GetRootWindow(),
225 scoped_ptr<ui::EventTargeter>(new TestNullTargeter));
226 message_loop()->PostTask(
227 FROM_HERE,
228 base::Bind(&MenuControllerTest::DispatchEscapeAndExpect,
229 base::Unretained(this),
230 ui::POST_DISPATCH_PERFORM_DEFAULT));
231 RunMenu(owner.get());
232 }
233 }
234 #endif
235
153 } // namespace views 236 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698