blob: 7a3a52445b23ad21e8f55894c56930a74897d186 [file] [log] [blame]
// 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/input/normalizing_input_filter_win.h"
#include <stdint.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() = default;
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