|  | // Copyright 2017 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. | 
|  |  | 
|  | #ifndef SRC_LIB_UI_INPUT_DEVICE_STATE_H_ | 
|  | #define SRC_LIB_UI_INPUT_DEVICE_STATE_H_ | 
|  |  | 
|  | #include <fuchsia/math/cpp/fidl.h> | 
|  | #include <fuchsia/ui/input/cpp/fidl.h> | 
|  | #include <lib/fit/function.h> | 
|  | #include <lib/zx/time.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include <vector> | 
|  |  | 
|  | #include <hid/hid.h> | 
|  | #include <hid/usages.h> | 
|  |  | 
|  | #include "src/lib/fxl/memory/ref_counted.h" | 
|  | #include "src/lib/fxl/memory/weak_ptr.h" | 
|  |  | 
|  | namespace ui_input { | 
|  |  | 
|  | using OnEventCallback = fit::function<void(fuchsia::ui::input::InputEvent event)>; | 
|  |  | 
|  | // In contrast to keyboard and mouse devices, which require extra state to | 
|  | // correctly interpret their data, sensor devices are simpler, so we just pass | 
|  | // through the raw InputReport. We do need a device_id to understand which | 
|  | // sensor the report came from. | 
|  | using OnSensorEventCallback = | 
|  | fit::function<void(uint32_t device_id, fuchsia::ui::input::InputReport event)>; | 
|  |  | 
|  | using OnMediaButtonsEventCallback = fit::function<void(fuchsia::ui::input::InputReport event)>; | 
|  |  | 
|  | class DeviceState; | 
|  |  | 
|  | class State { | 
|  | public: | 
|  | void OnRegistered() {} | 
|  | void OnUnregistered() {} | 
|  | }; | 
|  |  | 
|  | class KeyboardState : public State { | 
|  | public: | 
|  | KeyboardState(DeviceState* device_state); | 
|  | void Update(fuchsia::ui::input::InputReport report); | 
|  |  | 
|  | private: | 
|  | void SendEvent(fuchsia::ui::input::KeyboardEventPhase phase, uint32_t key, uint64_t modifiers, | 
|  | uint64_t timestamp); | 
|  | void Repeat(uint64_t sequence); | 
|  | void ScheduleRepeat(uint64_t sequence, zx::duration delta); | 
|  |  | 
|  | DeviceState* device_state_; | 
|  | const keychar_t* keymap_;  // assigned to a global static qwerty_map or dvorak_map | 
|  |  | 
|  | std::vector<uint32_t> keys_; | 
|  | std::vector<uint32_t> repeat_keys_; | 
|  | uint64_t modifiers_ = 0; | 
|  | uint64_t repeat_sequence_ = 0; | 
|  |  | 
|  | fxl::WeakPtrFactory<KeyboardState> weak_ptr_factory_; | 
|  | }; | 
|  |  | 
|  | class MouseState : public State { | 
|  | public: | 
|  | MouseState(DeviceState* device_state) : device_state_(device_state) {} | 
|  | void Update(fuchsia::ui::input::InputReport report, fuchsia::math::Size display_size); | 
|  | void OnRegistered(); | 
|  | void OnUnregistered(); | 
|  |  | 
|  | private: | 
|  | void SendEvent(float rel_x, float rel_y, int64_t timestamp, | 
|  | fuchsia::ui::input::PointerEventPhase phase, uint32_t buttons); | 
|  |  | 
|  | DeviceState* device_state_; | 
|  | uint8_t buttons_ = 0; | 
|  | fuchsia::math::PointF position_; | 
|  | }; | 
|  |  | 
|  | class StylusState : public State { | 
|  | public: | 
|  | StylusState(DeviceState* device_state) : device_state_(device_state) {} | 
|  | void Update(fuchsia::ui::input::InputReport report, fuchsia::math::Size display_size); | 
|  |  | 
|  | private: | 
|  | void SendEvent(int64_t timestamp, fuchsia::ui::input::PointerEventPhase phase, | 
|  | fuchsia::ui::input::PointerEventType type, float x, float y, uint32_t buttons); | 
|  |  | 
|  | DeviceState* device_state_; | 
|  | bool stylus_down_ = false; | 
|  | bool stylus_in_range_ = false; | 
|  | bool inverted_stylus_ = false; | 
|  | fuchsia::ui::input::PointerEvent stylus_; | 
|  | }; | 
|  |  | 
|  | class TouchscreenState : public State { | 
|  | public: | 
|  | TouchscreenState(DeviceState* device_state) : device_state_(device_state) {} | 
|  | void Update(fuchsia::ui::input::InputReport report, fuchsia::math::Size display_size); | 
|  |  | 
|  | private: | 
|  | DeviceState* device_state_; | 
|  | std::vector<fuchsia::ui::input::PointerEvent> pointers_; | 
|  | }; | 
|  |  | 
|  | class SensorState : public State { | 
|  | public: | 
|  | SensorState(DeviceState* device_state) : device_state_(device_state) {} | 
|  | void Update(fuchsia::ui::input::InputReport report); | 
|  |  | 
|  | private: | 
|  | DeviceState* device_state_; | 
|  | // TODO(fxbug.dev/23853): Remember sampling frequency and physical units. | 
|  | }; | 
|  |  | 
|  | class MediaButtonState : public State { | 
|  | public: | 
|  | MediaButtonState(DeviceState* device_state) : device_state_(device_state) {} | 
|  | void Update(fuchsia::ui::input::InputReport report); | 
|  |  | 
|  | private: | 
|  | DeviceState* device_state_; | 
|  | }; | 
|  |  | 
|  | class DeviceState { | 
|  | public: | 
|  | DeviceState(uint32_t device_id, fuchsia::ui::input::DeviceDescriptor* descriptor, | 
|  | OnEventCallback callback); | 
|  | DeviceState(uint32_t device_id, fuchsia::ui::input::DeviceDescriptor* descriptor, | 
|  | OnSensorEventCallback callback); | 
|  | DeviceState(uint32_t device_id, fuchsia::ui::input::DeviceDescriptor* descriptor, | 
|  | OnMediaButtonsEventCallback callback); | 
|  | ~DeviceState(); | 
|  |  | 
|  | void OnRegistered(); | 
|  | void OnUnregistered(); | 
|  |  | 
|  | void Update(fuchsia::ui::input::InputReport report, fuchsia::math::Size display_size); | 
|  |  | 
|  | uint32_t device_id() { return device_id_; } | 
|  | const OnEventCallback& callback() { return callback_; } | 
|  | const OnSensorEventCallback& sensor_callback() { return sensor_callback_; } | 
|  | const OnMediaButtonsEventCallback& media_buttons_callback() { return media_buttons_callback_; } | 
|  |  | 
|  | fuchsia::ui::input::KeyboardDescriptor* keyboard_descriptor() { | 
|  | return descriptor_->keyboard.get(); | 
|  | } | 
|  | fuchsia::ui::input::MouseDescriptor* mouse_descriptor() { return descriptor_->mouse.get(); } | 
|  | fuchsia::ui::input::StylusDescriptor* stylus_descriptor() { return descriptor_->stylus.get(); } | 
|  | fuchsia::ui::input::TouchscreenDescriptor* touchscreen_descriptor() { | 
|  | return descriptor_->touchscreen.get(); | 
|  | } | 
|  | fuchsia::ui::input::SensorDescriptor* sensor_descriptor() { return descriptor_->sensor.get(); } | 
|  | fuchsia::ui::input::MediaButtonsDescriptor* media_buttons_descriptor() { | 
|  | return descriptor_->media_buttons.get(); | 
|  | } | 
|  |  | 
|  | private: | 
|  | uint32_t device_id_; | 
|  | fuchsia::ui::input::DeviceDescriptor* descriptor_; | 
|  |  | 
|  | KeyboardState keyboard_; | 
|  | MouseState mouse_; | 
|  | StylusState stylus_; | 
|  | TouchscreenState touchscreen_; | 
|  | OnEventCallback callback_; | 
|  |  | 
|  | SensorState sensor_; | 
|  | OnSensorEventCallback sensor_callback_; | 
|  |  | 
|  | OnMediaButtonsEventCallback media_buttons_callback_; | 
|  | MediaButtonState media_buttons_; | 
|  | }; | 
|  |  | 
|  | }  // namespace ui_input | 
|  |  | 
|  | #endif  // SRC_LIB_UI_INPUT_DEVICE_STATE_H_ |