Skip to main content

embedder_traits/
input_events.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::sync::atomic::{AtomicUsize, Ordering};
6
7use bitflags::bitflags;
8use keyboard_types::{Code, CompositionEvent, Key, KeyState, Location, Modifiers};
9use malloc_size_of_derive::MallocSizeOf;
10use serde::{Deserialize, Serialize};
11
12use crate::WebViewPoint;
13
14/// An opaque id for an [`InputEvent`].
15#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
16pub struct InputEventId(usize);
17
18static INPUT_EVENT_ID: AtomicUsize = AtomicUsize::new(0);
19
20impl InputEventId {
21    fn new() -> Self {
22        Self(INPUT_EVENT_ID.fetch_add(1, Ordering::Relaxed))
23    }
24}
25
26bitflags! {
27    /// Flags representing the state of an [`InputEvent`] after Servo has handled it.
28    #[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
29    pub struct InputEventResult: u8 {
30        /// Whether or not this input event's default behavior was prevented via script.
31        const DefaultPrevented = 1 << 0;
32        /// Whether or not the WebView handled this event. Some events have default handlers in
33        /// Servo, such as keyboard events that insert characters in `<input>` areas. When these
34        /// handlers are triggered, this flag is included. This can be used to prevent triggering
35        /// behavior (such as keybindings) when the WebView has already consumed the event for its
36        /// own purpose.
37        const Consumed = 1 << 1;
38        /// Whether or not the input event failed to dispatch. This can happen when an event
39        /// is sent while Servo is shutting down or when it is in an intermediate state.
40        /// Typically these events should be considered to be consumed.
41        const DispatchFailed = 1 << 2;
42    }
43}
44
45#[derive(Deserialize, Serialize)]
46pub struct InputEventOutcome {
47    pub id: InputEventId,
48    pub result: InputEventResult,
49}
50
51/// An input event that is sent from the embedder to Servo.
52#[derive(Clone, Debug, Deserialize, Serialize)]
53pub enum InputEvent {
54    EditingAction(EditingActionEvent),
55    #[cfg(feature = "gamepad")]
56    Gamepad(GamepadEvent),
57    Ime(ImeEvent),
58    Keyboard(KeyboardEvent),
59    MouseButton(MouseButtonEvent),
60    MouseLeftViewport(MouseLeftViewportEvent),
61    MouseMove(MouseMoveEvent),
62    Touch(TouchEvent),
63    Wheel(WheelEvent),
64}
65
66#[derive(Clone, Debug, Deserialize, Serialize)]
67pub struct InputEventAndId {
68    pub event: InputEvent,
69    pub id: InputEventId,
70}
71
72impl From<InputEvent> for InputEventAndId {
73    fn from(event: InputEvent) -> Self {
74        Self {
75            event,
76            id: InputEventId::new(),
77        }
78    }
79}
80
81/// An editing action that should be performed on a `WebView`.
82#[derive(Clone, Debug, Deserialize, Serialize)]
83pub enum EditingActionEvent {
84    Copy,
85    Cut,
86    Paste,
87}
88
89impl InputEvent {
90    pub fn point(&self) -> Option<WebViewPoint> {
91        match self {
92            InputEvent::EditingAction(..) => None,
93            #[cfg(feature = "gamepad")]
94            InputEvent::Gamepad(..) => None,
95            InputEvent::Ime(..) => None,
96            InputEvent::Keyboard(..) => None,
97            InputEvent::MouseButton(event) => Some(event.point),
98            InputEvent::MouseMove(event) => Some(event.point),
99            InputEvent::MouseLeftViewport(_) => None,
100            InputEvent::Touch(event) => Some(event.point),
101            InputEvent::Wheel(event) => Some(event.point),
102        }
103    }
104}
105
106#[derive(Clone, Debug, Default, Deserialize, Serialize)]
107pub struct KeyboardEvent {
108    pub event: ::keyboard_types::KeyboardEvent,
109}
110
111impl KeyboardEvent {
112    pub fn new(keyboard_event: ::keyboard_types::KeyboardEvent) -> Self {
113        Self {
114            event: keyboard_event,
115        }
116    }
117
118    pub fn new_without_event(
119        state: KeyState,
120        key: Key,
121        code: Code,
122        location: Location,
123        modifiers: Modifiers,
124        repeat: bool,
125        is_composing: bool,
126    ) -> Self {
127        Self::new(::keyboard_types::KeyboardEvent {
128            state,
129            key,
130            code,
131            location,
132            modifiers,
133            repeat,
134            is_composing,
135        })
136    }
137
138    pub fn from_state_and_key(state: KeyState, key: Key) -> Self {
139        Self::new(::keyboard_types::KeyboardEvent {
140            state,
141            key,
142            ..::keyboard_types::KeyboardEvent::default()
143        })
144    }
145}
146
147#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
148pub struct MouseButtonEvent {
149    pub action: MouseButtonAction,
150    pub button: MouseButton,
151    pub point: WebViewPoint,
152}
153
154impl MouseButtonEvent {
155    pub fn new(action: MouseButtonAction, button: MouseButton, point: WebViewPoint) -> Self {
156        Self {
157            action,
158            button,
159            point,
160        }
161    }
162}
163
164/// The types of mouse buttons.
165///
166/// <https://w3c.github.io/pointerevents/#the-button-property>
167#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
168pub enum MouseButton {
169    #[doc(hidden)]
170    None,
171    Primary,
172    Auxiliary,
173    Secondary,
174    Back,
175    Forward,
176    Other(u16),
177}
178
179impl<T: Into<i128>> From<T> for MouseButton {
180    fn from(value: T) -> Self {
181        let value = value.into();
182        match value {
183            -1 => MouseButton::None,
184            0 => MouseButton::Primary,
185            1 => MouseButton::Auxiliary,
186            2 => MouseButton::Secondary,
187            3 => MouseButton::Back,
188            4 => MouseButton::Forward,
189            _ => MouseButton::Other(value as u16),
190        }
191    }
192}
193
194impl From<MouseButton> for i16 {
195    fn from(value: MouseButton) -> Self {
196        match value {
197            MouseButton::None => -1,
198            MouseButton::Primary => 0,
199            MouseButton::Auxiliary => 1,
200            MouseButton::Secondary => 2,
201            MouseButton::Back => 3,
202            MouseButton::Forward => 4,
203            MouseButton::Other(value) => value as i16,
204        }
205    }
206}
207
208/// The types of mouse events.
209#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
210pub enum MouseButtonAction {
211    /// Mouse button down.
212    Down,
213    /// Mouse button up.
214    Up,
215}
216
217#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
218pub struct MouseMoveEvent {
219    pub point: WebViewPoint,
220    #[doc(hidden)]
221    // An internal flag used to avoid refreshing the cursor in response to move
222    // events for touch devices since they are simulated in Servo using mouse events.
223    pub is_compatibility_event_for_touch: bool,
224}
225
226impl MouseMoveEvent {
227    pub fn new(point: WebViewPoint) -> Self {
228        Self {
229            point,
230            is_compatibility_event_for_touch: false,
231        }
232    }
233
234    #[doc(hidden)]
235    pub fn new_compatibility_for_touch(point: WebViewPoint) -> Self {
236        Self {
237            point,
238            is_compatibility_event_for_touch: true,
239        }
240    }
241}
242
243#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
244pub struct MouseLeftViewportEvent {
245    pub focus_moving_to_another_iframe: bool,
246}
247
248/// The type of input represented by a multi-touch event.
249#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
250pub enum TouchEventType {
251    /// A new touch point came in contact with the screen.
252    Down,
253    /// An existing touch point changed location.
254    Move,
255    /// A touch point was removed from the screen.
256    Up,
257    /// The system stopped tracking a touch point.
258    Cancel,
259}
260
261/// An opaque identifier for a touch point.
262///
263/// <http://w3c.github.io/touch-events/#widl-Touch-identifier>
264#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
265pub struct TouchId(pub i32);
266
267/// Distinguishes the kind of physical input that produced a [`TouchEvent`].
268/// Servo routes both pen and finger-touch input through the touch event path,
269/// but the originating subtype determines the `pointerType` reported to script.
270#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
271pub enum TouchPointerType {
272    Pen,
273    Touch,
274}
275
276#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
277pub struct TouchEvent {
278    pub event_type: TouchEventType,
279    pub touch_id: TouchId,
280    pub point: WebViewPoint,
281    pub pointer_type: TouchPointerType,
282    /// cancelable default value is true, once the first move has been processed by script disable it.
283    cancelable: bool,
284}
285
286impl TouchEvent {
287    pub fn new(
288        event_type: TouchEventType,
289        touch_id: TouchId,
290        point: WebViewPoint,
291        pointer_type: TouchPointerType,
292    ) -> Self {
293        TouchEvent {
294            event_type,
295            touch_id,
296            point,
297            pointer_type,
298            cancelable: true,
299        }
300    }
301
302    #[doc(hidden)]
303    pub fn disable_cancelable(&mut self) {
304        self.cancelable = false;
305    }
306
307    #[doc(hidden)]
308    pub fn is_cancelable(&self) -> bool {
309        self.cancelable
310    }
311}
312
313/// Unit of a [`WheelDelta`].
314#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
315pub enum WheelMode {
316    /// Delta values are specified in pixels.
317    DeltaPixel = 0x00,
318    /// Delta values are specified in lines.
319    DeltaLine = 0x01,
320    /// Delta values are specified in pages.
321    DeltaPage = 0x02,
322}
323
324/// The wheel event deltas for every direction.
325#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
326pub struct WheelDelta {
327    /// Delta in the left/right direction. A positive value means that the view scrolls left,
328    /// revealing more content to the left of the current viewport.
329    pub x: f64,
330    /// Delta in the up/down direction. A positive value means that the view scrolls up, revealing
331    /// more content above the current viewport.
332    pub y: f64,
333    /// Delta in the direction going into/out of the screen
334    pub z: f64,
335    /// Mode to measure the floats in
336    pub mode: WheelMode,
337}
338
339#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
340pub struct WheelEvent {
341    pub delta: WheelDelta,
342    pub point: WebViewPoint,
343}
344
345impl WheelEvent {
346    pub fn new(delta: WheelDelta, point: WebViewPoint) -> Self {
347        WheelEvent { delta, point }
348    }
349}
350
351/// The types of an input method event.
352#[derive(Clone, Debug, Deserialize, Serialize)]
353pub enum ImeEvent {
354    Composition(CompositionEvent),
355    Dismissed,
356}
357
358#[cfg(feature = "gamepad")]
359#[derive(
360    Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
361)]
362/// Index of gamepad in list of system's connected gamepads.
363pub struct GamepadIndex(pub usize);
364
365#[cfg(feature = "gamepad")]
366#[derive(Clone, Debug, Deserialize, Serialize)]
367/// The minimum and maximum values that can be reported for axis or button input from this gamepad.
368pub struct GamepadInputBounds {
369    /// Minimum and maximum axis values.
370    pub axis_bounds: (f64, f64),
371    /// Minimum and maximum button values.
372    pub button_bounds: (f64, f64),
373}
374
375#[cfg(feature = "gamepad")]
376#[derive(Clone, Debug, Deserialize, Serialize)]
377/// The haptic effects supported by this gamepad.
378pub struct GamepadSupportedHapticEffects {
379    /// Whether gamepad has support for dual rumble effects.
380    pub supports_dual_rumble: bool,
381    /// Whether gamepad has support for trigger rumble effects.
382    pub supports_trigger_rumble: bool,
383}
384
385#[cfg(feature = "gamepad")]
386#[derive(Clone, Debug, Deserialize, Serialize)]
387/// The types of Gamepad event.
388pub enum GamepadEvent {
389    /// A new gamepad has been connected.
390    ///
391    /// <https://www.w3.org/TR/gamepad/#event-gamepadconnected>
392    Connected(
393        GamepadIndex,
394        String,
395        GamepadInputBounds,
396        GamepadSupportedHapticEffects,
397    ),
398    /// An existing gamepad has been disconnected.
399    ///
400    /// <https://www.w3.org/TR/gamepad/#event-gamepaddisconnected>
401    Disconnected(GamepadIndex),
402    /// An existing gamepad has been updated.
403    ///
404    /// <https://www.w3.org/TR/gamepad/#receiving-inputs>
405    Updated(GamepadIndex, GamepadUpdateType),
406}
407
408#[cfg(feature = "gamepad")]
409#[derive(Clone, Debug, Deserialize, Serialize)]
410/// The type of Gamepad input being updated.
411pub enum GamepadUpdateType {
412    /// Axis index and input value.
413    ///
414    /// <https://www.w3.org/TR/gamepad/#dfn-represents-a-standard-gamepad-axis>
415    Axis(usize, f64),
416    /// Button index and input value.
417    ///
418    /// <https://www.w3.org/TR/gamepad/#dfn-represents-a-standard-gamepad-button>
419    Button(usize, f64),
420}