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