ul_next/event.rs
1//! Events that can be fired in [`View`](crate::view::View)s.
2
3use std::sync::Arc;
4
5use crate::{error::CreationError, key_code::VirtualKeyCode, string::UlString, Library};
6
7#[derive(Clone, Copy)]
8/// The type of the [`KeyEvent`].
9pub enum KeyEventType {
10 /// Raw Key-Down type. Use this when a physical key is pressed.
11 ///
12 /// You should use `RawKeyDown` for physical key presses since it allows the renderer to
13 /// handle accelerator command translation.
14 RawKeyDown = ul_sys::ULKeyEventType_kKeyEventType_RawKeyDown as isize,
15
16 /// Key-Down event type. (Does not trigger accelerator commands in WebCore)
17 /// (eg, Ctrl+C for copy is an accelerator command).
18 ///
19 /// You should probably use `RawKeyDown` instead when a physical key is pressed.
20 /// This type is only here for historic compatibility with WebCore's key event types.
21 KeyDown = ul_sys::ULKeyEventType_kKeyEventType_KeyDown as isize,
22
23 /// Key-Up event type. Use this when a physical key is released.
24 KeyUp = ul_sys::ULKeyEventType_kKeyEventType_KeyUp as isize,
25
26 /// Character input event type. Use this when the OS generates text from a physical key being
27 /// pressed (for example, this maps to `WM_CHAR` on Windows).
28 Char = ul_sys::ULKeyEventType_kKeyEventType_Char as isize,
29}
30
31/// Modifiers that can be pressed with a key.
32pub struct KeyEventModifiers {
33 /// Whether or not an ALT key is down
34 pub alt: bool,
35 /// Whether or not a Control key is down
36 pub ctrl: bool,
37 /// Whether or not a meta key (Command-key on Mac, Windows-key on Win) is down
38 pub meta: bool,
39 /// Whether or not a Shift key is down
40 pub shift: bool,
41}
42
43impl KeyEventModifiers {
44 fn to_u32(&self) -> u32 {
45 let mut n = 0;
46
47 if self.alt {
48 n |= 1 << 0;
49 }
50 if self.ctrl {
51 n |= 1 << 1;
52 }
53 if self.meta {
54 n |= 1 << 2;
55 }
56 if self.shift {
57 n |= 1 << 3;
58 }
59
60 n
61 }
62}
63
64/// Wrapper around all arguments needed to create a [`KeyEvent`].
65pub struct KeyEventCreationInfo<'a, 'b> {
66 /// The type of the event.
67 pub ty: KeyEventType,
68
69 /// The modifiers that were pressed with the key.
70 pub modifiers: KeyEventModifiers,
71
72 /// The virtual key-code associated with this keyboard event.
73 /// This is either directly from the event (ie, WPARAM on Windows) or via a
74 /// mapping function.
75 pub virtual_key_code: VirtualKeyCode,
76
77 /// The actual key-code generated by the platform.
78 /// The DOM spec primarily uses Windows-equivalent codes
79 /// (hence `virtual_key_code` above) but it helps to also specify the
80 /// platform-specific key-code as well.
81 pub native_key_code: i32,
82
83 /// The actual text generated by this keyboard event.
84 /// This is usually only a single character.
85 pub text: &'a str,
86
87 /// The text generated by this keyboard event before
88 /// all modifiers except shift are applied. This is used internally for
89 /// working out shortcut keys. This is usually only a single character.
90 pub unmodified_text: &'b str,
91 /// Whether or not this is a keypad event.
92 pub is_keypad: bool,
93 /// Whether or not this was generated as the result
94 /// of an auto-repeat (eg, holding down a key)
95 pub is_auto_repeat: bool,
96 /// Whether or not the pressed key is a "system key".
97 /// This is a Windows-only concept and should be "false" for all
98 /// non-Windows platforms. For more information, see the following link:
99 /// <http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx>
100 pub is_system_key: bool,
101}
102
103/// A generic keyboard event, that can be used to fire a key event in a
104/// `view` by [`View::fire_key_event`](crate::view::View::fire_key_event).
105pub struct KeyEvent {
106 lib: Arc<Library>,
107 internal: ul_sys::ULKeyEvent,
108}
109
110impl KeyEvent {
111 /// Create a new `KeyEvent`.
112 ///
113 /// # Arguments
114 /// * `lib` - The ultralight library.
115 /// * `creation_info` - The information needed to create the key event.
116 pub fn new(
117 lib: Arc<Library>,
118 creation_info: KeyEventCreationInfo,
119 ) -> Result<KeyEvent, CreationError> {
120 let ul_string_text = unsafe { UlString::from_str(lib.clone(), creation_info.text) }?;
121 let ul_string_unmodified_text =
122 unsafe { UlString::from_str(lib.clone(), creation_info.unmodified_text) }?;
123
124 let internal = unsafe {
125 lib.ultralight().ulCreateKeyEvent(
126 creation_info.ty as u32,
127 creation_info.modifiers.to_u32(),
128 creation_info.virtual_key_code.into(),
129 creation_info.native_key_code,
130 ul_string_text.to_ul(),
131 ul_string_unmodified_text.to_ul(),
132 creation_info.is_keypad,
133 creation_info.is_auto_repeat,
134 creation_info.is_system_key,
135 )
136 };
137
138 if internal.is_null() {
139 Err(CreationError::NullReference)
140 } else {
141 Ok(Self { lib, internal })
142 }
143 }
144
145 /// Returns the underlying [`ul_sys::ULKeyEvent`] struct, to be used locally for
146 /// calling the underlying C API.
147 pub(crate) unsafe fn to_ul(&self) -> ul_sys::ULKeyEvent {
148 self.internal
149 }
150}
151
152impl Drop for KeyEvent {
153 fn drop(&mut self) {
154 unsafe {
155 self.lib.ultralight().ulDestroyKeyEvent(self.internal);
156 }
157 }
158}
159
160#[derive(Clone, Copy)]
161/// The type of the [`MouseEvent`].
162pub enum MouseEventType {
163 /// Mouse moved event type
164 MouseMoved = ul_sys::ULMouseEventType_kMouseEventType_MouseMoved as isize,
165 /// Mouse button pressed event type
166 MouseDown = ul_sys::ULMouseEventType_kMouseEventType_MouseDown as isize,
167 /// Mouse button released event type
168 MouseUp = ul_sys::ULMouseEventType_kMouseEventType_MouseUp as isize,
169}
170
171#[derive(Clone, Copy)]
172/// The type of button that was pressed or released.
173pub enum MouseButton {
174 None = ul_sys::ULMouseButton_kMouseButton_None as isize,
175 Left = ul_sys::ULMouseButton_kMouseButton_Left as isize,
176 Middle = ul_sys::ULMouseButton_kMouseButton_Middle as isize,
177 Right = ul_sys::ULMouseButton_kMouseButton_Right as isize,
178}
179
180/// A generic mouse event, that can be used to fire a key event in a
181/// `view` by [`View::fire_mouse_event`](crate::view::View::fire_mouse_event).
182pub struct MouseEvent {
183 lib: Arc<Library>,
184 internal: ul_sys::ULMouseEvent,
185}
186
187impl MouseEvent {
188 /// Create a new `MouseEvent`.
189 ///
190 /// # Arguments
191 /// * `lib` - The ultralight library.
192 /// * `ty` - The type of the event.
193 /// * `x` - The x-position of the mouse. relative to the view.
194 /// * `y` - The y-position of the mouse. relative to the view.
195 /// * `button` - The button that was pressed or released if any.
196 pub fn new(
197 lib: Arc<Library>,
198 ty: MouseEventType,
199 x: i32,
200 y: i32,
201 button: MouseButton,
202 ) -> Result<MouseEvent, CreationError> {
203 let internal = unsafe {
204 lib.ultralight()
205 .ulCreateMouseEvent(ty as u32, x, y, button as u32)
206 };
207
208 if internal.is_null() {
209 Err(CreationError::NullReference)
210 } else {
211 Ok(Self { lib, internal })
212 }
213 }
214
215 /// Returns the underlying [`ul_sys::ULMouseEvent`] struct, to be used locally for
216 /// calling the underlying C API.
217 pub(crate) unsafe fn to_ul(&self) -> ul_sys::ULMouseEvent {
218 self.internal
219 }
220}
221
222impl Drop for MouseEvent {
223 fn drop(&mut self) {
224 unsafe {
225 self.lib.ultralight().ulDestroyMouseEvent(self.internal);
226 }
227 }
228}
229
230#[derive(Clone, Copy)]
231/// The type of the [`ScrollEvent`].
232pub enum ScrollEventType {
233 /// The delta value is interpreted as number of pixels
234 ScrollByPixel = ul_sys::ULScrollEventType_kScrollEventType_ScrollByPixel as isize,
235 /// The delta value is interpreted as number of pages
236 ScrollByPage = ul_sys::ULScrollEventType_kScrollEventType_ScrollByPage as isize,
237}
238
239/// A generic scroll event, that can be used to fire a key event in a
240/// `view` by [`View::fire_scroll_event`](crate::view::View::fire_scroll_event).
241pub struct ScrollEvent {
242 lib: Arc<Library>,
243 internal: ul_sys::ULScrollEvent,
244}
245
246impl ScrollEvent {
247 /// Create a new `ScrollEvent`.
248 ///
249 /// # Arguments
250 /// * `lib` - The ultralight library.
251 /// * `ty` - The type of the event.
252 /// * `delta_x` - The horizontal scroll amount.
253 /// * `delta_y` - The vertical scroll amount.
254 pub fn new(
255 lib: Arc<Library>,
256 ty: ScrollEventType,
257 delta_x: i32,
258 delta_y: i32,
259 ) -> Result<ScrollEvent, CreationError> {
260 let internal = unsafe {
261 lib.ultralight()
262 .ulCreateScrollEvent(ty as u32, delta_x, delta_y)
263 };
264
265 if internal.is_null() {
266 Err(CreationError::NullReference)
267 } else {
268 Ok(Self { lib, internal })
269 }
270 }
271
272 /// Returns the underlying [`ul_sys::ULScrollEvent`] struct, to be used locally for
273 /// calling the underlying C API.
274 pub(crate) unsafe fn to_ul(&self) -> ul_sys::ULScrollEvent {
275 self.internal
276 }
277}
278
279impl Drop for ScrollEvent {
280 fn drop(&mut self) {
281 unsafe {
282 self.lib.ultralight().ulDestroyScrollEvent(self.internal);
283 }
284 }
285}
286
287#[derive(Clone, Copy)]
288/// The type of the [`GamepadEvent`].
289pub enum GamepadEventType {
290 /// This event type should be fired when a gamepad is connected
291 ///
292 /// Note: You will need to previously declare the gamepad, its index, and details about
293 /// its axis and button layout via [`Renderer::set_gamepad_details`][crate::renderer::Renderer::set_gamepad_details]
294 /// prior to calling [`Renderer::fire_gamepad_event`][crate::renderer::Renderer::fire_gamepad_event].
295 Connected = ul_sys::ULGamepadEventType_kGamepadEventType_Connected as isize,
296 /// This event type should be fired when a gamepad is disconnected.
297 Disconnected = ul_sys::ULGamepadEventType_kGamepadEventType_Disconnected as isize,
298}
299
300/// Event representing a change in gamepad connection state
301///
302/// See [`Renderer::fire_gamepad_event`][crate::renderer::Renderer::fire_gamepad_event].
303pub struct GamepadEvent {
304 lib: Arc<Library>,
305 internal: ul_sys::ULGamepadEvent,
306}
307
308impl GamepadEvent {
309 /// Create a new `GamepadEvent`.
310 ///
311 /// # Arguments
312 /// * `lib` - The ultralight library.
313 /// * `index` - The index of the gamepad, this should match the value previously set in
314 /// [`Renderer::set_gamepad_details`][crate::renderer::Renderer::set_gamepad_details].
315 /// * `ty` - The type of this GamepadEvent.
316 pub fn new(
317 lib: Arc<Library>,
318 index: u32,
319 ty: GamepadEventType,
320 ) -> Result<GamepadEvent, CreationError> {
321 let internal = unsafe { lib.ultralight().ulCreateGamepadEvent(index, ty as u32) };
322
323 if internal.is_null() {
324 Err(CreationError::NullReference)
325 } else {
326 Ok(Self { lib, internal })
327 }
328 }
329
330 /// Returns the underlying [`ul_sys::ULGamepadEvent`] struct, to be used locally for
331 /// calling the underlying C API.
332 pub(crate) unsafe fn to_ul(&self) -> ul_sys::ULGamepadEvent {
333 self.internal
334 }
335}
336
337impl Drop for GamepadEvent {
338 fn drop(&mut self) {
339 unsafe {
340 self.lib.ultralight().ulDestroyGamepadEvent(self.internal);
341 }
342 }
343}
344
345/// Event representing a change in gamepad axis state (eg, pressing a stick in a certain direction).
346///
347/// See [`Renderer::fire_gamepad_axis_event`][crate::renderer::Renderer::fire_gamepad_axis_event].
348pub struct GamepadAxisEvent {
349 lib: Arc<Library>,
350 internal: ul_sys::ULGamepadAxisEvent,
351}
352
353impl GamepadAxisEvent {
354 /// Create a new `GamepadAxisEvent`.
355 ///
356 /// # Arguments
357 /// * `lib` - The ultralight library.
358 /// * `index` - The index of the gamepad, this should match the value previously set in
359 /// [`Renderer::set_gamepad_details`][crate::renderer::Renderer::set_gamepad_details].
360 /// * `axis_index` - The index of the axis whose value has changed.
361 /// This value should be in the range previously set in [`Renderer::set_gamepad_details`][crate::renderer::Renderer::set_gamepad_details].
362 /// * `value` - The new value of the axis. This value should be normalized to the range [-1.0, 1.0].
363 pub fn new(
364 lib: Arc<Library>,
365 index: u32,
366 axis_index: u32,
367 value: f64,
368 ) -> Result<GamepadAxisEvent, CreationError> {
369 let internal = unsafe {
370 lib.ultralight()
371 .ulCreateGamepadAxisEvent(index, axis_index, value)
372 };
373
374 if internal.is_null() {
375 Err(CreationError::NullReference)
376 } else {
377 Ok(Self { lib, internal })
378 }
379 }
380
381 /// Returns the underlying [`ul_sys::ULGamepadAxisEvent`] struct, to be used locally for
382 /// calling the underlying C API.
383 pub(crate) unsafe fn to_ul(&self) -> ul_sys::ULGamepadAxisEvent {
384 self.internal
385 }
386}
387
388impl Drop for GamepadAxisEvent {
389 fn drop(&mut self) {
390 unsafe {
391 self.lib
392 .ultralight()
393 .ulDestroyGamepadAxisEvent(self.internal);
394 }
395 }
396}
397
398/// Event representing a change in gamepad button state (eg, pressing a button on a gamepad).
399///
400/// See [`Renderer::fire_gamepad_button_event`][crate::renderer::Renderer::fire_gamepad_button_event].
401pub struct GamepadButtonEvent {
402 lib: Arc<Library>,
403 internal: ul_sys::ULGamepadButtonEvent,
404}
405
406impl GamepadButtonEvent {
407 /// Create a new `GamepadButtonEvent`.
408 ///
409 /// # Arguments
410 /// * `lib` - The ultralight library.
411 /// * `index` - The index of the gamepad, this should match the value previously set in
412 /// [`Renderer::set_gamepad_details`][crate::renderer::Renderer::set_gamepad_details].
413 /// * `button_index` - The index of the button whose value has changed.
414 /// This value should be in the range previously set in [`Renderer::set_gamepad_details`][crate::renderer::Renderer::set_gamepad_details].
415 /// * `value` - The new value of the axis. This value should be normalized to the range [-1.0, 1.0].
416 /// with any value greater than 0.0 to be considered "pressed".
417 pub fn new(
418 lib: Arc<Library>,
419 index: u32,
420 button_index: u32,
421 value: f64,
422 ) -> Result<GamepadButtonEvent, CreationError> {
423 let internal = unsafe {
424 lib.ultralight()
425 .ulCreateGamepadButtonEvent(index, button_index, value)
426 };
427
428 if internal.is_null() {
429 Err(CreationError::NullReference)
430 } else {
431 Ok(Self { lib, internal })
432 }
433 }
434
435 /// Returns the underlying [`ul_sys::ULGamepadButtonEvent`] struct, to be used locally for
436 /// calling the underlying C API.
437 pub(crate) unsafe fn to_ul(&self) -> ul_sys::ULGamepadButtonEvent {
438 self.internal
439 }
440}
441
442impl Drop for GamepadButtonEvent {
443 fn drop(&mut self) {
444 unsafe {
445 self.lib
446 .ultralight()
447 .ulDestroyGamepadButtonEvent(self.internal);
448 }
449 }
450}