summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/accelerators/accelerator_dispatcher.cc15
-rw-r--r--ash/accelerators/accelerator_dispatcher.h37
-rw-r--r--ash/accelerators/accelerator_dispatcher_linux.cc46
-rw-r--r--ash/accelerators/accelerator_dispatcher_win.cc39
-rw-r--r--ash/accelerators/nested_dispatcher_controller.cc31
-rw-r--r--ash/accelerators/nested_dispatcher_controller.h34
-rw-r--r--ash/ash.gyp6
-rw-r--r--ash/shell.cc2
-rw-r--r--ash/shell.h3
-rw-r--r--ui/aura/aura.gyp2
-rw-r--r--ui/aura/client/dispatcher_client.cc31
-rw-r--r--ui/aura/client/dispatcher_client.h29
-rw-r--r--ui/views/controls/menu/menu_controller.cc5
13 files changed, 280 insertions, 0 deletions
diff --git a/ash/accelerators/accelerator_dispatcher.cc b/ash/accelerators/accelerator_dispatcher.cc
new file mode 100644
index 0000000..46d7bec
--- /dev/null
+++ b/ash/accelerators/accelerator_dispatcher.cc
@@ -0,0 +1,15 @@
+// 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 "ash/accelerators/accelerator_dispatcher.h"
+
+namespace ash {
+
+AcceleratorDispatcher::AcceleratorDispatcher(
+ MessageLoop::Dispatcher* nested_dispatcher)
+ : nested_dispatcher_(nested_dispatcher) {
+ DCHECK(nested_dispatcher_);
+}
+
+} // namespace ash
diff --git a/ash/accelerators/accelerator_dispatcher.h b/ash/accelerators/accelerator_dispatcher.h
new file mode 100644
index 0000000..9de596c
--- /dev/null
+++ b/ash/accelerators/accelerator_dispatcher.h
@@ -0,0 +1,37 @@
+// 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.
+
+#ifndef ASH_ACCELERATORS_ACCELERATOR_DISPATCHER_H_
+#define ASH_ACCELERATORS_ACCELERATOR_DISPATCHER_H_
+#pragma once
+
+#include "ash/ash_export.h"
+#include "base/message_loop.h"
+
+namespace ash {
+
+// Dispatcher for handling accelerators in ash.
+// Wraps a nested dispatcher to which control is passed if no accelerator key
+// has been pressed.
+// TODO(pkotwicz): Port AcceleratorDispatcher to mac.
+class ASH_EXPORT AcceleratorDispatcher : public MessageLoop::Dispatcher {
+ public:
+ explicit AcceleratorDispatcher(MessageLoop::Dispatcher* nested_dispatcher);
+
+#if defined(USE_X11)
+ virtual base::MessagePumpDispatcher::DispatchStatus Dispatch(
+ XEvent* xev) OVERRIDE;
+#elif defined(OS_WIN)
+ bool AcceleratorDispatcher::Dispatch(const MSG& msg) OVERRIDE;
+#endif
+
+ private:
+ MessageLoop::Dispatcher* nested_dispatcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(AcceleratorDispatcher);
+};
+
+} // namespace ash
+
+#endif // ASH_ACCELERATORS_ACCELERATOR_DISPATCHER_H_
diff --git a/ash/accelerators/accelerator_dispatcher_linux.cc b/ash/accelerators/accelerator_dispatcher_linux.cc
new file mode 100644
index 0000000..82b98aa
--- /dev/null
+++ b/ash/accelerators/accelerator_dispatcher_linux.cc
@@ -0,0 +1,46 @@
+// 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 "ash/accelerators/accelerator_dispatcher.h"
+
+#include <X11/Xlib.h>
+
+// Xlib defines RootWindow
+#ifdef RootWindow
+#undef RootWindow
+#endif
+
+#include "ash/accelerators/accelerator_controller.h"
+#include "ash/shell.h"
+#include "ui/aura/event.h"
+#include "ui/aura/root_window.h"
+#include "ui/base/accelerators/accelerator.h"
+
+namespace ash {
+
+namespace {
+
+const int kModifierMask = (ui::EF_SHIFT_DOWN |
+ ui::EF_CONTROL_DOWN |
+ ui::EF_ALT_DOWN);
+} // namespace
+
+base::MessagePumpDispatcher::DispatchStatus AcceleratorDispatcher::Dispatch(
+ XEvent* xev) {
+ ash::Shell* shell = ash::Shell::GetInstance();
+ if (shell->IsScreenLocked())
+ return aura::RootWindow::GetInstance()->GetDispatcher()->Dispatch(xev);
+
+ if (xev->type == KeyPress) {
+ ash::AcceleratorController* accelerator_controller =
+ shell->accelerator_controller();
+ ui::Accelerator accelerator(ui::KeyboardCodeFromNative(xev),
+ ui::EventFlagsFromNative(xev) & kModifierMask);
+ if (accelerator_controller && accelerator_controller->Process(accelerator))
+ return EVENT_PROCESSED;
+ }
+ return nested_dispatcher_->Dispatch(xev);
+}
+
+} // namespace ash
diff --git a/ash/accelerators/accelerator_dispatcher_win.cc b/ash/accelerators/accelerator_dispatcher_win.cc
new file mode 100644
index 0000000..4682275
--- /dev/null
+++ b/ash/accelerators/accelerator_dispatcher_win.cc
@@ -0,0 +1,39 @@
+// 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 "ash/accelerators/accelerator_dispatcher.h"
+
+#include "ash/accelerators/accelerator_controller.h"
+#include "ash/shell.h"
+#include "ui/aura/event.h"
+#include "ui/aura/root_window.h"
+#include "ui/base/accelerators/accelerator.h"
+
+namespace ash {
+
+namespace {
+
+const int kModifierMask = (ui::EF_SHIFT_DOWN |
+ ui::EF_CONTROL_DOWN |
+ ui::EF_ALT_DOWN);
+} // namespace
+
+bool AcceleratorDispatcher::Dispatch(const MSG& msg) {
+ ash::Shell* shell = ash::Shell::GetInstance();
+ if (shell->IsScreenLocked())
+ return aura::RootWindow::GetInstance()->GetDispatcher()->Dispatch(msg);
+
+ if(msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN) {
+ ash::AcceleratorController* accelerator_controller =
+ shell->accelerator_controller();
+ ui::Accelerator accelerator(ui::KeyboardCodeFromNative(msg),
+ ui::EventFlagsFromNative(msg) & kModifierMask);
+ if (accelerator_controller && accelerator_controller->Process(accelerator))
+ return true;
+ }
+
+ return nested_dispatcher_->Dispatch(msg);
+}
+
+} // namespace ash
diff --git a/ash/accelerators/nested_dispatcher_controller.cc b/ash/accelerators/nested_dispatcher_controller.cc
new file mode 100644
index 0000000..758b63d
--- /dev/null
+++ b/ash/accelerators/nested_dispatcher_controller.cc
@@ -0,0 +1,31 @@
+// 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 "ash/accelerators/nested_dispatcher_controller.h"
+
+#include "ash/accelerators/accelerator_dispatcher.h"
+
+namespace ash {
+
+NestedDispatcherController::NestedDispatcherController() {
+ aura::client::SetDispatcherClient(this);
+}
+
+NestedDispatcherController::~NestedDispatcherController() {
+}
+
+void NestedDispatcherController::RunWithDispatcher(
+ MessageLoop::Dispatcher* nested_dispatcher,
+ bool nestable_tasks_allowed) {
+ MessageLoopForUI* loop = MessageLoopForUI::current();
+ bool did_allow_task_nesting = loop->NestableTasksAllowed();
+ loop->SetNestableTasksAllowed(nestable_tasks_allowed);
+
+ AcceleratorDispatcher dispatcher(nested_dispatcher);
+
+ loop->RunWithDispatcher(&dispatcher);
+ loop->SetNestableTasksAllowed(did_allow_task_nesting);
+}
+
+} // namespace ash
diff --git a/ash/accelerators/nested_dispatcher_controller.h b/ash/accelerators/nested_dispatcher_controller.h
new file mode 100644
index 0000000..33acfd0
--- /dev/null
+++ b/ash/accelerators/nested_dispatcher_controller.h
@@ -0,0 +1,34 @@
+// 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.
+
+#ifndef ASH_ACCELERATORS_NESTED_DISPATCHER_CONTROLLER_H_
+#define ASH_ACCELERATORS_NESTED_DISPATCHER_CONTROLLER_H_
+#pragma once
+
+#include "ash/ash_export.h"
+#include "base/message_loop.h"
+#include "ui/aura/client/dispatcher_client.h"
+
+namespace ash {
+
+// Creates a dispatcher which wraps another dispatcher.
+// The outer dispatcher runs first and performs ash specific handling.
+// If it does not consume the event it forwards the event to the nested
+// dispatcher.
+class ASH_EXPORT NestedDispatcherController
+ : public aura::client::DispatcherClient {
+ public:
+ NestedDispatcherController();
+ virtual ~NestedDispatcherController();
+
+ virtual void RunWithDispatcher(MessageLoop::Dispatcher* dispatcher,
+ bool nestable_tasks_allowed) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NestedDispatcherController);
+};
+
+} // namespace ash
+
+#endif // ASH_ACCELERATORS_NESTED_DISPATCHER_CONTROLLER_H_
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 88f6c06..4af5092 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -36,8 +36,14 @@
# All .cc, .h under ash, except unittests
'accelerators/accelerator_controller.cc',
'accelerators/accelerator_controller.h',
+ 'accelerators/accelerator_dispatcher.cc',
+ 'accelerators/accelerator_dispatcher.h',
+ 'accelerators/accelerator_dispatcher_linux.cc',
+ 'accelerators/accelerator_dispatcher_win.cc',
'accelerators/accelerator_filter.cc',
'accelerators/accelerator_filter.h',
+ 'accelerators/nested_dispatcher_controller.cc',
+ 'accelerators/nested_dispatcher_controller.h',
'app_list/app_list.cc',
'app_list/app_list.h',
'app_list/app_list_groups_view.cc',
diff --git a/ash/shell.cc b/ash/shell.cc
index f47938c..5bfd3d4 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -8,6 +8,7 @@
#include "ash/accelerators/accelerator_controller.h"
#include "ash/accelerators/accelerator_filter.h"
+#include "ash/accelerators/nested_dispatcher_controller.h"
#include "ash/app_list/app_list.h"
#include "ash/ash_switches.h"
#include "ash/drag_drop/drag_drop_controller.h"
@@ -205,6 +206,7 @@ Shell* Shell::instance_ = NULL;
Shell::Shell(ShellDelegate* delegate)
: ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
+ nested_dispatcher_controller_(new NestedDispatcherController),
accelerator_controller_(new AcceleratorController),
delegate_(delegate),
window_mode_(MODE_OVERLAPPING),
diff --git a/ash/shell.h b/ash/shell.h
index 374015d..9e48aa2 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -37,6 +37,7 @@ namespace ash {
class AcceleratorController;
class Launcher;
+class NestedDispatcherController;
class PowerButtonController;
class ShellDelegate;
class VideoDetector;
@@ -183,6 +184,8 @@ class ASH_EXPORT Shell {
base::WeakPtrFactory<Shell> method_factory_;
+ scoped_ptr<NestedDispatcherController> nested_dispatcher_controller_;
+
scoped_ptr<AcceleratorController> accelerator_controller_;
scoped_ptr<ShellDelegate> delegate_;
diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp
index c84a74e..8c4bc99 100644
--- a/ui/aura/aura.gyp
+++ b/ui/aura/aura.gyp
@@ -32,6 +32,8 @@
'client/activation_delegate.h',
'client/aura_constants.cc',
'client/aura_constants.h',
+ 'client/dispatcher_client.cc',
+ 'client/dispatcher_client.h',
'client/drag_drop_client.cc',
'client/drag_drop_client.h',
'client/drag_drop_delegate.cc',
diff --git a/ui/aura/client/dispatcher_client.cc b/ui/aura/client/dispatcher_client.cc
new file mode 100644
index 0000000..f9cd3ac
--- /dev/null
+++ b/ui/aura/client/dispatcher_client.cc
@@ -0,0 +1,31 @@
+// 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/aura/client/dispatcher_client.h"
+
+#include "ui/aura/root_window.h"
+
+namespace aura {
+
+namespace client {
+
+namespace {
+
+// A property key to store the nested dispatcher controller. The type of the
+// value is |aura::client::DispatcherClient*|.
+const char kDispatcherClient[] = "AuraDispatcherClient";
+
+} // namespace
+
+void SetDispatcherClient(DispatcherClient* client) {
+ RootWindow::GetInstance()->SetProperty(kDispatcherClient, client);
+}
+
+DispatcherClient* GetDispatcherClient() {
+ return reinterpret_cast<DispatcherClient*>(
+ RootWindow::GetInstance()->GetProperty(kDispatcherClient));
+}
+
+} // namespace client
+} // namespace aura
diff --git a/ui/aura/client/dispatcher_client.h b/ui/aura/client/dispatcher_client.h
new file mode 100644
index 0000000..099e370
--- /dev/null
+++ b/ui/aura/client/dispatcher_client.h
@@ -0,0 +1,29 @@
+// 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.
+
+#ifndef UI_AURA_CLIENT_DISPATCHER_CLIENT_H_
+#define UI_AURA_CLIENT_DISPATCHER_CLIENT_H_
+#pragma once
+
+#include "ui/aura/aura_export.h"
+#include "base/message_loop.h"
+
+namespace aura {
+
+namespace client {
+
+// An interface implemented by an object which handles nested dispatchers.
+class AURA_EXPORT DispatcherClient {
+ public:
+ virtual void RunWithDispatcher(MessageLoop::Dispatcher* dispatcher,
+ bool nestable_tasks_allowed) = 0;
+};
+
+AURA_EXPORT void SetDispatcherClient(DispatcherClient* client);
+AURA_EXPORT DispatcherClient* GetDispatcherClient();
+
+} // namespace client
+} // namespace aura
+
+#endif // UI_AURA_CLIENT_DISPATCHER_CLIENT_H_
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 87199dc9..0f16a60 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -25,6 +25,7 @@
#include "ui/views/widget/widget.h"
#if defined(USE_AURA)
+#include "ui/aura/client/dispatcher_client.h"
#include "ui/aura/root_window.h"
#elif defined(TOOLKIT_USES_GTK)
#include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
@@ -318,11 +319,15 @@ MenuItemView* MenuController::Run(Widget* parent,
// one) the menus are run from a task. If we don't do this and are invoked
// from a task none of the tasks we schedule are processed and the menu
// appears totally broken.
+#if defined(USE_AURA)
+ aura::client::GetDispatcherClient()->RunWithDispatcher(this, true);
+#else
MessageLoopForUI* loop = MessageLoopForUI::current();
bool did_allow_task_nesting = loop->NestableTasksAllowed();
loop->SetNestableTasksAllowed(true);
loop->RunWithDispatcher(this);
loop->SetNestableTasksAllowed(did_allow_task_nesting);
+#endif
if (ViewsDelegate::views_delegate)
ViewsDelegate::views_delegate->ReleaseRef();