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

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

Issue 1586353004: Update reposting of events from menus (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 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 (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/macros.h" 9 #include "base/macros.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 672
673 if (!part.submenu) 673 if (!part.submenu)
674 return; 674 return;
675 part.submenu->OnGestureEvent(event); 675 part.submenu->OnGestureEvent(event);
676 } 676 }
677 677
678 void MenuController::OnTouchEvent(SubmenuView* source, ui::TouchEvent* event) { 678 void MenuController::OnTouchEvent(SubmenuView* source, ui::TouchEvent* event) {
679 if (event->type() == ui::ET_TOUCH_PRESSED) { 679 if (event->type() == ui::ET_TOUCH_PRESSED) {
680 MenuPart part = GetMenuPart(source, event->location()); 680 MenuPart part = GetMenuPart(source, event->location());
681 if (part.type == MenuPart::NONE) { 681 if (part.type == MenuPart::NONE) {
682 RepostEvent(source, event); 682 RepostEventAndCancel(source, event);
683 event->SetHandled(); 683 event->SetHandled();
684 } 684 }
685 } 685 }
686 } 686 }
687 687
688 View* MenuController::GetTooltipHandlerForPoint(SubmenuView* source, 688 View* MenuController::GetTooltipHandlerForPoint(SubmenuView* source,
689 const gfx::Point& point) { 689 const gfx::Point& point) {
690 MenuHostRootView* root_view = GetRootView(source, point); 690 MenuHostRootView* root_view = GetRootView(source, point);
691 return root_view ? root_view->ProcessGetTooltipHandlerForPoint(point) 691 return root_view ? root_view->ProcessGetTooltipHandlerForPoint(point)
692 : nullptr; 692 : nullptr;
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
994 (event->flags() & ui::EF_FROM_TOUCH)) 994 (event->flags() & ui::EF_FROM_TOUCH))
995 return; 995 return;
996 996
997 if (part.type == MenuPart::NONE || 997 if (part.type == MenuPart::NONE ||
998 (part.type == MenuPart::MENU_ITEM && part.menu && 998 (part.type == MenuPart::MENU_ITEM && part.menu &&
999 part.menu->GetRootMenuItem() != state_.item->GetRootMenuItem())) { 999 part.menu->GetRootMenuItem() != state_.item->GetRootMenuItem())) {
1000 // Remember the time stamp of the current (press down) event. The owner can 1000 // Remember the time stamp of the current (press down) event. The owner can
1001 // then use this to figure out if this menu was finished with the same click 1001 // then use this to figure out if this menu was finished with the same click
1002 // which is sent to it thereafter. 1002 // which is sent to it thereafter.
1003 closing_event_time_ = event->time_stamp(); 1003 closing_event_time_ = event->time_stamp();
1004 1004 // Event wasn't pressed over any menu, or the active menu, cancel.
1005 // Mouse wasn't pressed over any menu, or the active menu, cancel. 1005 RepostEventAndCancel(source, event);
1006
1007 #if defined(OS_WIN)
1008 // We're going to close and we own the mouse capture. We need to repost the
1009 // mouse down, otherwise the window the user clicked on won't get the event.
1010 RepostEvent(source, event);
1011 #endif
1012
1013 // And close.
1014 ExitType exit_type = EXIT_ALL;
1015 if (!menu_stack_.empty()) {
1016 // We're running nested menus. Only exit all if the mouse wasn't over one
1017 // of the menus from the last run.
1018 gfx::Point screen_loc(event->location());
1019 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
1020 MenuPart last_part = GetMenuPartByScreenCoordinateUsingMenu(
1021 menu_stack_.back().first.item, screen_loc);
1022 if (last_part.type != MenuPart::NONE)
1023 exit_type = EXIT_OUTERMOST;
1024 }
1025 Cancel(exit_type);
1026
1027 #if defined(OS_CHROMEOS)
1028 // We're going to exit the menu and want to repost the event so that is
1029 // is handled normally after the context menu has exited. We call
1030 // RepostEvent after Cancel so that mouse capture has been released so
1031 // that finding the event target is unaffected by the current capture.
1032 RepostEvent(source, event);
1033 #endif
1034 // Do not repost events for Linux Aura because this behavior is more 1006 // Do not repost events for Linux Aura because this behavior is more
1035 // consistent with the behavior of other Linux apps. 1007 // consistent with the behavior of other Linux apps.
1036 return; 1008 return;
1037 } 1009 }
1038 1010
1039 // On a press we immediately commit the selection, that way a submenu 1011 // On a press we immediately commit the selection, that way a submenu
1040 // pops up immediately rather than after a delay. 1012 // pops up immediately rather than after a delay.
1041 int selection_types = SELECTION_UPDATE_IMMEDIATELY; 1013 int selection_types = SELECTION_UPDATE_IMMEDIATELY;
1042 if (!part.menu) { 1014 if (!part.menu) {
1043 part.menu = part.parent; 1015 part.menu = part.parent;
(...skipping 1137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2181 item->GetSubmenu()->GetPrefixSelector()->InsertText(char_array); 2153 item->GetSubmenu()->GetPrefixSelector()->InsertText(char_array);
2182 } else { 2154 } else {
2183 // If no mnemonics found, look at first character of titles. 2155 // If no mnemonics found, look at first character of titles.
2184 details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic); 2156 details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic);
2185 if (details.first_match != -1) 2157 if (details.first_match != -1)
2186 AcceptOrSelect(item, details); 2158 AcceptOrSelect(item, details);
2187 } 2159 }
2188 } 2160 }
2189 2161
2190 void MenuController::RepostEvent(SubmenuView* source, 2162 void MenuController::RepostEvent(SubmenuView* source,
2191 const ui::LocatedEvent* event) { 2163 const ui::LocatedEvent* event,
2164 const gfx::Point& screen_loc,
2165 gfx::NativeView native_view,
2166 gfx::NativeWindow window) {
2192 if (!event->IsMouseEvent() && !event->IsTouchEvent()) { 2167 if (!event->IsMouseEvent() && !event->IsTouchEvent()) {
2193 // TODO(rbyers): Gesture event repost is tricky to get right 2168 // TODO(rbyers): Gesture event repost is tricky to get right
2194 // crbug.com/170987. 2169 // crbug.com/170987.
2195 DCHECK(event->IsGestureEvent()); 2170 DCHECK(event->IsGestureEvent());
2196 return; 2171 return;
2197 } 2172 }
2198 2173
2199 #if defined(OS_WIN) 2174 #if defined(OS_WIN)
2200 if (!state_.item) { 2175 if (!state_.item) {
2201 // We some times get an event after closing all the menus. Ignore it. Make 2176 // We some times get an event after closing all the menus. Ignore it. Make
2202 // sure the menu is in fact not visible. If the menu is visible, then 2177 // sure the menu is in fact not visible. If the menu is visible, then
2203 // we're in a bad state where we think the menu isn't visibile but it is. 2178 // we're in a bad state where we think the menu isn't visibile but it is.
2204 DCHECK(!source->GetWidget()->IsVisible()); 2179 DCHECK(!source->GetWidget()->IsVisible());
2205 return; 2180 return;
2206 } 2181 }
2207 2182
2208 state_.item->GetRootMenuItem()->GetSubmenu()->ReleaseCapture(); 2183 state_.item->GetRootMenuItem()->GetSubmenu()->ReleaseCapture();
2209 #endif 2184 #endif
2210 2185
2211 gfx::Point screen_loc(event->location());
2212 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
2213 gfx::NativeView native_view = source->GetWidget()->GetNativeView();
2214 if (!native_view) 2186 if (!native_view)
2215 return; 2187 return;
2216 2188
2217 gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view);
2218 gfx::NativeWindow window = screen->GetWindowAtScreenPoint(screen_loc);
2219
2220 #if defined(OS_WIN) 2189 #if defined(OS_WIN)
2221 gfx::Point screen_loc_pixels = gfx::win::DIPToScreenPoint(screen_loc); 2190 gfx::Point screen_loc_pixels = gfx::win::DIPToScreenPoint(screen_loc);
2222 HWND target_window = ::WindowFromPoint(screen_loc_pixels.ToPOINT()); 2191 HWND target_window = ::WindowFromPoint(screen_loc_pixels.ToPOINT());
2223 // If we don't find a native window for the HWND at the current location, 2192 // If we don't find a native window for the HWND at the current location,
2224 // then attempt to find a native window from its parent if one exists. 2193 // then attempt to find a native window from its parent if one exists.
2225 // There are HWNDs created outside views, which don't have associated 2194 // There are HWNDs created outside views, which don't have associated
2226 // native windows. 2195 // native windows.
2227 if (!window) { 2196 if (!window) {
2228 HWND parent = ::GetParent(target_window); 2197 HWND parent = ::GetParent(target_window);
2229 if (parent) { 2198 if (parent) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2287 return; 2256 return;
2288 } 2257 }
2289 #endif 2258 #endif
2290 // Non Aura window. 2259 // Non Aura window.
2291 if (!window) 2260 if (!window)
2292 return; 2261 return;
2293 2262
2294 MenuMessageLoop::RepostEventToWindow(event, window, screen_loc); 2263 MenuMessageLoop::RepostEventToWindow(event, window, screen_loc);
2295 } 2264 }
2296 2265
2266 void MenuController::RepostEventAndCancel(SubmenuView* source,
2267 const ui::LocatedEvent* event) {
2268 // Cancel can lead to the deletion |source| so we save the view and window to
2269 // be used when reposting the event.
2270 gfx::Point screen_loc(event->location());
2271 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
2272 gfx::NativeView native_view = source->GetWidget()->GetNativeView();
2273 gfx::NativeWindow window = nullptr;
2274 if (native_view) {
2275 gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view);
2276 window = screen->GetWindowAtScreenPoint(screen_loc);
2277 }
2278
2279 #if defined(OS_WIN)
2280 // We're going to close and we own the event capture. We need to repost the
2281 // event, otherwise the window the user clicked on won't get the event.
2282 RepostEvent(source, event, screen_loc, native_view, window);
2283 #endif
2284
2285 // Determine target to see if a complete or partial close of the menu should
2286 // occur.
2287 ExitType exit_type = EXIT_ALL;
2288 if (!menu_stack_.empty()) {
2289 // We're running nested menus. Only exit all if the mouse wasn't over one
2290 // of the menus from the last run.
2291 MenuPart last_part = GetMenuPartByScreenCoordinateUsingMenu(
2292 menu_stack_.back().first.item, screen_loc);
2293 if (last_part.type != MenuPart::NONE)
2294 exit_type = EXIT_OUTERMOST;
2295 }
2296 Cancel(exit_type);
2297
2298 #if defined(OS_CHROMEOS)
2299 // We're going to exit the menu and want to repost the event so that is
2300 // is handled normally after the context menu has exited. We call
2301 // RepostEvent after Cancel so that event capture has been released so
2302 // that finding the event target is unaffected by the current capture.
2303 RepostEvent(source, event, screen_loc, native_view, window);
2304 #endif
2305 }
2306
2297 void MenuController::SetDropMenuItem( 2307 void MenuController::SetDropMenuItem(
2298 MenuItemView* new_target, 2308 MenuItemView* new_target,
2299 MenuDelegate::DropPosition new_position) { 2309 MenuDelegate::DropPosition new_position) {
2300 if (new_target == drop_target_ && new_position == drop_position_) 2310 if (new_target == drop_target_ && new_position == drop_position_)
2301 return; 2311 return;
2302 2312
2303 if (drop_target_) { 2313 if (drop_target_) {
2304 drop_target_->GetParentMenuItem()->GetSubmenu()->SetDropMenuItem( 2314 drop_target_->GetParentMenuItem()->GetSubmenu()->SetDropMenuItem(
2305 NULL, MenuDelegate::DROP_NONE); 2315 NULL, MenuDelegate::DROP_NONE);
2306 } 2316 }
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
2558 } 2568 }
2559 } 2569 }
2560 2570
2561 gfx::Screen* MenuController::GetScreen() { 2571 gfx::Screen* MenuController::GetScreen() {
2562 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL; 2572 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL;
2563 return root ? gfx::Screen::GetScreenFor(root->GetNativeView()) 2573 return root ? gfx::Screen::GetScreenFor(root->GetNativeView())
2564 : gfx::Screen::GetNativeScreen(); 2574 : gfx::Screen::GetNativeScreen();
2565 } 2575 }
2566 2576
2567 } // namespace views 2577 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/menu/menu_controller.h ('k') | ui/views/controls/menu/menu_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698