summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-31 13:46:57 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-31 13:46:57 +0000
commitf6b96f5d51352e6f55e723dd15c8793f73a9cee0 (patch)
tree33e7c05e1f202f1735befffdc43a5254e28fbda5
parentca72f097519271d23f24a6336056ad07c67f192c (diff)
downloadchromium_src-f6b96f5d51352e6f55e723dd15c8793f73a9cee0.zip
chromium_src-f6b96f5d51352e6f55e723dd15c8793f73a9cee0.tar.gz
chromium_src-f6b96f5d51352e6f55e723dd15c8793f73a9cee0.tar.bz2
views: Some MenuController cleanup.
Notable changes: * Move code out of menu_controller_aura.cc into menu_controller.cc since it doesn't make sense to have separate files anymore. * Move the message-pump dispatching code out of MenuController into a separate MenuMessagePumpDispatcher object. BUG=343577 R=sky@chromium.org Review URL: https://codereview.chromium.org/216423015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260540 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/views/controls/menu/menu_controller.cc195
-rw-r--r--ui/views/controls/menu/menu_controller.h19
-rw-r--r--ui/views/controls/menu/menu_controller_aura.cc114
-rw-r--r--ui/views/controls/menu/menu_message_pump_dispatcher.cc16
-rw-r--r--ui/views/controls/menu/menu_message_pump_dispatcher.h36
-rw-r--r--ui/views/controls/menu/menu_message_pump_dispatcher_linux.cc48
-rw-r--r--ui/views/controls/menu/menu_message_pump_dispatcher_win.cc78
-rw-r--r--ui/views/views.gyp5
8 files changed, 287 insertions, 224 deletions
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 5d58c69..ea854a2 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -21,8 +21,6 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_utils.h"
-#include "ui/events/keycodes/keyboard_code_conversion.h"
-#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/screen.h"
@@ -32,6 +30,7 @@
#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_message_pump_dispatcher.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"
@@ -43,17 +42,16 @@
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/tooltip_manager.h"
#include "ui/views/widget/widget.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_client.h"
#include "ui/wm/public/dispatcher_client.h"
+#include "ui/wm/public/drag_drop_client.h"
#if defined(OS_WIN)
#include "ui/base/win/internal_constants.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;
@@ -101,6 +99,67 @@ bool TitleMatchesMnemonic(MenuItemView* menu, base::char16 key) {
return !lower_title.empty() && lower_title[0] == key;
}
+aura::Window* GetOwnerRootWindow(views::Widget* owner) {
+ return owner ? owner->GetNativeWindow()->GetRootWindow() : NULL;
+}
+
+// ActivationChangeObserverImpl is used to observe activation changes and close
+// the menu. Additionally it listens for the root window to be destroyed and
+// cancel the menu as well.
+class ActivationChangeObserverImpl
+ : public aura::client::ActivationChangeObserver,
+ public aura::WindowObserver,
+ public ui::EventHandler {
+ public:
+ ActivationChangeObserverImpl(MenuController* controller, aura::Window* root)
+ : controller_(controller),
+ root_(root) {
+ aura::client::GetActivationClient(root_)->AddObserver(this);
+ root_->AddObserver(this);
+ root_->AddPreTargetHandler(this);
+ }
+
+ virtual ~ActivationChangeObserverImpl() {
+ Cleanup();
+ }
+
+ // aura::client::ActivationChangeObserver:
+ virtual void OnWindowActivated(aura::Window* gained_active,
+ aura::Window* lost_active) OVERRIDE {
+ if (!controller_->drag_in_progress())
+ controller_->CancelAll();
+ }
+
+ // aura::WindowObserver:
+ virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
+ Cleanup();
+ }
+
+ // ui::EventHandler:
+ virtual void OnCancelMode(ui::CancelModeEvent* event) OVERRIDE {
+ controller_->CancelAll();
+ }
+
+ private:
+ void Cleanup() {
+ if (!root_)
+ return;
+ // The ActivationClient may have been destroyed by the time we get here.
+ aura::client::ActivationClient* client =
+ aura::client::GetActivationClient(root_);
+ if (client)
+ client->RemoveObserver(this);
+ root_->RemovePreTargetHandler(this);
+ root_->RemoveObserver(this);
+ root_ = NULL;
+ }
+
+ MenuController* controller_;
+ aura::Window* root_;
+
+ DISALLOW_COPY_AND_ASSIGN(ActivationChangeObserverImpl);
+};
+
} // namespace
// Returns the first descendant of |view| that is hot tracked.
@@ -1001,94 +1060,6 @@ void MenuController::StartDrag(SubmenuView* source,
} // else case, someone canceled us, don't do anything
}
-#if defined(OS_WIN)
-uint32_t MenuController::Dispatch(const MSG& msg) {
- DCHECK(blocking_run_);
-
- if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED)
- return (POST_DISPATCH_QUIT_LOOP | POST_DISPATCH_PERFORM_DEFAULT);
-
- // 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 POST_DISPATCH_NONE;
- }
-
- // 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 ? POST_DISPATCH_NONE : POST_DISPATCH_QUIT_LOOP;
- }
- case WM_CHAR: {
- bool should_exit = SelectByChar(static_cast<base::char16>(msg.wParam));
- return should_exit ? POST_DISPATCH_QUIT_LOOP : POST_DISPATCH_NONE;
- }
- case WM_KEYUP:
- return POST_DISPATCH_NONE;
-
- 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 POST_DISPATCH_NONE;
-
- case WM_CANCELMODE:
- case WM_SYSKEYDOWN:
- // Exit immediately on system keys.
- Cancel(EXIT_ALL);
- return POST_DISPATCH_QUIT_LOOP;
-
- default:
- break;
- }
- return POST_DISPATCH_PERFORM_DEFAULT |
- (exit_type_ == EXIT_NONE ? POST_DISPATCH_NONE
- : POST_DISPATCH_QUIT_LOOP);
-}
-#else
-uint32_t MenuController::Dispatch(const base::NativeEvent& event) {
- if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED)
- return (POST_DISPATCH_QUIT_LOOP | POST_DISPATCH_PERFORM_DEFAULT);
-
- switch (ui::EventTypeFromNative(event)) {
- case ui::ET_KEY_PRESSED: {
- if (!OnKeyDown(ui::KeyboardCodeFromNative(event)))
- return POST_DISPATCH_QUIT_LOOP;
-
- // Do not check mnemonics if the Alt or Ctrl modifiers are pressed.
- int flags = ui::EventFlagsFromNative(event);
- if ((flags & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) == 0) {
- char c = ui::GetCharacterFromKeyCode(
- ui::KeyboardCodeFromNative(event), flags);
- if (SelectByChar(c))
- return POST_DISPATCH_QUIT_LOOP;
- }
- return POST_DISPATCH_NONE;
- }
- case ui::ET_KEY_RELEASED:
- return POST_DISPATCH_NONE;
- default:
- break;
- }
-
- return POST_DISPATCH_PERFORM_DEFAULT |
- (exit_type_ == EXIT_NONE ? POST_DISPATCH_NONE
- : POST_DISPATCH_QUIT_LOOP);
-}
-#endif
-
bool MenuController::OnKeyDown(ui::KeyboardCode key_code) {
DCHECK(blocking_run_);
@@ -1155,11 +1126,6 @@ bool MenuController::OnKeyDown(ui::KeyboardCode key_code) {
CloseSubmenu();
break;
-#if defined(OS_WIN)
- case VK_APPS:
- break;
-#endif
-
default:
break;
}
@@ -1205,6 +1171,25 @@ MenuController::~MenuController() {
StopCancelAllTimer();
}
+void MenuController::RunMessageLoop(bool nested_menu) {
+ internal::MenuMessagePumpDispatcher nested_dispatcher(this);
+
+ // |owner_| may be NULL.
+ aura::Window* root = GetOwnerRootWindow(owner_);
+ if (root) {
+ scoped_ptr<ActivationChangeObserverImpl> observer;
+ if (!nested_menu)
+ observer.reset(new ActivationChangeObserverImpl(this, root));
+ aura::client::GetDispatcherClient(root)
+ ->RunWithDispatcher(&nested_dispatcher);
+ } else {
+ base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+ base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+ base::RunLoop run_loop(&nested_dispatcher);
+ run_loop.Run();
+ }
+}
+
MenuController::SendAcceleratorResultType
MenuController::SendAcceleratorToHotTrackedView() {
CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item);
@@ -2321,6 +2306,12 @@ void MenuController::SetExitType(ExitType type) {
}
}
+bool MenuController::ShouldQuitNow() const {
+ aura::Window* root = GetOwnerRootWindow(owner_);
+ return !aura::client::GetDragDropClient(root) ||
+ !aura::client::GetDragDropClient(root)->IsDragDropInProgress();
+}
+
void MenuController::HandleMouseLocation(SubmenuView* source,
const gfx::Point& mouse_location) {
if (showing_submenu_)
@@ -2353,4 +2344,10 @@ void MenuController::HandleMouseLocation(SubmenuView* source,
}
}
+gfx::Screen* MenuController::GetScreen() {
+ aura::Window* root = GetOwnerRootWindow(owner_);
+ return root ? gfx::Screen::GetScreenFor(root)
+ : gfx::Screen::GetNativeScreen();
+}
+
} // namespace views
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h
index 3425caf3..cab7bae 100644
--- a/ui/views/controls/menu/menu_controller.h
+++ b/ui/views/controls/menu/menu_controller.h
@@ -13,20 +13,22 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_pump_dispatcher.h"
#include "base/timer/timer.h"
#include "ui/events/event_constants.h"
#include "ui/views/controls/menu/menu_delegate.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/widget/widget_observer.h"
-namespace ui {
-class NativeTheme;
-class OSExchangeData;
+namespace base {
+class MessagePumpDispatcher;
}
namespace gfx {
class Screen;
}
+namespace ui {
+class NativeTheme;
+class OSExchangeData;
+}
namespace views {
class MenuButton;
@@ -37,6 +39,7 @@ class View;
namespace internal {
class MenuControllerDelegate;
+class MenuMessagePumpDispatcher;
class MenuRunnerImpl;
}
@@ -45,8 +48,7 @@ class MenuRunnerImpl;
// MenuController is used internally by the various menu classes to manage
// showing, selecting and drag/drop for menus. All relevant events are
// forwarded to the MenuController from SubmenuView and MenuHost.
-class VIEWS_EXPORT MenuController : public base::MessagePumpDispatcher,
- public WidgetObserver {
+class VIEWS_EXPORT MenuController : public WidgetObserver {
public:
// Enumeration of how the menu should exit.
enum ExitType {
@@ -140,6 +142,7 @@ class VIEWS_EXPORT MenuController : public base::MessagePumpDispatcher,
static void TurnOffMenuSelectionHoldForTest();
private:
+ friend class internal::MenuMessagePumpDispatcher;
friend class internal::MenuRunnerImpl;
friend class MenuHostRootView;
friend class MenuItemView;
@@ -251,10 +254,6 @@ class VIEWS_EXPORT MenuController : public base::MessagePumpDispatcher,
const ui::LocatedEvent& event);
void StartDrag(SubmenuView* source, const gfx::Point& location);
- // Dispatcher method. This returns true if the menu was canceled, or
- // if the message is such that the menu should be closed.
- virtual uint32_t Dispatch(const base::NativeEvent& event) OVERRIDE;
-
// Key processing. The return value of this is returned from Dispatch.
// In other words, if this returns false (which happens if escape was
// pressed, or a matching mnemonic was found) the message loop returns.
diff --git a/ui/views/controls/menu/menu_controller_aura.cc b/ui/views/controls/menu/menu_controller_aura.cc
deleted file mode 100644
index ec402c7..0000000
--- a/ui/views/controls/menu/menu_controller_aura.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/menu/menu_controller.h"
-
-#include "base/run_loop.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
-#include "ui/gfx/screen.h"
-#include "ui/views/widget/widget.h"
-#include "ui/wm/public/activation_change_observer.h"
-#include "ui/wm/public/activation_client.h"
-#include "ui/wm/public/dispatcher_client.h"
-#include "ui/wm/public/drag_drop_client.h"
-
-namespace views {
-
-namespace {
-
-// ActivationChangeObserverImpl is used to observe activation changes and close
-// the menu. Additionally it listens for the root window to be destroyed and
-// cancel the menu as well.
-class ActivationChangeObserverImpl
- : public aura::client::ActivationChangeObserver,
- public aura::WindowObserver,
- public ui::EventHandler {
- public:
- ActivationChangeObserverImpl(MenuController* controller,
- aura::Window* root)
- : controller_(controller),
- root_(root) {
- aura::client::GetActivationClient(root_)->AddObserver(this);
- root_->AddObserver(this);
- root_->AddPreTargetHandler(this);
- }
-
- virtual ~ActivationChangeObserverImpl() {
- Cleanup();
- }
-
- // aura::client::ActivationChangeObserver overrides:
- virtual void OnWindowActivated(aura::Window* gained_active,
- aura::Window* lost_active) OVERRIDE {
- if (!controller_->drag_in_progress())
- controller_->CancelAll();
- }
-
- // aura::WindowObserver overrides:
- virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
- Cleanup();
- }
-
- // ui::EventHandler overrides:
- virtual void OnCancelMode(ui::CancelModeEvent* event) OVERRIDE {
- controller_->CancelAll();
- }
-
- private:
- void Cleanup() {
- if (!root_)
- return;
- // The ActivationClient may have been destroyed by the time we get here.
- aura::client::ActivationClient* client =
- aura::client::GetActivationClient(root_);
- if (client)
- client->RemoveObserver(this);
- root_->RemovePreTargetHandler(this);
- root_->RemoveObserver(this);
- root_ = NULL;
- }
-
- MenuController* controller_;
- aura::Window* root_;
-
- DISALLOW_COPY_AND_ASSIGN(ActivationChangeObserverImpl);
-};
-
-aura::Window* GetOwnerRootWindow(views::Widget* owner) {
- return owner ? owner->GetNativeWindow()->GetRootWindow() : NULL;
-}
-
-} // namespace
-
-void MenuController::RunMessageLoop(bool nested_menu) {
- // |owner_| may be NULL.
- aura::Window* root = GetOwnerRootWindow(owner_);
- if (root) {
- scoped_ptr<ActivationChangeObserverImpl> observer;
- if (!nested_menu)
- observer.reset(new ActivationChangeObserverImpl(this, root));
- aura::client::GetDispatcherClient(root)->RunWithDispatcher(this);
- } else {
- base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
- base::MessageLoop::ScopedNestableTaskAllower allow(loop);
- base::RunLoop run_loop(this);
- run_loop.Run();
- }
-}
-
-bool MenuController::ShouldQuitNow() const {
- aura::Window* root = GetOwnerRootWindow(owner_);
- return !aura::client::GetDragDropClient(root) ||
- !aura::client::GetDragDropClient(root)->IsDragDropInProgress();
-}
-
-gfx::Screen* MenuController::GetScreen() {
- aura::Window* root = GetOwnerRootWindow(owner_);
- return root ?
- gfx::Screen::GetScreenFor(root) : gfx::Screen::GetNativeScreen();
-}
-
-
-} // namespace views
diff --git a/ui/views/controls/menu/menu_message_pump_dispatcher.cc b/ui/views/controls/menu/menu_message_pump_dispatcher.cc
new file mode 100644
index 0000000..00d7930
--- /dev/null
+++ b/ui/views/controls/menu/menu_message_pump_dispatcher.cc
@@ -0,0 +1,16 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_message_pump_dispatcher.h"
+
+namespace views {
+namespace internal {
+
+MenuMessagePumpDispatcher::MenuMessagePumpDispatcher(MenuController* controller)
+ : menu_controller_(controller) {}
+
+MenuMessagePumpDispatcher::~MenuMessagePumpDispatcher() {}
+
+} // namespace internal
+} // namespace views
diff --git a/ui/views/controls/menu/menu_message_pump_dispatcher.h b/ui/views/controls/menu/menu_message_pump_dispatcher.h
new file mode 100644
index 0000000..2f5696b
--- /dev/null
+++ b/ui/views/controls/menu/menu_message_pump_dispatcher.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_PUMP_DISPATCHER_H_
+#define UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_PUMP_DISPATCHER_H_
+
+#include "base/macros.h"
+#include "base/message_loop/message_pump_dispatcher.h"
+
+namespace views {
+
+class MenuController;
+
+namespace internal {
+
+// A message-pump dispatcher object used to dispatch events from the nested
+// message-loop initiated by the MenuController.
+class MenuMessagePumpDispatcher : public base::MessagePumpDispatcher {
+ public:
+ explicit MenuMessagePumpDispatcher(MenuController* menu_controller);
+ virtual ~MenuMessagePumpDispatcher();
+
+ private:
+ // base::MessagePumpDispatcher:
+ virtual uint32_t Dispatch(const base::NativeEvent& event) OVERRIDE;
+
+ MenuController* menu_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(MenuMessagePumpDispatcher);
+};
+
+} // namespace internal
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_MENU_MENU_MESSAGE_PUMP_DISPATCHER_H_
diff --git a/ui/views/controls/menu/menu_message_pump_dispatcher_linux.cc b/ui/views/controls/menu/menu_message_pump_dispatcher_linux.cc
new file mode 100644
index 0000000..0172f8b
--- /dev/null
+++ b/ui/views/controls/menu/menu_message_pump_dispatcher_linux.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_message_pump_dispatcher.h"
+
+#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/views/controls/menu/menu_controller.h"
+
+namespace views {
+namespace internal {
+
+uint32_t MenuMessagePumpDispatcher::Dispatch(const base::NativeEvent& event) {
+ if (menu_controller_->exit_type() == MenuController::EXIT_ALL ||
+ menu_controller_->exit_type() == MenuController::EXIT_DESTROYED)
+ return (POST_DISPATCH_QUIT_LOOP | POST_DISPATCH_PERFORM_DEFAULT);
+
+ switch (ui::EventTypeFromNative(event)) {
+ case ui::ET_KEY_PRESSED: {
+ if (!menu_controller_->OnKeyDown(ui::KeyboardCodeFromNative(event)))
+ return POST_DISPATCH_QUIT_LOOP;
+
+ // Do not check mnemonics if the Alt or Ctrl modifiers are pressed.
+ int flags = ui::EventFlagsFromNative(event);
+ if ((flags & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) == 0) {
+ char c = ui::GetCharacterFromKeyCode(ui::KeyboardCodeFromNative(event),
+ flags);
+ if (menu_controller_->SelectByChar(c))
+ return POST_DISPATCH_QUIT_LOOP;
+ }
+ return POST_DISPATCH_NONE;
+ }
+ case ui::ET_KEY_RELEASED:
+ return POST_DISPATCH_NONE;
+ default:
+ break;
+ }
+
+ return POST_DISPATCH_PERFORM_DEFAULT |
+ (menu_controller_->exit_type() == MenuController::EXIT_NONE
+ ? POST_DISPATCH_NONE
+ : POST_DISPATCH_QUIT_LOOP);
+}
+
+} // namespace internal
+} // namespace views
diff --git a/ui/views/controls/menu/menu_message_pump_dispatcher_win.cc b/ui/views/controls/menu/menu_message_pump_dispatcher_win.cc
new file mode 100644
index 0000000..f49b536
--- /dev/null
+++ b/ui/views/controls/menu/menu_message_pump_dispatcher_win.cc
@@ -0,0 +1,78 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_message_pump_dispatcher.h"
+
+#include <windowsx.h>
+
+#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/views/controls/menu/menu_controller.h"
+
+namespace views {
+namespace internal {
+
+uint32_t MenuMessagePumpDispatcher::Dispatch(const MSG& msg) {
+ DCHECK(menu_controller_->IsBlockingRun());
+
+ if (menu_controller_->exit_type() == MenuController::EXIT_ALL ||
+ menu_controller_->exit_type() == MenuController::EXIT_DESTROYED)
+ return (POST_DISPATCH_QUIT_LOOP | POST_DISPATCH_PERFORM_DEFAULT);
+
+ // NOTE: we don't get WM_ACTIVATE or anything else interesting in here.
+ switch (msg.message) {
+ case WM_CONTEXTMENU: {
+ MenuItemView* item = menu_controller_->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 POST_DISPATCH_NONE;
+ }
+
+ // 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 =
+ menu_controller_->OnKeyDown(ui::KeyboardCodeFromNative(msg));
+ TranslateMessage(&msg);
+ return result ? POST_DISPATCH_NONE : POST_DISPATCH_QUIT_LOOP;
+ }
+ case WM_CHAR: {
+ bool should_exit =
+ menu_controller_->SelectByChar(static_cast<base::char16>(msg.wParam));
+ return should_exit ? POST_DISPATCH_QUIT_LOOP : POST_DISPATCH_NONE;
+ }
+ case WM_KEYUP:
+ return POST_DISPATCH_NONE;
+
+ 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 POST_DISPATCH_NONE;
+
+ case WM_CANCELMODE:
+ case WM_SYSKEYDOWN:
+ // Exit immediately on system keys.
+ menu_controller_->Cancel(MenuController::EXIT_ALL);
+ return POST_DISPATCH_QUIT_LOOP;
+
+ default:
+ break;
+ }
+ return POST_DISPATCH_PERFORM_DEFAULT |
+ (menu_controller_->exit_type() == MenuController::EXIT_NONE
+ ? POST_DISPATCH_NONE
+ : POST_DISPATCH_QUIT_LOOP);
+}
+
+} // namespace internal
+} // namespace views
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index feb92d8..77d3e8b 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -117,10 +117,13 @@
'controls/menu/menu_config_win.cc',
'controls/menu/menu_controller.cc',
'controls/menu/menu_controller.h',
- 'controls/menu/menu_controller_aura.cc',
'controls/menu/menu_controller_delegate.h',
'controls/menu/menu_delegate.cc',
'controls/menu/menu_delegate.h',
+ 'controls/menu/menu_message_pump_dispatcher.cc',
+ 'controls/menu/menu_message_pump_dispatcher.h',
+ 'controls/menu/menu_message_pump_dispatcher_linux.cc',
+ 'controls/menu/menu_message_pump_dispatcher_win.cc',
'controls/menu/menu_host.cc',
'controls/menu/menu_host.h',
'controls/menu/menu_host_root_view.cc',