OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/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/run_loop.h" | 9 #include "base/run_loop.h" |
10 #include "base/time.h" | 10 #include "base/time.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 // Period of the scroll timer (in milliseconds). | 46 // Period of the scroll timer (in milliseconds). |
47 static const int kScrollTimerMS = 30; | 47 static const int kScrollTimerMS = 30; |
48 | 48 |
49 // Amount of time from when the drop exits the menu and the menu is hidden. | 49 // Amount of time from when the drop exits the menu and the menu is hidden. |
50 static const int kCloseOnExitTime = 1200; | 50 static const int kCloseOnExitTime = 1200; |
51 | 51 |
52 // If a context menu is invoked by touch, we shift the menu by this offset so | 52 // If a context menu is invoked by touch, we shift the menu by this offset so |
53 // that the finger does not obscure the menu. | 53 // that the finger does not obscure the menu. |
54 static const int kCenteredContextMenuYOffset = -15; | 54 static const int kCenteredContextMenuYOffset = -15; |
55 | 55 |
| 56 // When showing context menu on mouse down, the user might accidentally select |
| 57 // the menu item on the subsequent mouse up. To prevent this, we add the |
| 58 // following delay before the user is able to select an item. |
| 59 static const int kContextMenuSelectionHoldTimeMs = 200; |
| 60 |
56 namespace views { | 61 namespace views { |
57 | 62 |
58 namespace { | 63 namespace { |
59 | 64 |
60 // The spacing offset for the bubble tip. | 65 // The spacing offset for the bubble tip. |
61 const int kBubbleTipSizeLeftRight = 12; | 66 const int kBubbleTipSizeLeftRight = 12; |
62 const int kBubbleTipSizeTopBottom = 11; | 67 const int kBubbleTipSizeTopBottom = 11; |
63 | 68 |
64 // Returns true if the mnemonic of |menu| matches key. | 69 // Returns true if the mnemonic of |menu| matches key. |
65 bool MatchesMnemonic(MenuItemView* menu, char16 key) { | 70 bool MatchesMnemonic(MenuItemView* menu, char16 key) { |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 MenuButton* button, | 284 MenuButton* button, |
280 MenuItemView* root, | 285 MenuItemView* root, |
281 const gfx::Rect& bounds, | 286 const gfx::Rect& bounds, |
282 MenuItemView::AnchorPosition position, | 287 MenuItemView::AnchorPosition position, |
283 bool context_menu, | 288 bool context_menu, |
284 int* result_event_flags) { | 289 int* result_event_flags) { |
285 exit_type_ = EXIT_NONE; | 290 exit_type_ = EXIT_NONE; |
286 possible_drag_ = false; | 291 possible_drag_ = false; |
287 drag_in_progress_ = false; | 292 drag_in_progress_ = false; |
288 closing_event_time_ = base::TimeDelta(); | 293 closing_event_time_ = base::TimeDelta(); |
| 294 menu_start_time_ = base::TimeTicks::Now(); |
| 295 |
| 296 // If we are shown on mouse press, we will eat the subsequent mouse down and |
| 297 // the parent widget will not be able to reset its state (it might have mouse |
| 298 // capture from the mouse down). So we clear its state here. |
| 299 if (parent && parent->GetRootView()) |
| 300 parent->GetRootView()->SetMouseHandler(NULL); |
289 | 301 |
290 bool nested_menu = showing_; | 302 bool nested_menu = showing_; |
291 if (showing_) { | 303 if (showing_) { |
292 // Only support nesting of blocking_run menus, nesting of | 304 // Only support nesting of blocking_run menus, nesting of |
293 // blocking/non-blocking shouldn't be needed. | 305 // blocking/non-blocking shouldn't be needed. |
294 DCHECK(blocking_run_); | 306 DCHECK(blocking_run_); |
295 | 307 |
296 // We're already showing, push the current state. | 308 // We're already showing, push the current state. |
297 menu_stack_.push_back(state_); | 309 menu_stack_.push_back(state_); |
298 | 310 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 return; | 501 return; |
490 } | 502 } |
491 if (part.menu->GetDelegate()->ShouldExecuteCommandWithoutClosingMenu( | 503 if (part.menu->GetDelegate()->ShouldExecuteCommandWithoutClosingMenu( |
492 part.menu->GetCommand(), event)) { | 504 part.menu->GetCommand(), event)) { |
493 part.menu->GetDelegate()->ExecuteCommand(part.menu->GetCommand(), | 505 part.menu->GetDelegate()->ExecuteCommand(part.menu->GetCommand(), |
494 event.flags()); | 506 event.flags()); |
495 return; | 507 return; |
496 } | 508 } |
497 if (!part.menu->NonIconChildViewsCount() && | 509 if (!part.menu->NonIconChildViewsCount() && |
498 part.menu->GetDelegate()->IsTriggerableEvent(part.menu, event)) { | 510 part.menu->GetDelegate()->IsTriggerableEvent(part.menu, event)) { |
499 Accept(part.menu, event.flags()); | 511 int64 time_since_menu_start = |
| 512 (base::TimeTicks::Now() - menu_start_time_).InMilliseconds(); |
| 513 if (!state_.context_menu || !View::ShouldShowContextMenuOnMousePress() || |
| 514 time_since_menu_start > kContextMenuSelectionHoldTimeMs) |
| 515 Accept(part.menu, event.flags()); |
500 return; | 516 return; |
501 } | 517 } |
502 } else if (part.type == MenuPart::MENU_ITEM) { | 518 } else if (part.type == MenuPart::MENU_ITEM) { |
503 // User either clicked on empty space, or a menu that has children. | 519 // User either clicked on empty space, or a menu that has children. |
504 SetSelection(part.menu ? part.menu : state_.item, | 520 SetSelection(part.menu ? part.menu : state_.item, |
505 SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); | 521 SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); |
506 } | 522 } |
507 SendMouseCaptureLostToActiveView(); | 523 SendMouseCaptureLostToActiveView(); |
508 } | 524 } |
509 | 525 |
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 possible_drag_(false), | 1102 possible_drag_(false), |
1087 drag_in_progress_(false), | 1103 drag_in_progress_(false), |
1088 valid_drop_coordinates_(false), | 1104 valid_drop_coordinates_(false), |
1089 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), | 1105 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), |
1090 showing_submenu_(false), | 1106 showing_submenu_(false), |
1091 menu_button_(NULL), | 1107 menu_button_(NULL), |
1092 active_mouse_view_(NULL), | 1108 active_mouse_view_(NULL), |
1093 delegate_(delegate), | 1109 delegate_(delegate), |
1094 message_loop_depth_(0), | 1110 message_loop_depth_(0), |
1095 menu_config_(theme), | 1111 menu_config_(theme), |
1096 closing_event_time_(base::TimeDelta()) { | 1112 closing_event_time_(base::TimeDelta()), |
| 1113 menu_start_time_(base::TimeTicks()) { |
1097 active_instance_ = this; | 1114 active_instance_ = this; |
1098 } | 1115 } |
1099 | 1116 |
1100 MenuController::~MenuController() { | 1117 MenuController::~MenuController() { |
1101 DCHECK(!showing_); | 1118 DCHECK(!showing_); |
1102 if (owner_) | 1119 if (owner_) |
1103 owner_->RemoveObserver(this); | 1120 owner_->RemoveObserver(this); |
1104 if (active_instance_ == this) | 1121 if (active_instance_ == this) |
1105 active_instance_ = NULL; | 1122 active_instance_ = NULL; |
1106 StopShowTimer(); | 1123 StopShowTimer(); |
(...skipping 1146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2253 (!pending_state_.item->HasSubmenu() || | 2270 (!pending_state_.item->HasSubmenu() || |
2254 !pending_state_.item->GetSubmenu()->IsShowing())) { | 2271 !pending_state_.item->GetSubmenu()->IsShowing())) { |
2255 // On exit if the user hasn't selected an item with a submenu, move the | 2272 // On exit if the user hasn't selected an item with a submenu, move the |
2256 // selection back to the parent menu item. | 2273 // selection back to the parent menu item. |
2257 SetSelection(pending_state_.item->GetParentMenuItem(), | 2274 SetSelection(pending_state_.item->GetParentMenuItem(), |
2258 SELECTION_OPEN_SUBMENU); | 2275 SELECTION_OPEN_SUBMENU); |
2259 } | 2276 } |
2260 } | 2277 } |
2261 | 2278 |
2262 } // namespace views | 2279 } // namespace views |
OLD | NEW |