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

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

Issue 245993005: views: move native event reposting back to MenuController as it's the only (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: win compile Created 6 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | ui/views/event_utils.h » ('j') | 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 #if defined(OS_WIN) 7 #if defined(OS_WIN)
8 #include <windowsx.h> 8 #include <windowsx.h>
9 #endif 9 #endif
10 10
11 #include "base/i18n/case_conversion.h" 11 #include "base/i18n/case_conversion.h"
12 #include "base/i18n/rtl.h" 12 #include "base/i18n/rtl.h"
13 #include "base/run_loop.h" 13 #include "base/run_loop.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "base/time/time.h" 15 #include "base/time/time.h"
16 #include "ui/aura/client/screen_position_client.h"
16 #include "ui/aura/env.h" 17 #include "ui/aura/env.h"
17 #include "ui/aura/window.h" 18 #include "ui/aura/window.h"
18 #include "ui/aura/window_event_dispatcher.h" 19 #include "ui/aura/window_event_dispatcher.h"
20 #include "ui/aura/window_tree_host.h"
19 #include "ui/base/dragdrop/drag_utils.h" 21 #include "ui/base/dragdrop/drag_utils.h"
20 #include "ui/base/dragdrop/os_exchange_data.h" 22 #include "ui/base/dragdrop/os_exchange_data.h"
21 #include "ui/base/l10n/l10n_util.h" 23 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/events/event_constants.h" 24 #include "ui/events/event.h"
23 #include "ui/events/event_utils.h" 25 #include "ui/events/event_utils.h"
24 #include "ui/events/platform/platform_event_source.h" 26 #include "ui/events/platform/platform_event_source.h"
25 #include "ui/events/platform/scoped_event_dispatcher.h" 27 #include "ui/events/platform/scoped_event_dispatcher.h"
26 #include "ui/gfx/canvas.h" 28 #include "ui/gfx/canvas.h"
27 #include "ui/gfx/native_widget_types.h" 29 #include "ui/gfx/native_widget_types.h"
30 #include "ui/gfx/point.h"
28 #include "ui/gfx/screen.h" 31 #include "ui/gfx/screen.h"
29 #include "ui/gfx/vector2d.h" 32 #include "ui/gfx/vector2d.h"
30 #include "ui/native_theme/native_theme.h" 33 #include "ui/native_theme/native_theme.h"
31 #include "ui/views/controls/button/menu_button.h" 34 #include "ui/views/controls/button/menu_button.h"
32 #include "ui/views/controls/menu/menu_config.h" 35 #include "ui/views/controls/menu/menu_config.h"
33 #include "ui/views/controls/menu/menu_controller_delegate.h" 36 #include "ui/views/controls/menu/menu_controller_delegate.h"
34 #include "ui/views/controls/menu/menu_host_root_view.h" 37 #include "ui/views/controls/menu/menu_host_root_view.h"
35 #include "ui/views/controls/menu/menu_scroll_view_container.h" 38 #include "ui/views/controls/menu/menu_scroll_view_container.h"
36 #include "ui/views/controls/menu/submenu_view.h" 39 #include "ui/views/controls/menu/submenu_view.h"
37 #include "ui/views/drag_utils.h" 40 #include "ui/views/drag_utils.h"
38 #include "ui/views/event_utils.h"
39 #include "ui/views/focus/view_storage.h" 41 #include "ui/views/focus/view_storage.h"
40 #include "ui/views/mouse_constants.h" 42 #include "ui/views/mouse_constants.h"
43 #include "ui/views/view.h"
41 #include "ui/views/view_constants.h" 44 #include "ui/views/view_constants.h"
42 #include "ui/views/views_delegate.h" 45 #include "ui/views/views_delegate.h"
43 #include "ui/views/widget/root_view.h" 46 #include "ui/views/widget/root_view.h"
44 #include "ui/views/widget/tooltip_manager.h" 47 #include "ui/views/widget/tooltip_manager.h"
45 #include "ui/views/widget/widget.h" 48 #include "ui/views/widget/widget.h"
46 #include "ui/wm/public/activation_change_observer.h" 49 #include "ui/wm/public/activation_change_observer.h"
47 #include "ui/wm/public/activation_client.h" 50 #include "ui/wm/public/activation_client.h"
48 #include "ui/wm/public/dispatcher_client.h" 51 #include "ui/wm/public/dispatcher_client.h"
49 #include "ui/wm/public/drag_drop_client.h" 52 #include "ui/wm/public/drag_drop_client.h"
50 53
51 #if defined(OS_WIN) 54 #if defined(OS_WIN)
52 #include "ui/base/win/internal_constants.h" 55 #include "ui/base/win/internal_constants.h"
53 #include "ui/views/controls/menu/menu_message_pump_dispatcher_win.h" 56 #include "ui/views/controls/menu/menu_message_pump_dispatcher_win.h"
54 #include "ui/views/win/hwnd_util.h" 57 #include "ui/views/win/hwnd_util.h"
55 #else 58 #else
56 #include "ui/views/controls/menu/menu_event_dispatcher_linux.h" 59 #include "ui/views/controls/menu/menu_event_dispatcher_linux.h"
57 #endif 60 #endif
58 61
62 using aura::client::ScreenPositionClient;
59 using base::Time; 63 using base::Time;
60 using base::TimeDelta; 64 using base::TimeDelta;
61 using ui::OSExchangeData; 65 using ui::OSExchangeData;
62 66
63 // Period of the scroll timer (in milliseconds). 67 // Period of the scroll timer (in milliseconds).
64 static const int kScrollTimerMS = 30; 68 static const int kScrollTimerMS = 30;
65 69
66 // Amount of time from when the drop exits the menu and the menu is hidden. 70 // Amount of time from when the drop exits the menu and the menu is hidden.
67 static const int kCloseOnExitTime = 1200; 71 static const int kCloseOnExitTime = 1200;
68 72
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 // used since the reposting will set a new timestamp when the event gets 970 // used since the reposting will set a new timestamp when the event gets
967 // processed. As such it is better to take the current time which will be 971 // processed. As such it is better to take the current time which will be
968 // closer to the time when it arrives again in the menu handler. 972 // closer to the time when it arrives again in the menu handler.
969 closing_event_time_ = ui::EventTimeForNow(); 973 closing_event_time_ = ui::EventTimeForNow();
970 974
971 // Mouse wasn't pressed over any menu, or the active menu, cancel. 975 // Mouse wasn't pressed over any menu, or the active menu, cancel.
972 976
973 #if defined(OS_WIN) 977 #if defined(OS_WIN)
974 // We're going to close and we own the mouse capture. We need to repost the 978 // We're going to close and we own the mouse capture. We need to repost the
975 // mouse down, otherwise the window the user clicked on won't get the event. 979 // mouse down, otherwise the window the user clicked on won't get the event.
976 if (!state_.item) { 980 RepostEvent(source, event);
977 // We some times get an event after closing all the menus. Ignore it. Make
978 // sure the menu is in fact not visible. If the menu is visible, then
979 // we're in a bad state where we think the menu isn't visibile but it is.
980 DCHECK(!source->GetWidget()->IsVisible());
981 } else {
982 RepostEvent(source, event);
983 }
984 #endif 981 #endif
985 982
986 // And close. 983 // And close.
987 ExitType exit_type = EXIT_ALL; 984 ExitType exit_type = EXIT_ALL;
988 if (!menu_stack_.empty()) { 985 if (!menu_stack_.empty()) {
989 // We're running nested menus. Only exit all if the mouse wasn't over one 986 // We're running nested menus. Only exit all if the mouse wasn't over one
990 // of the menus from the last run. 987 // of the menus from the last run.
991 gfx::Point screen_loc(event.location()); 988 gfx::Point screen_loc(event.location());
992 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc); 989 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
993 MenuPart last_part = GetMenuPartByScreenCoordinateUsingMenu( 990 MenuPart last_part = GetMenuPartByScreenCoordinateUsingMenu(
(...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after
2138 details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic); 2135 details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic);
2139 if (details.first_match != -1) 2136 if (details.first_match != -1)
2140 return AcceptOrSelect(item, details); 2137 return AcceptOrSelect(item, details);
2141 } 2138 }
2142 2139
2143 return false; 2140 return false;
2144 } 2141 }
2145 2142
2146 void MenuController::RepostEvent(SubmenuView* source, 2143 void MenuController::RepostEvent(SubmenuView* source,
2147 const ui::LocatedEvent& event) { 2144 const ui::LocatedEvent& event) {
2145 if (!event.IsMouseEvent()) {
2146 // TODO(rbyers): Gesture event repost is tricky to get right
2147 // crbug.com/170987.
2148 DCHECK(event.IsGestureEvent());
2149 return;
2150 }
2151
2152 #if defined(OS_WIN)
2153 if (!state_.item) {
2154 // We some times get an event after closing all the menus. Ignore it. Make
2155 // sure the menu is in fact not visible. If the menu is visible, then
2156 // we're in a bad state where we think the menu isn't visibile but it is.
2157 DCHECK(!source->GetWidget()->IsVisible());
2158 return;
2159 }
2160
2161 state_.item->GetRootMenuItem()->GetSubmenu()->ReleaseCapture();
2162 #endif
2163
2148 gfx::Point screen_loc(event.location()); 2164 gfx::Point screen_loc(event.location());
2149 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc); 2165 View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc);
2166 gfx::NativeView native_view = source->GetWidget()->GetNativeView();
2167 if (!native_view)
2168 return;
2150 2169
2151 gfx::NativeView native_view = source->GetWidget()->GetNativeView();
2152 gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view); 2170 gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view);
2153 gfx::NativeWindow window = screen->GetWindowAtScreenPoint(screen_loc); 2171 gfx::NativeWindow window = screen->GetWindowAtScreenPoint(screen_loc);
2154 2172
2155 // On Windows, it is ok for window to be NULL. Please refer to the
2156 // RepostLocatedEvent function for more information.
2157 #if defined(OS_WIN) 2173 #if defined(OS_WIN)
2158 // Release the capture. 2174 // PostMessage() to metro windows isn't allowed (access will be denied). Don't
2159 SubmenuView* submenu = state_.item->GetRootMenuItem()->GetSubmenu(); 2175 // try to repost with Win32 if the window under the mouse press is in metro.
2160 submenu->ReleaseCapture(); 2176 if (!ViewsDelegate::views_delegate ||
2161 2177 !ViewsDelegate::views_delegate->IsWindowInMetro(window)) {
2162 gfx::NativeView view = submenu->GetWidget()->GetNativeView(); 2178 HWND target_window = window ? HWNDForNativeWindow(window) :
2163 if (view && window) { 2179 WindowFromPoint(screen_loc.ToPOINT());
2164 DWORD view_tid = GetWindowThreadProcessId(HWNDForNativeView(view), NULL); 2180 HWND source_window = HWNDForNativeView(native_view);
2165 if (view_tid != GetWindowThreadProcessId(HWNDForNativeView(window), NULL)) { 2181 if (!target_window || !source_window ||
2182 GetWindowThreadProcessId(source_window, NULL) !=
2183 GetWindowThreadProcessId(target_window, NULL)) {
2166 // Even though we have mouse capture, windows generates a mouse event if 2184 // Even though we have mouse capture, windows generates a mouse event if
2167 // the other window is in a separate thread. Only repost an event if 2185 // the other window is in a separate thread. Only repost an event if
2168 // |view| was created on the same thread, else the target window can get 2186 // |target_window| and |source_window| were created on the same thread,
2169 // double events leading to bad behavior. 2187 // else double events can occur and lead to bad behavior.
2170 return; 2188 return;
2171 } 2189 }
2190
2191 // Determine whether the click was in the client area or not.
2192 // NOTE: WM_NCHITTEST coordinates are relative to the screen.
2193 LPARAM coords = MAKELPARAM(screen_loc.x(), screen_loc.y());
2194 LRESULT nc_hit_result = SendMessage(target_window, WM_NCHITTEST, 0, coords);
2195 const bool client_area = nc_hit_result == HTCLIENT;
2196
2197 // TODO(sky): this isn't right. The event to generate should correspond with
2198 // the event we just got. MouseEvent only tells us what is down, which may
2199 // differ. Need to add ability to get changed button from MouseEvent.
2200 int event_type;
2201 int flags = event.flags();
2202 if (flags & ui::EF_LEFT_MOUSE_BUTTON) {
2203 event_type = client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN;
2204 } else if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) {
2205 event_type = client_area ? WM_MBUTTONDOWN : WM_NCMBUTTONDOWN;
2206 } else if (flags & ui::EF_RIGHT_MOUSE_BUTTON) {
2207 event_type = client_area ? WM_RBUTTONDOWN : WM_NCRBUTTONDOWN;
2208 } else {
2209 NOTREACHED();
2210 return;
2211 }
2212
2213 int window_x = screen_loc.x();
2214 int window_y = screen_loc.y();
2215 if (client_area) {
2216 POINT pt = { window_x, window_y };
2217 ScreenToClient(target_window, &pt);
2218 window_x = pt.x;
2219 window_y = pt.y;
2220 }
2221
2222 WPARAM target = client_area ? event.native_event().wParam : nc_hit_result;
2223 LPARAM window_coords = MAKELPARAM(window_x, window_y);
2224 PostMessage(target_window, event_type, target, window_coords);
2225 return;
2172 } 2226 }
2173 #else 2227 #endif
2228 // Non-Windows Aura or |window| is in metro mode.
2174 if (!window) 2229 if (!window)
2175 return; 2230 return;
2176 #endif
2177 2231
2178 scoped_ptr<ui::LocatedEvent> clone; 2232 aura::Window* root = window->GetRootWindow();
2179 if (event.IsMouseEvent()) { 2233 ScreenPositionClient* spc = aura::client::GetScreenPositionClient(root);
2180 clone.reset(new ui::MouseEvent(static_cast<const ui::MouseEvent&>(event))); 2234 if (!spc)
2181 } else if (event.IsGestureEvent()) {
2182 // TODO(rbyers): Gesture event repost is tricky to get right
2183 // crbug.com/170987.
2184 return; 2235 return;
2185 } else {
2186 NOTREACHED();
2187 return;
2188 }
2189 clone->set_location(screen_loc);
2190 2236
2191 RepostLocatedEvent(window, *clone); 2237 gfx::Point root_loc(screen_loc);
2238 spc->ConvertPointFromScreen(root, &root_loc);
2239
2240 ui::MouseEvent clone(static_cast<const ui::MouseEvent&>(event));
2241 clone.set_location(root_loc);
2242 clone.set_root_location(root_loc);
2243 root->GetHost()->dispatcher()->RepostEvent(clone);
2192 } 2244 }
2193 2245
2194
2195 void MenuController::SetDropMenuItem( 2246 void MenuController::SetDropMenuItem(
2196 MenuItemView* new_target, 2247 MenuItemView* new_target,
2197 MenuDelegate::DropPosition new_position) { 2248 MenuDelegate::DropPosition new_position) {
2198 if (new_target == drop_target_ && new_position == drop_position_) 2249 if (new_target == drop_target_ && new_position == drop_position_)
2199 return; 2250 return;
2200 2251
2201 if (drop_target_) { 2252 if (drop_target_) {
2202 drop_target_->GetParentMenuItem()->GetSubmenu()->SetDropMenuItem( 2253 drop_target_->GetParentMenuItem()->GetSubmenu()->SetDropMenuItem(
2203 NULL, MenuDelegate::DROP_NONE); 2254 NULL, MenuDelegate::DROP_NONE);
2204 } 2255 }
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
2377 } 2428 }
2378 } 2429 }
2379 2430
2380 gfx::Screen* MenuController::GetScreen() { 2431 gfx::Screen* MenuController::GetScreen() {
2381 aura::Window* root = GetOwnerRootWindow(owner_); 2432 aura::Window* root = GetOwnerRootWindow(owner_);
2382 return root ? gfx::Screen::GetScreenFor(root) 2433 return root ? gfx::Screen::GetScreenFor(root)
2383 : gfx::Screen::GetNativeScreen(); 2434 : gfx::Screen::GetNativeScreen();
2384 } 2435 }
2385 2436
2386 } // namespace views 2437 } // namespace views
OLDNEW
« no previous file with comments | « no previous file | ui/views/event_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698