normalizing_input_filter_mac.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1// Copyright 2013 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 "remoting/client/plugin/normalizing_input_filter_mac.h" 6 7#include <map> 8#include <vector> 9 10#include "base/logging.h" 11#include "remoting/proto/event.pb.h" 12 13namespace remoting { 14 15namespace { 16 17const unsigned int kUsbCapsLock = 0x070039; 18const unsigned int kUsbLeftControl = 0x0700e0; 19const unsigned int kUsbLeftShift = 0x0700e1; 20const unsigned int kUsbLeftOption = 0x0700e2; 21const unsigned int kUsbLeftCmd = 0x0700e3; 22const unsigned int kUsbRightControl = 0x0700e4; 23const unsigned int kUsbRightShift = 0x0700e5; 24const unsigned int kUsbRightOption = 0x0700e6; 25const unsigned int kUsbRightCmd = 0x0700e7; 26const unsigned int kUsbTab = 0x07002b; 27 28} // namespace 29 30NormalizingInputFilterMac::NormalizingInputFilterMac( 31 protocol::InputStub* input_stub) 32 : protocol::InputFilter(input_stub) { 33} 34 35NormalizingInputFilterMac::~NormalizingInputFilterMac() {} 36 37void NormalizingInputFilterMac::InjectKeyEvent(const protocol::KeyEvent& event) 38{ 39 DCHECK(event.has_usb_keycode()); 40 41 bool is_special_key = event.usb_keycode() == kUsbLeftControl || 42 event.usb_keycode() == kUsbLeftShift || 43 event.usb_keycode() == kUsbLeftOption || 44 event.usb_keycode() == kUsbRightControl || 45 event.usb_keycode() == kUsbRightShift || 46 event.usb_keycode() == kUsbRightOption || 47 event.usb_keycode() == kUsbTab; 48 49 bool is_cmd_key = event.usb_keycode() == kUsbLeftCmd || 50 event.usb_keycode() == kUsbRightCmd; 51 52 if (event.usb_keycode() == kUsbCapsLock) { 53 // Mac OS X generates keydown/keyup on lock-state transitions, rather than 54 // when the key is pressed & released, so fake keydown/keyup on each event. 55 protocol::KeyEvent newEvent(event); 56 57 newEvent.set_pressed(true); 58 InputFilter::InjectKeyEvent(newEvent); 59 newEvent.set_pressed(false); 60 InputFilter::InjectKeyEvent(newEvent); 61 62 return; 63 } else if (!is_cmd_key && !is_special_key) { 64 // Track keydown/keyup events for non-modifiers, so we can release them if 65 // necessary (see below). 66 if (event.pressed()) { 67 key_pressed_map_[event.usb_keycode()] = event; 68 } else { 69 key_pressed_map_.erase(event.usb_keycode()); 70 } 71 } 72 73 if (is_cmd_key && !event.pressed()) { 74 // Mac OS X will not generate release events for keys pressed while Cmd is 75 // pressed, so release all pressed keys when Cmd is released. 76 GenerateKeyupEvents(); 77 } 78 79 InputFilter::InjectKeyEvent(event); 80} 81 82void NormalizingInputFilterMac::GenerateKeyupEvents() { 83 for (KeyPressedMap::iterator i = key_pressed_map_.begin(); 84 i != key_pressed_map_.end(); ++i) { 85 // The generated key up event will have the same key code and lock states 86 // as the original key down event. 87 protocol::KeyEvent event = i->second; 88 event.set_pressed(false); 89 InputFilter::InjectKeyEvent(event); 90 } 91 92 // Clearing the map now that we have released all the pressed keys. 93 key_pressed_map_.clear(); 94} 95 96} // namespace remoting 97