1 /* 2 * Copyright 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //! Common definitions of the Android Input Framework in rust. 18 19 use crate::ffi::RustInputDeviceIdentifier; 20 use bitflags::bitflags; 21 use inputconstants::aidl::android::os::IInputConstants; 22 use std::fmt; 23 24 /// The InputDevice ID. 25 #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 26 pub struct DeviceId(pub i32); 27 28 /// The InputDevice equivalent for Rust inputflinger 29 #[derive(Debug)] 30 pub struct InputDevice { 31 /// InputDevice ID 32 pub device_id: DeviceId, 33 /// InputDevice unique identifier 34 pub identifier: RustInputDeviceIdentifier, 35 /// InputDevice classes (equivalent to EventHub InputDeviceClass) 36 pub classes: DeviceClass, 37 } 38 39 #[repr(u32)] 40 pub enum SourceClass { 41 None = input_bindgen::AINPUT_SOURCE_CLASS_NONE, 42 Button = input_bindgen::AINPUT_SOURCE_CLASS_BUTTON, 43 Pointer = input_bindgen::AINPUT_SOURCE_CLASS_POINTER, 44 Navigation = input_bindgen::AINPUT_SOURCE_CLASS_NAVIGATION, 45 Position = input_bindgen::AINPUT_SOURCE_CLASS_POSITION, 46 Joystick = input_bindgen::AINPUT_SOURCE_CLASS_JOYSTICK, 47 } 48 49 bitflags! { 50 /// Source of the input device or input events. 51 #[derive(Debug, PartialEq)] 52 pub struct Source: u32 { 53 // Constants from SourceClass, added here for compatibility reasons 54 /// SourceClass::Button 55 const SourceClassButton = SourceClass::Button as u32; 56 /// SourceClass::Pointer 57 const SourceClassPointer = SourceClass::Pointer as u32; 58 /// SourceClass::Navigation 59 const SourceClassNavigation = SourceClass::Navigation as u32; 60 /// SourceClass::Position 61 const SourceClassPosition = SourceClass::Position as u32; 62 /// SourceClass::Joystick 63 const SourceClassJoystick = SourceClass::Joystick as u32; 64 65 /// SOURCE_UNKNOWN 66 const Unknown = input_bindgen::AINPUT_SOURCE_UNKNOWN; 67 /// SOURCE_KEYBOARD 68 const Keyboard = input_bindgen::AINPUT_SOURCE_KEYBOARD; 69 /// SOURCE_DPAD 70 const Dpad = input_bindgen::AINPUT_SOURCE_DPAD; 71 /// SOURCE_GAMEPAD 72 const Gamepad = input_bindgen::AINPUT_SOURCE_GAMEPAD; 73 /// SOURCE_TOUCHSCREEN 74 const Touchscreen = input_bindgen::AINPUT_SOURCE_TOUCHSCREEN; 75 /// SOURCE_MOUSE 76 const Mouse = input_bindgen::AINPUT_SOURCE_MOUSE; 77 /// SOURCE_STYLUS 78 const Stylus = input_bindgen::AINPUT_SOURCE_STYLUS; 79 /// SOURCE_BLUETOOTH_STYLUS 80 const BluetoothStylus = input_bindgen::AINPUT_SOURCE_BLUETOOTH_STYLUS; 81 /// SOURCE_TRACKBALL 82 const Trackball = input_bindgen::AINPUT_SOURCE_TRACKBALL; 83 /// SOURCE_MOUSE_RELATIVE 84 const MouseRelative = input_bindgen::AINPUT_SOURCE_MOUSE_RELATIVE; 85 /// SOURCE_TOUCHPAD 86 const Touchpad = input_bindgen::AINPUT_SOURCE_TOUCHPAD; 87 /// SOURCE_TOUCH_NAVIGATION 88 const TouchNavigation = input_bindgen::AINPUT_SOURCE_TOUCH_NAVIGATION; 89 /// SOURCE_JOYSTICK 90 const Joystick = input_bindgen::AINPUT_SOURCE_JOYSTICK; 91 /// SOURCE_HDMI 92 const HDMI = input_bindgen::AINPUT_SOURCE_HDMI; 93 /// SOURCE_SENSOR 94 const Sensor = input_bindgen::AINPUT_SOURCE_SENSOR; 95 /// SOURCE_ROTARY_ENCODER 96 const RotaryEncoder = input_bindgen::AINPUT_SOURCE_ROTARY_ENCODER; 97 } 98 } 99 100 /// A rust enum representation of a MotionEvent action. 101 #[repr(u32)] 102 pub enum MotionAction { 103 /// ACTION_DOWN 104 Down = input_bindgen::AMOTION_EVENT_ACTION_DOWN, 105 /// ACTION_UP 106 Up = input_bindgen::AMOTION_EVENT_ACTION_UP, 107 /// ACTION_MOVE 108 Move = input_bindgen::AMOTION_EVENT_ACTION_MOVE, 109 /// ACTION_CANCEL 110 Cancel = input_bindgen::AMOTION_EVENT_ACTION_CANCEL, 111 /// ACTION_OUTSIDE 112 Outside = input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE, 113 /// ACTION_POINTER_DOWN 114 PointerDown { 115 /// The index of the affected pointer. 116 action_index: usize, 117 } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN, 118 /// ACTION_POINTER_UP 119 PointerUp { 120 /// The index of the affected pointer. 121 action_index: usize, 122 } = input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP, 123 /// ACTION_HOVER_ENTER 124 HoverEnter = input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER, 125 /// ACTION_HOVER_MOVE 126 HoverMove = input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE, 127 /// ACTION_HOVER_EXIT 128 HoverExit = input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT, 129 /// ACTION_SCROLL 130 Scroll = input_bindgen::AMOTION_EVENT_ACTION_SCROLL, 131 /// ACTION_BUTTON_PRESS 132 ButtonPress = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS, 133 /// ACTION_BUTTON_RELEASE 134 ButtonRelease = input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE, 135 } 136 137 impl fmt::Display for MotionAction { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 139 match self { 140 MotionAction::Down => write!(f, "DOWN"), 141 MotionAction::Up => write!(f, "UP"), 142 MotionAction::Move => write!(f, "MOVE"), 143 MotionAction::Cancel => write!(f, "CANCEL"), 144 MotionAction::Outside => write!(f, "OUTSIDE"), 145 MotionAction::PointerDown { action_index } => { 146 write!(f, "POINTER_DOWN({})", action_index) 147 } 148 MotionAction::PointerUp { action_index } => write!(f, "POINTER_UP({})", action_index), 149 MotionAction::HoverMove => write!(f, "HOVER_MOVE"), 150 MotionAction::Scroll => write!(f, "SCROLL"), 151 MotionAction::HoverEnter => write!(f, "HOVER_ENTER"), 152 MotionAction::HoverExit => write!(f, "HOVER_EXIT"), 153 MotionAction::ButtonPress => write!(f, "BUTTON_PRESS"), 154 MotionAction::ButtonRelease => write!(f, "BUTTON_RELEASE"), 155 } 156 } 157 } 158 159 impl From<u32> for MotionAction { from(action: u32) -> Self160 fn from(action: u32) -> Self { 161 let (action_masked, action_index) = MotionAction::breakdown_action(action); 162 match action_masked { 163 input_bindgen::AMOTION_EVENT_ACTION_DOWN => MotionAction::Down, 164 input_bindgen::AMOTION_EVENT_ACTION_UP => MotionAction::Up, 165 input_bindgen::AMOTION_EVENT_ACTION_MOVE => MotionAction::Move, 166 input_bindgen::AMOTION_EVENT_ACTION_CANCEL => MotionAction::Cancel, 167 input_bindgen::AMOTION_EVENT_ACTION_OUTSIDE => MotionAction::Outside, 168 input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN => { 169 MotionAction::PointerDown { action_index } 170 } 171 input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP => { 172 MotionAction::PointerUp { action_index } 173 } 174 input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER => MotionAction::HoverEnter, 175 input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE => MotionAction::HoverMove, 176 input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT => MotionAction::HoverExit, 177 input_bindgen::AMOTION_EVENT_ACTION_SCROLL => MotionAction::Scroll, 178 input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS => MotionAction::ButtonPress, 179 input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE => MotionAction::ButtonRelease, 180 _ => panic!("Unknown action: {}", action), 181 } 182 } 183 } 184 185 impl MotionAction { breakdown_action(action: u32) -> (u32, usize)186 fn breakdown_action(action: u32) -> (u32, usize) { 187 let action_masked = action & input_bindgen::AMOTION_EVENT_ACTION_MASK; 188 let index = (action & input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) 189 >> input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; 190 (action_masked, index.try_into().unwrap()) 191 } 192 } 193 194 bitflags! { 195 /// MotionEvent flags. 196 #[derive(Debug)] 197 pub struct MotionFlags: u32 { 198 /// FLAG_WINDOW_IS_OBSCURED 199 const WINDOW_IS_OBSCURED = IInputConstants::MOTION_EVENT_FLAG_WINDOW_IS_OBSCURED as u32; 200 /// FLAG_WINDOW_IS_PARTIALLY_OBSCURED 201 const WINDOW_IS_PARTIALLY_OBSCURED = IInputConstants::MOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED as u32; 202 /// FLAG_HOVER_EXIT_PENDING 203 const HOVER_EXIT_PENDING = IInputConstants::MOTION_EVENT_FLAG_HOVER_EXIT_PENDING as u32; 204 /// FLAG_IS_GENERATED_GESTURE 205 const IS_GENERATED_GESTURE = IInputConstants::MOTION_EVENT_FLAG_IS_GENERATED_GESTURE as u32; 206 /// FLAG_CANCELED 207 const CANCELED = IInputConstants::INPUT_EVENT_FLAG_CANCELED as u32; 208 /// FLAG_NO_FOCUS_CHANGE 209 const NO_FOCUS_CHANGE = IInputConstants::MOTION_EVENT_FLAG_NO_FOCUS_CHANGE as u32; 210 /// PRIVATE_FLAG_SUPPORTS_ORIENTATION 211 const PRIVATE_SUPPORTS_ORIENTATION = IInputConstants::MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION as u32; 212 /// PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION 213 const PRIVATE_SUPPORTS_DIRECTIONAL_ORIENTATION = 214 IInputConstants::MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION as u32; 215 /// FLAG_IS_ACCESSIBILITY_EVENT 216 const IS_ACCESSIBILITY_EVENT = IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT as u32; 217 /// FLAG_TAINTED 218 const TAINTED = IInputConstants::INPUT_EVENT_FLAG_TAINTED as u32; 219 /// FLAG_TARGET_ACCESSIBILITY_FOCUS 220 const TARGET_ACCESSIBILITY_FOCUS = IInputConstants::MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS as u32; 221 } 222 } 223 224 impl Source { 225 /// Return true if this source is from the provided class is_from_class(&self, source_class: SourceClass) -> bool226 pub fn is_from_class(&self, source_class: SourceClass) -> bool { 227 let class_bits = source_class as u32; 228 self.bits() & class_bits == class_bits 229 } 230 } 231 232 bitflags! { 233 /// Device class of the input device. These are duplicated from Eventhub.h 234 /// We need to make sure the two version remain in sync when adding new classes. 235 #[derive(Debug, PartialEq)] 236 pub struct DeviceClass: u32 { 237 /// The input device is a keyboard or has buttons 238 const Keyboard = IInputConstants::DEVICE_CLASS_KEYBOARD as u32; 239 /// The input device is an alpha-numeric keyboard (not just a dial pad) 240 const AlphabeticKey = IInputConstants::DEVICE_CLASS_ALPHAKEY as u32; 241 /// The input device is a touchscreen or a touchpad (either single-touch or multi-touch) 242 const Touch = IInputConstants::DEVICE_CLASS_TOUCH as u32; 243 /// The input device is a cursor device such as a trackball or mouse. 244 const Cursor = IInputConstants::DEVICE_CLASS_CURSOR as u32; 245 /// The input device is a multi-touch touchscreen or touchpad. 246 const MultiTouch = IInputConstants::DEVICE_CLASS_TOUCH_MT as u32; 247 /// The input device is a directional pad (implies keyboard, has DPAD keys). 248 const Dpad = IInputConstants::DEVICE_CLASS_DPAD as u32; 249 /// The input device is a gamepad (implies keyboard, has BUTTON keys). 250 const Gamepad = IInputConstants::DEVICE_CLASS_GAMEPAD as u32; 251 /// The input device has switches. 252 const Switch = IInputConstants::DEVICE_CLASS_SWITCH as u32; 253 /// The input device is a joystick (implies gamepad, has joystick absolute axes). 254 const Joystick = IInputConstants::DEVICE_CLASS_JOYSTICK as u32; 255 /// The input device has a vibrator (supports FF_RUMBLE). 256 const Vibrator = IInputConstants::DEVICE_CLASS_VIBRATOR as u32; 257 /// The input device has a microphone. 258 const Mic = IInputConstants::DEVICE_CLASS_MIC as u32; 259 /// The input device is an external stylus (has data we want to fuse with touch data). 260 const ExternalStylus = IInputConstants::DEVICE_CLASS_EXTERNAL_STYLUS as u32; 261 /// The input device has a rotary encoder 262 const RotaryEncoder = IInputConstants::DEVICE_CLASS_ROTARY_ENCODER as u32; 263 /// The input device has a sensor like accelerometer, gyro, etc 264 const Sensor = IInputConstants::DEVICE_CLASS_SENSOR as u32; 265 /// The input device has a battery 266 const Battery = IInputConstants::DEVICE_CLASS_BATTERY as u32; 267 /// The input device has sysfs controllable lights 268 const Light = IInputConstants::DEVICE_CLASS_LIGHT as u32; 269 /// The input device is a touchpad, requiring an on-screen cursor. 270 const Touchpad = IInputConstants::DEVICE_CLASS_TOUCHPAD as u32; 271 /// The input device is virtual (not a real device, not part of UI configuration). 272 const Virtual = IInputConstants::DEVICE_CLASS_VIRTUAL as u32; 273 /// The input device is external (not built-in). 274 const External = IInputConstants::DEVICE_CLASS_EXTERNAL as u32; 275 } 276 } 277 278 bitflags! { 279 /// Modifier state flags 280 #[derive(Default, Debug, Copy, Clone, Eq, PartialEq)] 281 pub struct ModifierState: u32 { 282 /// No meta keys are pressed 283 const None = input_bindgen::AMETA_NONE; 284 /// This mask is used to check whether one of the ALT meta keys is pressed 285 const AltOn = input_bindgen::AMETA_ALT_ON; 286 /// This mask is used to check whether the left ALT meta key is pressed 287 const AltLeftOn = input_bindgen::AMETA_ALT_LEFT_ON; 288 /// This mask is used to check whether the right ALT meta key is pressed 289 const AltRightOn = input_bindgen::AMETA_ALT_RIGHT_ON; 290 /// This mask is used to check whether one of the SHIFT meta keys is pressed 291 const ShiftOn = input_bindgen::AMETA_SHIFT_ON; 292 /// This mask is used to check whether the left SHIFT meta key is pressed 293 const ShiftLeftOn = input_bindgen::AMETA_SHIFT_LEFT_ON; 294 /// This mask is used to check whether the right SHIFT meta key is pressed 295 const ShiftRightOn = input_bindgen::AMETA_SHIFT_RIGHT_ON; 296 /// This mask is used to check whether the SYM meta key is pressed 297 const SymOn = input_bindgen::AMETA_SYM_ON; 298 /// This mask is used to check whether the FUNCTION meta key is pressed 299 const FunctionOn = input_bindgen::AMETA_FUNCTION_ON; 300 /// This mask is used to check whether one of the CTRL meta keys is pressed 301 const CtrlOn = input_bindgen::AMETA_CTRL_ON; 302 /// This mask is used to check whether the left CTRL meta key is pressed 303 const CtrlLeftOn = input_bindgen::AMETA_CTRL_LEFT_ON; 304 /// This mask is used to check whether the right CTRL meta key is pressed 305 const CtrlRightOn = input_bindgen::AMETA_CTRL_RIGHT_ON; 306 /// This mask is used to check whether one of the META meta keys is pressed 307 const MetaOn = input_bindgen::AMETA_META_ON; 308 /// This mask is used to check whether the left META meta key is pressed 309 const MetaLeftOn = input_bindgen::AMETA_META_LEFT_ON; 310 /// This mask is used to check whether the right META meta key is pressed 311 const MetaRightOn = input_bindgen::AMETA_META_RIGHT_ON; 312 /// This mask is used to check whether the CAPS LOCK meta key is on 313 const CapsLockOn = input_bindgen::AMETA_CAPS_LOCK_ON; 314 /// This mask is used to check whether the NUM LOCK meta key is on 315 const NumLockOn = input_bindgen::AMETA_NUM_LOCK_ON; 316 /// This mask is used to check whether the SCROLL LOCK meta key is on 317 const ScrollLockOn = input_bindgen::AMETA_SCROLL_LOCK_ON; 318 } 319 } 320 321 /// A rust enum representation of a Keyboard type. 322 #[repr(u32)] 323 #[derive(Debug, Copy, Clone, Eq, PartialEq)] 324 pub enum KeyboardType { 325 /// KEYBOARD_TYPE_NONE 326 None = input_bindgen::AINPUT_KEYBOARD_TYPE_NONE, 327 /// KEYBOARD_TYPE_NON_ALPHABETIC 328 NonAlphabetic = input_bindgen::AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, 329 /// KEYBOARD_TYPE_ALPHABETIC 330 Alphabetic = input_bindgen::AINPUT_KEYBOARD_TYPE_ALPHABETIC, 331 } 332 333 #[cfg(test)] 334 mod tests { 335 use crate::input::SourceClass; 336 use crate::Source; 337 #[test] convert_source_class_pointer()338 fn convert_source_class_pointer() { 339 let source = Source::from_bits(input_bindgen::AINPUT_SOURCE_CLASS_POINTER).unwrap(); 340 assert!(source.is_from_class(SourceClass::Pointer)); 341 } 342 } 343