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

Side by Side Diff: views/controls/menu/menu_controller.cc

Issue 8597010: Send fake event when event_type is set to exit menu (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use xdisplay_ Created 9 years, 1 month 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
« no previous file with comments | « views/controls/menu/menu_controller.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "views/controls/menu/menu_controller.h" 5 #include "views/controls/menu/menu_controller.h"
6 6
7 #include "base/i18n/case_conversion.h" 7 #include "base/i18n/case_conversion.h"
8 #include "base/i18n/rtl.h" 8 #include "base/i18n/rtl.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
11 #include "ui/base/dragdrop/os_exchange_data.h" 11 #include "ui/base/dragdrop/os_exchange_data.h"
12 #include "ui/base/events.h" 12 #include "ui/base/events.h"
13 #include "ui/base/keycodes/keyboard_codes.h" 13 #include "ui/base/keycodes/keyboard_codes.h"
14 #include "ui/base/l10n/l10n_util.h" 14 #include "ui/base/l10n/l10n_util.h"
15 #include "ui/gfx/canvas_skia.h" 15 #include "ui/gfx/canvas_skia.h"
16 #include "ui/gfx/screen.h" 16 #include "ui/gfx/screen.h"
17 #include "views/controls/button/menu_button.h" 17 #include "views/controls/button/menu_button.h"
18 #include "views/controls/menu/menu_controller_delegate.h" 18 #include "views/controls/menu/menu_controller_delegate.h"
19 #include "views/controls/menu/menu_scroll_view_container.h" 19 #include "views/controls/menu/menu_scroll_view_container.h"
20 #include "views/controls/menu/submenu_view.h" 20 #include "views/controls/menu/submenu_view.h"
21 #include "views/drag_utils.h" 21 #include "views/drag_utils.h"
22 #include "views/view_constants.h" 22 #include "views/view_constants.h"
23 #include "views/views_delegate.h" 23 #include "views/views_delegate.h"
24 #include "views/widget/root_view.h" 24 #include "views/widget/root_view.h"
25 #include "views/widget/widget.h" 25 #include "views/widget/widget.h"
26 26
27 #if defined(USE_AURA) && !defined(OS_WIN) 27 #if defined(USE_AURA)
28 #include "ui/aura/desktop.h" 28 #include "ui/aura/desktop.h"
29 #endif 29 #endif
30 30
31 #if defined(OS_LINUX) 31 #if defined(TOOLKIT_USES_GTK)
32 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h" 32 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
33 #endif 33 #endif
34 34
35 #if defined(TOUCH_UI) 35 #if defined(TOUCH_UI)
36 #include "views/focus/accelerator_handler.h" 36 #include "views/focus/accelerator_handler.h"
37 #endif 37 #endif
38 38
39 using base::Time; 39 using base::Time;
40 using base::TimeDelta; 40 using base::TimeDelta;
41 using ui::OSExchangeData; 41 using ui::OSExchangeData;
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 } 341 }
342 342
343 MenuItemView* result = result_; 343 MenuItemView* result = result_;
344 // In case we're nested, reset result_. 344 // In case we're nested, reset result_.
345 result_ = NULL; 345 result_ = NULL;
346 346
347 if (result_mouse_event_flags) 347 if (result_mouse_event_flags)
348 *result_mouse_event_flags = result_mouse_event_flags_; 348 *result_mouse_event_flags = result_mouse_event_flags_;
349 349
350 if (exit_type_ == EXIT_OUTERMOST) { 350 if (exit_type_ == EXIT_OUTERMOST) {
351 exit_type_ = EXIT_NONE; 351 SetExitType(EXIT_NONE);
352 } else { 352 } else {
353 if (nested_menu && result) { 353 if (nested_menu && result) {
354 // We're nested and about to return a value. The caller might enter 354 // We're nested and about to return a value. The caller might enter
355 // another blocking loop. We need to make sure all menus are hidden 355 // another blocking loop. We need to make sure all menus are hidden
356 // before that happens otherwise the menus will stay on screen. 356 // before that happens otherwise the menus will stay on screen.
357 CloseAllNestedMenus(); 357 CloseAllNestedMenus();
358 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); 358 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
359 359
360 // Set exit_all_, which makes sure all nested loops exit immediately. 360 // Set exit_all_, which makes sure all nested loops exit immediately.
361 if (exit_type_ != EXIT_DESTROYED) 361 if (exit_type_ != EXIT_DESTROYED)
362 exit_type_ = EXIT_ALL; 362 SetExitType(EXIT_ALL);
363 } 363 }
364 } 364 }
365 365
366 // If we stopped running because one of the menus was destroyed chances are 366 // If we stopped running because one of the menus was destroyed chances are
367 // the button was also destroyed. 367 // the button was also destroyed.
368 if (exit_type_ != EXIT_DESTROYED && menu_button_) { 368 if (exit_type_ != EXIT_DESTROYED && menu_button_) {
369 menu_button_->SetState(CustomButton::BS_NORMAL); 369 menu_button_->SetState(CustomButton::BS_NORMAL);
370 menu_button_->SchedulePaint(); 370 menu_button_->SchedulePaint();
371 } 371 }
372 372
373 return result; 373 return result;
374 } 374 }
375 375
376 void MenuController::Cancel(ExitType type) { 376 void MenuController::Cancel(ExitType type) {
377 // If the menu has already been destroyed, no further cancellation is 377 // If the menu has already been destroyed, no further cancellation is
378 // needed. We especially don't want to set the |exit_type_| to a lesser 378 // needed. We especially don't want to set the |exit_type_| to a lesser
379 // value. 379 // value.
380 if (exit_type_ == EXIT_DESTROYED || exit_type_ == type) 380 if (exit_type_ == EXIT_DESTROYED || exit_type_ == type)
381 return; 381 return;
382 382
383 if (!showing_) { 383 if (!showing_) {
384 // This occurs if we're in the process of notifying the delegate for a drop 384 // This occurs if we're in the process of notifying the delegate for a drop
385 // and the delegate cancels us. 385 // and the delegate cancels us.
386 return; 386 return;
387 } 387 }
388 388
389 MenuItemView* selected = state_.item; 389 MenuItemView* selected = state_.item;
390 exit_type_ = type; 390 SetExitType(type);
391 391
392 SendMouseCaptureLostToActiveView(); 392 SendMouseCaptureLostToActiveView();
393 393
394 // Hide windows immediately. 394 // Hide windows immediately.
395 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); 395 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
396 396
397 if (!blocking_run_) { 397 if (!blocking_run_) {
398 // If we didn't block the caller we need to notify the menu, which 398 // If we didn't block the caller we need to notify the menu, which
399 // triggers deleting us. 399 // triggers deleting us.
400 DCHECK(selected); 400 DCHECK(selected);
(...skipping 18 matching lines...) Expand all
419 return; // Ignore presses on scroll buttons. 419 return; // Ignore presses on scroll buttons.
420 420
421 if (part.type == MenuPart::NONE || 421 if (part.type == MenuPart::NONE ||
422 (part.type == MenuPart::MENU_ITEM && part.menu && 422 (part.type == MenuPart::MENU_ITEM && part.menu &&
423 part.menu->GetRootMenuItem() != state_.item->GetRootMenuItem())) { 423 part.menu->GetRootMenuItem() != state_.item->GetRootMenuItem())) {
424 // Mouse wasn't pressed over any menu, or the active menu, cancel. 424 // Mouse wasn't pressed over any menu, or the active menu, cancel.
425 425
426 // We're going to close and we own the mouse capture. We need to repost the 426 // We're going to close and we own the mouse capture. We need to repost the
427 // mouse down, otherwise the window the user clicked on won't get the 427 // mouse down, otherwise the window the user clicked on won't get the
428 // event. 428 // event.
429 #if defined(OS_WIN) 429 #if defined(OS_WIN) && !defined(USE_AURA)
430 RepostEvent(source, event); 430 RepostEvent(source, event);
431 // NOTE: not reposting on linux seems fine. 431 // NOTE: not reposting on linux seems fine.
432 #endif 432 #endif
433 433
434 // And close. 434 // And close.
435 ExitType exit_type = EXIT_ALL; 435 ExitType exit_type = EXIT_ALL;
436 if (!menu_stack_.empty()) { 436 if (!menu_stack_.empty()) {
437 // We're running nested menus. Only exit all if the mouse wasn't over one 437 // We're running nested menus. Only exit all if the mouse wasn't over one
438 // of the menus from the last run. 438 // of the menus from the last run.
439 gfx::Point screen_loc(event.location()); 439 gfx::Point screen_loc(event.location());
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 713
714 MenuItemView* drop_target = drop_target_; 714 MenuItemView* drop_target = drop_target_;
715 MenuDelegate::DropPosition drop_position = drop_position_; 715 MenuDelegate::DropPosition drop_position = drop_position_;
716 716
717 // Close all menus, including any nested menus. 717 // Close all menus, including any nested menus.
718 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); 718 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
719 CloseAllNestedMenus(); 719 CloseAllNestedMenus();
720 720
721 // Set state such that we exit. 721 // Set state such that we exit.
722 showing_ = false; 722 showing_ = false;
723 exit_type_ = EXIT_ALL; 723 SetExitType(EXIT_ALL);
724 724
725 // If over an empty menu item, drop occurs on the parent. 725 // If over an empty menu item, drop occurs on the parent.
726 if (drop_target->id() == MenuItemView::kEmptyMenuItemViewID) 726 if (drop_target->id() == MenuItemView::kEmptyMenuItemViewID)
727 drop_target = drop_target->GetParentMenuItem(); 727 drop_target = drop_target->GetParentMenuItem();
728 728
729 if (!IsBlockingRun()) { 729 if (!IsBlockingRun()) {
730 delegate_->DropMenuClosed( 730 delegate_->DropMenuClosed(
731 internal::MenuControllerDelegate::DONT_NOTIFY_DELEGATE, 731 internal::MenuControllerDelegate::DONT_NOTIFY_DELEGATE,
732 item->GetRootMenuItem()); 732 item->GetRootMenuItem());
733 } 733 }
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 // avoid repeated system queries for the info. 1094 // avoid repeated system queries for the info.
1095 pending_state_.monitor_bounds = gfx::Screen::GetMonitorWorkAreaNearestPoint( 1095 pending_state_.monitor_bounds = gfx::Screen::GetMonitorWorkAreaNearestPoint(
1096 bounds.origin()); 1096 bounds.origin());
1097 } 1097 }
1098 1098
1099 void MenuController::Accept(MenuItemView* item, int mouse_event_flags) { 1099 void MenuController::Accept(MenuItemView* item, int mouse_event_flags) {
1100 DCHECK(IsBlockingRun()); 1100 DCHECK(IsBlockingRun());
1101 result_ = item; 1101 result_ = item;
1102 if (item && !menu_stack_.empty() && 1102 if (item && !menu_stack_.empty() &&
1103 !item->GetDelegate()->ShouldCloseAllMenusOnExecute(item->GetCommand())) { 1103 !item->GetDelegate()->ShouldCloseAllMenusOnExecute(item->GetCommand())) {
1104 exit_type_ = EXIT_OUTERMOST; 1104 SetExitType(EXIT_OUTERMOST);
1105 } else { 1105 } else {
1106 exit_type_ = EXIT_ALL; 1106 SetExitType(EXIT_ALL);
1107 } 1107 }
1108 result_mouse_event_flags_ = mouse_event_flags; 1108 result_mouse_event_flags_ = mouse_event_flags;
1109 } 1109 }
1110 1110
1111 bool MenuController::ShowSiblingMenu(SubmenuView* source, 1111 bool MenuController::ShowSiblingMenu(SubmenuView* source,
1112 const MouseEvent& event) { 1112 const MouseEvent& event) {
1113 if (!menu_stack_.empty() || !menu_button_) 1113 if (!menu_stack_.empty() || !menu_button_)
1114 return false; 1114 return false;
1115 1115
1116 View* source_view = source->GetScrollViewContainer(); 1116 View* source_view = source->GetScrollViewContainer();
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after
1775 } 1775 }
1776 1776
1777 // If no mnemonics found, look at first character of titles. 1777 // If no mnemonics found, look at first character of titles.
1778 details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic); 1778 details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic);
1779 if (details.first_match != -1) 1779 if (details.first_match != -1)
1780 return AcceptOrSelect(item, details); 1780 return AcceptOrSelect(item, details);
1781 1781
1782 return false; 1782 return false;
1783 } 1783 }
1784 1784
1785 #if defined(OS_WIN) 1785 #if defined(OS_WIN) && !defined(USE_AURA)
1786 #if defined(USE_AURA)
1787 void MenuController::RepostEvent(SubmenuView* source,
1788 const MouseEvent& event) {
1789 }
1790 #else
1791 void MenuController::RepostEvent(SubmenuView* source, 1786 void MenuController::RepostEvent(SubmenuView* source,
1792 const MouseEvent& event) { 1787 const MouseEvent& event) {
1793 if (!state_.item) { 1788 if (!state_.item) {
1794 // We some times get an event after closing all the menus. Ignore it. 1789 // We some times get an event after closing all the menus. Ignore it.
1795 // Make sure the menu is in fact not visible. If the menu is visible, then 1790 // Make sure the menu is in fact not visible. If the menu is visible, then
1796 // we're in a bad state where we think the menu isn't visibile but it is. 1791 // we're in a bad state where we think the menu isn't visibile but it is.
1797 DCHECK(!source->GetWidget()->IsVisible()); 1792 DCHECK(!source->GetWidget()->IsVisible());
1798 return; 1793 return;
1799 } 1794 }
1800 1795
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1847 if (in_client_area) { 1842 if (in_client_area) {
1848 PostMessage(window, event_type, event.native_event().wParam, 1843 PostMessage(window, event_type, event.native_event().wParam,
1849 MAKELPARAM(window_x, window_y)); 1844 MAKELPARAM(window_x, window_y));
1850 } else { 1845 } else {
1851 PostMessage(window, event_type, nc_hit_result, 1846 PostMessage(window, event_type, nc_hit_result,
1852 MAKELPARAM(screen_loc.x(), screen_loc.y())); 1847 MAKELPARAM(screen_loc.x(), screen_loc.y()));
1853 } 1848 }
1854 } 1849 }
1855 } 1850 }
1856 } 1851 }
1857 #endif // !defined(USE_AURA)
1858 #endif // defined(OS_WIN) 1852 #endif // defined(OS_WIN)
1859 1853
1860 void MenuController::SetDropMenuItem( 1854 void MenuController::SetDropMenuItem(
1861 MenuItemView* new_target, 1855 MenuItemView* new_target,
1862 MenuDelegate::DropPosition new_position) { 1856 MenuDelegate::DropPosition new_position) {
1863 if (new_target == drop_target_ && new_position == drop_position_) 1857 if (new_target == drop_target_ && new_position == drop_position_)
1864 return; 1858 return;
1865 1859
1866 if (drop_target_) { 1860 if (drop_target_) {
1867 drop_target_->GetParentMenuItem()->GetSubmenu()->SetDropMenuItem( 1861 drop_target_->GetParentMenuItem()->GetSubmenu()->SetDropMenuItem(
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1954 if (!active_mouse_view_) 1948 if (!active_mouse_view_)
1955 return; 1949 return;
1956 1950
1957 // Reset the active_mouse_view_ before sending mouse capture lost. That way if 1951 // Reset the active_mouse_view_ before sending mouse capture lost. That way if
1958 // it calls back to us, we aren't in a weird state. 1952 // it calls back to us, we aren't in a weird state.
1959 View* active_view = active_mouse_view_; 1953 View* active_view = active_mouse_view_;
1960 active_mouse_view_ = NULL; 1954 active_mouse_view_ = NULL;
1961 active_view->OnMouseCaptureLost(); 1955 active_view->OnMouseCaptureLost();
1962 } 1956 }
1963 1957
1958 void MenuController::SetExitType(ExitType type) {
1959 exit_type_ = type;
1960 #if defined(USE_AURA)
1961 // On aura, closing menu may not trigger next native event, which
1962 // is necessary to exit from nested loop (See Dispatch methods).
1963 // Send non-op event so that Dispatch method will always be called.
1964 // crbug.com/104684.
1965 if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED)
1966 aura::Desktop::GetInstance()->PostNativeEvent(ui::CreateNoopEvent());
1967 #endif
1968 }
1969
1970
1964 } // namespace views 1971 } // namespace views
OLDNEW
« no previous file with comments | « views/controls/menu/menu_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698