blob: 7b0628082487b353aa77b7bfac9ac87ff8f82c23 [file] [log] [blame]
// Copyright 2017 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 "ui/aura/mus/system_input_injector_mus.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/window_manager_delegate.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/gfx/geometry/point_conversions.h"
namespace aura {
namespace {
int KeyboardCodeToModifier(ui::KeyboardCode key) {
switch (key) {
case ui::VKEY_MENU:
case ui::VKEY_LMENU:
case ui::VKEY_RMENU:
return ui::MODIFIER_ALT;
case ui::VKEY_ALTGR:
return ui::MODIFIER_ALTGR;
case ui::VKEY_CAPITAL:
return ui::MODIFIER_CAPS_LOCK;
case ui::VKEY_CONTROL:
case ui::VKEY_LCONTROL:
case ui::VKEY_RCONTROL:
return ui::MODIFIER_CONTROL;
case ui::VKEY_LWIN:
case ui::VKEY_RWIN:
return ui::MODIFIER_COMMAND;
case ui::VKEY_SHIFT:
case ui::VKEY_LSHIFT:
case ui::VKEY_RSHIFT:
return ui::MODIFIER_SHIFT;
default:
return ui::MODIFIER_NONE;
}
}
} // namespace
SystemInputInjectorMus::SystemInputInjectorMus(WindowManagerClient* client)
: client_(client) {}
SystemInputInjectorMus::~SystemInputInjectorMus() {}
void SystemInputInjectorMus::MoveCursorTo(const gfx::PointF& location) {
ui::MouseEvent event(
ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(),
modifiers_.GetModifierFlags(),
/* changed_button_flags */ 0,
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE));
event.set_location_f(location);
event.set_root_location_f(location);
InjectEventAt(ui::PointerEvent(event), gfx::ToRoundedPoint(location));
}
void SystemInputInjectorMus::InjectMouseButton(ui::EventFlags button,
bool down) {
gfx::Point location = aura::Env::GetInstance()->last_mouse_location();
int modifier = ui::MODIFIER_NONE;
switch (button) {
case ui::EF_LEFT_MOUSE_BUTTON:
modifier = ui::MODIFIER_LEFT_MOUSE_BUTTON;
break;
case ui::EF_RIGHT_MOUSE_BUTTON:
modifier = ui::MODIFIER_RIGHT_MOUSE_BUTTON;
break;
case ui::EF_MIDDLE_MOUSE_BUTTON:
modifier = ui::MODIFIER_MIDDLE_MOUSE_BUTTON;
default:
LOG(WARNING) << "Invalid flag: " << button << " for the button parameter";
return;
}
int flag = modifiers_.GetEventFlagFromModifier(modifier);
bool was_down = modifiers_.GetModifierFlags() & flag;
modifiers_.UpdateModifier(modifier, down);
down = modifiers_.GetModifierFlags() & flag;
// Suppress nested clicks. EventModifiers counts presses, we only
// dispatch an event on 0-1 (first press) and 1-0 (last release) transitions.
if (down == was_down)
return;
ui::MouseEvent event(
down ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED, location, location,
ui::EventTimeForNow(), modifiers_.GetModifierFlags() | flag,
/* changed_button_flags */ flag,
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE));
InjectEventAt(ui::PointerEvent(event), location);
}
void SystemInputInjectorMus::InjectMouseWheel(int delta_x, int delta_y) {
gfx::Point location = aura::Env::GetInstance()->last_mouse_location();
ui::MouseWheelEvent event(gfx::Vector2d(delta_x, delta_y), location, location,
ui::EventTimeForNow(),
modifiers_.GetModifierFlags(),
/* changed_button_flags */ 0);
InjectEventAt(ui::PointerEvent(event), location);
}
void SystemInputInjectorMus::InjectKeyEvent(ui::DomCode dom_code,
bool down,
bool suppress_auto_repeat) {
// |suppress_auto_repeat| is always true, and can be ignored.
ui::KeyboardCode key_code = ui::DomCodeToUsLayoutKeyboardCode(dom_code);
int modifier = KeyboardCodeToModifier(key_code);
if (modifier)
UpdateModifier(modifier, down);
ui::KeyEvent e(down ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, key_code,
dom_code, modifiers_.GetModifierFlags());
InjectEventAt(e, display::Screen::GetScreen()->GetCursorScreenPoint());
}
void SystemInputInjectorMus::InjectEventAt(const ui::Event& event,
const gfx::Point& location) {
display::Screen* screen = display::Screen::GetScreen();
display::Display display = screen->GetDisplayNearestPoint(location);
client_->InjectEvent(event, display.id());
}
void SystemInputInjectorMus::UpdateModifier(unsigned int modifier, bool down) {
if (modifier == ui::MODIFIER_NONE)
return;
// KeyboardEvdev performs a transformation here from MODIFIER_CAPS_LOCK to
// MODIFIER_MOD3. That was needed to work around X11, we actually want to
// ship this state across the wire without modification.
modifiers_.UpdateModifier(modifier, down);
}
} // namespace aura