blob: 1da7004017f022f49931058f41fa5ef3e9b8eb4b [file] [log] [blame]
// Copyright 2021 The Fuchsia 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 "src/ui/scenic/lib/input/mouse_injector.h"
#include <lib/syslog/cpp/macros.h>
namespace scenic_impl::input {
namespace {
ScrollInfo CreateScrollInfo(const fuchsia::input::report::Axis& axis,
std::optional<int64_t> scroll_value) {
ScrollInfo scroll_info = {
.unit = axis.unit.type,
.exponent = axis.unit.exponent,
.range = {axis.range.min, axis.range.max},
};
if (scroll_value.has_value()) {
scroll_info.scroll_value = scroll_value.value();
}
return scroll_info;
}
} // namespace
MouseInjector::MouseInjector(inspect::Node inspect_node, InjectorSettings settings,
Viewport viewport,
fidl::InterfaceRequest<fuchsia::ui::pointerinjector::Device> device,
fit::function<bool(/*descendant*/ zx_koid_t, /*ancestor*/ zx_koid_t)>
is_descendant_and_connected,
fit::function<void(const InternalMouseEvent&, StreamId)> inject,
fit::function<void(StreamId stream_id)> cancel_stream,
fit::function<void()> on_channel_closed)
: Injector(std::move(inspect_node), settings, std::move(viewport), std::move(device),
std::move(is_descendant_and_connected), std::move(on_channel_closed)),
inject_(std::move(inject)),
cancel_stream_(std::move(cancel_stream)) {
FX_DCHECK(inject_);
FX_DCHECK(settings.device_type == fuchsia::ui::pointerinjector::DeviceType::MOUSE);
}
void MouseInjector::ForwardEvent(const fuchsia::ui::pointerinjector::Event& event,
StreamId stream_id) {
{ // For CANCEL and REMOVE phase we need to cancel the stream. Otherwise inject normally.
FX_DCHECK(event.has_data());
const auto& data = event.data();
if (data.is_pointer_sample()) {
FX_DCHECK(data.pointer_sample().has_phase());
const auto phase = data.pointer_sample().phase();
if (phase == fuchsia::ui::pointerinjector::EventPhase::CANCEL ||
phase == fuchsia::ui::pointerinjector::EventPhase::REMOVE) {
cancel_stream_(stream_id);
return;
}
}
}
inject_(PointerInjectorEventToInternalMouseEvent(event), stream_id);
}
InternalMouseEvent MouseInjector::PointerInjectorEventToInternalMouseEvent(
const fuchsia::ui::pointerinjector::Event& event) const {
FX_DCHECK(event.has_data());
FX_DCHECK(event.data().is_pointer_sample());
InternalMouseEvent internal_event;
const InjectorSettings& settings = Injector::settings();
// General
internal_event.timestamp = event.timestamp();
internal_event.device_id = settings.device_id;
internal_event.context = settings.context_koid;
internal_event.target = settings.target_koid;
const fuchsia::ui::pointerinjector::PointerSample& pointer_sample = event.data().pointer_sample();
// Coordinates
internal_event.viewport = viewport();
internal_event.position_in_viewport = {pointer_sample.position_in_viewport()[0],
pointer_sample.position_in_viewport()[1]};
// Buttons
internal_event.buttons = {.identifiers = settings.button_identifiers};
if (pointer_sample.has_pressed_buttons()) {
internal_event.buttons.pressed = pointer_sample.pressed_buttons();
}
// Scroll V
if (settings.scroll_v_range.has_value()) {
std::optional<int64_t> scroll_value;
if (pointer_sample.has_scroll_v()) {
scroll_value = pointer_sample.scroll_v();
}
internal_event.scroll_v = CreateScrollInfo(settings.scroll_v_range.value(), scroll_value);
}
// Scroll H
if (settings.scroll_h_range.has_value()) {
std::optional<int64_t> scroll_value;
if (pointer_sample.has_scroll_h()) {
scroll_value = pointer_sample.scroll_h();
}
internal_event.scroll_h = CreateScrollInfo(settings.scroll_h_range.value(), scroll_value);
}
if (pointer_sample.has_scroll_v_physical_pixel()) {
internal_event.scroll_v_physical_pixel = pointer_sample.scroll_v_physical_pixel();
}
if (pointer_sample.has_scroll_h_physical_pixel()) {
internal_event.scroll_h_physical_pixel = pointer_sample.scroll_h_physical_pixel();
}
if (pointer_sample.has_is_precision_scroll()) {
internal_event.is_precision_scroll = pointer_sample.is_precision_scroll();
}
// Relative Motion
if (pointer_sample.has_relative_motion()) {
internal_event.relative_motion = {pointer_sample.relative_motion()[0],
pointer_sample.relative_motion()[1]};
}
return internal_event;
}
void MouseInjector::CancelStream(uint32_t pointer_id, StreamId stream_id) {
cancel_stream_(stream_id);
}
} // namespace scenic_impl::input