Commit de026795 authored by pkotwicz@chromium.org's avatar pkotwicz@chromium.org

Translates events so that accelerators which require ET_TRANSLATED_KEY_RELEASE...

Translates events so that accelerators which require ET_TRANSLATED_KEY_RELEASE and ET_TRANSLATED_KEY_PRESS
are triggered.

Translation is always done, so nested dispatcher should not be used for any widgets which have editable content.

BUG=113247
TEST=NestedDispatcherTest.AcceleratorHandled

Review URL: http://codereview.chromium.org/9538015

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@124963 0039d316-1c4b-4281-b951-d872f2087c98
parent d4628ed8
...@@ -17,6 +17,8 @@ namespace ash { ...@@ -17,6 +17,8 @@ namespace ash {
// Wraps a nested dispatcher to which control is passed if no accelerator key // Wraps a nested dispatcher to which control is passed if no accelerator key
// has been pressed. // has been pressed.
// TODO(pkotwicz): Port AcceleratorDispatcher to mac. // TODO(pkotwicz): Port AcceleratorDispatcher to mac.
// TODO(pkotwicz): Add support for a |nested_dispatcher| which sends
// events to a system IME.
class ASH_EXPORT AcceleratorDispatcher : public MessageLoop::Dispatcher, class ASH_EXPORT AcceleratorDispatcher : public MessageLoop::Dispatcher,
public aura::WindowObserver { public aura::WindowObserver {
public: public:
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#endif #endif
#include "ash/accelerators/accelerator_controller.h" #include "ash/accelerators/accelerator_controller.h"
#include "ash/ime/event.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ui/aura/env.h" #include "ui/aura/env.h"
#include "ui/aura/event.h" #include "ui/aura/event.h"
...@@ -30,18 +31,25 @@ const int kModifierMask = (ui::EF_SHIFT_DOWN | ...@@ -30,18 +31,25 @@ const int kModifierMask = (ui::EF_SHIFT_DOWN |
base::MessagePumpDispatcher::DispatchStatus AcceleratorDispatcher::Dispatch( base::MessagePumpDispatcher::DispatchStatus AcceleratorDispatcher::Dispatch(
XEvent* xev) { XEvent* xev) {
// TODO(oshima): Consolidate win and linux. http://crbug.com/116282
if (!associated_window_) if (!associated_window_)
return EVENT_QUIT; return EVENT_QUIT;
if (!ui::IsNoopEvent(xev) && !associated_window_->CanReceiveEvents()) if (!ui::IsNoopEvent(xev) && !associated_window_->CanReceiveEvents())
return aura::Env::GetInstance()->GetDispatcher()->Dispatch(xev); return aura::Env::GetInstance()->GetDispatcher()->Dispatch(xev);
if (xev->type == KeyPress) { if (xev->type == KeyPress || xev->type == KeyRelease) {
ash::AcceleratorController* accelerator_controller = ash::AcceleratorController* accelerator_controller =
ash::Shell::GetInstance()->accelerator_controller(); ash::Shell::GetInstance()->accelerator_controller();
ui::Accelerator accelerator(ui::KeyboardCodeFromNative(xev), if (accelerator_controller) {
ui::EventFlagsFromNative(xev) & kModifierMask); ui::Accelerator accelerator(ui::KeyboardCodeFromNative(xev),
if (accelerator_controller && accelerator_controller->Process(accelerator)) ui::EventFlagsFromNative(xev) & kModifierMask);
return EVENT_PROCESSED; if (accelerator_controller->Process(accelerator))
return EVENT_PROCESSED;
accelerator.set_type(TranslatedKeyEvent(xev, false).type());
if (accelerator_controller->Process(accelerator))
return EVENT_PROCESSED;
}
} }
return nested_dispatcher_->Dispatch(xev); return nested_dispatcher_->Dispatch(xev);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ash/accelerators/accelerator_dispatcher.h" #include "ash/accelerators/accelerator_dispatcher.h"
#include "ash/accelerators/accelerator_controller.h" #include "ash/accelerators/accelerator_controller.h"
#include "ash/ime/event.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ui/aura/env.h" #include "ui/aura/env.h"
#include "ui/aura/event.h" #include "ui/aura/event.h"
...@@ -22,18 +23,25 @@ const int kModifierMask = (ui::EF_SHIFT_DOWN | ...@@ -22,18 +23,25 @@ const int kModifierMask = (ui::EF_SHIFT_DOWN |
} // namespace } // namespace
bool AcceleratorDispatcher::Dispatch(const MSG& msg) { bool AcceleratorDispatcher::Dispatch(const MSG& msg) {
// TODO(oshima): Consolidate win and linux. http://crbug.com/116282
if (!associated_window_) if (!associated_window_)
return false; return false;
if (!ui::IsNoopEvent(msg) && !associated_window_->CanReceiveEvents()) if (!ui::IsNoopEvent(msg) && !associated_window_->CanReceiveEvents())
return aura::Env::GetInstance()->GetDispatcher()->Dispatch(msg); return aura::Env::GetInstance()->GetDispatcher()->Dispatch(msg);
if(msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN) { if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN ||
msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP) {
ash::AcceleratorController* accelerator_controller = ash::AcceleratorController* accelerator_controller =
ash::Shell::GetInstance()->accelerator_controller(); ash::Shell::GetInstance()->accelerator_controller();
ui::Accelerator accelerator(ui::KeyboardCodeFromNative(msg), if (accelerator_controller) {
ui::EventFlagsFromNative(msg) & kModifierMask); ui::Accelerator accelerator(ui::KeyboardCodeFromNative(msg),
if (accelerator_controller && accelerator_controller->Process(accelerator)) ui::EventFlagsFromNative(msg) & kModifierMask);
return true; if (accelerator_controller->Process(accelerator))
return true;
accelerator.set_type(TranslatedKeyEvent(msg, false).type());
if (accelerator_controller->Process(accelerator))
return true;
}
} }
return nested_dispatcher_->Dispatch(msg); return nested_dispatcher_->Dispatch(msg);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "ash/accelerators/accelerator_controller.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/shell_window_ids.h" #include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h" #include "ash/test/ash_test_base.h"
...@@ -12,6 +13,7 @@ ...@@ -12,6 +13,7 @@
#include "ui/aura/root_window.h" #include "ui/aura/root_window.h"
#include "ui/aura/test/test_windows.h" #include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/base/accelerators/accelerator.h"
#if defined(USE_X11) #if defined(USE_X11)
#include <X11/Xlib.h> #include <X11/Xlib.h>
...@@ -50,7 +52,33 @@ class MockDispatcher : public MessageLoop::Dispatcher { ...@@ -50,7 +52,33 @@ class MockDispatcher : public MessageLoop::Dispatcher {
int num_key_events_dispatched_; int num_key_events_dispatched_;
}; };
void DispatchKeyEvent() { class TestTarget : public ui::AcceleratorTarget {
public:
TestTarget() : accelerator_pressed_count_(0) {
}
virtual ~TestTarget() {
}
int accelerator_pressed_count() const {
return accelerator_pressed_count_;
}
// Overridden from ui::AcceleratorTarget:
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE {
accelerator_pressed_count_++;
return true;
}
virtual bool CanHandleAccelerators() const OVERRIDE {
return true;
}
private:
int accelerator_pressed_count_;
DISALLOW_COPY_AND_ASSIGN(TestTarget);
};
void DispatchKeyReleaseA() {
#if defined(OS_WIN) #if defined(OS_WIN)
MSG native_event = { NULL, WM_KEYUP, ui::VKEY_A, 0 }; MSG native_event = { NULL, WM_KEYUP, ui::VKEY_A, 0 };
ash::Shell::GetRootWindow()->PostNativeEvent(native_event); ash::Shell::GetRootWindow()->PostNativeEvent(native_event);
...@@ -75,7 +103,7 @@ typedef AshTestBase NestedDispatcherTest; ...@@ -75,7 +103,7 @@ typedef AshTestBase NestedDispatcherTest;
TEST_F(NestedDispatcherTest, AssociatedWindowBelowLockScreen) { TEST_F(NestedDispatcherTest, AssociatedWindowBelowLockScreen) {
MockDispatcher inner_dispatcher; MockDispatcher inner_dispatcher;
aura::Window* default_container = Shell::GetInstance()->GetContainer( aura::Window* default_container = Shell::GetInstance()->GetContainer(
ash::internal::kShellWindowId_DefaultContainer); internal::kShellWindowId_DefaultContainer);
scoped_ptr<aura::Window>associated_window(aura::test::CreateTestWindowWithId( scoped_ptr<aura::Window>associated_window(aura::test::CreateTestWindowWithId(
0, default_container)); 0, default_container));
scoped_ptr<aura::Window>mock_lock_container( scoped_ptr<aura::Window>mock_lock_container(
...@@ -84,10 +112,7 @@ TEST_F(NestedDispatcherTest, AssociatedWindowBelowLockScreen) { ...@@ -84,10 +112,7 @@ TEST_F(NestedDispatcherTest, AssociatedWindowBelowLockScreen) {
aura::test::CreateTestWindowWithId(0, mock_lock_container.get()); aura::test::CreateTestWindowWithId(0, mock_lock_container.get());
EXPECT_TRUE(aura::test::WindowIsAbove(mock_lock_container.get(), EXPECT_TRUE(aura::test::WindowIsAbove(mock_lock_container.get(),
associated_window.get())); associated_window.get()));
MessageLoop::current()->PostDelayedTask( DispatchKeyReleaseA();
FROM_HERE,
base::Bind(&DispatchKeyEvent),
base::TimeDelta::FromMilliseconds(100));
aura::RootWindow* root_window = ash::Shell::GetInstance()->GetRootWindow(); aura::RootWindow* root_window = ash::Shell::GetInstance()->GetRootWindow();
aura::client::GetDispatcherClient(root_window)->RunWithDispatcher( aura::client::GetDispatcherClient(root_window)->RunWithDispatcher(
&inner_dispatcher, &inner_dispatcher,
...@@ -101,7 +126,7 @@ TEST_F(NestedDispatcherTest, AssociatedWindowAboveLockScreen) { ...@@ -101,7 +126,7 @@ TEST_F(NestedDispatcherTest, AssociatedWindowAboveLockScreen) {
MockDispatcher inner_dispatcher; MockDispatcher inner_dispatcher;
aura::Window* default_container = Shell::GetInstance()->GetContainer( aura::Window* default_container = Shell::GetInstance()->GetContainer(
ash::internal::kShellWindowId_DefaultContainer); internal::kShellWindowId_DefaultContainer);
scoped_ptr<aura::Window>mock_lock_container( scoped_ptr<aura::Window>mock_lock_container(
aura::test::CreateTestWindowWithId(0, default_container)); aura::test::CreateTestWindowWithId(0, default_container));
mock_lock_container->set_stops_event_propagation(true); mock_lock_container->set_stops_event_propagation(true);
...@@ -111,10 +136,7 @@ TEST_F(NestedDispatcherTest, AssociatedWindowAboveLockScreen) { ...@@ -111,10 +136,7 @@ TEST_F(NestedDispatcherTest, AssociatedWindowAboveLockScreen) {
EXPECT_TRUE(aura::test::WindowIsAbove(associated_window.get(), EXPECT_TRUE(aura::test::WindowIsAbove(associated_window.get(),
mock_lock_container.get())); mock_lock_container.get()));
MessageLoop::current()->PostDelayedTask( DispatchKeyReleaseA();
FROM_HERE,
base::Bind(&DispatchKeyEvent),
base::TimeDelta::FromMilliseconds(100));
aura::RootWindow* root_window = ash::Shell::GetInstance()->GetRootWindow(); aura::RootWindow* root_window = ash::Shell::GetInstance()->GetRootWindow();
aura::client::GetDispatcherClient(root_window)->RunWithDispatcher( aura::client::GetDispatcherClient(root_window)->RunWithDispatcher(
&inner_dispatcher, &inner_dispatcher,
...@@ -123,5 +145,25 @@ TEST_F(NestedDispatcherTest, AssociatedWindowAboveLockScreen) { ...@@ -123,5 +145,25 @@ TEST_F(NestedDispatcherTest, AssociatedWindowAboveLockScreen) {
EXPECT_EQ(1, inner_dispatcher.num_key_events_dispatched()); EXPECT_EQ(1, inner_dispatcher.num_key_events_dispatched());
} }
// Test that the nested dispatcher handles accelerators.
TEST_F(NestedDispatcherTest, AcceleratorsHandled) {
MockDispatcher inner_dispatcher;
aura::RootWindow* root_window = ash::Shell::GetInstance()->GetRootWindow();
ui::Accelerator accelerator(ui::VKEY_A, false, false, false);
accelerator.set_type(ui::ET_TRANSLATED_KEY_RELEASE);
TestTarget target;
Shell::GetInstance()->accelerator_controller()->Register(accelerator,
&target);
DispatchKeyReleaseA();
aura::client::GetDispatcherClient(root_window)->RunWithDispatcher(
&inner_dispatcher,
root_window,
true /* nestable_tasks_allowed */);
EXPECT_EQ(0, inner_dispatcher.num_key_events_dispatched());
EXPECT_EQ(1, target.accelerator_pressed_count());
}
} // namespace test } // namespace test
} // namespace ash } // namespace ash
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment