diff options
author | nkostylev@chromium.org <nkostylev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-13 07:15:53 +0000 |
---|---|---|
committer | nkostylev@chromium.org <nkostylev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-13 07:15:53 +0000 |
commit | ad907cab8a57d73110eec0b75c8e8376497d39a2 (patch) | |
tree | 38180260d892beb11c37d009b94c5c5d9921b793 /remoting/client | |
parent | 1ed51f572f13b695021ac8c187a30b91ae33fb95 (diff) | |
download | chromium_src-ad907cab8a57d73110eec0b75c8e8376497d39a2.zip chromium_src-ad907cab8a57d73110eec0b75c8e8376497d39a2.tar.gz chromium_src-ad907cab8a57d73110eec0b75c8e8376497d39a2.tar.bz2 |
Revert 217207 "Work around OSKey being used as a rewriting modif..."
> Work around OSKey being used as a rewriting modifier to get extended keys on CrOS.
>
> Moves MacKeyEventProcessor to NormalizingInputFilterMac and adds a NormalizingInputFilterAsh which tries to properly distinguish the key-writing versus key-modifying behaviours of OSKey (CrOS' Search key).
>
> BUG=230049
>
> Review URL: https://chromiumcodereview.appspot.com/18345018
TBR=wez@chromium.org
Review URL: https://codereview.chromium.org/22897003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217223 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/client')
-rw-r--r-- | remoting/client/plugin/chromoting_instance.cc | 10 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_instance.h | 6 | ||||
-rw-r--r-- | remoting/client/plugin/mac_key_event_processor.cc (renamed from remoting/client/plugin/normalizing_input_filter_mac.cc) | 79 | ||||
-rw-r--r-- | remoting/client/plugin/mac_key_event_processor.h | 76 | ||||
-rw-r--r-- | remoting/client/plugin/mac_key_event_processor_unittest.cc (renamed from remoting/client/plugin/normalizing_input_filter_mac_unittest.cc) | 92 | ||||
-rw-r--r-- | remoting/client/plugin/normalizing_input_filter.cc | 20 | ||||
-rw-r--r-- | remoting/client/plugin/normalizing_input_filter.h | 21 | ||||
-rw-r--r-- | remoting/client/plugin/normalizing_input_filter_ash.cc | 206 | ||||
-rw-r--r-- | remoting/client/plugin/normalizing_input_filter_ash_unittest.cc | 212 |
9 files changed, 140 insertions, 582 deletions
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index 3469ca2..e22452a 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc @@ -174,9 +174,15 @@ ChromotingInstance::ChromotingInstance(PP_Instance pp_instance) plugin_task_runner_(new PluginThreadTaskRunner(&plugin_thread_delegate_)), context_(plugin_task_runner_.get()), input_tracker_(&mouse_input_filter_), +#if defined(OS_MACOSX) + // On Mac we need an extra filter to inject missing keyup events. + // See remoting/client/plugin/mac_key_event_processor.h for more details. + mac_key_event_processor_(&input_tracker_), + key_mapper_(&mac_key_event_processor_), +#else key_mapper_(&input_tracker_), - normalizing_input_filter_(CreateNormalizingInputFilter(&key_mapper_)), - input_handler_(normalizing_input_filter_.get()), +#endif + input_handler_(&key_mapper_), use_async_pin_dialog_(false), weak_factory_(this) { RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL); diff --git a/remoting/client/plugin/chromoting_instance.h b/remoting/client/plugin/chromoting_instance.h index 4c786e1..23c4c49 100644 --- a/remoting/client/plugin/chromoting_instance.h +++ b/remoting/client/plugin/chromoting_instance.h @@ -31,7 +31,7 @@ #include "remoting/client/client_context.h" #include "remoting/client/client_user_interface.h" #include "remoting/client/key_event_mapper.h" -#include "remoting/client/plugin/normalizing_input_filter.h" +#include "remoting/client/plugin/mac_key_event_processor.h" #include "remoting/client/plugin/pepper_input_handler.h" #include "remoting/client/plugin/pepper_plugin_thread_delegate.h" #include "remoting/proto/event.pb.h" @@ -248,8 +248,10 @@ class ChromotingInstance : // Input pipeline components, in reverse order of distance from input source. protocol::MouseInputFilter mouse_input_filter_; protocol::InputEventTracker input_tracker_; +#if defined(OS_MACOSX) + MacKeyEventProcessor mac_key_event_processor_; +#endif KeyEventMapper key_mapper_; - scoped_ptr<protocol::InputFilter> normalizing_input_filter_; PepperInputHandler input_handler_; // PIN Fetcher. diff --git a/remoting/client/plugin/normalizing_input_filter_mac.cc b/remoting/client/plugin/mac_key_event_processor.cc index 56b327e..175924bf 100644 --- a/remoting/client/plugin/normalizing_input_filter_mac.cc +++ b/remoting/client/plugin/mac_key_event_processor.cc @@ -1,49 +1,12 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// 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. -// NormalizingInputFilterMac is designed to solve the problem of missing keyup -// events on Mac. -// -// PROBLEM -// -// On Mac if user presses CMD and then C key there is no keyup event generated -// for C when user releases the C key before the CMD key. -// The cause is that CMD + C triggers a system action and Chrome injects only a -// keydown event for the C key. Safari shares the same behavior. -// -// SOLUTION -// -// When a keyup event for CMD key happens we will check all prior keydown -// events received and inject corresponding keyup events artificially, with -// the exception of: -// -// SHIFT, CONTROL, OPTION, LEFT CMD, RIGHT CMD and CAPS LOCK -// -// because they are reported by Chrome correctly. -// -// There are a couple cases that this solution doesn't work perfectly, one -// of them leads to duplicated keyup events. -// -// User performs this sequence of actions: -// -// CMD DOWN, C DOWN, CMD UP, C UP -// -// In this case the algorithm will generate: -// -// CMD DOWN, C DOWN, C UP, CMD UP, C UP -// -// Because we artificially generate keyup events the C UP event is duplicated -// as user releases the key after CMD key. This would not be a problem as the -// receiver end will drop this duplicated keyup event. - -#include "remoting/client/plugin/normalizing_input_filter.h" - -#include <map> +#include "remoting/client/plugin/mac_key_event_processor.h" + #include <vector> #include "base/logging.h" -#include "remoting/proto/event.pb.h" namespace remoting { @@ -62,32 +25,14 @@ const unsigned int kUsbTab = 0x07002b; } // namespace -class NormalizingInputFilterMac : public protocol::InputFilter { - public: - explicit NormalizingInputFilterMac(protocol::InputStub* input_stub); - virtual ~NormalizingInputFilterMac() {} - - // InputFilter overrides. - virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE; - - private: - // Generate keyup events for any keys pressed with CMD. - void GenerateKeyupEvents(); - - // A map that stores pressed keycodes and the corresponding key event. - typedef std::map<int, protocol::KeyEvent> KeyPressedMap; - KeyPressedMap key_pressed_map_; - - DISALLOW_COPY_AND_ASSIGN(NormalizingInputFilterMac); -}; - -NormalizingInputFilterMac::NormalizingInputFilterMac( - protocol::InputStub* input_stub) +MacKeyEventProcessor::MacKeyEventProcessor(protocol::InputStub* input_stub) : protocol::InputFilter(input_stub) { } -void NormalizingInputFilterMac::InjectKeyEvent(const protocol::KeyEvent& event) -{ +MacKeyEventProcessor::~MacKeyEventProcessor() { +} + +void MacKeyEventProcessor::InjectKeyEvent(const protocol::KeyEvent& event) { DCHECK(event.has_usb_keycode()); bool is_special_key = event.usb_keycode() == kUsbLeftControl || @@ -131,7 +76,7 @@ void NormalizingInputFilterMac::InjectKeyEvent(const protocol::KeyEvent& event) InputFilter::InjectKeyEvent(event); } -void NormalizingInputFilterMac::GenerateKeyupEvents() { +void MacKeyEventProcessor::GenerateKeyupEvents() { for (KeyPressedMap::iterator i = key_pressed_map_.begin(); i != key_pressed_map_.end(); ++i) { // The generated key up event will have the same key code and lock states @@ -145,10 +90,4 @@ void NormalizingInputFilterMac::GenerateKeyupEvents() { key_pressed_map_.clear(); } -scoped_ptr<protocol::InputFilter> CreateNormalizingInputFilter( - protocol::InputStub* input_stub) { - return scoped_ptr<protocol::InputFilter>( - new NormalizingInputFilterMac(input_stub)); -} - } // namespace remoting diff --git a/remoting/client/plugin/mac_key_event_processor.h b/remoting/client/plugin/mac_key_event_processor.h new file mode 100644 index 0000000..56bc974 --- /dev/null +++ b/remoting/client/plugin/mac_key_event_processor.h @@ -0,0 +1,76 @@ +// 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. + +// MacKeyEventProcessor is designed to solve the problem of missing keyup +// events on Mac. +// +// PROBLEM +// +// On Mac if user presses CMD and then C key there is no keyup event generated +// for C when user releases the C key before the CMD key. +// The cause is that CMD + C triggers a system action and Chrome injects only a +// keydown event for the C key. Safari shares the same behavior. +// +// SOLUTION +// +// When a keyup event for CMD key happens we will check all prior keydown +// events received and inject corresponding keyup events artificially, with +// the exception of: +// +// SHIFT, CONTROL, OPTION, LEFT CMD, RIGHT CMD and CAPS LOCK +// +// because they are reported by Chrome correctly. +// +// There are a couple cases that this solution doesn't work perfectly, one +// of them leads to duplicated keyup events. +// +// User performs this sequence of actions: +// +// CMD DOWN, C DOWN, CMD UP, C UP +// +// In this case the algorithm will generate: +// +// CMD DOWN, C DOWN, C UP, CMD UP, C UP +// +// Because we artificially generate keyup events the C UP event is duplicated +// as user releases the key after CMD key. This would not be a problem as the +// receiver end will drop this duplicated keyup event. + +#ifndef REMOTING_CLIENT_PLUGIN_MAC_KEY_EVENT_PROCESSOR_H_ +#define REMOTING_CLIENT_PLUGIN_MAC_KEY_EVENT_PROCESSOR_H_ + +#include <map> + +#include "base/basictypes.h" +#include "remoting/proto/event.pb.h" +#include "remoting/protocol/input_filter.h" + +namespace remoting { + +namespace protocol { +class InputStub; +} // namespace protocol + +class MacKeyEventProcessor : public protocol::InputFilter { + public: + explicit MacKeyEventProcessor(protocol::InputStub* input_stub); + virtual ~MacKeyEventProcessor(); + + // InputFilter overrides. + virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE; + + private: + // Generate keyup events for any keys pressed with CMD. + void GenerateKeyupEvents(); + + // A map that stores pressed keycodes and the corresponding key event. + typedef std::map<int, protocol::KeyEvent> KeyPressedMap; + KeyPressedMap key_pressed_map_; + + DISALLOW_COPY_AND_ASSIGN(MacKeyEventProcessor); +}; + +} // namespace remoting + +#endif // REMOTING_CLIENT_PLUGIN_MAC_KEY_EVENT_PROCESSOR_H_ diff --git a/remoting/client/plugin/normalizing_input_filter_mac_unittest.cc b/remoting/client/plugin/mac_key_event_processor_unittest.cc index 8221223..a2604d5 100644 --- a/remoting/client/plugin/normalizing_input_filter_mac_unittest.cc +++ b/remoting/client/plugin/mac_key_event_processor_unittest.cc @@ -1,8 +1,8 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// 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 "remoting/client/plugin/normalizing_input_filter.h" +#include "remoting/client/plugin/mac_key_event_processor.h" #include "remoting/proto/event.pb.h" #include "remoting/protocol/protocol_mock_objects.h" #include "testing/gmock/include/gmock/gmock.h" @@ -44,10 +44,9 @@ KeyEvent MakeKeyEvent(uint32 keycode, bool pressed) { } // namespace // Test CapsLock press/release. -TEST(NormalizingInputFilterMacTest, CapsLock) { +TEST(MacKeyEventProcessorTest, CapsLock) { MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); + MacKeyEventProcessor processor(&stub); { InSequence s; @@ -58,14 +57,13 @@ TEST(NormalizingInputFilterMacTest, CapsLock) { } // Injecting a CapsLock down event with NumLock on. - processor->InjectKeyEvent(MakeKeyEvent(kUsbCapsLock, true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbCapsLock, true)); } // Test without pressing command key. -TEST(NormalizingInputFilterMacTest, NoInjection) { +TEST(MacKeyEventProcessorTest, NoInjection) { MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); + MacKeyEventProcessor processor(&stub); { InSequence s; @@ -77,15 +75,14 @@ TEST(NormalizingInputFilterMacTest, NoInjection) { } // C Down and C Up. - processor->InjectKeyEvent(MakeKeyEvent('C', true)); - processor->InjectKeyEvent(MakeKeyEvent('C', false)); + processor.InjectKeyEvent(MakeKeyEvent('C', true)); + processor.InjectKeyEvent(MakeKeyEvent('C', false)); } // Test pressing command key and other normal keys. -TEST(NormalizingInputFilterMacTest, CmdKey) { +TEST(MacKeyEventProcessorTest, CmdKey) { MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); + MacKeyEventProcessor processor(&stub); { InSequence s; @@ -126,27 +123,26 @@ TEST(NormalizingInputFilterMacTest, CmdKey) { } // Left command key. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); - processor->InjectKeyEvent(MakeKeyEvent('C', true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); + processor.InjectKeyEvent(MakeKeyEvent('C', true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); // Right command key. - processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); - processor->InjectKeyEvent(MakeKeyEvent('C', true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, false)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); + processor.InjectKeyEvent(MakeKeyEvent('C', true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, false)); // More than one keys after CMD. - processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); - processor->InjectKeyEvent(MakeKeyEvent('C', true)); - processor->InjectKeyEvent(MakeKeyEvent('V', true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, false)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); + processor.InjectKeyEvent(MakeKeyEvent('C', true)); + processor.InjectKeyEvent(MakeKeyEvent('V', true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, false)); } // Test pressing command and special keys. -TEST(NormalizingInputFilterMacTest, SpecialKeys) { +TEST(MacKeyEventProcessorTest, SpecialKeys) { MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); + MacKeyEventProcessor processor(&stub); { InSequence s; @@ -173,23 +169,22 @@ TEST(NormalizingInputFilterMacTest, SpecialKeys) { } // Command + Shift. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftShift, true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftShift, false)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftShift, true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftShift, false)); // Command + Option. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOption, true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOption, false)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftOption, true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftOption, false)); } // Test pressing multiple command keys. -TEST(NormalizingInputFilterMacTest, MultipleCmdKeys) { +TEST(MacKeyEventProcessorTest, MultipleCmdKeys) { MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); + MacKeyEventProcessor processor(&stub); { InSequence s; @@ -208,17 +203,16 @@ TEST(NormalizingInputFilterMacTest, MultipleCmdKeys) { // Test multiple CMD keys at the same time. // L CMD Down, C Down, R CMD Down, L CMD Up. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); - processor->InjectKeyEvent(MakeKeyEvent('C', true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, true)); + processor.InjectKeyEvent(MakeKeyEvent('C', true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbLeftCmd, false)); } // Test press C key before command key. -TEST(NormalizingInputFilterMacTest, BeforeCmdKey) { +TEST(MacKeyEventProcessorTest, BeforeCmdKey) { MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); + MacKeyEventProcessor processor(&stub); { InSequence s; @@ -236,10 +230,10 @@ TEST(NormalizingInputFilterMacTest, BeforeCmdKey) { } // Press C before command key. - processor->InjectKeyEvent(MakeKeyEvent('C', true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, false)); - processor->InjectKeyEvent(MakeKeyEvent('C', false)); + processor.InjectKeyEvent(MakeKeyEvent('C', true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, true)); + processor.InjectKeyEvent(MakeKeyEvent(kUsbRightCmd, false)); + processor.InjectKeyEvent(MakeKeyEvent('C', false)); } } // namespace remoting diff --git a/remoting/client/plugin/normalizing_input_filter.cc b/remoting/client/plugin/normalizing_input_filter.cc deleted file mode 100644 index 7206305..0000000 --- a/remoting/client/plugin/normalizing_input_filter.cc +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 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 "remoting/client/plugin/normalizing_input_filter.h" - -#include "remoting/protocol/input_filter.h" - -namespace remoting { - -using protocol::InputFilter; -using protocol::InputStub; - -#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) -scoped_ptr<InputFilter> CreateNormalizingInputFilter(InputStub* input_stub) { - return scoped_ptr<InputFilter>(new InputFilter(input_stub)); -} -#endif // !defined(OS_MACOSX) && !defined(OS_CHROMEOS) - -} diff --git a/remoting/client/plugin/normalizing_input_filter.h b/remoting/client/plugin/normalizing_input_filter.h deleted file mode 100644 index ebe49fe..0000000 --- a/remoting/client/plugin/normalizing_input_filter.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2013 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 REMOTING_CLIENT_PLUGIN_NORMALIZING_INPUT_FILTER_H_ -#define REMOTING_CLIENT_PLUGIN_NORMALIZING_INPUT_FILTER_H_ - -#include "base/memory/scoped_ptr.h" -#include "remoting/protocol/input_filter.h" - -namespace remoting { - -// Returns an InputFilter which re-writes input events to work around -// platform-specific behaviours. If no re-writing is required then a -// pass-through InputFilter is returned. -scoped_ptr<protocol::InputFilter> CreateNormalizingInputFilter( - protocol::InputStub* input_stub); - -} // namespace remoting - -#endif // REMOTING_CLIENT_PLUGIN_NORMALIZING_INPUT_FILTER_H_ diff --git a/remoting/client/plugin/normalizing_input_filter_ash.cc b/remoting/client/plugin/normalizing_input_filter_ash.cc deleted file mode 100644 index 113d955..0000000 --- a/remoting/client/plugin/normalizing_input_filter_ash.cc +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2013 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. - -// NormalizingInputFilterAsh addresses the problems generated by key rewritings -// such as Down->PageDown, 1->F1, etc, when keys are pressed in combination with -// the OSKey (aka Search). Rewriting OSKey+Down, for example, causes us to -// receive the following: -// -// keydown OSKey -// keydown PageDown -// keyup PageDown -// keyup OSKey -// -// The host system will therefore behave as if OSKey+PageDown were pressed, -// rather than PageDown alone. -// -// This file must be kept up-to-date with changes to -// chrome/browser/ui/ash/event_rewriter.cc - -#include "remoting/client/plugin/normalizing_input_filter.h" - -#include "base/logging.h" -#include "remoting/proto/event.pb.h" - -namespace remoting { - -namespace { - -// Returns true for OSKey codes. -static bool IsOsKey(unsigned int code) { - const unsigned int kUsbLeftOsKey = 0x0700e3; - const unsigned int kUsbRightOsKey = 0x0700e7; - return code == kUsbLeftOsKey || code == kUsbRightOsKey; -} - -// Returns true for codes generated by EventRewriter::RewriteFunctionKeys(). -static bool IsRewrittenFunctionKey(unsigned int code) { - const unsigned int kUsbFunctionKeyMin = 0x07003a; - const unsigned int kUsbFunctionKeyMax = 0x070045; - return code >= kUsbFunctionKeyMin && code <= kUsbFunctionKeyMax; -} - -// Returns true for codes generated by EventRewriter::RewriteExtendedKeys(). -static bool IsRewrittenExtendedKey(unsigned int code) { - const unsigned int kUsbExtendedKeyMin = 0x070049; - const unsigned int kUsbExtendedKeyMax = 0x07004e; - return code >= kUsbExtendedKeyMin && code <= kUsbExtendedKeyMax; -} - -// Returns true for codes generated by EventRewriter::Rewrite(). -static bool IsRewrittenKey(unsigned int code) { - return IsRewrittenExtendedKey(code) || IsRewrittenFunctionKey(code); -} - -// The input filter tries to avoid sending keydown/keyup events for OSKey -// (aka Search, WinKey, Cmd, Super) when it is used to rewrite other key events. -// Rewriting via other combinations is not currently handled. -// -// OSKey events can be categorised as one of three kinds: -// - Modifying - Holding the key down while executing other input modifies the -// effect of that input, e.g. OSKey+L causes the workstation to lock, e.g. -// OSKey + mouse-move performs an extended selection. -// - Rewriting (ChromeOS only) - Holding the key down while pressing certain -// keys causes them to be treated as different keys, e.g. OSKey causes the -// Down key to behave as PageDown. -// - Normal - Press & release of the key trigger an action, e.g. showing the -// Start menu. -// -// The input filter has four states: -// 1. No OSKey has been pressed. -// - When an OSKey keydown is received, the event is deferred, and we move to -// State #2. -// 2. An OSKey is pressed, but may be Normal, Rewriting or Modifying. -// - If the OSKey keyup is received, the key is Normal, both events are sent -// and we return to State #1. -// - If a Rewritten event is received we move to State #3. -// - If a Modified event is received the OSKey keydown is sent and we enter -// State #4. -// 3. An OSKey is pressed, and is being used to Rewrite other key events. -// - If the OSKey keyup is received then it is suppressed, and we move to -// State #1. -// - If a Modified event is received the OSKey keydown is sent and we enter -// State #4. -// - If a Rewritten event is received then we stay in State #3. -// 4. An OSKey is pressed, and is Modifying. -// - If the OSKey keyup is received then we send it and we move to State #1. -// - All other key event pass through the filter unchanged. - -class NormalizingInputFilterAsh : public protocol::InputFilter { - public: - explicit NormalizingInputFilterAsh(protocol::InputStub* input_stub) - : protocol::InputFilter(input_stub), - deferred_key_is_rewriting_(false), - modifying_key_(0) { - } - virtual ~NormalizingInputFilterAsh() {} - - // InputFilter overrides. - virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE { - DCHECK(event.has_usb_keycode()); - DCHECK(event.has_pressed()); - - if (event.pressed()) - ProcessKeyDown(event); - else - ProcessKeyUp(event); - } - - virtual void InjectMouseEvent(const protocol::MouseEvent& event) OVERRIDE { - if (deferred_keydown_event_.has_usb_keycode()) - SwitchRewritingKeyToModifying(); - InputFilter::InjectMouseEvent(event); - } - - private: - void ProcessKeyDown(const protocol::KeyEvent& event) { - // If |event| is |deferred_keydown_event_| auto-repeat then assume - // that the user is holding the key down rather than using it to Rewrite. - if (deferred_keydown_event_.has_usb_keycode() && - deferred_keydown_event_.usb_keycode() == event.usb_keycode()) { - SwitchRewritingKeyToModifying(); - } - - // If |event| is a |modifying_key_| repeat then let it pass through. - if (modifying_key_ == event.usb_keycode()) { - InputFilter::InjectKeyEvent(event); - return; - } - - // If |event| is for an OSKey and we don't know whether it's a Normal, - // Rewriting or Modifying use, then hold the keydown event. - if (IsOsKey(event.usb_keycode())) { - deferred_keydown_event_ = event; - deferred_key_is_rewriting_ = false; - return; - } - - // If |event| is for a Rewritten key then set a flag to prevent any deferred - // OSKey keydown from being sent when keyup is received for it. Otherwise, - // inject the deferred OSKey keydown, if any, and switch that key into - // Modifying mode. - if (IsRewrittenKey(event.usb_keycode())) { - // Note that there may not be a deferred OSKey event if there is a full - // PC keyboard connected, which can generate e.g. PageDown without - // rewriting. - deferred_key_is_rewriting_ = true; - } else { - if (deferred_keydown_event_.has_usb_keycode()) - SwitchRewritingKeyToModifying(); - } - - InputFilter::InjectKeyEvent(event); - } - - void ProcessKeyUp(const protocol::KeyEvent& event) { - if (deferred_keydown_event_.has_usb_keycode() && - deferred_keydown_event_.usb_keycode() == event.usb_keycode()) { - if (deferred_key_is_rewriting_) { - // If we never sent the keydown then don't send a keyup. - deferred_keydown_event_ = protocol::KeyEvent(); - return; - } - - // If the OSKey hasn't Rewritten anything then treat as Modifying. - SwitchRewritingKeyToModifying(); - } - - if (modifying_key_ == event.usb_keycode()) - modifying_key_ = 0; - - InputFilter::InjectKeyEvent(event); - } - - void SwitchRewritingKeyToModifying() { - DCHECK(deferred_keydown_event_.has_usb_keycode()); - modifying_key_ = deferred_keydown_event_.usb_keycode(); - InputFilter::InjectKeyEvent(deferred_keydown_event_); - deferred_keydown_event_ = protocol::KeyEvent(); - } - - // Holds the keydown event for the most recent OSKey to have been pressed, - // while it is Rewriting, or we are not yet sure whether it is Normal, - // Rewriting or Modifying. The event is sent on if we switch to Modifying, or - // discarded if the OSKey is released while in Rewriting mode. - protocol::KeyEvent deferred_keydown_event_; - - // True while the |rewrite_keydown_event_| key is Rewriting, i.e. was followed - // by one or more Rewritten key events, and not by any Modified events. - bool deferred_key_is_rewriting_; - - // Stores the code of the OSKey while it is pressed for use as a Modifier. - uint32 modifying_key_; - - DISALLOW_COPY_AND_ASSIGN(NormalizingInputFilterAsh); -}; - -} // namespace - -scoped_ptr<protocol::InputFilter> CreateNormalizingInputFilter( - protocol::InputStub* input_stub) { - return scoped_ptr<protocol::InputFilter>( - new NormalizingInputFilterAsh(input_stub)); -} - -} // namespace remoting diff --git a/remoting/client/plugin/normalizing_input_filter_ash_unittest.cc b/remoting/client/plugin/normalizing_input_filter_ash_unittest.cc deleted file mode 100644 index e6ef6f9..0000000 --- a/remoting/client/plugin/normalizing_input_filter_ash_unittest.cc +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2013 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 "remoting/client/plugin/normalizing_input_filter.h" -#include "remoting/proto/event.pb.h" -#include "remoting/protocol/protocol_mock_objects.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using ::testing::InSequence; -using remoting::protocol::InputStub; -using remoting::protocol::KeyEvent; -using remoting::protocol::MockInputStub; -using remoting::protocol::MouseEvent; - -namespace remoting { - -namespace { - -const unsigned int kUsbLeftOsKey = 0x0700e3; -const unsigned int kUsbRightOsKey = 0x0700e7; - -const unsigned int kUsbFunctionKey = 0x07003a; // F1 -const unsigned int kUsbExtendedKey = 0x070049; // Insert -const unsigned int kUsbOtherKey = 0x07002b; // Tab - -// A hardcoded value used to verify |lock_states| is preserved. -static const uint32 kTestLockStates = protocol::KeyEvent::LOCK_STATES_NUMLOCK; - -MATCHER_P2(EqualsKeyEvent, usb_keycode, pressed, "") { - return arg.usb_keycode() == static_cast<uint32>(usb_keycode) && - arg.pressed() == pressed && - arg.lock_states() == kTestLockStates; -} - -KeyEvent MakeKeyEvent(uint32 keycode, bool pressed) { - KeyEvent event; - event.set_usb_keycode(keycode); - event.set_pressed(pressed); - event.set_lock_states(kTestLockStates); - return event; -} - -void PressAndReleaseKey(InputStub* input_stub, uint32 keycode) { - input_stub->InjectKeyEvent(MakeKeyEvent(keycode, true)); - input_stub->InjectKeyEvent(MakeKeyEvent(keycode, false)); -} - -MATCHER_P2(EqualsMouseMoveEvent, x, y, "") { - return arg.x() == x && arg.y() == y; -} - -static MouseEvent MakeMouseMoveEvent(int x, int y) { - MouseEvent event; - event.set_x(x); - event.set_y(y); - return event; -} - -} // namespace - -// Test OSKey press/release. -TEST(NormalizingInputFilterAshTest, PressReleaseOsKey) { - MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); - - { - InSequence s; - - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, false))); - - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbRightOsKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbRightOsKey, false))); - } - - // Inject press & release events for left & right OSKeys. - PressAndReleaseKey(processor.get(), kUsbLeftOsKey); - PressAndReleaseKey(processor.get(), kUsbRightOsKey); -} - -// Test OSKey key repeat switches it to "modifying" mode. -TEST(NormalizingInputFilterAshTest, OSKeyRepeats) { - MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); - - { - InSequence s; - - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true))); - } - - // Inject a press and repeats for the left OSKey, but don't release it, and - // verify that the repeats result in press events. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true)); -} - -// Test OSKey press followed by function key press and release results in -// just the function key events. -TEST(NormalizingInputFilterAshTest, FunctionKey) { - MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); - - { - InSequence s; - - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbFunctionKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbFunctionKey, false))); - } - - // Hold the left OSKey while pressing & releasing the function key. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true)); - PressAndReleaseKey(processor.get(), kUsbFunctionKey); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false)); -} - -// Test OSKey press followed by extended key press and release results in -// just the function key events. -TEST(NormalizingInputFilterAshTest, ExtendedKey) { - MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); - - { - InSequence s; - - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbExtendedKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbExtendedKey, false))); - } - - // Hold the left OSKey while pressing & releasing the function key. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true)); - PressAndReleaseKey(processor.get(), kUsbExtendedKey); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false)); -} - -// Test OSKey press followed by non-function, non-extended key press and release -// results in normal-looking sequence. -TEST(NormalizingInputFilterAshTest, OtherKey) { - MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); - - { - InSequence s; - - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbOtherKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbOtherKey, false))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, false))); - } - - // Hold the left OSKey while pressing & releasing the function key. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true)); - PressAndReleaseKey(processor.get(), kUsbOtherKey); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false)); -} - -// Test OSKey press followed by extended key press, then normal key press -// results in OSKey switching to modifying mode for the normal key. -TEST(NormalizingInputFilterAshTest, ExtendedThenOtherKey) { - MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); - - { - InSequence s; - - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbExtendedKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbExtendedKey, false))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbOtherKey, true))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbOtherKey, false))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, false))); - } - - // Hold the left OSKey while pressing & releasing the function key. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true)); - PressAndReleaseKey(processor.get(), kUsbExtendedKey); - PressAndReleaseKey(processor.get(), kUsbOtherKey); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false)); -} - -// Test OSKey press followed by mouse event puts the OSKey into modifying mode. -TEST(NormalizingInputFilterAshTest, MouseEvent) { - MockInputStub stub; - scoped_ptr<protocol::InputFilter> processor = - CreateNormalizingInputFilter(&stub); - - { - InSequence s; - - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, true))); - EXPECT_CALL(stub, InjectMouseEvent(EqualsMouseMoveEvent(0, 0))); - EXPECT_CALL(stub, InjectKeyEvent(EqualsKeyEvent(kUsbLeftOsKey, false))); - } - - // Hold the left OSKey while pressing & releasing the function key. - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, true)); - processor->InjectMouseEvent(MakeMouseMoveEvent(0, 0)); - processor->InjectKeyEvent(MakeKeyEvent(kUsbLeftOsKey, false)); -} - -} // namespace remoting |