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

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

Issue 1230163004: Selects last item in a menu when pressing 'up' initially (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Selects last item in a menu when pressing 'up' initially (comments) Created 5 years, 5 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
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 "base/strings/utf_string_conversions.h" 8 #include "base/strings/utf_string_conversions.h"
9 #include "ui/events/event_handler.h" 9 #include "ui/events/event_handler.h"
10 #include "ui/events/null_event_targeter.h" 10 #include "ui/events/null_event_targeter.h"
(...skipping 28 matching lines...) Expand all
39 39
40 class TestMenuItemView : public MenuItemView { 40 class TestMenuItemView : public MenuItemView {
41 public: 41 public:
42 TestMenuItemView() : MenuItemView(nullptr) {} 42 TestMenuItemView() : MenuItemView(nullptr) {}
43 ~TestMenuItemView() override {} 43 ~TestMenuItemView() override {}
44 44
45 private: 45 private:
46 DISALLOW_COPY_AND_ASSIGN(TestMenuItemView); 46 DISALLOW_COPY_AND_ASSIGN(TestMenuItemView);
47 }; 47 };
48 48
49 class SubmenuViewShown : public SubmenuView {
50 public:
51 SubmenuViewShown(MenuItemView* parent) : SubmenuView(parent) {}
52 ~SubmenuViewShown() override {}
53 bool IsShowing() override { return true; }
54
55 private:
56 DISALLOW_COPY_AND_ASSIGN(SubmenuViewShown);
57 };
58
59 class TestMenuItemViewShown : public MenuItemView {
60 public:
61 TestMenuItemViewShown() : MenuItemView(nullptr) {
62 submenu_ = new SubmenuViewShown(this);
63 }
64 ~TestMenuItemViewShown() override {}
65
66 private:
67 DISALLOW_COPY_AND_ASSIGN(TestMenuItemViewShown);
68 };
69
49 class TestPlatformEventSource : public ui::PlatformEventSource { 70 class TestPlatformEventSource : public ui::PlatformEventSource {
50 public: 71 public:
51 TestPlatformEventSource() { 72 TestPlatformEventSource() {
52 #if defined(USE_X11) 73 #if defined(USE_X11)
53 ui::DeviceDataManagerX11::CreateInstance(); 74 ui::DeviceDataManagerX11::CreateInstance();
54 #endif 75 #endif
55 } 76 }
56 ~TestPlatformEventSource() override {} 77 ~TestPlatformEventSource() override {}
57 78
58 uint32_t Dispatch(const ui::PlatformEvent& event) { 79 uint32_t Dispatch(const ui::PlatformEvent& event) {
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 #endif 184 #endif
164 return widget.Pass(); 185 return widget.Pass();
165 } 186 }
166 187
167 const MenuItemView* pending_state_item() const { 188 const MenuItemView* pending_state_item() const {
168 return controller_->pending_state_.item; 189 return controller_->pending_state_.item;
169 } 190 }
170 191
171 void SetPendingStateItem(MenuItemView* item) { 192 void SetPendingStateItem(MenuItemView* item) {
172 controller_->pending_state_.item = item; 193 controller_->pending_state_.item = item;
194 controller_->pending_state_.submenu_open = true;
173 } 195 }
174 196
175 void ResetSelection() { 197 void ResetSelection() {
176 controller_->SetSelection(nullptr, 198 controller_->SetSelection(nullptr,
177 MenuController::SELECTION_EXIT | 199 MenuController::SELECTION_EXIT |
178 MenuController::SELECTION_UPDATE_IMMEDIATELY); 200 MenuController::SELECTION_UPDATE_IMMEDIATELY);
179 } 201 }
180 202
181 void IncrementSelection(int delta) { 203 void IncrementSelection() {
182 controller_->IncrementSelection(delta); 204 controller_->IncrementSelection(MenuController::INCREMENT_SELECTION_DOWN);
183 } 205 }
184 206
185 MenuItemView* FindFirstSelectableMenuItem(MenuItemView* parent) { 207 void DecrementSelection() {
186 return controller_->FindFirstSelectableMenuItem(parent); 208 controller_->IncrementSelection(MenuController::INCREMENT_SELECTION_UP);
209 }
210
211 MenuItemView* FindInitialSelectableMenuItemDown(MenuItemView* parent) {
212 return controller_->FindInitialSelectableMenuItem(
213 parent, MenuController::INCREMENT_SELECTION_DOWN);
214 }
215
216 MenuItemView* FindInitialSelectableMenuItemUp(MenuItemView* parent) {
217 return controller_->FindInitialSelectableMenuItem(
218 parent, MenuController::INCREMENT_SELECTION_UP);
187 } 219 }
188 220
189 MenuItemView* FindNextSelectableMenuItem(MenuItemView* parent, 221 MenuItemView* FindNextSelectableMenuItem(MenuItemView* parent,
190 int index, 222 int index) {
191 int delta) { 223 return controller_->FindNextSelectableMenuItem(
192 return controller_->FindNextSelectableMenuItem(parent, index, delta); 224 parent, index, MenuController::INCREMENT_SELECTION_DOWN);
193 } 225 }
226
227 MenuItemView* FindPreviousSelectableMenuItem(MenuItemView* parent,
228 int index) {
229 return controller_->FindNextSelectableMenuItem(
230 parent, index, MenuController::INCREMENT_SELECTION_UP);
231 }
232
194 void SetupMenu(views::Widget* owner, views::MenuItemView* item) { 233 void SetupMenu(views::Widget* owner, views::MenuItemView* item) {
195 ResetMenuController(); 234 ResetMenuController();
196 controller_ = new MenuController(nullptr, true, nullptr); 235 controller_ = new MenuController(nullptr, true, nullptr);
197 controller_->owner_ = owner; 236 controller_->owner_ = owner;
198 controller_->showing_ = true; 237 controller_->showing_ = true;
199 controller_->SetSelection(item, 238 controller_->SetSelection(item,
200 MenuController::SELECTION_UPDATE_IMMEDIATELY); 239 MenuController::SELECTION_UPDATE_IMMEDIATELY);
201 } 240 }
202 241
203 void RunMenu(views::Widget* owner) { 242 void RunMenu(views::Widget* owner) {
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 break; 373 break;
335 } 374 }
336 } 375 }
337 376
338 int outstanding_touches() const { return outstanding_touches_; } 377 int outstanding_touches() const { return outstanding_touches_; }
339 378
340 private: 379 private:
341 int outstanding_touches_; 380 int outstanding_touches_;
342 }; 381 };
343 382
344 // Tests that touch event ids are released correctly. See 383 // Tests that touch event ids are released correctly. See crbug.com/439051 for
345 // crbug.com/439051 for details. When the ids aren't managed 384 // details. When the ids aren't managed correctly, we get stuck down touches.
346 // correctly, we get stuck down touches.
347 TEST_F(MenuControllerTest, TouchIdsReleasedCorrectly) { 385 TEST_F(MenuControllerTest, TouchIdsReleasedCorrectly) {
348 scoped_ptr<Widget> owner(CreateOwnerWidget()); 386 scoped_ptr<Widget> owner(CreateOwnerWidget());
349 TestEventHandler test_event_handler; 387 TestEventHandler test_event_handler;
350 owner->GetNativeWindow()->GetRootWindow()->AddPreTargetHandler( 388 owner->GetNativeWindow()->GetRootWindow()->AddPreTargetHandler(
351 &test_event_handler); 389 &test_event_handler);
352 390
353 std::vector<int> devices; 391 std::vector<int> devices;
354 devices.push_back(1); 392 devices.push_back(1);
355 ui::SetUpTouchDevicesForTest(devices); 393 ui::SetUpTouchDevicesForTest(devices);
356 394
(...skipping 11 matching lines...) Expand all
368 base::Unretained(this), MenuController::EXIT_OUTERMOST)); 406 base::Unretained(this), MenuController::EXIT_OUTERMOST));
369 407
370 RunMenu(owner.get()); 408 RunMenu(owner.get());
371 EXPECT_EQ(0, test_event_handler.outstanding_touches()); 409 EXPECT_EQ(0, test_event_handler.outstanding_touches());
372 410
373 owner->GetNativeWindow()->GetRootWindow()->RemovePreTargetHandler( 411 owner->GetNativeWindow()->GetRootWindow()->RemovePreTargetHandler(
374 &test_event_handler); 412 &test_event_handler);
375 } 413 }
376 #endif // defined(USE_X11) 414 #endif // defined(USE_X11)
377 415
378 TEST_F(MenuControllerTest, FirstSelectedItem) { 416 // Tests that initial selected menu items are correct when items are enabled or
417 // disabled.
418 TEST_F(MenuControllerTest, InitialSelectedItem) {
379 scoped_ptr<Widget> owner(CreateOwnerWidget()); 419 scoped_ptr<Widget> owner(CreateOwnerWidget());
380 scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView); 420 scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView);
381 menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One")); 421 menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One"));
382 menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two")); 422 menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two"));
383 // Disabling the item "One" gets it skipped when a menu is first opened. 423 menu_item->AppendMenuItemWithLabel(3, base::ASCIIToUTF16("Three"));
384 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(false);
385
386 SetupMenu(owner.get(), menu_item.get()); 424 SetupMenu(owner.get(), menu_item.get());
387 425
388 // First selectable item should be item "Two". 426 // Leave items "Two" and "Three" enabled.
389 MenuItemView* first_selectable = FindFirstSelectableMenuItem(menu_item.get()); 427 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(false);
428 // The first selectable item should be item "Two".
429 MenuItemView* first_selectable =
430 FindInitialSelectableMenuItemDown(menu_item.get());
431 ASSERT_NE(nullptr, first_selectable);
390 EXPECT_EQ(2, first_selectable->GetCommand()); 432 EXPECT_EQ(2, first_selectable->GetCommand());
433 // The last selectable item should be item "Three".
434 MenuItemView* last_selectable =
435 FindInitialSelectableMenuItemUp(menu_item.get());
436 ASSERT_NE(nullptr, last_selectable);
437 EXPECT_EQ(3, last_selectable->GetCommand());
438
439 // Leave items "One" and "Two" enabled.
440 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(true);
441 menu_item->GetSubmenu()->GetMenuItemAt(1)->SetEnabled(true);
442 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(false);
443 // The first selectable item should be item "One".
444 first_selectable = FindInitialSelectableMenuItemDown(menu_item.get());
445 ASSERT_NE(nullptr, first_selectable);
446 EXPECT_EQ(1, first_selectable->GetCommand());
447 // The last selectable item should be item "Two".
448 last_selectable = FindInitialSelectableMenuItemUp(menu_item.get());
449 ASSERT_NE(nullptr, last_selectable);
450 EXPECT_EQ(2, last_selectable->GetCommand());
451
452 // Leave only a single item "One" enabled.
453 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(true);
454 menu_item->GetSubmenu()->GetMenuItemAt(1)->SetEnabled(false);
455 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(false);
456 // The first selectable item should be item "One".
457 first_selectable = FindInitialSelectableMenuItemDown(menu_item.get());
458 ASSERT_NE(nullptr, first_selectable);
459 EXPECT_EQ(1, first_selectable->GetCommand());
460 // The last selectable item should be item "One".
461 last_selectable = FindInitialSelectableMenuItemUp(menu_item.get());
462 ASSERT_NE(nullptr, last_selectable);
463 EXPECT_EQ(1, last_selectable->GetCommand());
464
465 // Leave only a single item "Three" enabled.
466 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(false);
467 menu_item->GetSubmenu()->GetMenuItemAt(1)->SetEnabled(false);
468 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(true);
469 // The first selectable item should be item "Three".
470 first_selectable = FindInitialSelectableMenuItemDown(menu_item.get());
471 ASSERT_NE(nullptr, first_selectable);
472 EXPECT_EQ(3, first_selectable->GetCommand());
473 // The last selectable item should be item "Three".
474 last_selectable = FindInitialSelectableMenuItemUp(menu_item.get());
475 ASSERT_NE(nullptr, last_selectable);
476 EXPECT_EQ(3, last_selectable->GetCommand());
477
478 // Leave only a single item ("Two") selected. It should be the first and the
479 // last selectable item.
480 menu_item->GetSubmenu()->GetMenuItemAt(0)->SetEnabled(false);
481 menu_item->GetSubmenu()->GetMenuItemAt(1)->SetEnabled(true);
482 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(false);
483 first_selectable = FindInitialSelectableMenuItemDown(menu_item.get());
484 ASSERT_NE(nullptr, first_selectable);
485 EXPECT_EQ(2, first_selectable->GetCommand());
486 last_selectable = FindInitialSelectableMenuItemUp(menu_item.get());
487 ASSERT_NE(nullptr, last_selectable);
488 EXPECT_EQ(2, last_selectable->GetCommand());
391 489
392 // There should be no next or previous selectable item since there is only a 490 // There should be no next or previous selectable item since there is only a
393 // single enabled item in the menu. 491 // single enabled item in the menu.
394 SetPendingStateItem(first_selectable); 492 EXPECT_EQ(nullptr, FindNextSelectableMenuItem(menu_item.get(), 1));
395 EXPECT_EQ(nullptr, FindNextSelectableMenuItem(menu_item.get(), 1, 1)); 493 EXPECT_EQ(nullptr, FindPreviousSelectableMenuItem(menu_item.get(), 1));
396 EXPECT_EQ(nullptr, FindNextSelectableMenuItem(menu_item.get(), 1, -1));
397 494
398 // Clear references in menu controller to the menu item that is going away. 495 // Clear references in menu controller to the menu item that is going away.
399 ResetSelection(); 496 ResetSelection();
400 } 497 }
401 498
499 // Tests that opening menu and pressing 'Down' and 'Up' iterates over enabled
500 // items.
402 TEST_F(MenuControllerTest, NextSelectedItem) { 501 TEST_F(MenuControllerTest, NextSelectedItem) {
403 scoped_ptr<Widget> owner(CreateOwnerWidget()); 502 scoped_ptr<Widget> owner(CreateOwnerWidget());
404 scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView); 503 scoped_ptr<TestMenuItemView> menu_item(new TestMenuItemView);
405 menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One")); 504 menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One"));
406 menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two")); 505 menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two"));
407 menu_item->AppendMenuItemWithLabel(3, base::ASCIIToUTF16("Three")); 506 menu_item->AppendMenuItemWithLabel(3, base::ASCIIToUTF16("Three"));
408 menu_item->AppendMenuItemWithLabel(4, base::ASCIIToUTF16("Four")); 507 menu_item->AppendMenuItemWithLabel(4, base::ASCIIToUTF16("Four"));
409 // Disabling the item "Three" gets it skipped when using keyboard to navigate. 508 // Disabling the item "Three" gets it skipped when using keyboard to navigate.
410 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(false); 509 menu_item->GetSubmenu()->GetMenuItemAt(2)->SetEnabled(false);
411 510
412 SetupMenu(owner.get(), menu_item.get()); 511 SetupMenu(owner.get(), menu_item.get());
413 512
414 // Fake initial hot selection. 513 // Fake initial hot selection.
415 SetPendingStateItem(menu_item->GetSubmenu()->GetMenuItemAt(0)); 514 SetPendingStateItem(menu_item->GetSubmenu()->GetMenuItemAt(0));
416 EXPECT_EQ(1, pending_state_item()->GetCommand()); 515 EXPECT_EQ(1, pending_state_item()->GetCommand());
417 516
418 // Move down in the menu. 517 // Move down in the menu.
419 // Select next item. 518 // Select next item.
420 IncrementSelection(1); 519 IncrementSelection();
421 EXPECT_EQ(2, pending_state_item()->GetCommand()); 520 EXPECT_EQ(2, pending_state_item()->GetCommand());
422 521
423 // Skip disabled item. 522 // Skip disabled item.
424 IncrementSelection(1); 523 IncrementSelection();
425 EXPECT_EQ(4, pending_state_item()->GetCommand()); 524 EXPECT_EQ(4, pending_state_item()->GetCommand());
426 525
427 // Wrap around. 526 // Wrap around.
428 IncrementSelection(1); 527 IncrementSelection();
429 EXPECT_EQ(1, pending_state_item()->GetCommand()); 528 EXPECT_EQ(1, pending_state_item()->GetCommand());
430 529
431 // Move up in the menu. 530 // Move up in the menu.
432 // Wrap around. 531 // Wrap around.
433 IncrementSelection(-1); 532 DecrementSelection();
434 EXPECT_EQ(4, pending_state_item()->GetCommand()); 533 EXPECT_EQ(4, pending_state_item()->GetCommand());
435 534
436 // Skip disabled item. 535 // Skip disabled item.
437 IncrementSelection(-1); 536 DecrementSelection();
438 EXPECT_EQ(2, pending_state_item()->GetCommand()); 537 EXPECT_EQ(2, pending_state_item()->GetCommand());
439 538
440 // Select previous item. 539 // Select previous item.
441 IncrementSelection(-1); 540 DecrementSelection();
442 EXPECT_EQ(1, pending_state_item()->GetCommand()); 541 EXPECT_EQ(1, pending_state_item()->GetCommand());
443 542
444 // Clear references in menu controller to the menu item that is going away. 543 // Clear references in menu controller to the menu item that is going away.
445 ResetSelection(); 544 ResetSelection();
446 } 545 }
447 546
547 // Tests that opening menu and pressing 'Up' selects the last enabled menu item.
548 TEST_F(MenuControllerTest, PreviousSelectedItem) {
549 scoped_ptr<Widget> owner(CreateOwnerWidget());
550 scoped_ptr<TestMenuItemViewShown> menu_item(new TestMenuItemViewShown);
551 menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One"));
552 menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two"));
553 menu_item->AppendMenuItemWithLabel(3, base::ASCIIToUTF16("Three"));
554 menu_item->AppendMenuItemWithLabel(4, base::ASCIIToUTF16("Four"));
555 // Disabling the item "Four" gets it skipped when using keyboard to navigate.
556 menu_item->GetSubmenu()->GetMenuItemAt(3)->SetEnabled(false);
557
558 SetupMenu(owner.get(), menu_item.get());
559
560 // Fake initial root item selection and submenu showing.
561 SetPendingStateItem(menu_item.get());
562 EXPECT_EQ(0, pending_state_item()->GetCommand());
563
564 // Move up and select a previous (in our case the last enabled) item.
565 DecrementSelection();
566 EXPECT_EQ(3, pending_state_item()->GetCommand());
567
568 // Clear references in menu controller to the menu item that is going away.
569 ResetSelection();
570 }
571
448 } // namespace views 572 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698