animate/legacy/
input_device.rs

1use crate::{
2    Actor, Backend, DeviceManager, Event, EventSequence, InputAxis, InputDeviceType, InputMode,
3    InternalPoint, ModifierType, Stage,
4};
5use glib::{
6    object::{IsA, ObjectType as ObjectType_},
7    signal::{connect_raw, SignalHandlerId},
8    translate::*,
9    GString, StaticType, Value,
10};
11use std::boxed::Box as Box_;
12use std::{fmt, mem, mem::transmute};
13
14glib_wrapper! {
15    pub struct InputDevice(Object<ffi::ClutterInputDevice, ffi::ClutterInputDeviceClass, InputDeviceClass>);
16
17    match fn {
18        get_type => || ffi::clutter_input_device_get_type(),
19    }
20}
21
22impl InputDevice {
23    /// Retrieves a pointer to the `InputDevice` that has been
24    /// associated to `self`.
25    ///
26    /// If the `InputDevice:device-mode` property of `self` is
27    /// set to `InputMode::Master`, this function will return
28    /// `None`.
29    ///
30    /// # Returns
31    ///
32    /// a `InputDevice`, or `None`
33    pub fn get_associated_device(&self) -> Option<InputDevice> {
34        unsafe {
35            from_glib_none(ffi::clutter_input_device_get_associated_device(
36                self.to_glib_none().0,
37            ))
38        }
39    }
40
41    /// Retrieves the type of axis on `self` at the given index.
42    /// ## `index_`
43    /// the index of the axis
44    ///
45    /// # Returns
46    ///
47    /// the axis type
48    pub fn get_axis(&self, index_: u32) -> InputAxis {
49        unsafe {
50            from_glib(ffi::clutter_input_device_get_axis(
51                self.to_glib_none().0,
52                index_,
53            ))
54        }
55    }
56
57    //pub fn get_axis_value(&self, axes: &[f64], axis: InputAxis) -> Option<f64> {
58    //    unsafe { TODO: call clutter_sys:clutter_input_device_get_axis_value() }
59    //}
60
61    // /// Retrieves the latest coordinates of a pointer or touch point of
62    // /// `self`.
63    // /// ## `sequence`
64    // /// a `EventSequence`, or `None` if
65    // ///  the device is not touch-based
66    // /// ## `point`
67    // /// return location for the pointer
68    // ///  or touch point
69    // ///
70    // /// # Returns
71    // ///
72    // /// `false` if the device's sequence hasn't been found,
73    // ///  and `true` otherwise.
74    // pub fn get_coords(&self, sequence: Option<&mut EventSequence>) -> Option<Point> {
75    //     unsafe {
76    //         let mut point = Point::uninitialized();
77    //         let ret = from_glib(ffi::clutter_input_device_get_coords(
78    //             self.to_glib_none().0,
79    //             sequence.to_glib_none_mut().0,
80    //             point.to_glib_none_mut().0,
81    //         ));
82    //         if ret {
83    //             Some(point)
84    //         } else {
85    //             None
86    //         }
87    //     }
88    // }
89
90    /// Retrieves the unique identifier of `self`
91    ///
92    /// # Returns
93    ///
94    /// the identifier of the device
95    pub fn get_device_id(&self) -> i32 {
96        unsafe { ffi::clutter_input_device_get_device_id(self.to_glib_none().0) }
97    }
98
99    /// Retrieves the `InputMode` of `self`.
100    ///
101    /// # Returns
102    ///
103    /// the device mode
104    pub fn get_device_mode(&self) -> InputMode {
105        unsafe {
106            from_glib(ffi::clutter_input_device_get_device_mode(
107                self.to_glib_none().0,
108            ))
109        }
110    }
111
112    /// Retrieves the name of the `self`
113    ///
114    /// # Returns
115    ///
116    /// the name of the device, or `None`. The returned string
117    ///  is owned by the `InputDevice` and should never be modified
118    ///  or freed
119    pub fn get_device_name(&self) -> Option<GString> {
120        unsafe {
121            from_glib_none(ffi::clutter_input_device_get_device_name(
122                self.to_glib_none().0,
123            ))
124        }
125    }
126
127    /// Retrieves the type of `self`
128    ///
129    /// # Returns
130    ///
131    /// the type of the device
132    pub fn get_device_type(&self) -> InputDeviceType {
133        unsafe {
134            from_glib(ffi::clutter_input_device_get_device_type(
135                self.to_glib_none().0,
136            ))
137        }
138    }
139
140    /// Retrieves whether `self` is enabled.
141    ///
142    /// # Returns
143    ///
144    /// `true` if the device is enabled
145    pub fn get_enabled(&self) -> bool {
146        unsafe { from_glib(ffi::clutter_input_device_get_enabled(self.to_glib_none().0)) }
147    }
148
149    /// Retrieves a pointer to the `Actor` currently grabbing all
150    /// the events coming from `self`.
151    ///
152    /// # Returns
153    ///
154    /// a `Actor`, or `None`
155    pub fn get_grabbed_actor(&self) -> Option<Actor> {
156        unsafe {
157            from_glib_none(ffi::clutter_input_device_get_grabbed_actor(
158                self.to_glib_none().0,
159            ))
160        }
161    }
162
163    /// Retrieves whether `self` has a pointer that follows the
164    /// device motion.
165    ///
166    /// # Returns
167    ///
168    /// `true` if the device has a cursor
169    pub fn get_has_cursor(&self) -> bool {
170        unsafe {
171            from_glib(ffi::clutter_input_device_get_has_cursor(
172                self.to_glib_none().0,
173            ))
174        }
175    }
176
177    /// Retrieves the key set using `InputDevice::set_key`
178    /// ## `index_`
179    /// the index of the key
180    /// ## `keyval`
181    /// return location for the keyval at `index_`
182    /// ## `modifiers`
183    /// return location for the modifiers at `index_`
184    ///
185    /// # Returns
186    ///
187    /// `true` if a key was set at the given index
188    pub fn get_key(&self, index_: u32) -> Option<(u32, ModifierType)> {
189        unsafe {
190            let mut keyval = mem::MaybeUninit::uninit();
191            let mut modifiers = mem::MaybeUninit::uninit();
192            let ret = from_glib(ffi::clutter_input_device_get_key(
193                self.to_glib_none().0,
194                index_,
195                keyval.as_mut_ptr(),
196                modifiers.as_mut_ptr(),
197            ));
198            let keyval = keyval.assume_init();
199            let modifiers = modifiers.assume_init();
200            if ret {
201                Some((keyval, from_glib(modifiers)))
202            } else {
203                None
204            }
205        }
206    }
207
208    /// Retrieves the current modifiers state of the device, as seen
209    /// by the last event processed.
210    ///
211    /// # Returns
212    ///
213    /// the last known modifier state
214    pub fn get_modifier_state(&self) -> ModifierType {
215        unsafe {
216            from_glib(ffi::clutter_input_device_get_modifier_state(
217                self.to_glib_none().0,
218            ))
219        }
220    }
221
222    /// Retrieves the number of axes available on `self`.
223    ///
224    /// # Returns
225    ///
226    /// the number of axes on the device
227    pub fn get_n_axes(&self) -> u32 {
228        unsafe { ffi::clutter_input_device_get_n_axes(self.to_glib_none().0) }
229    }
230
231    /// Retrieves the number of keys registered for `self`.
232    ///
233    /// # Returns
234    ///
235    /// the number of registered keys
236    pub fn get_n_keys(&self) -> u32 {
237        unsafe { ffi::clutter_input_device_get_n_keys(self.to_glib_none().0) }
238    }
239
240    /// Retrieves the `Actor` underneath the pointer of `self`
241    ///
242    /// # Returns
243    ///
244    /// a pointer to the `Actor` or `None`
245    pub fn get_pointer_actor(&self) -> Option<Actor> {
246        unsafe {
247            from_glib_none(ffi::clutter_input_device_get_pointer_actor(
248                self.to_glib_none().0,
249            ))
250        }
251    }
252
253    /// Retrieves the `Stage` underneath the pointer of `self`
254    ///
255    /// # Returns
256    ///
257    /// a pointer to the `Stage` or `None`
258    pub fn get_pointer_stage(&self) -> Option<Stage> {
259        unsafe {
260            from_glib_none(ffi::clutter_input_device_get_pointer_stage(
261                self.to_glib_none().0,
262            ))
263        }
264    }
265
266    /// Gets the product ID of this device.
267    ///
268    /// # Returns
269    ///
270    /// the product ID
271    pub fn get_product_id(&self) -> Option<GString> {
272        unsafe {
273            from_glib_none(ffi::clutter_input_device_get_product_id(
274                self.to_glib_none().0,
275            ))
276        }
277    }
278
279    /// Retrieves the slave devices attached to `self`.
280    ///
281    /// # Returns
282    ///
283    /// a
284    ///  list of `InputDevice`, or `None`. The contents of the list are
285    ///  owned by the device. Use `glib::List::free` when done
286    pub fn get_slave_devices(&self) -> Vec<InputDevice> {
287        unsafe {
288            FromGlibPtrContainer::from_glib_container(ffi::clutter_input_device_get_slave_devices(
289                self.to_glib_none().0,
290            ))
291        }
292    }
293
294    /// Gets the vendor ID of this device.
295    ///
296    /// # Returns
297    ///
298    /// the vendor ID
299    pub fn get_vendor_id(&self) -> Option<GString> {
300        unsafe {
301            from_glib_none(ffi::clutter_input_device_get_vendor_id(
302                self.to_glib_none().0,
303            ))
304        }
305    }
306
307    /// Acquires a grab on `actor` for the given `self`.
308    ///
309    /// Any event coming from `self` will be delivered to `actor`, bypassing
310    /// the usual event delivery mechanism, until the grab is released by
311    /// calling `InputDevice::ungrab`.
312    ///
313    /// The grab is client-side: even if the windowing system used by the
314    /// backend has the concept of "device grabs", it will not use them.
315    ///
316    /// Only `InputDevice` of types `InputDeviceType::PointerDevice` and
317    /// `InputDeviceType::KeyboardDevice` can hold a grab.
318    /// ## `actor`
319    /// a `Actor`
320    pub fn grab<P: IsA<Actor>>(&self, actor: &P) {
321        unsafe {
322            ffi::clutter_input_device_grab(self.to_glib_none().0, actor.as_ref().to_glib_none().0);
323        }
324    }
325
326    // /// Translates a hardware keycode from a `KeyEvent` to the
327    // /// equivalent evdev keycode. Note that depending on the input backend
328    // /// used by this function can fail if there is no obvious
329    // /// mapping between the key codes. The hardware keycode can be taken
330    // /// from the `KeyEvent.hardware_keycode` member of `KeyEvent`.
331    // /// ## `hardware_keycode`
332    // /// The hardware keycode from a `KeyEvent`
333    // /// ## `evdev_keycode`
334    // /// The return location for the evdev keycode
335    // ///
336    // /// # Returns
337    // ///
338    // /// `true` if the conversion succeeded, `false` otherwise.
339    // pub fn keycode_to_evdev(&self, hardware_keycode: u32, evdev_keycode: u32) -> bool {
340    //     unsafe {
341    //         from_glib(ffi::clutter_input_device_keycode_to_evdev(
342    //             self.to_glib_none().0,
343    //             hardware_keycode,
344    //             evdev_keycode,
345    //         ))
346    //     }
347    // }
348
349    /// Retrieves a pointer to the `Actor` currently grabbing the
350    /// touch events coming from `self` given the `sequence`.
351    /// ## `sequence`
352    /// a `EventSequence`
353    ///
354    /// # Returns
355    ///
356    /// a `Actor`, or `None`
357    pub fn sequence_get_grabbed_actor(&self, sequence: &mut EventSequence) -> Option<Actor> {
358        unsafe {
359            from_glib_none(ffi::clutter_input_device_sequence_get_grabbed_actor(
360                self.to_glib_none().0,
361                sequence.to_glib_none_mut().0,
362            ))
363        }
364    }
365
366    /// Acquires a grab on `actor` for the given `self` and the given touch
367    /// `sequence`.
368    ///
369    /// Any touch event coming from `self` and from `sequence` will be
370    /// delivered to `actor`, bypassing the usual event delivery mechanism,
371    /// until the grab is released by calling
372    /// `InputDevice::sequence_ungrab`.
373    ///
374    /// The grab is client-side: even if the windowing system used by the
375    /// backend has the concept of "device grabs", it will not use them.
376    /// ## `sequence`
377    /// a `EventSequence`
378    /// ## `actor`
379    /// a `Actor`
380    pub fn sequence_grab<P: IsA<Actor>>(&self, sequence: &mut EventSequence, actor: &P) {
381        unsafe {
382            ffi::clutter_input_device_sequence_grab(
383                self.to_glib_none().0,
384                sequence.to_glib_none_mut().0,
385                actor.as_ref().to_glib_none().0,
386            );
387        }
388    }
389
390    /// Releases the grab on the `self` for the given `sequence`, if one is
391    /// in place.
392    /// ## `sequence`
393    /// a `EventSequence`
394    pub fn sequence_ungrab(&self, sequence: &mut EventSequence) {
395        unsafe {
396            ffi::clutter_input_device_sequence_ungrab(
397                self.to_glib_none().0,
398                sequence.to_glib_none_mut().0,
399            );
400        }
401    }
402
403    /// Enables or disables a `InputDevice`.
404    ///
405    /// Only devices with a `InputDevice:device-mode` property set
406    /// to `InputMode::Slave` or `InputMode::Floating` can
407    /// be disabled.
408    /// ## `enabled`
409    /// `true` to enable the `self`
410    pub fn set_enabled(&self, enabled: bool) {
411        unsafe {
412            ffi::clutter_input_device_set_enabled(self.to_glib_none().0, enabled.to_glib());
413        }
414    }
415
416    /// Sets the keyval and modifiers at the given `index_` for `self`.
417    ///
418    /// will use the keyval and modifiers set when filling out
419    /// an event coming from the same input device.
420    /// ## `index_`
421    /// the index of the key
422    /// ## `keyval`
423    /// the keyval
424    /// ## `modifiers`
425    /// a bitmask of modifiers
426    pub fn set_key(&self, index_: u32, keyval: u32, modifiers: ModifierType) {
427        unsafe {
428            ffi::clutter_input_device_set_key(
429                self.to_glib_none().0,
430                index_,
431                keyval,
432                modifiers.to_glib(),
433            );
434        }
435    }
436
437    /// Releases the grab on the `self`, if one is in place.
438    pub fn ungrab(&self) {
439        unsafe {
440            ffi::clutter_input_device_ungrab(self.to_glib_none().0);
441        }
442    }
443
444    /// Forcibly updates the state of the `self` using a `Event`
445    ///
446    /// This function should never be used by applications: it is meant
447    /// for integration with embedding toolkits, like clutter-gtk
448    ///
449    /// Embedding toolkits that disable the event collection inside
450    /// need to use this function to update the state of input devices depending
451    /// on a `Event` that they are going to submit to the event handling code
452    /// in it though `do_event`. Since the input devices hold the state
453    /// that is going to be used to fill in fields like the `ButtonEvent`
454    /// click count, or to emit synthesized events like `EventType::Enter` and
455    /// `EventType::Leave`, it is necessary for embedding toolkits to also be
456    /// responsible of updating the input device state.
457    ///
458    /// For instance, this might be the code to translate an embedding toolkit
459    /// native motion notification into a `MotionEvent` and ask
460    /// to process it:
461    ///
462    ///
463    /// ```text
464    ///   Event c_event;
465    ///
466    ///   translate_native_event_to_clutter (native_event, &c_event);
467    ///
468    ///   do_event (&c_event);
469    /// ```
470    ///
471    /// Before letting `do_event` process the event, it is necessary to call
472    /// `InputDevice::update_from_event`:
473    ///
474    ///
475    /// ```text
476    ///   Event c_event;
477    ///   DeviceManager *manager;
478    ///   InputDevice *device;
479    ///
480    ///   translate_native_event_to_clutter (native_event, &c_event);
481    ///
482    ///   // get the device manager
483    ///   manager = device_manager_get_default ();
484    ///
485    ///   // use the default Core Pointer that backends register by default
486    ///   device = device_manager_get_core_device (manager, %POINTER_DEVICE);
487    ///
488    ///   // update the state of the input device
489    ///   input_device_update_from_event (device, &c_event, FALSE);
490    ///
491    ///   do_event (&c_event);
492    /// ```
493    ///
494    /// The `update_stage` boolean argument should be used when the input device
495    /// enters and leaves a `Stage`; it will use the `Stage` field
496    /// of the passed `event` to update the stage associated to the input device.
497    /// ## `event`
498    /// a `Event`
499    /// ## `update_stage`
500    /// whether to update the `Stage` of the `self`
501    ///  using the stage of the event
502    pub fn update_from_event(&self, event: &mut Event, update_stage: bool) {
503        unsafe {
504            ffi::clutter_input_device_update_from_event(
505                self.to_glib_none().0,
506                event.to_glib_none_mut().0,
507                update_stage.to_glib(),
508            );
509        }
510    }
511
512    /// The `Backend` that created the device.
513    pub fn get_property_backend(&self) -> Option<Backend> {
514        unsafe {
515            let mut value = Value::from_type(<Backend as StaticType>::static_type());
516            gobject_sys::g_object_get_property(
517                self.as_ptr() as *mut gobject_sys::GObject,
518                b"backend\0".as_ptr() as *const _,
519                value.to_glib_none_mut().0,
520            );
521            value
522                .get()
523                .expect("Return Value for property `backend` getter")
524        }
525    }
526
527    /// The `DeviceManager` instance which owns the device
528    pub fn get_property_device_manager(&self) -> Option<DeviceManager> {
529        unsafe {
530            let mut value = Value::from_type(<DeviceManager as StaticType>::static_type());
531            gobject_sys::g_object_get_property(
532                self.as_ptr() as *mut gobject_sys::GObject,
533                b"device-manager\0".as_ptr() as *const _,
534                value.to_glib_none_mut().0,
535            );
536            value
537                .get()
538                .expect("Return Value for property `device-manager` getter")
539        }
540    }
541
542    /// The unique identifier of the device
543    pub fn get_property_id(&self) -> i32 {
544        unsafe {
545            let mut value = Value::from_type(<i32 as StaticType>::static_type());
546            gobject_sys::g_object_get_property(
547                self.as_ptr() as *mut gobject_sys::GObject,
548                b"id\0".as_ptr() as *const _,
549                value.to_glib_none_mut().0,
550            );
551            value
552                .get()
553                .expect("Return Value for property `id` getter")
554                .unwrap()
555        }
556    }
557
558    /// The name of the device
559    pub fn get_property_name(&self) -> Option<GString> {
560        unsafe {
561            let mut value = Value::from_type(<GString as StaticType>::static_type());
562            gobject_sys::g_object_get_property(
563                self.as_ptr() as *mut gobject_sys::GObject,
564                b"name\0".as_ptr() as *const _,
565                value.to_glib_none_mut().0,
566            );
567            value
568                .get()
569                .expect("Return Value for property `name` getter")
570        }
571    }
572
573    pub fn connect_property_enabled_notify<F: Fn(&InputDevice) + 'static>(
574        &self,
575        f: F,
576    ) -> SignalHandlerId {
577        unsafe extern "C" fn notify_enabled_trampoline<F: Fn(&InputDevice) + 'static>(
578            this: *mut ffi::ClutterInputDevice,
579            _param_spec: glib_sys::gpointer,
580            f: glib_sys::gpointer,
581        ) {
582            let f: &F = &*(f as *const F);
583            f(&from_glib_borrow(this))
584        }
585        unsafe {
586            let f: Box_<F> = Box_::new(f);
587            connect_raw(
588                self.as_ptr() as *mut _,
589                b"notify::enabled\0".as_ptr() as *const _,
590                Some(transmute::<_, unsafe extern "C" fn()>(
591                    notify_enabled_trampoline::<F> as *const (),
592                )),
593                Box_::into_raw(f),
594            )
595        }
596    }
597
598    pub fn connect_property_n_axes_notify<F: Fn(&InputDevice) + 'static>(
599        &self,
600        f: F,
601    ) -> SignalHandlerId {
602        unsafe extern "C" fn notify_n_axes_trampoline<F: Fn(&InputDevice) + 'static>(
603            this: *mut ffi::ClutterInputDevice,
604            _param_spec: glib_sys::gpointer,
605            f: glib_sys::gpointer,
606        ) {
607            let f: &F = &*(f as *const F);
608            f(&from_glib_borrow(this))
609        }
610        unsafe {
611            let f: Box_<F> = Box_::new(f);
612            connect_raw(
613                self.as_ptr() as *mut _,
614                b"notify::n-axes\0".as_ptr() as *const _,
615                Some(transmute::<_, unsafe extern "C" fn()>(
616                    notify_n_axes_trampoline::<F> as *const (),
617                )),
618                Box_::into_raw(f),
619            )
620        }
621    }
622}
623
624impl fmt::Display for InputDevice {
625    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
626        write!(f, "InputDevice")
627    }
628}