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

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

Issue 547303003: Keep reference view pressed while extension actions have a popup (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: VIEWS_EXPORT fix Created 6 years, 3 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
« no previous file with comments | « ui/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) 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/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 } 318 }
319 } 319 }
320 320
321 bool nested_menu = showing_; 321 bool nested_menu = showing_;
322 if (showing_) { 322 if (showing_) {
323 // Only support nesting of blocking_run menus, nesting of 323 // Only support nesting of blocking_run menus, nesting of
324 // blocking/non-blocking shouldn't be needed. 324 // blocking/non-blocking shouldn't be needed.
325 DCHECK(blocking_run_); 325 DCHECK(blocking_run_);
326 326
327 // We're already showing, push the current state. 327 // We're already showing, push the current state.
328 menu_stack_.push_back(state_); 328 menu_stack_.push_back(
329 std::make_pair(state_, make_linked_ptr(pressed_lock_.release())));
329 330
330 // The context menu should be owned by the same parent. 331 // The context menu should be owned by the same parent.
331 DCHECK_EQ(owner_, parent); 332 DCHECK_EQ(owner_, parent);
332 } else { 333 } else {
333 showing_ = true; 334 showing_ = true;
334 } 335 }
335 336
336 // Reset current state. 337 // Reset current state.
337 pending_state_ = State(); 338 pending_state_ = State();
338 state_ = State(); 339 state_ = State();
(...skipping 11 matching lines...) Expand all
350 if (!blocking_run_) { 351 if (!blocking_run_) {
351 if (!is_nested_drag) { 352 if (!is_nested_drag) {
352 // Start the timer to hide the menu. This is needed as we get no 353 // Start the timer to hide the menu. This is needed as we get no
353 // notification when the drag has finished. 354 // notification when the drag has finished.
354 StartCancelAllTimer(); 355 StartCancelAllTimer();
355 } 356 }
356 return NULL; 357 return NULL;
357 } 358 }
358 359
359 if (button) 360 if (button)
360 menu_button_ = button; 361 pressed_lock_.reset(new MenuButton::PressedLock(button));
361 362
362 // Make sure Chrome doesn't attempt to shut down while the menu is showing. 363 // Make sure Chrome doesn't attempt to shut down while the menu is showing.
363 if (ViewsDelegate::views_delegate) 364 if (ViewsDelegate::views_delegate)
364 ViewsDelegate::views_delegate->AddRef(); 365 ViewsDelegate::views_delegate->AddRef();
365 366
366 // We need to turn on nestable tasks as in some situations (pressing alt-f for 367 // We need to turn on nestable tasks as in some situations (pressing alt-f for
367 // one) the menus are run from a task. If we don't do this and are invoked 368 // one) the menus are run from a task. If we don't do this and are invoked
368 // from a task none of the tasks we schedule are processed and the menu 369 // from a task none of the tasks we schedule are processed and the menu
369 // appears totally broken. 370 // appears totally broken.
370 message_loop_depth_++; 371 message_loop_depth_++;
(...skipping 21 matching lines...) Expand all
392 ::GetCursorPos(&cursor_pos); 393 ::GetCursorPos(&cursor_pos);
393 HWND window = ::WindowFromPoint(cursor_pos); 394 HWND window = ::WindowFromPoint(cursor_pos);
394 if (::GetWindowThreadProcessId(window, NULL) == 395 if (::GetWindowThreadProcessId(window, NULL) ==
395 ::GetCurrentThreadId()) { 396 ::GetCurrentThreadId()) {
396 ::SetProp(window, ui::kIgnoreTouchMouseActivateForWindow, 397 ::SetProp(window, ui::kIgnoreTouchMouseActivateForWindow,
397 reinterpret_cast<HANDLE>(true)); 398 reinterpret_cast<HANDLE>(true));
398 } 399 }
399 } 400 }
400 #endif 401 #endif
401 402
403 linked_ptr<MenuButton::PressedLock> nested_pressed_lock;
402 if (nested_menu) { 404 if (nested_menu) {
403 DCHECK(!menu_stack_.empty()); 405 DCHECK(!menu_stack_.empty());
404 // We're running from within a menu, restore the previous state. 406 // We're running from within a menu, restore the previous state.
405 // The menus are already showing, so we don't have to show them. 407 // The menus are already showing, so we don't have to show them.
406 state_ = menu_stack_.back(); 408 state_ = menu_stack_.back().first;
407 pending_state_ = menu_stack_.back(); 409 pending_state_ = menu_stack_.back().first;
410 nested_pressed_lock = menu_stack_.back().second;
408 menu_stack_.pop_back(); 411 menu_stack_.pop_back();
409 } else { 412 } else {
410 showing_ = false; 413 showing_ = false;
411 did_capture_ = false; 414 did_capture_ = false;
412 } 415 }
413 416
414 MenuItemView* result = result_; 417 MenuItemView* result = result_;
415 // In case we're nested, reset result_. 418 // In case we're nested, reset result_.
416 result_ = NULL; 419 result_ = NULL;
417 420
418 if (result_event_flags) 421 if (result_event_flags)
419 *result_event_flags = accept_event_flags_; 422 *result_event_flags = accept_event_flags_;
420 423
421 if (exit_type_ == EXIT_OUTERMOST) { 424 if (exit_type_ == EXIT_OUTERMOST) {
422 SetExitType(EXIT_NONE); 425 SetExitType(EXIT_NONE);
423 } else { 426 } else {
424 if (nested_menu && result) { 427 if (nested_menu && result) {
425 // We're nested and about to return a value. The caller might enter 428 // We're nested and about to return a value. The caller might enter
426 // another blocking loop. We need to make sure all menus are hidden 429 // another blocking loop. We need to make sure all menus are hidden
427 // before that happens otherwise the menus will stay on screen. 430 // before that happens otherwise the menus will stay on screen.
428 CloseAllNestedMenus(); 431 CloseAllNestedMenus();
429 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); 432 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
430 433
431 // Set exit_all_, which makes sure all nested loops exit immediately. 434 // Set exit_all_, which makes sure all nested loops exit immediately.
432 if (exit_type_ != EXIT_DESTROYED) 435 if (exit_type_ != EXIT_DESTROYED)
433 SetExitType(EXIT_ALL); 436 SetExitType(EXIT_ALL);
434 } 437 }
435 } 438 }
436 439
437 // If we stopped running because one of the menus was destroyed chances are 440 // Reset our pressed lock to the previous state's, if there was one.
438 // the button was also destroyed. 441 // The lock handles the case if the button was destroyed.
439 if (exit_type_ != EXIT_DESTROYED && menu_button_) { 442 pressed_lock_.reset(nested_pressed_lock.release());
440 menu_button_->SetState(CustomButton::STATE_NORMAL); 443
441 menu_button_->SchedulePaint();
442 }
443 return result; 444 return result;
444 } 445 }
445 446
446 void MenuController::Cancel(ExitType type) { 447 void MenuController::Cancel(ExitType type) {
447 // If the menu has already been destroyed, no further cancellation is 448 // If the menu has already been destroyed, no further cancellation is
448 // needed. We especially don't want to set the |exit_type_| to a lesser 449 // needed. We especially don't want to set the |exit_type_| to a lesser
449 // value. 450 // value.
450 if (exit_type_ == EXIT_DESTROYED || exit_type_ == type) 451 if (exit_type_ == EXIT_DESTROYED || exit_type_ == type)
451 return; 452 return;
452 453
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 #endif 927 #endif
927 928
928 // And close. 929 // And close.
929 ExitType exit_type = EXIT_ALL; 930 ExitType exit_type = EXIT_ALL;
930 if (!menu_stack_.empty()) { 931 if (!menu_stack_.empty()) {
931 // We're running nested menus. Only exit all if the mouse wasn't over one 932 // We're running nested menus. Only exit all if the mouse wasn't over one
932 // of the menus from the last run. 933 // of the menus from the last run.
933 gfx::Point screen_loc(event.location()); 934 gfx::Point screen_loc(event.location());
934 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc); 935 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
935 MenuPart last_part = GetMenuPartByScreenCoordinateUsingMenu( 936 MenuPart last_part = GetMenuPartByScreenCoordinateUsingMenu(
936 menu_stack_.back().item, screen_loc); 937 menu_stack_.back().first.item, screen_loc);
937 if (last_part.type != MenuPart::NONE) 938 if (last_part.type != MenuPart::NONE)
938 exit_type = EXIT_OUTERMOST; 939 exit_type = EXIT_OUTERMOST;
939 } 940 }
940 Cancel(exit_type); 941 Cancel(exit_type);
941 942
942 #if defined(OS_CHROMEOS) 943 #if defined(OS_CHROMEOS)
943 // We're going to exit the menu and want to repost the event so that is 944 // We're going to exit the menu and want to repost the event so that is
944 // is handled normally after the context menu has exited. We call 945 // is handled normally after the context menu has exited. We call
945 // RepostEvent after Cancel so that mouse capture has been released so 946 // RepostEvent after Cancel so that mouse capture has been released so
946 // that finding the event target is unaffected by the current capture. 947 // that finding the event target is unaffected by the current capture.
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 accept_event_flags_(0), 1086 accept_event_flags_(0),
1086 drop_target_(NULL), 1087 drop_target_(NULL),
1087 drop_position_(MenuDelegate::DROP_UNKNOWN), 1088 drop_position_(MenuDelegate::DROP_UNKNOWN),
1088 owner_(NULL), 1089 owner_(NULL),
1089 possible_drag_(false), 1090 possible_drag_(false),
1090 drag_in_progress_(false), 1091 drag_in_progress_(false),
1091 did_initiate_drag_(false), 1092 did_initiate_drag_(false),
1092 valid_drop_coordinates_(false), 1093 valid_drop_coordinates_(false),
1093 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), 1094 last_drop_operation_(MenuDelegate::DROP_UNKNOWN),
1094 showing_submenu_(false), 1095 showing_submenu_(false),
1095 menu_button_(NULL),
1096 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()), 1096 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()),
1097 delegate_(delegate), 1097 delegate_(delegate),
1098 message_loop_depth_(0), 1098 message_loop_depth_(0),
1099 menu_config_(theme), 1099 menu_config_(theme),
1100 closing_event_time_(base::TimeDelta()), 1100 closing_event_time_(base::TimeDelta()),
1101 menu_start_time_(base::TimeTicks()), 1101 menu_start_time_(base::TimeTicks()),
1102 is_combobox_(false), 1102 is_combobox_(false),
1103 item_selected_by_touch_(false), 1103 item_selected_by_touch_(false),
1104 message_loop_(MenuMessageLoop::Create()) { 1104 message_loop_(MenuMessageLoop::Create()) {
1105 active_instance_ = this; 1105 active_instance_ = this;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 !item->GetDelegate()->ShouldCloseAllMenusOnExecute(item->GetCommand())) { 1176 !item->GetDelegate()->ShouldCloseAllMenusOnExecute(item->GetCommand())) {
1177 SetExitType(EXIT_OUTERMOST); 1177 SetExitType(EXIT_OUTERMOST);
1178 } else { 1178 } else {
1179 SetExitType(EXIT_ALL); 1179 SetExitType(EXIT_ALL);
1180 } 1180 }
1181 accept_event_flags_ = event_flags; 1181 accept_event_flags_ = event_flags;
1182 } 1182 }
1183 1183
1184 bool MenuController::ShowSiblingMenu(SubmenuView* source, 1184 bool MenuController::ShowSiblingMenu(SubmenuView* source,
1185 const gfx::Point& mouse_location) { 1185 const gfx::Point& mouse_location) {
1186 if (!menu_stack_.empty() || !menu_button_) 1186 if (!menu_stack_.empty() || !pressed_lock_.get())
1187 return false; 1187 return false;
1188 1188
1189 View* source_view = source->GetScrollViewContainer(); 1189 View* source_view = source->GetScrollViewContainer();
1190 if (mouse_location.x() >= 0 && 1190 if (mouse_location.x() >= 0 &&
1191 mouse_location.x() < source_view->width() && 1191 mouse_location.x() < source_view->width() &&
1192 mouse_location.y() >= 0 && 1192 mouse_location.y() >= 0 &&
1193 mouse_location.y() < source_view->height()) { 1193 mouse_location.y() < source_view->height()) {
1194 // The mouse is over the menu, no need to continue. 1194 // The mouse is over the menu, no need to continue.
1195 return false; 1195 return false;
1196 } 1196 }
(...skipping 19 matching lines...) Expand all
1216 delegate_->SiblingMenuCreated(alt_menu); 1216 delegate_->SiblingMenuCreated(alt_menu);
1217 1217
1218 if (!button) { 1218 if (!button) {
1219 // If the delegate returns a menu, they must also return a button. 1219 // If the delegate returns a menu, they must also return a button.
1220 NOTREACHED(); 1220 NOTREACHED();
1221 return false; 1221 return false;
1222 } 1222 }
1223 1223
1224 // There is a sibling menu, update the button state, hide the current menu 1224 // There is a sibling menu, update the button state, hide the current menu
1225 // and show the new one. 1225 // and show the new one.
1226 menu_button_->SetState(CustomButton::STATE_NORMAL); 1226 pressed_lock_.reset(new MenuButton::PressedLock(button));
1227 menu_button_->SchedulePaint();
1228 menu_button_ = button;
1229 menu_button_->SetState(CustomButton::STATE_PRESSED);
1230 menu_button_->SchedulePaint();
1231 1227
1232 // Need to reset capture when we show the menu again, otherwise we aren't 1228 // Need to reset capture when we show the menu again, otherwise we aren't
1233 // going to get any events. 1229 // going to get any events.
1234 did_capture_ = false; 1230 did_capture_ = false;
1235 gfx::Point screen_menu_loc; 1231 gfx::Point screen_menu_loc;
1236 View::ConvertPointToScreen(button, &screen_menu_loc); 1232 View::ConvertPointToScreen(button, &screen_menu_loc);
1237 1233
1238 // It is currently not possible to show a submenu recursively in a bubble. 1234 // It is currently not possible to show a submenu recursively in a bubble.
1239 DCHECK(!MenuItemView::IsBubble(anchor)); 1235 DCHECK(!MenuItemView::IsBubble(anchor));
1240 // Subtract 1 from the height to make the popup flush with the button border. 1236 // Subtract 1 from the height to make the popup flush with the button border.
(...skipping 23 matching lines...) Expand all
1264 1260
1265 if (menu_item->GetDelegate()->ShowContextMenu( 1261 if (menu_item->GetDelegate()->ShowContextMenu(
1266 menu_item, menu_item->GetCommand(), loc, source_type)) { 1262 menu_item, menu_item->GetCommand(), loc, source_type)) {
1267 SendMouseCaptureLostToActiveView(); 1263 SendMouseCaptureLostToActiveView();
1268 return true; 1264 return true;
1269 } 1265 }
1270 return false; 1266 return false;
1271 } 1267 }
1272 1268
1273 void MenuController::CloseAllNestedMenus() { 1269 void MenuController::CloseAllNestedMenus() {
1274 for (std::list<State>::iterator i = menu_stack_.begin(); 1270 for (std::list<NestedState>::iterator i = menu_stack_.begin();
1275 i != menu_stack_.end(); ++i) { 1271 i != menu_stack_.end(); ++i) {
1276 MenuItemView* last_item = i->item; 1272 State& state = i->first;
1273 MenuItemView* last_item = state.item;
1277 for (MenuItemView* item = last_item; item; 1274 for (MenuItemView* item = last_item; item;
1278 item = item->GetParentMenuItem()) { 1275 item = item->GetParentMenuItem()) {
1279 CloseMenu(item); 1276 CloseMenu(item);
1280 last_item = item; 1277 last_item = item;
1281 } 1278 }
1282 i->submenu_open = false; 1279 state.submenu_open = false;
1283 i->item = last_item; 1280 state.item = last_item;
1284 } 1281 }
1285 } 1282 }
1286 1283
1287 MenuItemView* MenuController::GetMenuItemAt(View* source, int x, int y) { 1284 MenuItemView* MenuController::GetMenuItemAt(View* source, int x, int y) {
1288 // Walk the view hierarchy until we find a menu item (or the root). 1285 // Walk the view hierarchy until we find a menu item (or the root).
1289 View* child_under_mouse = source->GetEventHandlerForPoint(gfx::Point(x, y)); 1286 View* child_under_mouse = source->GetEventHandlerForPoint(gfx::Point(x, y));
1290 while (child_under_mouse && 1287 while (child_under_mouse &&
1291 child_under_mouse->id() != MenuItemView::kMenuItemViewID) { 1288 child_under_mouse->id() != MenuItemView::kMenuItemViewID) {
1292 child_under_mouse = child_under_mouse->parent(); 1289 child_under_mouse = child_under_mouse->parent();
1293 } 1290 }
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after
2309 } 2306 }
2310 } 2307 }
2311 2308
2312 gfx::Screen* MenuController::GetScreen() { 2309 gfx::Screen* MenuController::GetScreen() {
2313 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL; 2310 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL;
2314 return root ? gfx::Screen::GetScreenFor(root->GetNativeView()) 2311 return root ? gfx::Screen::GetScreenFor(root->GetNativeView())
2315 : gfx::Screen::GetNativeScreen(); 2312 : gfx::Screen::GetNativeScreen();
2316 } 2313 }
2317 2314
2318 } // namespace views 2315 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/menu/menu_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698