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