| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // MacKeyEventProcessor is designed to solve the problem of missing keyup | 5 // MacKeyEventProcessor is designed to solve the problem of missing keyup |
| 6 // events on Mac. | 6 // events on Mac. |
| 7 // | 7 // |
| 8 // PROBLEM | 8 // PROBLEM |
| 9 // | 9 // |
| 10 // On Mac if user presses CMD and then C key there is no keyup event generated | 10 // On Mac if user presses CMD and then C key there is no keyup event generated |
| 11 // for C when user releases the C key before the CMD key. | 11 // for C when user releases the C key before the CMD key. |
| 12 // The cause is that CMD + C triggers a system action and Chrome injects only a | 12 // The cause is that CMD + C triggers a system action and Chrome injects only a |
| 13 // keydown event for the C key. Safari shares the same behavior. | 13 // keydown event for the C key. Safari shares the same behavior. |
| 14 // | 14 // |
| 15 // This is a list of sample edge cases: | |
| 16 // | |
| 17 // CMD DOWN, C DOWN, C UP, CMD UP | |
| 18 // CMD DOWN, SHIFT DOWN, C DOWN, C UP, CMD UP, SHIFT UP | |
| 19 // CMD DOWN, CAPS LOCK DOWN, CMD DOWN, CAPS LOCK DOWN | |
| 20 // L CMD DOWN, C DOWN, R CMD DOWN, L CMD UP, C UP, R CMD UP | |
| 21 // | |
| 22 // SOLUTION | 15 // SOLUTION |
| 23 // | 16 // |
| 24 // When a keyup event for CMD key happens we will check all prior keydown | 17 // When a keyup event for CMD key happens we will check all prior keydown |
| 25 // events received and inject corresponding keyup events artificially, with | 18 // events received and inject corresponding keyup events artificially, with |
| 26 // the exception of: | 19 // the exception of: |
| 27 // | 20 // |
| 28 // SHIFT, CONTROL, OPTION, LEFT CMD, RIGHT CMD and CAPS LOCK | 21 // SHIFT, CONTROL, OPTION, LEFT CMD, RIGHT CMD and CAPS LOCK |
| 29 // | 22 // |
| 30 // because they are reported by Chrome correctly. | 23 // because they are reported by Chrome correctly. |
| 31 // | 24 // |
| 32 // There are a couple cases that this solution doesn't work perfectly, one | 25 // There are a couple cases that this solution doesn't work perfectly, one |
| 33 // of them leads to duplicated keyup events. | 26 // of them leads to duplicated keyup events. |
| 34 // | 27 // |
| 35 // User performs this sequence of actions: | 28 // User performs this sequence of actions: |
| 36 // | 29 // |
| 37 // CMD DOWN, C DOWN, CMD UP, C UP | 30 // CMD DOWN, C DOWN, CMD UP, C UP |
| 38 // | 31 // |
| 39 // In this case the algorithm will generate: | 32 // In this case the algorithm will generate: |
| 40 // | 33 // |
| 41 // CMD DOWN, C DOWN, C UP, CMD UP, C UP | 34 // CMD DOWN, C DOWN, C UP, CMD UP, C UP |
| 42 // | 35 // |
| 43 // Because we artificially generate keyup events the C UP event is duplicated | 36 // Because we artificially generate keyup events the C UP event is duplicated |
| 44 // as user releases the key after CMD key. | 37 // as user releases the key after CMD key. This would not be a problem as the |
| 38 // receiver end will drop this duplicated keyup event. |
| 45 | 39 |
| 46 #ifndef REMOTING_CLIENT_PLUGIN_MAC_KEY_EVENT_PROCESSOR_H_ | 40 #ifndef REMOTING_CLIENT_PLUGIN_MAC_KEY_EVENT_PROCESSOR_H_ |
| 47 #define REMOTING_CLIENT_PLUGIN_MAC_KEY_EVENT_PROCESSOR_H_ | 41 #define REMOTING_CLIENT_PLUGIN_MAC_KEY_EVENT_PROCESSOR_H_ |
| 48 | 42 |
| 49 #include <map> | 43 #include <map> |
| 50 | 44 |
| 51 #include "base/basictypes.h" | 45 #include "base/basictypes.h" |
| 52 #include "remoting/proto/event.pb.h" | 46 #include "remoting/proto/event.pb.h" |
| 53 #include "remoting/protocol/input_filter.h" | 47 #include "remoting/protocol/input_filter.h" |
| 54 | 48 |
| 55 namespace remoting { | 49 namespace remoting { |
| 56 | 50 |
| 57 namespace protocol { | 51 namespace protocol { |
| 58 class InputStub; | 52 class InputStub; |
| 59 } // namespace protocol | 53 } // namespace protocol |
| 60 | 54 |
| 61 class MacKeyEventProcessor : public protocol::InputFilter { | 55 class MacKeyEventProcessor : public protocol::InputFilter { |
| 62 public: | 56 public: |
| 63 explicit MacKeyEventProcessor(protocol::InputStub* input_stub); | 57 explicit MacKeyEventProcessor(protocol::InputStub* input_stub); |
| 64 virtual ~MacKeyEventProcessor(); | 58 virtual ~MacKeyEventProcessor(); |
| 65 | 59 |
| 66 // InputFilter overrides. | 60 // InputFilter overrides. |
| 67 virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE; | 61 virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE; |
| 68 | 62 |
| 69 // Return the number of keys pressed. This method is used by unit test to | |
| 70 // test correctness of this class. | |
| 71 int NumberOfPressedKeys() const; | |
| 72 | |
| 73 private: | 63 private: |
| 74 // Iterate the current pressed keys and generate keyup events. | 64 // Generate keyup events for any keys pressed with CMD. |
| 75 void GenerateKeyupEvents(); | 65 void GenerateKeyupEvents(); |
| 76 | 66 |
| 77 // A map that stores pressed keycodes and the corresponding key event. | 67 // A map that stores pressed keycodes and the corresponding key event. |
| 78 typedef std::map<int, protocol::KeyEvent> KeyPressedMap; | 68 typedef std::map<int, protocol::KeyEvent> KeyPressedMap; |
| 79 KeyPressedMap key_pressed_map_; | 69 KeyPressedMap key_pressed_map_; |
| 80 | 70 |
| 81 DISALLOW_COPY_AND_ASSIGN(MacKeyEventProcessor); | 71 DISALLOW_COPY_AND_ASSIGN(MacKeyEventProcessor); |
| 82 }; | 72 }; |
| 83 | 73 |
| 84 } // namespace remoting | 74 } // namespace remoting |
| 85 | 75 |
| 86 #endif // REMOTING_CLIENT_PLUGIN_MAC_KEY_EVENT_PROCESSOR_H_ | 76 #endif // REMOTING_CLIENT_PLUGIN_MAC_KEY_EVENT_PROCESSOR_H_ |
| OLD | NEW |