Index: remoting/client/normalizing_input_filter_win.cc |
diff --git a/remoting/client/normalizing_input_filter_win.cc b/remoting/client/normalizing_input_filter_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..20950da06d704204d5d8c73357e22acfc460aa27 |
--- /dev/null |
+++ b/remoting/client/normalizing_input_filter_win.cc |
@@ -0,0 +1,106 @@ |
+// Copyright 2015 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/normalizing_input_filter_win.h" |
+ |
+#include "base/logging.h" |
+#include "ui/events/keycodes/dom/dom_code.h" |
+ |
+namespace remoting { |
+ |
+static bool IsLeftControl(uint32_t code) { |
+ return code == static_cast<uint32_t>(ui::DomCode::CONTROL_LEFT); |
+} |
+ |
+static bool IsRightAlt(uint32_t code) { |
+ return code == static_cast<uint32_t>(ui::DomCode::ALT_RIGHT); |
+} |
+ |
+NormalizingInputFilterWin::NormalizingInputFilterWin( |
+ protocol::InputStub* input_stub) |
+ : protocol::InputFilter(input_stub) {} |
+ |
+NormalizingInputFilterWin::~NormalizingInputFilterWin() {} |
+ |
+void NormalizingInputFilterWin::InjectKeyEvent( |
+ const protocol::KeyEvent& event) { |
+ DCHECK(event.has_usb_keycode()); |
+ DCHECK(event.has_pressed()); |
+ |
+ if (event.pressed()) { |
+ ProcessKeyDown(event); |
+ } else { |
+ ProcessKeyUp(event); |
+ } |
+} |
+ |
+void NormalizingInputFilterWin::InjectMouseEvent( |
+ const protocol::MouseEvent& event) { |
+ FlushDeferredKeydownEvent(); |
+ InputFilter::InjectMouseEvent(event); |
+} |
+ |
+void NormalizingInputFilterWin::ProcessKeyDown( |
+ const protocol::KeyEvent& event) { |
+ if (IsRightAlt(event.usb_keycode())) { |
+ // If there's a deferred LeftControl event then treat it as part of an |
+ // AltGr press, so swallow it. |
+ if (deferred_control_keydown_.has_usb_keycode()) { |
+ altgr_is_pressed_ = true; |
+ deferred_control_keydown_ = protocol::KeyEvent(); |
+ } |
+ } |
+ |
+ // If a keydown for something other than RightAlt is received while there |
+ // is a deferred LeftControl event then treat it as an actual LeftControl |
+ // event, and flush it. |
+ FlushDeferredKeydownEvent(); |
+ |
+ if (IsLeftControl(event.usb_keycode())) { |
+ // If AltGr is pressed then ignore the LeftControl keydown repeat. |
+ if (altgr_is_pressed_) |
+ return; |
+ |
+ // If LeftControl is not already pressed then defer the event. |
+ if (!left_control_is_pressed_) { |
+ deferred_control_keydown_ = event; |
+ return; |
+ } |
+ } |
+ |
+ InputFilter::InjectKeyEvent(event); |
+} |
+ |
+void NormalizingInputFilterWin::ProcessKeyUp(const protocol::KeyEvent& event) { |
+ if (IsLeftControl(event.usb_keycode())) { |
+ // If we treated the LeftControl as part of AltGr, and never sent the |
+ // keydown, then ignore the keyup as well. |
+ if (altgr_is_pressed_) { |
+ altgr_is_pressed_ = false; |
+ return; |
+ } |
+ |
+ // If there is still a deferred event then flush it, so that LeftControl |
+ // press-and-release works. |
+ FlushDeferredKeydownEvent(); |
+ |
+ left_control_is_pressed_ = false; |
+ } |
+ |
+ InputFilter::InjectKeyEvent(event); |
+} |
+ |
+void NormalizingInputFilterWin::FlushDeferredKeydownEvent() { |
+ if (!deferred_control_keydown_.has_usb_keycode()) |
+ return; |
+ |
+ DCHECK_EQ(static_cast<uint32_t>(ui::DomCode::CONTROL_LEFT), |
+ deferred_control_keydown_.usb_keycode()); |
+ |
+ left_control_is_pressed_ = true; |
+ InputFilter::InjectKeyEvent(deferred_control_keydown_); |
+ deferred_control_keydown_ = protocol::KeyEvent(); |
+} |
+ |
+} // namespace remoting |