| /* |
| * Copyright 2023 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| //! The rust component of libinput. |
| |
| mod input; |
| mod input_verifier; |
| mod keyboard_classifier; |
| |
| pub use input::{ |
| DeviceClass, DeviceId, InputDevice, ModifierState, MotionAction, MotionFlags, Source, |
| }; |
| pub use input_verifier::InputVerifier; |
| pub use keyboard_classifier::KeyboardClassifier; |
| |
| #[cxx::bridge(namespace = "android::input")] |
| #[allow(clippy::needless_maybe_sized)] |
| #[allow(unsafe_op_in_unsafe_fn)] |
| mod ffi { |
| #[namespace = "android"] |
| unsafe extern "C++" { |
| include!("ffi/FromRustToCpp.h"); |
| fn shouldLog(tag: &str) -> bool; |
| } |
| |
| #[namespace = "android::input::verifier"] |
| extern "Rust" { |
| /// Used to validate the incoming motion stream. |
| /// This class is not thread-safe. |
| /// State is stored in the "InputVerifier" object |
| /// that can be created via the 'create' method. |
| /// Usage: |
| /// |
| /// ```ignore |
| /// Box<InputVerifier> verifier = create("inputChannel name"); |
| /// result = process_movement(verifier, ...); |
| /// if (result) { |
| /// crash(result.error_message()); |
| /// } |
| /// ``` |
| type InputVerifier; |
| #[cxx_name = create] |
| fn create_input_verifier(name: String) -> Box<InputVerifier>; |
| fn process_movement( |
| verifier: &mut InputVerifier, |
| device_id: i32, |
| source: u32, |
| action: u32, |
| pointer_properties: &[RustPointerProperties], |
| flags: u32, |
| ) -> String; |
| fn reset_device(verifier: &mut InputVerifier, device_id: i32); |
| } |
| |
| #[namespace = "android::input::keyboardClassifier"] |
| extern "Rust" { |
| /// Used to classify a keyboard into alphabetic and non-alphabetic |
| type KeyboardClassifier; |
| #[cxx_name = create] |
| fn create_keyboard_classifier() -> Box<KeyboardClassifier>; |
| #[cxx_name = notifyKeyboardChanged] |
| fn notify_keyboard_changed( |
| classifier: &mut KeyboardClassifier, |
| device_id: i32, |
| identifier: RustInputDeviceIdentifier, |
| device_classes: u32, |
| ); |
| #[cxx_name = getKeyboardType] |
| fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32; |
| #[cxx_name = isFinalized] |
| fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool; |
| #[cxx_name = processKey] |
| fn process_key( |
| classifier: &mut KeyboardClassifier, |
| device_id: i32, |
| evdev_code: i32, |
| modifier_state: u32, |
| ); |
| } |
| |
| #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] |
| pub struct RustPointerProperties { |
| pub id: i32, |
| } |
| |
| #[derive(Debug)] |
| pub struct RustInputDeviceIdentifier { |
| pub name: String, |
| pub location: String, |
| pub unique_id: String, |
| pub bus: u16, |
| pub vendor: u16, |
| pub product: u16, |
| pub version: u16, |
| pub descriptor: String, |
| } |
| } |
| |
| use crate::ffi::{RustInputDeviceIdentifier, RustPointerProperties}; |
| |
| fn create_input_verifier(name: String) -> Box<InputVerifier> { |
| Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents"))) |
| } |
| |
| fn process_movement( |
| verifier: &mut InputVerifier, |
| device_id: i32, |
| source: u32, |
| action: u32, |
| pointer_properties: &[RustPointerProperties], |
| flags: u32, |
| ) -> String { |
| let motion_flags = MotionFlags::from_bits(flags); |
| if motion_flags.is_none() { |
| panic!( |
| "The conversion of flags 0x{:08x} failed, please check if some flags have not been \ |
| added to MotionFlags.", |
| flags |
| ); |
| } |
| let result = verifier.process_movement( |
| DeviceId(device_id), |
| Source::from_bits(source).unwrap(), |
| action, |
| pointer_properties, |
| motion_flags.unwrap(), |
| ); |
| match result { |
| Ok(()) => "".to_string(), |
| Err(e) => e, |
| } |
| } |
| |
| fn reset_device(verifier: &mut InputVerifier, device_id: i32) { |
| verifier.reset_device(DeviceId(device_id)); |
| } |
| |
| fn create_keyboard_classifier() -> Box<KeyboardClassifier> { |
| Box::new(KeyboardClassifier::new()) |
| } |
| |
| fn notify_keyboard_changed( |
| classifier: &mut KeyboardClassifier, |
| device_id: i32, |
| identifier: RustInputDeviceIdentifier, |
| device_classes: u32, |
| ) { |
| let classes = DeviceClass::from_bits(device_classes); |
| if classes.is_none() { |
| panic!( |
| "The conversion of device class 0x{:08x} failed, please check if some device classes |
| have not been added to DeviceClass.", |
| device_classes |
| ); |
| } |
| classifier.notify_keyboard_changed(InputDevice { |
| device_id: DeviceId(device_id), |
| identifier, |
| classes: classes.unwrap(), |
| }); |
| } |
| |
| fn get_keyboard_type(classifier: &mut KeyboardClassifier, device_id: i32) -> u32 { |
| classifier.get_keyboard_type(DeviceId(device_id)) as u32 |
| } |
| |
| fn is_finalized(classifier: &mut KeyboardClassifier, device_id: i32) -> bool { |
| classifier.is_finalized(DeviceId(device_id)) |
| } |
| |
| fn process_key( |
| classifier: &mut KeyboardClassifier, |
| device_id: i32, |
| evdev_code: i32, |
| meta_state: u32, |
| ) { |
| let modifier_state = ModifierState::from_bits(meta_state); |
| if modifier_state.is_none() { |
| panic!( |
| "The conversion of meta state 0x{:08x} failed, please check if some meta state |
| have not been added to ModifierState.", |
| meta_state |
| ); |
| } |
| classifier.process_key(DeviceId(device_id), evdev_code, modifier_state.unwrap()); |
| } |