Sort unlaunched apps on app list start page by apps grid order.
[chromium-blink-merge.git] / ui / views / widget / root_view_unittest.cc
blobfcefb7033020c19e0e19b8890838937b54e233f4
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/views/widget/root_view.h"
7 #include "ui/views/context_menu_controller.h"
8 #include "ui/views/test/views_test_base.h"
9 #include "ui/views/view_targeter.h"
10 #include "ui/views/widget/root_view.h"
12 namespace views {
13 namespace test {
15 typedef ViewsTestBase RootViewTest;
17 class DeleteOnKeyEventView : public View {
18 public:
19 explicit DeleteOnKeyEventView(bool* set_on_key) : set_on_key_(set_on_key) {}
20 ~DeleteOnKeyEventView() override {}
22 bool OnKeyPressed(const ui::KeyEvent& event) override {
23 *set_on_key_ = true;
24 delete this;
25 return true;
28 private:
29 // Set to true in OnKeyPressed().
30 bool* set_on_key_;
32 DISALLOW_COPY_AND_ASSIGN(DeleteOnKeyEventView);
35 // Verifies deleting a View in OnKeyPressed() doesn't crash and that the
36 // target is marked as destroyed in the returned EventDispatchDetails.
37 TEST_F(RootViewTest, DeleteViewDuringKeyEventDispatch) {
38 Widget widget;
39 Widget::InitParams init_params =
40 CreateParams(Widget::InitParams::TYPE_POPUP);
41 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
42 widget.Init(init_params);
44 bool got_key_event = false;
46 View* content = new View;
47 widget.SetContentsView(content);
49 View* child = new DeleteOnKeyEventView(&got_key_event);
50 content->AddChildView(child);
52 // Give focus to |child| so that it will be the target of the key event.
53 child->SetFocusable(true);
54 child->RequestFocus();
56 internal::RootView* root_view =
57 static_cast<internal::RootView*>(widget.GetRootView());
58 ViewTargeter* view_targeter = new ViewTargeter(root_view);
59 root_view->SetEventTargeter(make_scoped_ptr(view_targeter));
61 ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, ui::EF_NONE);
62 ui::EventDispatchDetails details = root_view->OnEventFromSource(&key_event);
63 EXPECT_TRUE(details.target_destroyed);
64 EXPECT_FALSE(details.dispatcher_destroyed);
65 EXPECT_TRUE(got_key_event);
68 // Tracks whether a context menu is shown.
69 class TestContextMenuController : public ContextMenuController {
70 public:
71 TestContextMenuController()
72 : show_context_menu_calls_(0),
73 menu_source_view_(NULL),
74 menu_source_type_(ui::MENU_SOURCE_NONE) {
76 ~TestContextMenuController() override {}
78 int show_context_menu_calls() const { return show_context_menu_calls_; }
79 View* menu_source_view() const { return menu_source_view_; }
80 ui::MenuSourceType menu_source_type() const { return menu_source_type_; }
82 void Reset() {
83 show_context_menu_calls_ = 0;
84 menu_source_view_ = NULL;
85 menu_source_type_ = ui::MENU_SOURCE_NONE;
88 // ContextMenuController:
89 void ShowContextMenuForView(View* source,
90 const gfx::Point& point,
91 ui::MenuSourceType source_type) override {
92 show_context_menu_calls_++;
93 menu_source_view_ = source;
94 menu_source_type_ = source_type;
97 private:
98 int show_context_menu_calls_;
99 View* menu_source_view_;
100 ui::MenuSourceType menu_source_type_;
102 DISALLOW_COPY_AND_ASSIGN(TestContextMenuController);
105 // Tests that context menus are shown for certain key events (Shift+F10
106 // and VKEY_APPS) by the pre-target handler installed on RootView.
107 TEST_F(RootViewTest, ContextMenuFromKeyEvent) {
108 Widget widget;
109 Widget::InitParams init_params =
110 CreateParams(Widget::InitParams::TYPE_POPUP);
111 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
112 widget.Init(init_params);
113 internal::RootView* root_view =
114 static_cast<internal::RootView*>(widget.GetRootView());
116 TestContextMenuController controller;
117 View* focused_view = new View;
118 focused_view->set_context_menu_controller(&controller);
119 widget.SetContentsView(focused_view);
120 focused_view->SetFocusable(true);
121 focused_view->RequestFocus();
123 // No context menu should be shown for a keypress of 'A'.
124 ui::KeyEvent nomenu_key_event('a', ui::VKEY_A, ui::EF_NONE);
125 ui::EventDispatchDetails details =
126 root_view->OnEventFromSource(&nomenu_key_event);
127 EXPECT_FALSE(details.target_destroyed);
128 EXPECT_FALSE(details.dispatcher_destroyed);
129 EXPECT_EQ(0, controller.show_context_menu_calls());
130 EXPECT_EQ(NULL, controller.menu_source_view());
131 EXPECT_EQ(ui::MENU_SOURCE_NONE, controller.menu_source_type());
132 controller.Reset();
134 // A context menu should be shown for a keypress of Shift+F10.
135 ui::KeyEvent menu_key_event(
136 ui::ET_KEY_PRESSED, ui::VKEY_F10, ui::EF_SHIFT_DOWN);
137 details = root_view->OnEventFromSource(&menu_key_event);
138 EXPECT_FALSE(details.target_destroyed);
139 EXPECT_FALSE(details.dispatcher_destroyed);
140 EXPECT_EQ(1, controller.show_context_menu_calls());
141 EXPECT_EQ(focused_view, controller.menu_source_view());
142 EXPECT_EQ(ui::MENU_SOURCE_KEYBOARD, controller.menu_source_type());
143 controller.Reset();
145 // A context menu should be shown for a keypress of VKEY_APPS.
146 ui::KeyEvent menu_key_event2(ui::ET_KEY_PRESSED, ui::VKEY_APPS, ui::EF_NONE);
147 details = root_view->OnEventFromSource(&menu_key_event2);
148 EXPECT_FALSE(details.target_destroyed);
149 EXPECT_FALSE(details.dispatcher_destroyed);
150 EXPECT_EQ(1, controller.show_context_menu_calls());
151 EXPECT_EQ(focused_view, controller.menu_source_view());
152 EXPECT_EQ(ui::MENU_SOURCE_KEYBOARD, controller.menu_source_type());
153 controller.Reset();
156 // View which handles all gesture events.
157 class GestureHandlingView : public View {
158 public:
159 GestureHandlingView() {
162 ~GestureHandlingView() override {}
164 void OnGestureEvent(ui::GestureEvent* event) override { event->SetHandled(); }
166 private:
167 DISALLOW_COPY_AND_ASSIGN(GestureHandlingView);
170 // Tests that context menus are shown for long press by the post-target handler
171 // installed on the RootView only if the event is targetted at a view which can
172 // show a context menu.
173 TEST_F(RootViewTest, ContextMenuFromLongPress) {
174 Widget widget;
175 Widget::InitParams init_params =
176 CreateParams(Widget::InitParams::TYPE_POPUP);
177 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
178 init_params.bounds = gfx::Rect(100, 100);
179 widget.Init(init_params);
180 internal::RootView* root_view =
181 static_cast<internal::RootView*>(widget.GetRootView());
183 // Create a view capable of showing the context menu with two children one of
184 // which handles all gesture events (e.g. a button).
185 TestContextMenuController controller;
186 View* parent_view = new View;
187 parent_view->set_context_menu_controller(&controller);
188 widget.SetContentsView(parent_view);
190 View* gesture_handling_child_view = new GestureHandlingView;
191 gesture_handling_child_view->SetBoundsRect(gfx::Rect(10, 10));
192 parent_view->AddChildView(gesture_handling_child_view);
194 View* other_child_view = new View;
195 other_child_view->SetBoundsRect(gfx::Rect(20, 0, 10, 10));
196 parent_view->AddChildView(other_child_view);
198 // |parent_view| should not show a context menu as a result of a long press on
199 // |gesture_handling_child_view|.
200 ui::GestureEvent long_press1(
204 base::TimeDelta(),
205 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
206 ui::EventDispatchDetails details = root_view->OnEventFromSource(&long_press1);
208 ui::GestureEvent end1(
209 5, 5, 0, base::TimeDelta(), ui::GestureEventDetails(ui::ET_GESTURE_END));
210 details = root_view->OnEventFromSource(&end1);
212 EXPECT_FALSE(details.target_destroyed);
213 EXPECT_FALSE(details.dispatcher_destroyed);
214 EXPECT_EQ(0, controller.show_context_menu_calls());
215 controller.Reset();
217 // |parent_view| should show a context menu as a result of a long press on
218 // |other_child_view|.
219 ui::GestureEvent long_press2(
223 base::TimeDelta(),
224 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
225 details = root_view->OnEventFromSource(&long_press2);
227 ui::GestureEvent end2(
228 25, 5, 0, base::TimeDelta(), ui::GestureEventDetails(ui::ET_GESTURE_END));
229 details = root_view->OnEventFromSource(&end2);
231 EXPECT_FALSE(details.target_destroyed);
232 EXPECT_FALSE(details.dispatcher_destroyed);
233 EXPECT_EQ(1, controller.show_context_menu_calls());
234 controller.Reset();
236 // |parent_view| should show a context menu as a result of a long press on
237 // itself.
238 ui::GestureEvent long_press3(
242 base::TimeDelta(),
243 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
244 details = root_view->OnEventFromSource(&long_press3);
246 ui::GestureEvent end3(
247 25, 5, 0, base::TimeDelta(), ui::GestureEventDetails(ui::ET_GESTURE_END));
248 details = root_view->OnEventFromSource(&end3);
250 EXPECT_FALSE(details.target_destroyed);
251 EXPECT_FALSE(details.dispatcher_destroyed);
252 EXPECT_EQ(1, controller.show_context_menu_calls());
255 // Tests that context menus are not shown for disabled views on a long press.
256 TEST_F(RootViewTest, ContextMenuFromLongPressOnDisabledView) {
257 Widget widget;
258 Widget::InitParams init_params =
259 CreateParams(Widget::InitParams::TYPE_POPUP);
260 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
261 init_params.bounds = gfx::Rect(100, 100);
262 widget.Init(init_params);
263 internal::RootView* root_view =
264 static_cast<internal::RootView*>(widget.GetRootView());
266 // Create a view capable of showing the context menu with two children one of
267 // which handles all gesture events (e.g. a button). Also mark this view
268 // as disabled.
269 TestContextMenuController controller;
270 View* parent_view = new View;
271 parent_view->set_context_menu_controller(&controller);
272 parent_view->SetEnabled(false);
273 widget.SetContentsView(parent_view);
275 View* gesture_handling_child_view = new GestureHandlingView;
276 gesture_handling_child_view->SetBoundsRect(gfx::Rect(10, 10));
277 parent_view->AddChildView(gesture_handling_child_view);
279 View* other_child_view = new View;
280 other_child_view->SetBoundsRect(gfx::Rect(20, 0, 10, 10));
281 parent_view->AddChildView(other_child_view);
283 // |parent_view| should not show a context menu as a result of a long press on
284 // |gesture_handling_child_view|.
285 ui::GestureEvent long_press1(
289 base::TimeDelta(),
290 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
291 ui::EventDispatchDetails details = root_view->OnEventFromSource(&long_press1);
293 ui::GestureEvent end1(
294 5, 5, 0, base::TimeDelta(), ui::GestureEventDetails(ui::ET_GESTURE_END));
295 details = root_view->OnEventFromSource(&end1);
297 EXPECT_FALSE(details.target_destroyed);
298 EXPECT_FALSE(details.dispatcher_destroyed);
299 EXPECT_EQ(0, controller.show_context_menu_calls());
300 controller.Reset();
302 // |parent_view| should not show a context menu as a result of a long press on
303 // |other_child_view|.
304 ui::GestureEvent long_press2(
308 base::TimeDelta(),
309 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
310 details = root_view->OnEventFromSource(&long_press2);
312 ui::GestureEvent end2(
313 25, 5, 0, base::TimeDelta(), ui::GestureEventDetails(ui::ET_GESTURE_END));
314 details = root_view->OnEventFromSource(&end2);
316 EXPECT_FALSE(details.target_destroyed);
317 EXPECT_FALSE(details.dispatcher_destroyed);
318 EXPECT_EQ(0, controller.show_context_menu_calls());
319 controller.Reset();
321 // |parent_view| should not show a context menu as a result of a long press on
322 // itself.
323 ui::GestureEvent long_press3(
327 base::TimeDelta(),
328 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
329 details = root_view->OnEventFromSource(&long_press3);
331 ui::GestureEvent end3(
332 25, 5, 0, base::TimeDelta(), ui::GestureEventDetails(ui::ET_GESTURE_END));
333 details = root_view->OnEventFromSource(&end3);
335 EXPECT_FALSE(details.target_destroyed);
336 EXPECT_FALSE(details.dispatcher_destroyed);
337 EXPECT_EQ(0, controller.show_context_menu_calls());
340 } // namespace test
341 } // namespace views