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 a multiplier for pixel scroll events.
110 ///
111 /// Default: `1.0`
112 ///
113 /// This setting has no effect on scroll events created by a scroll wheel.
114 pub fn set_px_scroll_multiplier(self, mul: f64) {
115 get!().set_px_scroll_multiplier(self, mul);
116 }
117
118 /// Sets whether tap-to-click is enabled for this device.
119 ///
120 /// See <https://wayland.freedesktop.org/libinput/doc/latest/tapping.html>
121 pub fn set_tap_enabled(self, enabled: bool) {
122 get!().set_input_tap_enabled(self, enabled);
123 }
124
125 /// Sets whether tap-and-drag is enabled for this device.
126 ///
127 /// See <https://wayland.freedesktop.org/libinput/doc/latest/tapping.html>
128 pub fn set_drag_enabled(self, enabled: bool) {
129 get!().set_input_drag_enabled(self, enabled);
130 }
131
132 /// Sets whether drag lock is enabled for this device.
133 ///
134 /// See <https://wayland.freedesktop.org/libinput/doc/latest/tapping.html>
135 pub fn set_drag_lock_enabled(self, enabled: bool) {
136 get!().set_input_drag_lock_enabled(self, enabled);
137 }
138
139 /// Sets whether natural scrolling is enabled for this device.
140 ///
141 /// See <https://wayland.freedesktop.org/libinput/doc/latest/scrolling.html>
142 pub fn set_natural_scrolling_enabled(self, enabled: bool) {
143 get!().set_input_natural_scrolling_enabled(self, enabled);
144 }
145
146 /// Sets the click method of the device.
147 ///
148 /// See <https://wayland.freedesktop.org/libinput/doc/latest/configuration.html#click-method>
149 pub fn set_click_method(self, method: ClickMethod) {
150 get!().set_input_click_method(self, method);
151 }
152
153 /// Sets whether middle button emulation is enabled for this device.
154 ///
155 /// See <https://wayland.freedesktop.org/libinput/doc/latest/configuration.html#middle-button-emulation>
156 pub fn set_middle_button_emulation_enabled(self, enabled: bool) {
157 get!().set_input_middle_button_emulation_enabled(self, enabled);
158 }
159
160 /// Returns the syspath of this device.
161 ///
162 /// 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`.
163 pub fn syspath(self) -> String {
164 get!(String::new()).input_device_syspath(self)
165 }
166
167 /// Returns the devnode of this device.
168 ///
169 /// E.g. `/dev/input/event7`.
170 pub fn devnode(self) -> String {
171 get!(String::new()).input_device_devnode(self)
172 }
173
174 /// Sets a callback that will be run if this device triggers a switch event.
175 pub fn on_switch_event<F: FnMut(SwitchEvent) + 'static>(self, f: F) {
176 get!().on_switch_event(self, f)
177 }
178
179 /// Maps this input device to a connector.
180 ///
181 /// The connector should be connected.
182 ///
183 /// This should be used for touch screens and graphics tablets.
184 pub fn set_connector(self, connector: Connector) {
185 get!().set_input_device_connector(self, connector);
186 }
187
188 /// Removes the mapping of this device to a connector.
189 pub fn remove_mapping(self) {
190 get!().remove_input_mapping(self);
191 }
192}
193
194/// A direction in a timeline.
195#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
196pub enum Timeline {
197 Older,
198 Newer,
199}
200
201/// A direction for layer traversal.
202#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
203pub enum LayerDirection {
204 Below,
205 Above,
206}
207
208/// A seat.
209#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
210pub struct Seat(pub u64);
211
212impl Seat {
213 pub const INVALID: Self = Self(0);
214
215 /// Returns whether the seat is invalid.
216 pub fn is_invalid(self) -> bool {
217 self == Self::INVALID
218 }
219
220 #[doc(hidden)]
221 pub fn raw(self) -> u64 {
222 self.0
223 }
224
225 #[doc(hidden)]
226 pub fn from_raw(raw: u64) -> Self {
227 Self(raw)
228 }
229
230 /// Sets whether this seat's cursor uses the hardware cursor if available.
231 ///
232 /// Only one seat at a time can use the hardware cursor. Setting this to `true` for a
233 /// seat automatically unsets it for all other seats.
234 ///
235 /// By default, the first created seat uses the hardware cursor.
236 pub fn use_hardware_cursor(self, use_hardware_cursor: bool) {
237 get!().set_use_hardware_cursor(self, use_hardware_cursor);
238 }
239
240 /// Sets the size of the cursor theme.
241 ///
242 /// Default: 16.
243 pub fn set_cursor_size(self, size: i32) {
244 get!().set_cursor_size(self, size)
245 }
246
247 /// Creates a compositor-wide hotkey.
248 ///
249 /// The closure is invoked when the user presses the last key of the modified keysym.
250 /// Note that the keysym is calculated without modifiers applied. To perform an action
251 /// when `SHIFT+k` is pressed, use `SHIFT | SYM_k` not `SHIFT | SYM_K`.
252 ///
253 /// CapsLock and NumLock are ignored during modifier evaluation. Therefore, bindings
254 /// containing these modifiers will never be invoked.
255 pub fn bind<T: Into<ModifiedKeySym>, F: FnMut() + 'static>(self, mod_sym: T, f: F) {
256 self.bind_masked(Modifiers(!0), mod_sym, f)
257 }
258
259 /// Creates a compositor-wide hotkey while ignoring some modifiers.
260 ///
261 /// This is similar to `bind` except that only the masked modifiers are considered.
262 ///
263 /// For example, if this function is invoked with `mod_mask = Modifiers::NONE` and
264 /// `mod_sym = SYM_XF86AudioRaiseVolume`, then the callback will be invoked whenever
265 /// `SYM_XF86AudioRaiseVolume` is pressed. Even if the user is simultaneously holding
266 /// the shift key which would otherwise prevent the callback from taking effect.
267 ///
268 /// For example, if this function is invoked with `mod_mask = CTRL | SHIFT` and
269 /// `mod_sym = CTRL | SYM_x`, then the callback will be invoked whenever the user
270 /// presses `ctrl+x` without pressing the shift key. Even if the user is
271 /// simultaneously holding the alt key.
272 ///
273 /// If `mod_sym` contains any modifiers, then these modifiers are automatically added
274 /// to the mask. The synthetic `RELEASE` modifier is always added to the mask.
275 pub fn bind_masked<T: Into<ModifiedKeySym>, F: FnMut() + 'static>(
276 self,
277 mod_mask: Modifiers,
278 mod_sym: T,
279 f: F,
280 ) {
281 get!().bind_masked(self, mod_mask, mod_sym.into(), f)
282 }
283
284 /// Registers a callback to be executed when the currently pressed key is released.
285 ///
286 /// This should only be called in callbacks for key-press binds.
287 ///
288 /// The callback will be executed once when the key is released regardless of any
289 /// modifiers.
290 pub fn latch<F: FnOnce() + 'static>(self, f: F) {
291 get!().latch(self, f)
292 }
293
294 /// Unbinds a hotkey.
295 pub fn unbind<T: Into<ModifiedKeySym>>(self, mod_sym: T) {
296 get!().unbind(self, mod_sym.into())
297 }
298
299 /// Moves the focus in the focus history.
300 pub fn focus_history(self, timeline: Timeline) {
301 get!().seat_focus_history(self, timeline)
302 }
303
304 /// Configures whether the focus history only includes visible windows.
305 ///
306 /// If this is `false`, then hidden windows will be made visible before moving the
307 /// focus to them.
308 ///
309 /// The default is `false`.
310 pub fn focus_history_set_only_visible(self, only_visible: bool) {
311 get!().seat_focus_history_set_only_visible(self, only_visible)
312 }
313
314 /// Configures whether the focus history only includes windows on the same workspace
315 /// as the currently focused window.
316 ///
317 /// The default is `false`.
318 pub fn focus_history_set_same_workspace(self, same_workspace: bool) {
319 get!().seat_focus_history_set_same_workspace(self, same_workspace)
320 }
321
322 /// Moves the keyboard focus of the seat to the layer above or below the current
323 /// layer.
324 pub fn focus_layer_rel(self, direction: LayerDirection) {
325 get!().seat_focus_layer_rel(self, direction)
326 }
327
328 /// Moves the keyboard focus to the tile layer.
329 pub fn focus_tiles(self) {
330 get!().seat_focus_tiles(self)
331 }
332
333 /// Moves the keyboard focus of the seat in the specified direction.
334 pub fn focus(self, direction: Direction) {
335 get!().seat_focus(self, direction)
336 }
337
338 /// Moves the focused window in the specified direction.
339 pub fn move_(self, direction: Direction) {
340 get!().seat_move(self, direction)
341 }
342
343 /// Sets the keymap of the seat.
344 pub fn set_keymap(self, keymap: Keymap) {
345 get!().seat_set_keymap(self, keymap)
346 }
347
348 /// Returns the repeat rate of the seat.
349 ///
350 /// The returned tuple is `(rate, delay)` where `rate` is the number of times keys repeat per second
351 /// and `delay` is the time after the button press after which keys start repeating.
352 pub fn repeat_rate(self) -> (i32, i32) {
353 get!((25, 250)).seat_get_repeat_rate(self)
354 }
355
356 /// Sets the repeat rate of the seat.
357 pub fn set_repeat_rate(self, rate: i32, delay: i32) {
358 get!().seat_set_repeat_rate(self, rate, delay)
359 }
360
361 /// Returns whether the parent-container of the currently focused window is in mono-mode.
362 pub fn mono(self) -> bool {
363 get!(false).seat_mono(self)
364 }
365
366 /// Sets whether the parent-container of the currently focused window is in mono-mode.
367 pub fn set_mono(self, mono: bool) {
368 get!().set_seat_mono(self, mono)
369 }
370
371 /// Toggles whether the parent-container of the currently focused window is in mono-mode.
372 pub fn toggle_mono(self) {
373 self.set_mono(!self.mono());
374 }
375
376 /// Returns the split axis of the parent-container of the currently focused window.
377 pub fn split(self) -> Axis {
378 get!(Axis::Horizontal).seat_split(self)
379 }
380
381 /// Sets the split axis of the parent-container of the currently focused window.
382 pub fn set_split(self, axis: Axis) {
383 get!().set_seat_split(self, axis)
384 }
385
386 /// Toggles the split axis of the parent-container of the currently focused window.
387 pub fn toggle_split(self) {
388 self.set_split(self.split().other());
389 }
390
391 /// Returns the input devices assigned to this seat.
392 pub fn input_devices(self) -> Vec<InputDevice> {
393 get!().get_input_devices(Some(self))
394 }
395
396 /// Creates a new container with the specified split in place of the currently focused window.
397 pub fn create_split(self, axis: Axis) {
398 get!().create_seat_split(self, axis);
399 }
400
401 /// Focuses the parent node of the currently focused window.
402 pub fn focus_parent(self) {
403 get!().focus_seat_parent(self);
404 }
405
406 /// Requests the currently focused window to be closed.
407 pub fn close(self) {
408 get!().seat_close(self);
409 }
410
411 /// Returns whether the currently focused window is floating.
412 pub fn get_floating(self) -> bool {
413 get!().get_seat_floating(self)
414 }
415 /// Sets whether the currently focused window is floating.
416 pub fn set_floating(self, floating: bool) {
417 get!().set_seat_floating(self, floating);
418 }
419
420 /// Toggles whether the currently focused window is floating.
421 ///
422 /// You can do the same by double-clicking on the header.
423 pub fn toggle_floating(self) {
424 get!().toggle_seat_floating(self);
425 }
426
427 /// Returns the workspace that is currently active on the output that contains the seat's
428 /// cursor.
429 ///
430 /// If no such workspace exists, `exists` returns `false` for the returned workspace.
431 pub fn get_workspace(self) -> Workspace {
432 get!(Workspace(0)).get_seat_cursor_workspace(self)
433 }
434
435 /// Returns the workspace that is currently active on the output that contains the seat's
436 /// keyboard focus.
437 ///
438 /// If no such workspace exists, `exists` returns `false` for the returned workspace.
439 pub fn get_keyboard_workspace(self) -> Workspace {
440 get!(Workspace(0)).get_seat_keyboard_workspace(self)
441 }
442
443 /// Shows the workspace and sets the keyboard focus of the seat to that workspace.
444 ///
445 /// If the workspace doesn't currently exist, it is created on the output that contains the
446 /// seat's cursor.
447 ///
448 /// See also [`Workspace::show`].
449 pub fn show_workspace(self, workspace: Workspace) {
450 get!().show_workspace(self, workspace)
451 }
452
453 /// Shows the workspace and sets the keyboard focus of the seat to that workspace.
454 ///
455 /// If the workspace doesn't currently exist and the connector is connected, the
456 /// workspace is created on the given connector. If the connector is not connected,
457 /// the workspace is created on the output that contains the seat's cursor.
458 ///
459 /// See also [`Workspace::show`].
460 pub fn show_workspace_on(self, workspace: Workspace, connector: Connector) {
461 get!().show_workspace_on(self, workspace, connector)
462 }
463
464 /// Moves the currently focused window to the workspace.
465 pub fn set_workspace(self, workspace: Workspace) {
466 get!().set_seat_workspace(self, workspace)
467 }
468
469 /// Toggles whether the currently focused window is fullscreen.
470 pub fn toggle_fullscreen(self) {
471 let c = get!();
472 c.set_seat_fullscreen(self, !c.get_seat_fullscreen(self));
473 }
474 /// Returns whether the currently focused window is fullscreen.
475 pub fn fullscreen(self) -> bool {
476 get!(false).get_seat_fullscreen(self)
477 }
478
479 /// Sets whether the currently focused window is fullscreen.
480 pub fn set_fullscreen(self, fullscreen: bool) {
481 get!().set_seat_fullscreen(self, fullscreen)
482 }
483
484 /// Disables the currently active pointer constraint on this seat.
485 pub fn disable_pointer_constraint(self) {
486 get!().disable_pointer_constraint(self)
487 }
488
489 /// Moves the currently focused workspace to another output.
490 pub fn move_to_output(self, connector: Connector) {
491 get!().move_to_output(WorkspaceSource::Seat(self), connector);
492 }
493
494 /// Set whether the current key event is forwarded to the focused client.
495 ///
496 /// This only has an effect if called from a keyboard shortcut.
497 ///
498 /// By default, release events are forwarded and press events are consumed. Note that
499 /// consuming release events can cause clients to get stuck in the pressed state.
500 pub fn set_forward(self, forward: bool) {
501 get!().set_forward(self, forward);
502 }
503
504 /// This is a shorthand for `set_forward(true)`.
505 pub fn forward(self) {
506 self.set_forward(true)
507 }
508
509 /// This is a shorthand for `set_forward(false)`.
510 pub fn consume(self) {
511 self.set_forward(false)
512 }
513
514 /// Sets the focus-follows-mouse mode.
515 pub fn set_focus_follows_mouse_mode(self, mode: FocusFollowsMouseMode) {
516 get!().set_focus_follows_mouse_mode(self, mode);
517 }
518
519 /// Sets the fallback output mode.
520 ///
521 /// The default is `Cursor`.
522 pub fn set_fallback_output_mode(self, mode: FallbackOutputMode) {
523 get!().set_fallback_output_mode(self, mode);
524 }
525
526 /// Enables or disable window management mode.
527 ///
528 /// In window management mode, floating windows can be moved by pressing the left
529 /// mouse button and all windows can be resize by pressing the right mouse button.
530 pub fn set_window_management_enabled(self, enabled: bool) {
531 get!().set_window_management_enabled(self, enabled);
532 }
533
534 /// Sets a key that enables window management mode while pressed.
535 ///
536 /// This is a shorthand for
537 ///
538 /// ```rust,ignore
539 /// self.bind(mod_sym, move || {
540 /// self.set_window_management_enabled(true);
541 /// self.forward();
542 /// self.latch(move || {
543 /// self.set_window_management_enabled(false);
544 /// });
545 /// });
546 /// ```
547 pub fn set_window_management_key<T: Into<ModifiedKeySym>>(self, mod_sym: T) {
548 self.bind(mod_sym, move || {
549 self.set_window_management_enabled(true);
550 self.forward();
551 self.latch(move || {
552 self.set_window_management_enabled(false);
553 });
554 });
555 }
556
557 /// Gets whether the currently focused window is pinned.
558 ///
559 /// If a floating window is pinned, it will stay visible even when switching to a
560 /// different workspace.
561 pub fn float_pinned(self) -> bool {
562 get!().get_pinned(self)
563 }
564
565 /// Sets whether the currently focused window is pinned.
566 pub fn set_float_pinned(self, pinned: bool) {
567 get!().set_pinned(self, pinned);
568 }
569
570 /// Toggles whether the currently focused window is pinned.
571 pub fn toggle_float_pinned(self) {
572 self.set_float_pinned(!self.float_pinned());
573 }
574
575 /// Returns the focused window.
576 ///
577 /// If no window is focused, [`Window::exists`] returns false.
578 pub fn window(self) -> Window {
579 get!(Window(0)).get_seat_keyboard_window(self)
580 }
581
582 /// Puts the keyboard focus on the window.
583 ///
584 /// This has no effect if the window is not visible.
585 pub fn focus_window(self, window: Window) {
586 get!().focus_window(self, window)
587 }
588
589 /// Sets the key that can be used to revert the pointer to the default state.
590 ///
591 /// Pressing this key cancels any grabs, drags, selections, etc.
592 ///
593 /// The default is `SYM_Escape`. Setting this to `SYM_NoSymbol` effectively disables
594 /// this functionality.
595 pub fn set_pointer_revert_key(self, sym: KeySym) {
596 get!().set_pointer_revert_key(self, sym);
597 }
598
599 /// Creates a mark for the currently focused window.
600 ///
601 /// `kc` should be an evdev keycode. If `kc` is none, then the keycode will be
602 /// inferred from the next key press. Pressing escape during this interactive
603 /// selection aborts the process.
604 ///
605 /// Currently very few `u32` are valid keycodes. Large numbers can therefore be used
606 /// to create marks that do not correspond to a key. However, `kc` should always be
607 /// less than `u32::MAX - 8`.
608 pub fn create_mark(self, kc: Option<u32>) {
609 get!().seat_create_mark(self, kc);
610 }
611
612 /// Moves the keyboard focus to a window identified by a mark.
613 ///
614 /// See [`Seat::create_mark`] for information about the `kc` parameter.
615 pub fn jump_to_mark(self, kc: Option<u32>) {
616 get!().seat_jump_to_mark(self, kc);
617 }
618
619 /// Copies a mark from one keycode to another.
620 ///
621 /// If the `src` keycode identifies a mark before this function is called, the `dst`
622 /// keycode will identify the same mark afterwards.
623 pub fn copy_mark(self, src: u32, dst: u32) {
624 get!().seat_copy_mark(self, src, dst);
625 }
626
627 /// Sets whether the simple, XCompose based input method is enabled.
628 ///
629 /// Regardless of this setting, this input method is not used if an external input
630 /// method is running.
631 ///
632 /// The default is `true`.
633 pub fn set_simple_im_enabled(self, enabled: bool) {
634 get!().seat_set_simple_im_enabled(self, enabled);
635 }
636
637 /// Returns whether the simple, XCompose based input method is enabled.
638 pub fn simple_im_enabled(self) -> bool {
639 get!(true).seat_get_simple_im_enabled(self)
640 }
641
642 /// Toggles whether the simple, XCompose based input method is enabled.
643 pub fn toggle_simple_im_enabled(self) {
644 let get = get!();
645 get.seat_set_simple_im_enabled(self, !get.seat_get_simple_im_enabled(self));
646 }
647
648 /// Reloads the simple, XCompose based input method.
649 ///
650 /// This is useful if you change the XCompose files after starting the compositor.
651 pub fn reload_simple_im(self) {
652 get!().seat_reload_simple_im(self);
653 }
654
655 /// Enables Unicode input in the simple, XCompose based input method.
656 ///
657 /// This has no effect if the simple IM is not currently active.
658 pub fn enable_unicode_input(self) {
659 get!().seat_enable_unicode_input(self);
660 }
661
662 /// Warps the cursor to the center of the currently focused window.
663 pub fn warp_mouse_to_focus(self) {
664 get!().seat_warp_mouse_to_focus(self)
665 }
666
667 /// Resizes the focused window.
668 pub fn resize(self, dx1: i32, dy1: i32, dx2: i32, dy2: i32) {
669 self.window().resize(dx1, dy1, dx2, dy2);
670 }
671
672 /// Sets whether the cursor should automatically move to the center of a window
673 /// when focus changes via keyboard commands (move-left, focus-right, show-workspace, etc.).
674 ///
675 /// The default is `false`.
676 #[deprecated = "This setting is unstable and might be removed in the future"]
677 pub fn unstable_set_mouse_follows_focus(self, enabled: bool) {
678 get!().seat_set_mouse_follows_focus(self, enabled)
679 }
680
681 /// Returns the output that contains the seat's cursor.
682 ///
683 /// If no such connector exists, `exists` returns `false` for the returned connector.
684 pub fn get_cursor_connector(self) -> Connector {
685 get!(Connector(0)).get_seat_cursor_connector(self)
686 }
687
688 /// Returns the output that contains the seat's keyboard focus.
689 ///
690 /// If no such connector exists, `exists` returns `false` for the returned connector.
691 pub fn get_keyboard_connector(self) -> Connector {
692 get!(Connector(0)).get_seat_keyboard_connector(self)
693 }
694}
695
696/// A focus-follows-mouse mode.
697#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
698pub enum FocusFollowsMouseMode {
699 /// When the mouse moves and enters a toplevel, that toplevel gets the keyboard focus.
700 True,
701 /// The keyboard focus changes only when clicking on a window or the previously
702 /// focused window becomes invisible.
703 False,
704}
705
706/// Defines which output is used when no particular output is specified.
707///
708/// This configures where to place a newly opened window or workspace, what window to focus when a
709/// window is closed, which workspace is moved with [`Seat::move_to_output`], and similar actions.
710#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
711#[non_exhaustive]
712pub enum FallbackOutputMode {
713 /// Use the output the cursor is on.
714 Cursor,
715 /// Use the output the focus is on (highlighted window).
716 Focus,
717}
718
719/// Returns all seats.
720pub fn get_seats() -> Vec<Seat> {
721 get!().seats()
722}
723
724/// Returns all input devices.
725pub fn input_devices() -> Vec<InputDevice> {
726 get!().get_input_devices(None)
727}
728
729/// Returns or creates a seat.
730///
731/// Seats are identified by their name. If no seat with the name exists, a new seat will be created.
732///
733/// NOTE: You should prefer [`get_default_seat`] instead. Most applications cannot handle more than
734/// one seat and will only process input from one of the seats.
735pub fn get_seat(name: &str) -> Seat {
736 get!(Seat(0)).get_seat(name)
737}
738
739/// Returns or creates the default seat.
740///
741/// This is equivalent to `get_seat("default")`.
742pub fn get_default_seat() -> Seat {
743 get_seat(DEFAULT_SEAT_NAME)
744}
745
746/// Sets a closure to run when a new seat has been created.
747pub fn on_new_seat<F: FnMut(Seat) + 'static>(f: F) {
748 get!().on_new_seat(f)
749}
750
751/// Sets a closure to run when a new input device has been added.
752pub fn on_new_input_device<F: FnMut(InputDevice) + 'static>(f: F) {
753 get!().on_new_input_device(f)
754}
755
756/// Sets a closure to run when an input device has been removed.
757pub fn on_input_device_removed<F: FnMut(InputDevice) + 'static>(f: F) {
758 get!().on_input_device_removed(f)
759}
760
761/// Sets the maximum time between two clicks to be registered as a double click by the
762/// compositor.
763///
764/// This only affects interactions with the compositor UI and has no effect on
765/// applications.
766///
767/// The default is 400 ms.
768pub fn set_double_click_time(duration: Duration) {
769 let usec = duration.as_micros().min(u64::MAX as u128);
770 get!().set_double_click_interval(usec as u64)
771}
772
773/// Sets the maximum distance between two clicks to be registered as a double click by the
774/// compositor.
775///
776/// This only affects interactions with the compositor UI and has no effect on
777/// applications.
778///
779/// Setting a negative distance disables double clicks.
780///
781/// The default is 5.
782pub fn set_double_click_distance(distance: i32) {
783 get!().set_double_click_distance(distance)
784}
785
786/// Disables the creation of a default seat.
787///
788/// Unless this function is called at startup of the compositor, a seat called `default`
789/// will automatically be created.
790///
791/// When a new input device is attached and a seat called `default` exists, the input
792/// device is initially attached to this seat.
793pub fn disable_default_seat() {
794 get!().disable_default_seat();
795}
796
797/// An event generated by a switch.
798#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
799pub enum SwitchEvent {
800 /// The lid of the device (usually a laptop) has been opened.
801 ///
802 /// This is the default state.
803 LidOpened,
804 /// The lid of the device (usually a laptop) has been closed.
805 ///
806 /// If the device is already in this state when the device is discovered, a synthetic
807 /// event of this kind is generated.
808 LidClosed,
809 /// The device has been converted from tablet to laptop mode.
810 ///
811 /// This is the default state.
812 ConvertedToLaptop,
813 /// The device has been converted from laptop to tablet mode.
814 ///
815 /// If the device is already in this state when the device is discovered, a synthetic
816 /// event of this kind is generated.
817 ConvertedToTablet,
818}
819
820/// Enables or disables the unauthenticated libei socket.
821///
822/// Even if the socket is disabled, application can still request access via the portal.
823///
824/// The default is `false`.
825pub fn set_libei_socket_enabled(enabled: bool) {
826 get!().set_ei_socket_enabled(enabled);
827}