jay_config/
input.rs

1//! Tools for configuring input devices.
2
3pub mod acceleration;
4pub mod capability;
5pub mod clickmethod;
6
7use {
8    crate::{
9        _private::{DEFAULT_SEAT_NAME, ipc::WorkspaceSource},
10        Axis, Direction, ModifiedKeySym, Workspace,
11        input::{acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod},
12        keyboard::{Keymap, mods::Modifiers, syms::KeySym},
13        video::Connector,
14        window::Window,
15    },
16    serde::{Deserialize, Serialize},
17    std::time::Duration,
18};
19
20/// An input device.
21#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
22pub struct InputDevice(pub u64);
23
24impl InputDevice {
25    /// Assigns the input device to a seat.
26    pub fn set_seat(self, seat: Seat) {
27        get!().set_seat(self, seat)
28    }
29
30    /// Sets the keymap of the device.
31    ///
32    /// This overrides the keymap set for the seat. The keymap becomes active when a key
33    /// on the device is pressed.
34    ///
35    /// Setting the invalid keymap reverts to the seat keymap.
36    pub fn set_keymap(self, keymap: Keymap) {
37        get!().set_device_keymap(self, keymap)
38    }
39
40    /// Returns whether the device has the specified capability.
41    pub fn has_capability(self, cap: Capability) -> bool {
42        get!(false).has_capability(self, cap)
43    }
44
45    /// Sets the device to be left handed.
46    ///
47    /// This has the effect of swapping the left and right mouse button. See the libinput
48    /// documentation for more details.
49    pub fn set_left_handed(self, left_handed: bool) {
50        get!().set_left_handed(self, left_handed);
51    }
52
53    /// Sets the acceleration profile of the device.
54    ///
55    /// This corresponds to the libinput setting of the same name.
56    pub fn set_accel_profile(self, profile: AccelProfile) {
57        get!().set_accel_profile(self, profile);
58    }
59
60    /// Sets the acceleration speed of the device.
61    ///
62    /// This corresponds to the libinput setting of the same name.
63    pub fn set_accel_speed(self, speed: f64) {
64        get!().set_accel_speed(self, speed);
65    }
66
67    /// Sets the transformation matrix of the device.
68    ///
69    /// This is not a libinput setting but a setting of the compositor. It currently affects
70    /// relative mouse motions in that the matrix is applied to the motion. To reduce the mouse
71    /// speed to 35%, use the following matrix:
72    ///
73    /// ```text
74    /// [
75    ///     [0.35, 1.0],
76    ///     [1.0, 0.35],
77    /// ]
78    /// ```
79    ///
80    /// This might give you better results than using `set_accel_profile` and `set_accel_speed`.
81    pub fn set_transform_matrix(self, matrix: [[f64; 2]; 2]) {
82        get!().set_transform_matrix(self, matrix);
83    }
84
85    /// Sets the calibration matrix of the device.
86    ///
87    /// This corresponds to the libinput setting of the same name.
88    pub fn set_calibration_matrix(self, matrix: [[f32; 3]; 2]) {
89        get!().set_calibration_matrix(self, matrix);
90    }
91
92    /// Returns the name of the device.
93    pub fn name(self) -> String {
94        get!(String::new()).device_name(self)
95    }
96
97    /// Sets how many pixel to scroll per scroll wheel dedent.
98    ///
99    /// Default: `15.0`
100    ///
101    /// This setting has no effect on non-wheel input such as touchpads.
102    ///
103    /// Some mouse wheels support high-resolution scrolling without discrete steps. In
104    /// this case a value proportional to this setting will be used.
105    pub fn set_px_per_wheel_scroll(self, px: f64) {
106        get!().set_px_per_wheel_scroll(self, px);
107    }
108
109    /// Sets whether tap-to-click is enabled for this device.
110    ///
111    /// See <https://wayland.freedesktop.org/libinput/doc/latest/tapping.html>
112    pub fn set_tap_enabled(self, enabled: bool) {
113        get!().set_input_tap_enabled(self, enabled);
114    }
115
116    /// Sets whether tap-and-drag is enabled for this device.
117    ///
118    /// See <https://wayland.freedesktop.org/libinput/doc/latest/tapping.html>
119    pub fn set_drag_enabled(self, enabled: bool) {
120        get!().set_input_drag_enabled(self, enabled);
121    }
122
123    /// Sets whether drag lock is enabled for this device.
124    ///
125    /// See <https://wayland.freedesktop.org/libinput/doc/latest/tapping.html>
126    pub fn set_drag_lock_enabled(self, enabled: bool) {
127        get!().set_input_drag_lock_enabled(self, enabled);
128    }
129
130    /// Sets whether natural scrolling is enabled for this device.
131    ///
132    /// See <https://wayland.freedesktop.org/libinput/doc/latest/scrolling.html>
133    pub fn set_natural_scrolling_enabled(self, enabled: bool) {
134        get!().set_input_natural_scrolling_enabled(self, enabled);
135    }
136
137    /// Sets the click method of the device.
138    ///
139    /// See <https://wayland.freedesktop.org/libinput/doc/latest/configuration.html#click-method>
140    pub fn set_click_method(self, method: ClickMethod) {
141        get!().set_input_click_method(self, method);
142    }
143
144    /// Sets whether middle button emulation is enabled for this device.
145    ///
146    /// See <https://wayland.freedesktop.org/libinput/doc/latest/configuration.html#middle-button-emulation>
147    pub fn set_middle_button_emulation_enabled(self, enabled: bool) {
148        get!().set_input_middle_button_emulation_enabled(self, enabled);
149    }
150
151    /// Returns the syspath of this device.
152    ///
153    /// E.g. `/sys/devices/pci0000:00/0000:00:08.1/0000:14:00.4/usb5/5-1/5-1.1/5-1.1.3/5-1.1.3:1.0`.
154    pub fn syspath(self) -> String {
155        get!(String::new()).input_device_syspath(self)
156    }
157
158    /// Returns the devnode of this device.
159    ///
160    /// E.g. `/dev/input/event7`.
161    pub fn devnode(self) -> String {
162        get!(String::new()).input_device_devnode(self)
163    }
164
165    /// Sets a callback that will be run if this device triggers a switch event.
166    pub fn on_switch_event<F: FnMut(SwitchEvent) + 'static>(self, f: F) {
167        get!().on_switch_event(self, f)
168    }
169
170    /// Maps this input device to a connector.
171    ///
172    /// The connector should be connected.
173    ///
174    /// This should be used for touch screens and graphics tablets.
175    pub fn set_connector(self, connector: Connector) {
176        get!().set_input_device_connector(self, connector);
177    }
178
179    /// Removes the mapping of this device to a connector.
180    pub fn remove_mapping(self) {
181        get!().remove_input_mapping(self);
182    }
183}
184
185/// A direction in a timeline.
186#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
187pub enum Timeline {
188    Older,
189    Newer,
190}
191
192/// A direction for layer traversal.
193#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
194pub enum LayerDirection {
195    Below,
196    Above,
197}
198
199/// A seat.
200#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
201pub struct Seat(pub u64);
202
203impl Seat {
204    pub const INVALID: Self = Self(0);
205
206    /// Returns whether the seat is invalid.
207    pub fn is_invalid(self) -> bool {
208        self == Self::INVALID
209    }
210
211    #[doc(hidden)]
212    pub fn raw(self) -> u64 {
213        self.0
214    }
215
216    #[doc(hidden)]
217    pub fn from_raw(raw: u64) -> Self {
218        Self(raw)
219    }
220
221    /// Sets whether this seat's cursor uses the hardware cursor if available.
222    ///
223    /// Only one seat at a time can use the hardware cursor. Setting this to `true` for a
224    /// seat automatically unsets it for all other seats.
225    ///
226    /// By default, the first created seat uses the hardware cursor.
227    pub fn use_hardware_cursor(self, use_hardware_cursor: bool) {
228        get!().set_use_hardware_cursor(self, use_hardware_cursor);
229    }
230
231    /// Sets the size of the cursor theme.
232    ///
233    /// Default: 16.
234    pub fn set_cursor_size(self, size: i32) {
235        get!().set_cursor_size(self, size)
236    }
237
238    /// Creates a compositor-wide hotkey.
239    ///
240    /// The closure is invoked when the user presses the last key of the modified keysym.
241    /// Note that the keysym is calculated without modifiers applied. To perform an action
242    /// when `SHIFT+k` is pressed, use `SHIFT | SYM_k` not `SHIFT | SYM_K`.
243    ///
244    /// CapsLock and NumLock are ignored during modifier evaluation. Therefore, bindings
245    /// containing these modifiers will never be invoked.
246    pub fn bind<T: Into<ModifiedKeySym>, F: FnMut() + 'static>(self, mod_sym: T, f: F) {
247        self.bind_masked(Modifiers(!0), mod_sym, f)
248    }
249
250    /// Creates a compositor-wide hotkey while ignoring some modifiers.
251    ///
252    /// This is similar to `bind` except that only the masked modifiers are considered.
253    ///
254    /// For example, if this function is invoked with `mod_mask = Modifiers::NONE` and
255    /// `mod_sym = SYM_XF86AudioRaiseVolume`, then the callback will be invoked whenever
256    /// `SYM_XF86AudioRaiseVolume` is pressed. Even if the user is simultaneously holding
257    /// the shift key which would otherwise prevent the callback from taking effect.
258    ///
259    /// For example, if this function is invoked with `mod_mask = CTRL | SHIFT` and
260    /// `mod_sym = CTRL | SYM_x`, then the callback will be invoked whenever the user
261    /// presses `ctrl+x` without pressing the shift key. Even if the user is
262    /// simultaneously holding the alt key.
263    ///
264    /// If `mod_sym` contains any modifiers, then these modifiers are automatically added
265    /// to the mask. The synthetic `RELEASE` modifier is always added to the mask.
266    pub fn bind_masked<T: Into<ModifiedKeySym>, F: FnMut() + 'static>(
267        self,
268        mod_mask: Modifiers,
269        mod_sym: T,
270        f: F,
271    ) {
272        get!().bind_masked(self, mod_mask, mod_sym.into(), f)
273    }
274
275    /// Registers a callback to be executed when the currently pressed key is released.
276    ///
277    /// This should only be called in callbacks for key-press binds.
278    ///
279    /// The callback will be executed once when the key is released regardless of any
280    /// modifiers.
281    pub fn latch<F: FnOnce() + 'static>(self, f: F) {
282        get!().latch(self, f)
283    }
284
285    /// Unbinds a hotkey.
286    pub fn unbind<T: Into<ModifiedKeySym>>(self, mod_sym: T) {
287        get!().unbind(self, mod_sym.into())
288    }
289
290    /// Moves the focus in the focus history.
291    pub fn focus_history(self, timeline: Timeline) {
292        get!().seat_focus_history(self, timeline)
293    }
294
295    /// Configures whether the focus history only includes visible windows.
296    ///
297    /// If this is `false`, then hidden windows will be made visible before moving the
298    /// focus to them.
299    ///
300    /// The default is `false`.
301    pub fn focus_history_set_only_visible(self, only_visible: bool) {
302        get!().seat_focus_history_set_only_visible(self, only_visible)
303    }
304
305    /// Configures whether the focus history only includes windows on the same workspace
306    /// as the currently focused window.
307    ///
308    /// The default is `false`.
309    pub fn focus_history_set_same_workspace(self, same_workspace: bool) {
310        get!().seat_focus_history_set_same_workspace(self, same_workspace)
311    }
312
313    /// Moves the keyboard focus of the seat to the layer above or below the current
314    /// layer.
315    pub fn focus_layer_rel(self, direction: LayerDirection) {
316        get!().seat_focus_layer_rel(self, direction)
317    }
318
319    /// Moves the keyboard focus to the tile layer.
320    pub fn focus_tiles(self) {
321        get!().seat_focus_tiles(self)
322    }
323
324    /// Moves the keyboard focus of the seat in the specified direction.
325    pub fn focus(self, direction: Direction) {
326        get!().seat_focus(self, direction)
327    }
328
329    /// Moves the focused window in the specified direction.
330    pub fn move_(self, direction: Direction) {
331        get!().seat_move(self, direction)
332    }
333
334    /// Sets the keymap of the seat.
335    pub fn set_keymap(self, keymap: Keymap) {
336        get!().seat_set_keymap(self, keymap)
337    }
338
339    /// Returns the repeat rate of the seat.
340    ///
341    /// The returned tuple is `(rate, delay)` where `rate` is the number of times keys repeat per second
342    /// and `delay` is the time after the button press after which keys start repeating.
343    pub fn repeat_rate(self) -> (i32, i32) {
344        get!((25, 250)).seat_get_repeat_rate(self)
345    }
346
347    /// Sets the repeat rate of the seat.
348    pub fn set_repeat_rate(self, rate: i32, delay: i32) {
349        get!().seat_set_repeat_rate(self, rate, delay)
350    }
351
352    /// Returns whether the parent-container of the currently focused window is in mono-mode.
353    pub fn mono(self) -> bool {
354        get!(false).seat_mono(self)
355    }
356
357    /// Sets whether the parent-container of the currently focused window is in mono-mode.
358    pub fn set_mono(self, mono: bool) {
359        get!().set_seat_mono(self, mono)
360    }
361
362    /// Toggles whether the parent-container of the currently focused window is in mono-mode.
363    pub fn toggle_mono(self) {
364        self.set_mono(!self.mono());
365    }
366
367    /// Returns the split axis of the parent-container of the currently focused window.
368    pub fn split(self) -> Axis {
369        get!(Axis::Horizontal).seat_split(self)
370    }
371
372    /// Sets the split axis of the parent-container of the currently focused window.
373    pub fn set_split(self, axis: Axis) {
374        get!().set_seat_split(self, axis)
375    }
376
377    /// Toggles the split axis of the parent-container of the currently focused window.
378    pub fn toggle_split(self) {
379        self.set_split(self.split().other());
380    }
381
382    /// Returns the input devices assigned to this seat.
383    pub fn input_devices(self) -> Vec<InputDevice> {
384        get!().get_input_devices(Some(self))
385    }
386
387    /// Creates a new container with the specified split in place of the currently focused window.
388    pub fn create_split(self, axis: Axis) {
389        get!().create_seat_split(self, axis);
390    }
391
392    /// Focuses the parent node of the currently focused window.
393    pub fn focus_parent(self) {
394        get!().focus_seat_parent(self);
395    }
396
397    /// Requests the currently focused window to be closed.
398    pub fn close(self) {
399        get!().seat_close(self);
400    }
401
402    /// Returns whether the currently focused window is floating.
403    pub fn get_floating(self) -> bool {
404        get!().get_seat_floating(self)
405    }
406    /// Sets whether the currently focused window is floating.
407    pub fn set_floating(self, floating: bool) {
408        get!().set_seat_floating(self, floating);
409    }
410
411    /// Toggles whether the currently focused window is floating.
412    ///
413    /// You can do the same by double-clicking on the header.
414    pub fn toggle_floating(self) {
415        get!().toggle_seat_floating(self);
416    }
417
418    /// Returns the workspace that is currently active on the output that contains the seat's
419    /// cursor.
420    ///
421    /// If no such workspace exists, `exists` returns `false` for the returned workspace.
422    pub fn get_workspace(self) -> Workspace {
423        get!(Workspace(0)).get_seat_workspace(self)
424    }
425
426    /// Returns the workspace that is currently active on the output that contains the seat's
427    /// keyboard focus.
428    ///
429    /// If no such workspace exists, `exists` returns `false` for the returned workspace.
430    pub fn get_keyboard_workspace(self) -> Workspace {
431        get!(Workspace(0)).get_seat_keyboard_workspace(self)
432    }
433
434    /// Shows the workspace and sets the keyboard focus of the seat to that workspace.
435    ///
436    /// If the workspace doesn't currently exist, it is created on the output that contains the
437    /// seat's cursor.
438    pub fn show_workspace(self, workspace: Workspace) {
439        get!().show_workspace(self, workspace)
440    }
441
442    /// Moves the currently focused window to the workspace.
443    pub fn set_workspace(self, workspace: Workspace) {
444        get!().set_seat_workspace(self, workspace)
445    }
446
447    /// Toggles whether the currently focused window is fullscreen.
448    pub fn toggle_fullscreen(self) {
449        let c = get!();
450        c.set_seat_fullscreen(self, !c.get_seat_fullscreen(self));
451    }
452    /// Returns whether the currently focused window is fullscreen.
453    pub fn fullscreen(self) -> bool {
454        get!(false).get_seat_fullscreen(self)
455    }
456
457    /// Sets whether the currently focused window is fullscreen.
458    pub fn set_fullscreen(self, fullscreen: bool) {
459        get!().set_seat_fullscreen(self, fullscreen)
460    }
461
462    /// Disables the currently active pointer constraint on this seat.
463    pub fn disable_pointer_constraint(self) {
464        get!().disable_pointer_constraint(self)
465    }
466
467    /// Moves the currently focused workspace to another output.
468    pub fn move_to_output(self, connector: Connector) {
469        get!().move_to_output(WorkspaceSource::Seat(self), connector);
470    }
471
472    /// Set whether the current key event is forwarded to the focused client.
473    ///
474    /// This only has an effect if called from a keyboard shortcut.
475    ///
476    /// By default, release events are forwarded and press events are consumed. Note that
477    /// consuming release events can cause clients to get stuck in the pressed state.
478    pub fn set_forward(self, forward: bool) {
479        get!().set_forward(self, forward);
480    }
481
482    /// This is a shorthand for `set_forward(true)`.
483    pub fn forward(self) {
484        self.set_forward(true)
485    }
486
487    /// This is a shorthand for `set_forward(false)`.
488    pub fn consume(self) {
489        self.set_forward(false)
490    }
491
492    /// Sets the focus-follows-mouse mode.
493    pub fn set_focus_follows_mouse_mode(self, mode: FocusFollowsMouseMode) {
494        get!().set_focus_follows_mouse_mode(self, mode);
495    }
496
497    /// Enables or disable window management mode.
498    ///
499    /// In window management mode, floating windows can be moved by pressing the left
500    /// mouse button and all windows can be resize by pressing the right mouse button.
501    pub fn set_window_management_enabled(self, enabled: bool) {
502        get!().set_window_management_enabled(self, enabled);
503    }
504
505    /// Sets a key that enables window management mode while pressed.
506    ///
507    /// This is a shorthand for
508    ///
509    /// ```rust,ignore
510    /// self.bind(mod_sym, move || {
511    ///     self.set_window_management_enabled(true);
512    ///     self.forward();
513    ///     self.latch(move || {
514    ///         self.set_window_management_enabled(false);
515    ///     });
516    /// });
517    /// ```
518    pub fn set_window_management_key<T: Into<ModifiedKeySym>>(self, mod_sym: T) {
519        self.bind(mod_sym, move || {
520            self.set_window_management_enabled(true);
521            self.forward();
522            self.latch(move || {
523                self.set_window_management_enabled(false);
524            });
525        });
526    }
527
528    /// Gets whether the currently focused window is pinned.
529    ///
530    /// If a floating window is pinned, it will stay visible even when switching to a
531    /// different workspace.
532    pub fn float_pinned(self) -> bool {
533        get!().get_pinned(self)
534    }
535
536    /// Sets whether the currently focused window is pinned.
537    pub fn set_float_pinned(self, pinned: bool) {
538        get!().set_pinned(self, pinned);
539    }
540
541    /// Toggles whether the currently focused window is pinned.
542    pub fn toggle_float_pinned(self) {
543        self.set_float_pinned(!self.float_pinned());
544    }
545
546    /// Returns the focused window.
547    ///
548    /// If no window is focused, [`Window::exists`] returns false.
549    pub fn window(self) -> Window {
550        get!(Window(0)).get_seat_keyboard_window(self)
551    }
552
553    /// Puts the keyboard focus on the window.
554    ///
555    /// This has no effect if the window is not visible.
556    pub fn focus_window(self, window: Window) {
557        get!().focus_window(self, window)
558    }
559
560    /// Sets the key that can be used to revert the pointer to the default state.
561    ///
562    /// Pressing this key cancels any grabs, drags, selections, etc.
563    ///
564    /// The default is `SYM_Escape`. Setting this to `SYM_NoSymbol` effectively disables
565    /// this functionality.
566    pub fn set_pointer_revert_key(self, sym: KeySym) {
567        get!().set_pointer_revert_key(self, sym);
568    }
569
570    /// Creates a mark for the currently focused window.
571    ///
572    /// `kc` should be an evdev keycode. If `kc` is none, then the keycode will be
573    /// inferred from the next key press. Pressing escape during this interactive
574    /// selection aborts the process.
575    ///
576    /// Currently very few `u32` are valid keycodes. Large numbers can therefore be used
577    /// to create marks that do not correspond to a key. However, `kc` should always be
578    /// less than `u32::MAX - 8`.
579    pub fn create_mark(self, kc: Option<u32>) {
580        get!().seat_create_mark(self, kc);
581    }
582
583    /// Moves the keyboard focus to a window identified by a mark.
584    ///
585    /// See [`Seat::create_mark`] for information about the `kc` parameter.
586    pub fn jump_to_mark(self, kc: Option<u32>) {
587        get!().seat_jump_to_mark(self, kc);
588    }
589
590    /// Copies a mark from one keycode to another.
591    ///
592    /// If the `src` keycode identifies a mark before this function is called, the `dst`
593    /// keycode will identify the same mark afterwards.
594    pub fn copy_mark(self, src: u32, dst: u32) {
595        get!().seat_copy_mark(self, src, dst);
596    }
597}
598
599/// A focus-follows-mouse mode.
600#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
601pub enum FocusFollowsMouseMode {
602    /// When the mouse moves and enters a toplevel, that toplevel gets the keyboard focus.
603    True,
604    /// The keyboard focus changes only when clicking on a window or the previously
605    /// focused window becomes invisible.
606    False,
607}
608
609/// Returns all seats.
610pub fn get_seats() -> Vec<Seat> {
611    get!().seats()
612}
613
614/// Returns all input devices.
615pub fn input_devices() -> Vec<InputDevice> {
616    get!().get_input_devices(None)
617}
618
619/// Returns or creates a seat.
620///
621/// Seats are identified by their name. If no seat with the name exists, a new seat will be created.
622///
623/// NOTE: You should prefer [`get_default_seat`] instead. Most applications cannot handle more than
624/// one seat and will only process input from one of the seats.
625pub fn get_seat(name: &str) -> Seat {
626    get!(Seat(0)).get_seat(name)
627}
628
629/// Returns or creates the default seat.
630///
631/// This is equivalent to `get_seat("default")`.
632pub fn get_default_seat() -> Seat {
633    get_seat(DEFAULT_SEAT_NAME)
634}
635
636/// Sets a closure to run when a new seat has been created.
637pub fn on_new_seat<F: FnMut(Seat) + 'static>(f: F) {
638    get!().on_new_seat(f)
639}
640
641/// Sets a closure to run when a new input device has been added.
642pub fn on_new_input_device<F: FnMut(InputDevice) + 'static>(f: F) {
643    get!().on_new_input_device(f)
644}
645
646/// Sets a closure to run when an input device has been removed.
647pub fn on_input_device_removed<F: FnMut(InputDevice) + 'static>(f: F) {
648    get!().on_input_device_removed(f)
649}
650
651/// Sets the maximum time between two clicks to be registered as a double click by the
652/// compositor.
653///
654/// This only affects interactions with the compositor UI and has no effect on
655/// applications.
656///
657/// The default is 400 ms.
658pub fn set_double_click_time(duration: Duration) {
659    let usec = duration.as_micros().min(u64::MAX as u128);
660    get!().set_double_click_interval(usec as u64)
661}
662
663/// Sets the maximum distance between two clicks to be registered as a double click by the
664/// compositor.
665///
666/// This only affects interactions with the compositor UI and has no effect on
667/// applications.
668///
669/// Setting a negative distance disables double clicks.
670///
671/// The default is 5.
672pub fn set_double_click_distance(distance: i32) {
673    get!().set_double_click_distance(distance)
674}
675
676/// Disables the creation of a default seat.
677///
678/// Unless this function is called at startup of the compositor, a seat called `default`
679/// will automatically be created.
680///
681/// When a new input device is attached and a seat called `default` exists, the input
682/// device is initially attached to this seat.
683pub fn disable_default_seat() {
684    get!().disable_default_seat();
685}
686
687/// An event generated by a switch.
688#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
689pub enum SwitchEvent {
690    /// The lid of the device (usually a laptop) has been opened.
691    ///
692    /// This is the default state.
693    LidOpened,
694    /// The lid of the device (usually a laptop) has been closed.
695    ///
696    /// If the device is already in this state when the device is discovered, a synthetic
697    /// event of this kind is generated.
698    LidClosed,
699    /// The device has been converted from tablet to laptop mode.
700    ///
701    /// This is the default state.
702    ConvertedToLaptop,
703    /// The device has been converted from laptop to tablet mode.
704    ///
705    /// If the device is already in this state when the device is discovered, a synthetic
706    /// event of this kind is generated.
707    ConvertedToTablet,
708}
709
710/// Enables or disables the unauthenticated libei socket.
711///
712/// Even if the socket is disabled, application can still request access via the portal.
713///
714/// The default is `false`.
715pub fn set_libei_socket_enabled(enabled: bool) {
716    get!().set_ei_socket_enabled(enabled);
717}