Skip to content

Commit

Permalink
Translates events so that accelerators which require ET_TRANSLATED_KE…
Browse files Browse the repository at this point in the history
…Y_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
  • Loading branch information
pkotwicz@chromium.org committed Mar 5, 2012
1 parent d4628ed commit de02679
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 21 deletions.
2 changes: 2 additions & 0 deletions ash/accelerators/accelerator_dispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace ash {
// Wraps a nested dispatcher to which control is passed if no accelerator key
// has been pressed.
// 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,
public aura::WindowObserver {
public:
Expand Down
18 changes: 13 additions & 5 deletions ash/accelerators/accelerator_dispatcher_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#endif

#include "ash/accelerators/accelerator_controller.h"
#include "ash/ime/event.h"
#include "ash/shell.h"
#include "ui/aura/env.h"
#include "ui/aura/event.h"
Expand All @@ -30,18 +31,25 @@ const int kModifierMask = (ui::EF_SHIFT_DOWN |

base::MessagePumpDispatcher::DispatchStatus AcceleratorDispatcher::Dispatch(
XEvent* xev) {
// TODO(oshima): Consolidate win and linux. http://crbug.com/116282
if (!associated_window_)
return EVENT_QUIT;
if (!ui::IsNoopEvent(xev) && !associated_window_->CanReceiveEvents())
return aura::Env::GetInstance()->GetDispatcher()->Dispatch(xev);

if (xev->type == KeyPress) {
if (xev->type == KeyPress || xev->type == KeyRelease) {
ash::AcceleratorController* accelerator_controller =
ash::Shell::GetInstance()->accelerator_controller();
ui::Accelerator accelerator(ui::KeyboardCodeFromNative(xev),
ui::EventFlagsFromNative(xev) & kModifierMask);
if (accelerator_controller && accelerator_controller->Process(accelerator))
return EVENT_PROCESSED;
if (accelerator_controller) {
ui::Accelerator accelerator(ui::KeyboardCodeFromNative(xev),
ui::EventFlagsFromNative(xev) & kModifierMask);
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);
}
Expand Down
18 changes: 13 additions & 5 deletions ash/accelerators/accelerator_dispatcher_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "ash/accelerators/accelerator_dispatcher.h"

#include "ash/accelerators/accelerator_controller.h"
#include "ash/ime/event.h"
#include "ash/shell.h"
#include "ui/aura/env.h"
#include "ui/aura/event.h"
Expand All @@ -22,18 +23,25 @@ const int kModifierMask = (ui::EF_SHIFT_DOWN |
} // namespace

bool AcceleratorDispatcher::Dispatch(const MSG& msg) {
// TODO(oshima): Consolidate win and linux. http://crbug.com/116282
if (!associated_window_)
return false;
if (!ui::IsNoopEvent(msg) && !associated_window_->CanReceiveEvents())
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::Shell::GetInstance()->accelerator_controller();
ui::Accelerator accelerator(ui::KeyboardCodeFromNative(msg),
ui::EventFlagsFromNative(msg) & kModifierMask);
if (accelerator_controller && accelerator_controller->Process(accelerator))
return true;
if (accelerator_controller) {
ui::Accelerator accelerator(ui::KeyboardCodeFromNative(msg),
ui::EventFlagsFromNative(msg) & kModifierMask);
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);
Expand Down
64 changes: 53 additions & 11 deletions ash/accelerators/nested_dispatcher_controller_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/accelerators/accelerator_controller.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/test/ash_test_base.h"
Expand All @@ -12,6 +13,7 @@
#include "ui/aura/root_window.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/base/accelerators/accelerator.h"

#if defined(USE_X11)
#include <X11/Xlib.h>
Expand Down Expand Up @@ -50,7 +52,33 @@ class MockDispatcher : public MessageLoop::Dispatcher {
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)
MSG native_event = { NULL, WM_KEYUP, ui::VKEY_A, 0 };
ash::Shell::GetRootWindow()->PostNativeEvent(native_event);
Expand All @@ -75,7 +103,7 @@ typedef AshTestBase NestedDispatcherTest;
TEST_F(NestedDispatcherTest, AssociatedWindowBelowLockScreen) {
MockDispatcher inner_dispatcher;
aura::Window* default_container = Shell::GetInstance()->GetContainer(
ash::internal::kShellWindowId_DefaultContainer);
internal::kShellWindowId_DefaultContainer);
scoped_ptr<aura::Window>associated_window(aura::test::CreateTestWindowWithId(
0, default_container));
scoped_ptr<aura::Window>mock_lock_container(
Expand All @@ -84,10 +112,7 @@ TEST_F(NestedDispatcherTest, AssociatedWindowBelowLockScreen) {
aura::test::CreateTestWindowWithId(0, mock_lock_container.get());
EXPECT_TRUE(aura::test::WindowIsAbove(mock_lock_container.get(),
associated_window.get()));
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&DispatchKeyEvent),
base::TimeDelta::FromMilliseconds(100));
DispatchKeyReleaseA();
aura::RootWindow* root_window = ash::Shell::GetInstance()->GetRootWindow();
aura::client::GetDispatcherClient(root_window)->RunWithDispatcher(
&inner_dispatcher,
Expand All @@ -101,7 +126,7 @@ TEST_F(NestedDispatcherTest, AssociatedWindowAboveLockScreen) {
MockDispatcher inner_dispatcher;

aura::Window* default_container = Shell::GetInstance()->GetContainer(
ash::internal::kShellWindowId_DefaultContainer);
internal::kShellWindowId_DefaultContainer);
scoped_ptr<aura::Window>mock_lock_container(
aura::test::CreateTestWindowWithId(0, default_container));
mock_lock_container->set_stops_event_propagation(true);
Expand All @@ -111,10 +136,7 @@ TEST_F(NestedDispatcherTest, AssociatedWindowAboveLockScreen) {
EXPECT_TRUE(aura::test::WindowIsAbove(associated_window.get(),
mock_lock_container.get()));

MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&DispatchKeyEvent),
base::TimeDelta::FromMilliseconds(100));
DispatchKeyReleaseA();
aura::RootWindow* root_window = ash::Shell::GetInstance()->GetRootWindow();
aura::client::GetDispatcherClient(root_window)->RunWithDispatcher(
&inner_dispatcher,
Expand All @@ -123,5 +145,25 @@ TEST_F(NestedDispatcherTest, AssociatedWindowAboveLockScreen) {
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 ash

0 comments on commit de02679

Please sign in to comment.