summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-07 22:21:52 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-07 22:21:52 +0000
commit45a6846c2efb0b934e3baed72027cba4ec1751b9 (patch)
treeeaeef11ca280c09f35e641038825c753d2ea94f4
parent2450c2dc0d0e5335fe6d35a29d5a550b343c5e42 (diff)
downloadchromium_src-45a6846c2efb0b934e3baed72027cba4ec1751b9.zip
chromium_src-45a6846c2efb0b934e3baed72027cba4ec1751b9.tar.gz
chromium_src-45a6846c2efb0b934e3baed72027cba4ec1751b9.tar.bz2
Ensure that menus put in Chrome ASH on Windows 8 are operatable using the keyboard.
When a menu is displayed we enter a nested message loop in the Chrome Browser. This loop expects to receive native events for WM_KEYDOWN/WM_KEYUP/WM_CHAR, etc. In desktop AURA this works well because the native events come in through the standard OS mechanism. In ASH we send over fabricated keyboard events from the viewer process to the browser where these are dispatched to the root window. This causes the secondary loop to never receive these events. Fix for now is to check if we are in a nested loop in the RemoteRootWindowHostWin IPC handlers and post the corresponding native event back to the queue. The other change in this CL is to add an event handler to listen for accelerator events in the viewer process. This is necessary to receive keystrokes like Alt, etc. We send over the same keydown/keyup/character IPC's when we receive this event. BUG=180738 R=cpu TBR=ben TEST=Will look into an ash based test for this in a subsequent CL. Review URL: https://codereview.chromium.org/12558008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186797 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/aura/remote_root_window_host_win.cc68
-rw-r--r--ui/aura/remote_root_window_host_win.h12
-rw-r--r--win8/metro_driver/chrome_app_view_ash.cc68
-rw-r--r--win8/metro_driver/chrome_app_view_ash.h6
4 files changed, 139 insertions, 15 deletions
diff --git a/ui/aura/remote_root_window_host_win.cc b/ui/aura/remote_root_window_host_win.cc
index 962f19d..e9be2a5 100644
--- a/ui/aura/remote_root_window_host_win.cc
+++ b/ui/aura/remote_root_window_host_win.cc
@@ -29,6 +29,29 @@ const char* kRootWindowHostWinKey = "__AURA_REMOTE_ROOT_WINDOW_HOST_WIN__";
// The touch id to be used for touch events coming in from Windows Ash.
const int kRemoteWindowTouchId = 10;
+// Sets the keystate for the virtual key passed in to down or up.
+void SetKeyState(uint8* key_states, bool key_down, uint32 virtual_key_code) {
+ DCHECK(key_states);
+
+ if (key_down)
+ key_states[virtual_key_code] |= 0x80;
+ else
+ key_states[virtual_key_code] &= 0x7F;
+}
+
+// Sets the keyboard states for the Shift/Control/Alt/Caps lock keys.
+void SetVirtualKeyStates(uint32 flags) {
+ uint8 keyboard_state[256] = {0};
+ ::GetKeyboardState(keyboard_state);
+
+ SetKeyState(keyboard_state, !!(flags & ui::EF_SHIFT_DOWN), VK_SHIFT);
+ SetKeyState(keyboard_state, !!(flags & ui::EF_CONTROL_DOWN), VK_CONTROL);
+ SetKeyState(keyboard_state, !!(flags & ui::EF_ALT_DOWN), VK_MENU);
+ SetKeyState(keyboard_state, !!(flags & ui::EF_CAPS_LOCK_DOWN), VK_CAPITAL);
+
+ ::SetKeyboardState(keyboard_state);
+}
+
} // namespace
void HandleOpenFile(
@@ -317,33 +340,24 @@ void RemoteRootWindowHostWin::OnKeyDown(uint32 vkey,
uint32 repeat_count,
uint32 scan_code,
uint32 flags) {
- ui::KeyEvent event(ui::ET_KEY_PRESSED,
- ui::KeyboardCodeForWindowsKeyCode(vkey),
- flags,
- false);
- delegate_->OnHostKeyEvent(&event);
+ DispatchKeyboardMessage(ui::ET_KEY_PRESSED, vkey, repeat_count, scan_code,
+ flags, false);
}
void RemoteRootWindowHostWin::OnKeyUp(uint32 vkey,
uint32 repeat_count,
uint32 scan_code,
uint32 flags) {
- ui::KeyEvent event(ui::ET_KEY_RELEASED,
- ui::KeyboardCodeForWindowsKeyCode(vkey),
- flags,
- false);
- delegate_->OnHostKeyEvent(&event);
+ DispatchKeyboardMessage(ui::ET_KEY_RELEASED, vkey, repeat_count, scan_code,
+ flags, false);
}
void RemoteRootWindowHostWin::OnChar(uint32 key_code,
uint32 repeat_count,
uint32 scan_code,
uint32 flags) {
- ui::KeyEvent event(ui::ET_KEY_PRESSED,
- ui::KeyboardCodeForWindowsKeyCode(key_code),
- flags,
- true);
- delegate_->OnHostKeyEvent(&event);
+ DispatchKeyboardMessage(ui::ET_KEY_PRESSED, key_code, repeat_count,
+ scan_code, flags, true);
}
void RemoteRootWindowHostWin::OnVisibilityChanged(bool visible) {
@@ -405,4 +419,28 @@ void RemoteRootWindowHostWin::OnMultiFileOpenDone(
multi_file_open_completion_callback_.Reset();
}
+void RemoteRootWindowHostWin::DispatchKeyboardMessage(ui::EventType type,
+ uint32 vkey,
+ uint32 repeat_count,
+ uint32 scan_code,
+ uint32 flags,
+ bool is_character) {
+ if (MessageLoop::current()->IsNested()) {
+ SetVirtualKeyStates(flags);
+
+ uint32 message = is_character ? WM_CHAR :
+ (type == ui::ET_KEY_PRESSED ? WM_KEYDOWN : WM_KEYUP);
+ ::PostThreadMessage(::GetCurrentThreadId(),
+ message,
+ vkey,
+ repeat_count | scan_code >> 15);
+ } else {
+ ui::KeyEvent event(type,
+ ui::KeyboardCodeForWindowsKeyCode(vkey),
+ flags,
+ is_character);
+ delegate_->OnHostKeyEvent(&event);
+ }
+}
+
} // namespace aura
diff --git a/ui/aura/remote_root_window_host_win.h b/ui/aura/remote_root_window_host_win.h
index 05959a9..34eac80 100644
--- a/ui/aura/remote_root_window_host_win.h
+++ b/ui/aura/remote_root_window_host_win.h
@@ -166,6 +166,18 @@ class AURA_EXPORT RemoteRootWindowHostWin : public RootWindowHost {
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
virtual void PrepareForShutdown() OVERRIDE;
+ // Helper function to dispatch a keyboard message to the desired target.
+ // The default target is the RootWindowHostDelegate. For nested message loop
+ // invocations we post a synthetic keyboard message directly into the message
+ // loop. The dispatcher for the nested loop would then decide how this
+ // message is routed.
+ void DispatchKeyboardMessage(ui::EventType type,
+ uint32 vkey,
+ uint32 repeat_count,
+ uint32 scan_code,
+ uint32 flags,
+ bool is_character);
+
RootWindowHostDelegate* delegate_;
IPC::Sender* host_;
scoped_ptr<ui::ViewProp> prop_;
diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc
index d3c128d..56c9afb 100644
--- a/win8/metro_driver/chrome_app_view_ash.cc
+++ b/win8/metro_driver/chrome_app_view_ash.cc
@@ -37,6 +37,10 @@ typedef winfoundtn::ITypedEventHandler<
winui::Core::KeyEventArgs*> KeyEventHandler;
typedef winfoundtn::ITypedEventHandler<
+ winui::Core::CoreDispatcher*,
+ winui::Core::AcceleratorKeyEventArgs*> AcceleratorKeyEventHandler;
+
+typedef winfoundtn::ITypedEventHandler<
winui::Core::CoreWindow*,
winui::Core::CharacterReceivedEventArgs*> CharEventHandler;
@@ -311,6 +315,21 @@ ChromeAppViewAsh::SetWindow(winui::Core::ICoreWindow* window) {
&keyup_token_);
CheckHR(hr);
+ mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher;
+ hr = window_->get_Dispatcher(&dispatcher);
+ CheckHR(hr, "Get Dispatcher failed.");
+
+ mswr::ComPtr<winui::Core::ICoreAcceleratorKeys> accelerator_keys;
+ hr = dispatcher.CopyTo(__uuidof(winui::Core::ICoreAcceleratorKeys),
+ reinterpret_cast<void**>(
+ accelerator_keys.GetAddressOf()));
+ CheckHR(hr, "QI for ICoreAcceleratorKeys failed.");
+ hr = accelerator_keys->add_AcceleratorKeyActivated(
+ mswr::Callback<AcceleratorKeyEventHandler>(
+ this, &ChromeAppViewAsh::OnAcceleratorKeyDown).Get(),
+ &accel_keydown_token_);
+ CheckHR(hr);
+
hr = window_->add_PointerWheelChanged(mswr::Callback<PointerEventHandler>(
this, &ChromeAppViewAsh::OnWheel).Get(),
&wheel_token_);
@@ -640,6 +659,55 @@ HRESULT ChromeAppViewAsh::OnKeyUp(
return S_OK;
}
+HRESULT ChromeAppViewAsh::OnAcceleratorKeyDown(
+ winui::Core::ICoreDispatcher* sender,
+ winui::Core::IAcceleratorKeyEventArgs* args) {
+ winsys::VirtualKey virtual_key;
+ HRESULT hr = args->get_VirtualKey(&virtual_key);
+ if (FAILED(hr))
+ return hr;
+ winui::Core::CorePhysicalKeyStatus status;
+ hr = args->get_KeyStatus(&status);
+ if (FAILED(hr))
+ return hr;
+
+ winui::Core::CoreAcceleratorKeyEventType event_type;
+ hr = args->get_EventType(&event_type);
+ if (FAILED(hr))
+ return hr;
+
+ // The AURA event handling code does not handle the system key down event for
+ // the Alt key if we pass in the flag EF_ALT_DOWN.
+ uint32 keyboard_flags = GetKeyboardEventFlags() & ~ui::EF_ALT_DOWN;
+
+ switch (event_type) {
+ case winui::Core::CoreAcceleratorKeyEventType_SystemCharacter:
+ ui_channel_->Send(new MetroViewerHostMsg_Character(virtual_key,
+ status.RepeatCount,
+ status.ScanCode,
+ keyboard_flags));
+ break;
+
+ case winui::Core::CoreAcceleratorKeyEventType_SystemKeyDown:
+ ui_channel_->Send(new MetroViewerHostMsg_KeyDown(virtual_key,
+ status.RepeatCount,
+ status.ScanCode,
+ keyboard_flags));
+ break;
+
+ case winui::Core::CoreAcceleratorKeyEventType_SystemKeyUp:
+ ui_channel_->Send(new MetroViewerHostMsg_KeyUp(virtual_key,
+ status.RepeatCount,
+ status.ScanCode,
+ keyboard_flags));
+ break;
+
+ default:
+ break;
+ }
+ return S_OK;
+}
+
HRESULT ChromeAppViewAsh::OnCharacterReceived(
winui::Core::ICoreWindow* sender,
winui::Core::ICharacterReceivedEventArgs* args) {
diff --git a/win8/metro_driver/chrome_app_view_ash.h b/win8/metro_driver/chrome_app_view_ash.h
index 9dd0e60..c13f757 100644
--- a/win8/metro_driver/chrome_app_view_ash.h
+++ b/win8/metro_driver/chrome_app_view_ash.h
@@ -86,6 +86,10 @@ class ChromeAppViewAsh
HRESULT OnKeyUp(winui::Core::ICoreWindow* sender,
winui::Core::IKeyEventArgs* args);
+ // Invoked for system keys like Alt, etc.
+ HRESULT OnAcceleratorKeyDown(winui::Core::ICoreDispatcher* sender,
+ winui::Core::IAcceleratorKeyEventArgs* args);
+
HRESULT OnCharacterReceived(winui::Core::ICoreWindow* sender,
winui::Core::ICharacterReceivedEventArgs* args);
@@ -103,6 +107,8 @@ class ChromeAppViewAsh
EventRegistrationToken keyup_token_;
EventRegistrationToken character_received_token_;
EventRegistrationToken visibility_changed_token_;
+ EventRegistrationToken accel_keydown_token_;
+ EventRegistrationToken accel_keyup_token_;
// Keep state about which button is currently down, if any, as PointerMoved
// events do not contain that state, but Ash's MouseEvents need it.