diff options
Diffstat (limited to 'chromium/ui/views/controls/menu/menu_controller.cc')
-rw-r--r-- | chromium/ui/views/controls/menu/menu_controller.cc | 376 |
1 files changed, 166 insertions, 210 deletions
diff --git a/chromium/ui/views/controls/menu/menu_controller.cc b/chromium/ui/views/controls/menu/menu_controller.cc index 3b0e5d552c0..d5b5a84e8f1 100644 --- a/chromium/ui/views/controls/menu/menu_controller.cc +++ b/chromium/ui/views/controls/menu/menu_controller.cc @@ -4,23 +4,18 @@ #include "ui/views/controls/menu/menu_controller.h" -#if defined(OS_WIN) -#include <windowsx.h> -#endif - #include "base/i18n/case_conversion.h" #include "base/i18n/rtl.h" -#include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "ui/base/dragdrop/drag_utils.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/events/event_constants.h" +#include "ui/events/event.h" #include "ui/events/event_utils.h" -#include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gfx/point.h" #include "ui/gfx/screen.h" #include "ui/gfx/vector2d.h" #include "ui/native_theme/native_theme.h" @@ -28,32 +23,26 @@ #include "ui/views/controls/menu/menu_config.h" #include "ui/views/controls/menu/menu_controller_delegate.h" #include "ui/views/controls/menu/menu_host_root_view.h" +#include "ui/views/controls/menu/menu_item_view.h" +#include "ui/views/controls/menu/menu_message_loop.h" #include "ui/views/controls/menu/menu_scroll_view_container.h" #include "ui/views/controls/menu/submenu_view.h" #include "ui/views/drag_utils.h" -#include "ui/views/event_utils.h" #include "ui/views/focus/view_storage.h" #include "ui/views/mouse_constants.h" +#include "ui/views/view.h" #include "ui/views/view_constants.h" #include "ui/views/views_delegate.h" #include "ui/views/widget/root_view.h" #include "ui/views/widget/tooltip_manager.h" #include "ui/views/widget/widget.h" -#if defined(USE_AURA) -#include "ui/aura/env.h" -#include "ui/aura/root_window.h" -#endif - #if defined(OS_WIN) -#include "ui/views/win/hwnd_message_handler.h" +#include "ui/base/win/internal_constants.h" +#include "ui/gfx/win/dpi.h" #include "ui/views/win/hwnd_util.h" #endif -#if defined(USE_X11) -#include <X11/Xlib.h> -#endif - using base::Time; using base::TimeDelta; using ui::OSExchangeData; @@ -87,17 +76,17 @@ const int kBubbleTipSizeTopBottom = 11; const float kMaximumLengthMovedToActivate = 4.0f; // Returns true if the mnemonic of |menu| matches key. -bool MatchesMnemonic(MenuItemView* menu, char16 key) { - return menu->GetMnemonic() == key; +bool MatchesMnemonic(MenuItemView* menu, base::char16 key) { + return key != 0 && menu->GetMnemonic() == key; } // Returns true if |menu| doesn't have a mnemonic and first character of the its // title is |key|. -bool TitleMatchesMnemonic(MenuItemView* menu, char16 key) { +bool TitleMatchesMnemonic(MenuItemView* menu, base::char16 key) { if (menu->GetMnemonic()) return false; - string16 lower_title = base::i18n::ToLower(menu->title()); + base::string16 lower_title = base::i18n::ToLower(menu->title()); return !lower_title.empty() && lower_title[0] == key; } @@ -279,8 +268,9 @@ struct MenuController::SelectByCharDetails { MenuController::State::State() : item(NULL), submenu_open(false), - anchor(MenuItemView::TOPLEFT), - context_menu(false) {} + anchor(MENU_ANCHOR_TOPLEFT), + context_menu(false) { +} MenuController::State::~State() {} @@ -298,7 +288,7 @@ MenuItemView* MenuController::Run(Widget* parent, MenuButton* button, MenuItemView* root, const gfx::Rect& bounds, - MenuItemView::AnchorPosition position, + MenuAnchorPosition position, bool context_menu, int* result_event_flags) { exit_type_ = EXIT_NONE; @@ -385,7 +375,7 @@ MenuItemView* MenuController::Run(Widget* parent, // Close any open menus. SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); -#if defined(OS_WIN) && defined(USE_AURA) +#if defined(OS_WIN) // On Windows, if we select the menu item by touch and if the window at the // location is another window on the same thread, that window gets a // WM_MOUSEACTIVATE message and ends up activating itself, which is not @@ -400,7 +390,7 @@ MenuItemView* MenuController::Run(Widget* parent, HWND window = ::WindowFromPoint(cursor_pos); if (::GetWindowThreadProcessId(window, NULL) == ::GetCurrentThreadId()) { - ::SetProp(window, views::kIgnoreTouchMouseActivateForWindow, + ::SetProp(window, ui::kIgnoreTouchMouseActivateForWindow, reinterpret_cast<HANDLE>(true)); } } @@ -596,13 +586,11 @@ void MenuController::OnMouseEntered(SubmenuView* source, // do anything here. } -#if defined(USE_AURA) bool MenuController::OnMouseWheel(SubmenuView* source, const ui::MouseWheelEvent& event) { MenuPart part = GetMenuPart(source, event.location()); return part.submenu && part.submenu->OnMouseWheel(event); } -#endif void MenuController::OnGestureEvent(SubmenuView* source, ui::GestureEvent* event) { @@ -809,6 +797,7 @@ void MenuController::OnWidgetDestroying(Widget* widget) { DCHECK_EQ(owner_, widget); owner_->RemoveObserver(this); owner_ = NULL; + message_loop_->ClearOwner(); } // static @@ -875,7 +864,7 @@ void MenuController::SetSelection(MenuItemView* menu_item, (MenuDepth(menu_item) != 1 || menu_item->GetType() != MenuItemView::SUBMENU)) { menu_item->NotifyAccessibilityEvent( - ui::AccessibilityTypes::EVENT_FOCUS, true); + ui::AX_EVENT_FOCUS, true); } } @@ -912,14 +901,7 @@ void MenuController::SetSelectionOnPointerDown(SubmenuView* source, #if defined(OS_WIN) // We're going to close and we own the mouse capture. We need to repost the // mouse down, otherwise the window the user clicked on won't get the event. - if (!state_.item) { - // We some times get an event after closing all the menus. Ignore it. Make - // sure the menu is in fact not visible. If the menu is visible, then - // we're in a bad state where we think the menu isn't visibile but it is. - DCHECK(!source->GetWidget()->IsVisible()); - } else { - RepostEvent(source, event); - } + RepostEvent(source, event); #endif // And close. @@ -936,14 +918,15 @@ void MenuController::SetSelectionOnPointerDown(SubmenuView* source, } Cancel(exit_type); -#if defined(USE_AURA) && !defined(OS_WIN) +#if defined(OS_CHROMEOS) // We're going to exit the menu and want to repost the event so that is // is handled normally after the context menu has exited. We call // RepostEvent after Cancel so that mouse capture has been released so // that finding the event target is unaffected by the current capture. RepostEvent(source, event); #endif - + // Do not repost events for Linux Aura because this behavior is more + // consistent with the behavior of other Linux apps. return; } @@ -982,7 +965,7 @@ void MenuController::StartDrag(SubmenuView* source, OSExchangeData data; item->GetDelegate()->WriteDragData(item, &data); - drag_utils::SetDragImageOnDataObject(*canvas, item->size(), + drag_utils::SetDragImageOnDataObject(*canvas, press_loc.OffsetFromOrigin(), &data); StopScrolling(); @@ -1002,94 +985,6 @@ void MenuController::StartDrag(SubmenuView* source, } // else case, someone canceled us, don't do anything } -#if defined(OS_WIN) -bool MenuController::Dispatch(const MSG& msg) { - DCHECK(blocking_run_); - - if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED) { - // We must translate/dispatch the message here, otherwise we would drop - // the message on the floor. - TranslateMessage(&msg); - DispatchMessage(&msg); - return false; - } - - // NOTE: we don't get WM_ACTIVATE or anything else interesting in here. - switch (msg.message) { - case WM_CONTEXTMENU: { - MenuItemView* item = pending_state_.item; - if (item && item->GetRootMenuItem() != item) { - gfx::Point screen_loc(0, item->height()); - View::ConvertPointToScreen(item, &screen_loc); - ui::MenuSourceType source_type = ui::MENU_SOURCE_MOUSE; - if (GET_X_LPARAM(msg.lParam) == -1 && GET_Y_LPARAM(msg.lParam) == -1) - source_type = ui::MENU_SOURCE_KEYBOARD; - item->GetDelegate()->ShowContextMenu(item, item->GetCommand(), - screen_loc, source_type); - } - return true; - } - - // NOTE: focus wasn't changed when the menu was shown. As such, don't - // dispatch key events otherwise the focused window will get the events. - case WM_KEYDOWN: { - bool result = OnKeyDown(ui::KeyboardCodeFromNative(msg)); - TranslateMessage(&msg); - return result; - } - case WM_CHAR: - return !SelectByChar(static_cast<char16>(msg.wParam)); - case WM_KEYUP: - return true; - - case WM_SYSKEYUP: - // We may have been shown on a system key, as such don't do anything - // here. If another system key is pushed we'll get a WM_SYSKEYDOWN and - // close the menu. - return true; - - case WM_CANCELMODE: - case WM_SYSKEYDOWN: - // Exit immediately on system keys. - Cancel(EXIT_ALL); - return false; - - default: - break; - } - TranslateMessage(&msg); - DispatchMessage(&msg); - return exit_type_ == EXIT_NONE; -} -#elif defined(USE_AURA) -bool MenuController::Dispatch(const base::NativeEvent& event) { - if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED) { - aura::Env::GetInstance()->GetDispatcher()->Dispatch(event); - return false; - } - // Activates mnemonics only when it it pressed without modifiers except for - // caps and shift. - int flags = ui::EventFlagsFromNative(event) & - ~ui::EF_CAPS_LOCK_DOWN & ~ui::EF_SHIFT_DOWN; - if (flags == ui::EF_NONE) { - switch (ui::EventTypeFromNative(event)) { - case ui::ET_KEY_PRESSED: - if (!OnKeyDown(ui::KeyboardCodeFromNative(event))) - return false; - - return !SelectByChar(ui::KeyboardCodeFromNative(event)); - case ui::ET_KEY_RELEASED: - return true; - default: - break; - } - } - - aura::Env::GetInstance()->GetDispatcher()->Dispatch(event); - return exit_type_ == EXIT_NONE; -} -#endif - bool MenuController::OnKeyDown(ui::KeyboardCode key_code) { DCHECK(blocking_run_); @@ -1124,7 +1019,7 @@ bool MenuController::OnKeyDown(ui::KeyboardCode key_code) { break; case ui::VKEY_F4: - if (!accept_on_f4_) + if (!is_combobox_) break; // Fallthrough to accept on F4, so combobox menus match Windows behavior. case ui::VKEY_RETURN: @@ -1156,11 +1051,6 @@ bool MenuController::OnKeyDown(ui::KeyboardCode key_code) { CloseSubmenu(); break; -#if defined(OS_WIN) - case VK_APPS: - break; -#endif - default: break; } @@ -1191,8 +1081,9 @@ MenuController::MenuController(ui::NativeTheme* theme, menu_config_(theme), closing_event_time_(base::TimeDelta()), menu_start_time_(base::TimeTicks()), - accept_on_f4_(false), - item_selected_by_touch_(false) { + is_combobox_(false), + item_selected_by_touch_(false), + message_loop_(MenuMessageLoop::Create()) { active_instance_ = this; } @@ -1206,6 +1097,10 @@ MenuController::~MenuController() { StopCancelAllTimer(); } +void MenuController::RunMessageLoop(bool nested_menu) { + message_loop_->Run(this, owner_, nested_menu); +} + MenuController::SendAcceleratorResultType MenuController::SendAcceleratorToHotTrackedView() { CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item); @@ -1220,10 +1115,9 @@ MenuController::SendAcceleratorResultType ACCELERATOR_PROCESSED : ACCELERATOR_PROCESSED_EXIT; } -void MenuController::UpdateInitialLocation( - const gfx::Rect& bounds, - MenuItemView::AnchorPosition position, - bool context_menu) { +void MenuController::UpdateInitialLocation(const gfx::Rect& bounds, + MenuAnchorPosition position, + bool context_menu) { pending_state_.context_menu = context_menu; pending_state_.initial_bounds = bounds; if (bounds.height() > 1) { @@ -1234,10 +1128,10 @@ void MenuController::UpdateInitialLocation( // Reverse anchor position for RTL languages. if (base::i18n::IsRTL() && - (position == MenuItemView::TOPRIGHT || - position == MenuItemView::TOPLEFT)) { - pending_state_.anchor = position == MenuItemView::TOPRIGHT ? - MenuItemView::TOPLEFT : MenuItemView::TOPRIGHT; + (position == MENU_ANCHOR_TOPRIGHT || position == MENU_ANCHOR_TOPLEFT)) { + pending_state_.anchor = position == MENU_ANCHOR_TOPRIGHT + ? MENU_ANCHOR_TOPLEFT + : MENU_ANCHOR_TOPRIGHT; } else { pending_state_.anchor = position; } @@ -1246,7 +1140,7 @@ void MenuController::UpdateInitialLocation( // avoid repeated system queries for the info. pending_state_.monitor_bounds = GetScreen()->GetDisplayNearestPoint( bounds.origin()).work_area(); -#if defined(USE_ASH) + if (!pending_state_.monitor_bounds.Contains(bounds)) { // Use the monitor area if the work area doesn't contain the bounds. This // handles showing a menu from the launcher. @@ -1255,7 +1149,6 @@ void MenuController::UpdateInitialLocation( if (monitor_area.Contains(bounds)) pending_state_.monitor_bounds = monitor_area; } -#endif } void MenuController::Accept(MenuItemView* item, int event_flags) { @@ -1293,7 +1186,7 @@ bool MenuController::ShowSiblingMenu(SubmenuView* source, // if there is a sibling menu we should show. gfx::Point screen_point(mouse_location); View::ConvertPointToScreen(source_view, &screen_point); - MenuItemView::AnchorPosition anchor; + MenuAnchorPosition anchor; bool has_mnemonics; MenuButton* button = NULL; MenuItemView* alt_menu = source->GetMenuItem()->GetDelegate()-> @@ -1717,11 +1610,11 @@ gfx::Rect MenuController::CalculateMenuBounds(MenuItemView* item, x += 1; y = state_.initial_bounds.bottom(); - if (state_.anchor == MenuItemView::TOPRIGHT) { + if (state_.anchor == MENU_ANCHOR_TOPRIGHT) { x = x + state_.initial_bounds.width() - pref.width(); if (menu_config.offset_context_menus && state_.context_menu) x -= 1; - } else if (state_.anchor == MenuItemView::BOTTOMCENTER) { + } else if (state_.anchor == MENU_ANCHOR_BOTTOMCENTER) { x = x - (pref.width() - state_.initial_bounds.width()) / 2; if (pref.height() > state_.initial_bounds.y() + kCenteredContextMenuYOffset) { @@ -1770,7 +1663,7 @@ gfx::Rect MenuController::CalculateMenuBounds(MenuItemView* item, // The menu should never overlap the owning button. So move it. // We use the anchor view style to determine the preferred position // relative to the owning button. - if (state_.anchor == MenuItemView::TOPLEFT) { + if (state_.anchor == MENU_ANCHOR_TOPLEFT) { // The menu starts with the same x coordinate as the owning button. if (x + state_.initial_bounds.width() + pref.width() > state_.monitor_bounds.right()) @@ -1883,16 +1776,16 @@ gfx::Rect MenuController::CalculateBubbleMenuBounds(MenuItemView* item, int max_height = state_.monitor_bounds.height(); // In case of bubbles, the maximum width is limited by the space // between the display corner and the target area + the tip size. - if (state_.anchor == MenuItemView::BUBBLE_LEFT) { + if (state_.anchor == MENU_ANCHOR_BUBBLE_LEFT) { max_width = owner_bounds.x() - state_.monitor_bounds.x() + kBubbleTipSizeLeftRight; - } else if (state_.anchor == MenuItemView::BUBBLE_RIGHT) { + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_RIGHT) { max_width = state_.monitor_bounds.right() - owner_bounds.right() + kBubbleTipSizeLeftRight; - } else if (state_.anchor == MenuItemView::BUBBLE_ABOVE) { + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE) { max_height = owner_bounds.y() - state_.monitor_bounds.y() + kBubbleTipSizeTopBottom; - } else if (state_.anchor == MenuItemView::BUBBLE_BELOW) { + } else if (state_.anchor == MENU_ANCHOR_BUBBLE_BELOW) { max_height = state_.monitor_bounds.bottom() - owner_bounds.bottom() + kBubbleTipSizeTopBottom; } @@ -1907,9 +1800,9 @@ gfx::Rect MenuController::CalculateBubbleMenuBounds(MenuItemView* item, item->GetDelegate()->GetMaxWidthForMenu(item))); int x, y; - if (state_.anchor == MenuItemView::BUBBLE_ABOVE || - state_.anchor == MenuItemView::BUBBLE_BELOW) { - if (state_.anchor == MenuItemView::BUBBLE_ABOVE) + if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE || + state_.anchor == MENU_ANCHOR_BUBBLE_BELOW) { + if (state_.anchor == MENU_ANCHOR_BUBBLE_ABOVE) y = owner_bounds.y() - pref.height() + kBubbleTipSizeTopBottom; else y = owner_bounds.bottom() - kBubbleTipSizeTopBottom; @@ -1924,7 +1817,7 @@ gfx::Rect MenuController::CalculateBubbleMenuBounds(MenuItemView* item, submenu->GetScrollViewContainer()->SetBubbleArrowOffset( pref.width() / 2 - x + x_old); } else { - if (state_.anchor == MenuItemView::BUBBLE_RIGHT) + if (state_.anchor == MENU_ANCHOR_BUBBLE_RIGHT) x = owner_bounds.right() - kBubbleTipSizeLeftRight; else x = owner_bounds.x() - pref.width() + kBubbleTipSizeLeftRight; @@ -2046,8 +1939,8 @@ void MenuController::CloseSubmenu() { MenuController::SelectByCharDetails MenuController::FindChildForMnemonic( MenuItemView* parent, - char16 key, - bool (*match_function)(MenuItemView* menu, char16 mnemonic)) { + base::char16 key, + bool (*match_function)(MenuItemView* menu, base::char16 mnemonic)) { SubmenuView* submenu = parent->GetSubmenu(); DCHECK(submenu); SelectByCharDetails details; @@ -2098,9 +1991,9 @@ bool MenuController::AcceptOrSelect(MenuItemView* parent, return false; } -bool MenuController::SelectByChar(char16 character) { - char16 char_array[] = { character, 0 }; - char16 key = base::i18n::ToLower(char_array)[0]; +bool MenuController::SelectByChar(base::char16 character) { + base::char16 char_array[] = { character, 0 }; + base::char16 key = base::i18n::ToLower(char_array)[0]; MenuItemView* item = pending_state_.item; if (!item->HasSubmenu() || !item->GetSubmenu()->IsShowing()) item = item->GetParentMenuItem(); @@ -2116,61 +2009,114 @@ bool MenuController::SelectByChar(char16 character) { if (details.first_match != -1) return AcceptOrSelect(item, details); - // If no mnemonics found, look at first character of titles. - details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic); - if (details.first_match != -1) - return AcceptOrSelect(item, details); + if (is_combobox_) { + item->GetSubmenu()->GetTextInputClient()->InsertChar(character, 0); + } else { + // If no mnemonics found, look at first character of titles. + details = FindChildForMnemonic(item, key, &TitleMatchesMnemonic); + if (details.first_match != -1) + return AcceptOrSelect(item, details); + } return false; } void MenuController::RepostEvent(SubmenuView* source, const ui::LocatedEvent& event) { + if (!event.IsMouseEvent()) { + // TODO(rbyers): Gesture event repost is tricky to get right + // crbug.com/170987. + DCHECK(event.IsGestureEvent()); + return; + } + +#if defined(OS_WIN) + if (!state_.item) { + // We some times get an event after closing all the menus. Ignore it. Make + // sure the menu is in fact not visible. If the menu is visible, then + // we're in a bad state where we think the menu isn't visibile but it is. + DCHECK(!source->GetWidget()->IsVisible()); + return; + } + + state_.item->GetRootMenuItem()->GetSubmenu()->ReleaseCapture(); +#endif + gfx::Point screen_loc(event.location()); View::ConvertPointToScreen(source->GetScrollViewContainer(), &screen_loc); - gfx::NativeView native_view = source->GetWidget()->GetNativeView(); + if (!native_view) + return; + gfx::Screen* screen = gfx::Screen::GetScreenFor(native_view); gfx::NativeWindow window = screen->GetWindowAtScreenPoint(screen_loc); - if (!window) - return; - #if defined(OS_WIN) - // Release the capture. - SubmenuView* submenu = state_.item->GetRootMenuItem()->GetSubmenu(); - submenu->ReleaseCapture(); - - gfx::NativeView view = submenu->GetWidget()->GetNativeView(); - if (view) { - DWORD view_tid = GetWindowThreadProcessId(HWNDForNativeView(view), NULL); - if (view_tid != GetWindowThreadProcessId(HWNDForNativeView(window), NULL)) { + // Convert screen_loc to pixels for the Win32 API's like WindowFromPoint, + // PostMessage/SendMessage to work correctly. These API's expect the + // coordinates to be in pixels. + // PostMessage() to metro windows isn't allowed (access will be denied). Don't + // try to repost with Win32 if the window under the mouse press is in metro. + if (!ViewsDelegate::views_delegate || + !ViewsDelegate::views_delegate->IsWindowInMetro(window)) { + gfx::Point screen_loc_pixels = gfx::win::DIPToScreenPoint(screen_loc); + HWND target_window = window ? HWNDForNativeWindow(window) : + WindowFromPoint(screen_loc_pixels.ToPOINT()); + HWND source_window = HWNDForNativeView(native_view); + if (!target_window || !source_window || + GetWindowThreadProcessId(source_window, NULL) != + GetWindowThreadProcessId(target_window, NULL)) { // Even though we have mouse capture, windows generates a mouse event if // the other window is in a separate thread. Only repost an event if - // |view| was created on the same thread, else the target window can get - // double events leading to bad behavior. + // |target_window| and |source_window| were created on the same thread, + // else double events can occur and lead to bad behavior. return; } - } -#endif - scoped_ptr<ui::LocatedEvent> clone; - if (event.IsMouseEvent()) { - clone.reset(new ui::MouseEvent(static_cast<const ui::MouseEvent&>(event))); - } else if (event.IsGestureEvent()) { - // TODO(rbyers): Gesture event repost is tricky to get right - // crbug.com/170987. - return; - } else { - NOTREACHED(); + // Determine whether the click was in the client area or not. + // NOTE: WM_NCHITTEST coordinates are relative to the screen. + LPARAM coords = MAKELPARAM(screen_loc_pixels.x(), screen_loc_pixels.y()); + LRESULT nc_hit_result = SendMessage(target_window, WM_NCHITTEST, 0, coords); + const bool client_area = nc_hit_result == HTCLIENT; + + // TODO(sky): this isn't right. The event to generate should correspond with + // the event we just got. MouseEvent only tells us what is down, which may + // differ. Need to add ability to get changed button from MouseEvent. + int event_type; + int flags = event.flags(); + if (flags & ui::EF_LEFT_MOUSE_BUTTON) { + event_type = client_area ? WM_LBUTTONDOWN : WM_NCLBUTTONDOWN; + } else if (flags & ui::EF_MIDDLE_MOUSE_BUTTON) { + event_type = client_area ? WM_MBUTTONDOWN : WM_NCMBUTTONDOWN; + } else if (flags & ui::EF_RIGHT_MOUSE_BUTTON) { + event_type = client_area ? WM_RBUTTONDOWN : WM_NCRBUTTONDOWN; + } else { + NOTREACHED(); + return; + } + + int window_x = screen_loc_pixels.x(); + int window_y = screen_loc_pixels.y(); + if (client_area) { + POINT pt = { window_x, window_y }; + ScreenToClient(target_window, &pt); + window_x = pt.x; + window_y = pt.y; + } + + WPARAM target = client_area ? event.native_event().wParam : nc_hit_result; + LPARAM window_coords = MAKELPARAM(window_x, window_y); + PostMessage(target_window, event_type, target, window_coords); return; } - clone->set_location(screen_loc); +#endif + // Non-Windows Aura or |window| is in metro mode. + if (!window) + return; - RepostLocatedEvent(window, *clone); + message_loop_->RepostEventToWindow(event, window, screen_loc); } - void MenuController::SetDropMenuItem( MenuItemView* new_target, MenuDelegate::DropPosition new_position) { @@ -2230,12 +2176,13 @@ void MenuController::UpdateActiveMouseView(SubmenuView* event_source, target_menu, active_mouse_view, &target_point); ui::MouseEvent mouse_entered_event(ui::ET_MOUSE_ENTERED, target_point, target_point, - 0); + 0, 0); active_mouse_view->OnMouseEntered(mouse_entered_event); ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, target_point, target_point, - event.flags()); + event.flags(), + event.changed_button_flags()); active_mouse_view->OnMousePressed(mouse_pressed_event); } } @@ -2245,7 +2192,8 @@ void MenuController::UpdateActiveMouseView(SubmenuView* event_source, View::ConvertPointToTarget(target_menu, active_mouse_view, &target_point); ui::MouseEvent mouse_dragged_event(ui::ET_MOUSE_DRAGGED, target_point, target_point, - event.flags()); + event.flags(), + event.changed_button_flags()); active_mouse_view->OnMouseDragged(mouse_dragged_event); } } @@ -2261,7 +2209,7 @@ void MenuController::SendMouseReleaseToActiveView(SubmenuView* event_source, &target_loc); View::ConvertPointFromScreen(active_mouse_view, &target_loc); ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, target_loc, target_loc, - event.flags()); + event.flags(), event.changed_button_flags()); // Reset active mouse view before sending mouse released. That way if it calls // back to us, we aren't in a weird state. SetActiveMouseView(NULL); @@ -2293,20 +2241,22 @@ View* MenuController::GetActiveMouseView() { void MenuController::SetExitType(ExitType type) { exit_type_ = type; // Exit nested message loops as soon as possible. We do this as - // MessageLoop::Dispatcher is only invoked before native events, which means + // MessagePumpDispatcher is only invoked before native events, which means // its entirely possible for a Widget::CloseNow() task to be processed before - // the next native message. By using QuitNow() we ensures the nested message - // loop returns as soon as possible and avoids having deleted views classes - // (such as widgets and rootviews) on the stack when the nested message loop - // stops. + // the next native message. We quite the nested message loop as soon as + // possible to avoid having deleted views classes (such as widgets and + // rootviews) on the stack when the nested message loop stops. // - // It's safe to invoke QuitNow multiple times, it only effects the current - // loop. - bool quit_now = ShouldQuitNow() && exit_type_ != EXIT_NONE && + // It's safe to invoke QuitNestedMessageLoop() multiple times, it only effects + // the current loop. + bool quit_now = message_loop_->ShouldQuitNow() && exit_type_ != EXIT_NONE && message_loop_depth_; - if (quit_now) - base::MessageLoop::current()->QuitNow(); + TerminateNestedMessageLoop(); +} + +void MenuController::TerminateNestedMessageLoop() { + message_loop_->QuitNow(); } void MenuController::HandleMouseLocation(SubmenuView* source, @@ -2341,4 +2291,10 @@ void MenuController::HandleMouseLocation(SubmenuView* source, } } +gfx::Screen* MenuController::GetScreen() { + Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL; + return root ? gfx::Screen::GetScreenFor(root->GetNativeView()) + : gfx::Screen::GetNativeScreen(); +} + } // namespace views |