srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/udev.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/wayland/src/udev.rs')
-rw-r--r--crates/wayland/src/udev.rs44
1 files changed, 41 insertions, 3 deletions
diff --git a/crates/wayland/src/udev.rs b/crates/wayland/src/udev.rs
index aca4865..30517f8 100644
--- a/crates/wayland/src/udev.rs
+++ b/crates/wayland/src/udev.rs
@@ -159,6 +159,9 @@ impl CompState {
// Drained before the `&mut self.udev` borrow below, so screencopy can
// be serviced with the renderer that borrow owns.
let mut captures = std::mem::take(&mut self.screencopy_pending);
+ // Same reason: the cursor needs the renderer that borrow owns.
+ let cursor_status = self.cursor_status.clone();
+ let cursor_buffer = self.cursor_buffer.clone();
// Which heads are eligible, and what each needs, gathered before the
// mutable borrow of `self.udev`.
@@ -196,6 +199,19 @@ impl CompState {
let mut custom_elements: Vec<MemoryRenderBufferRenderElement<PixmanRenderer>> = Vec::new();
if !locked {
+ // Cursor first: `render_output` draws custom elements
+ // front-to-back, so the earliest element is topmost. On a
+ // bare TTY nothing else draws a pointer - see `cursor.rs`.
+ let pointer_pos = udev.pointer_pos;
+ let hsize = udev.heads[index].size;
+ custom_elements.extend(crate::cursor::render_elements(
+ &cursor_status,
+ &cursor_buffer,
+ &mut udev.renderer,
+ pointer_pos,
+ origin,
+ hsize,
+ ));
for (geom, deco) in &decorations {
let pos = ((geom.x - origin.x) as f64, (geom.y - origin.y) as f64);
match MemoryRenderBufferRenderElement::from_buffer(&mut udev.renderer, pos, deco, None, None, None, Kind::Unspecified) {
@@ -538,6 +554,8 @@ impl UdevPlatform {
_screencopy_state: crate::screencopy::ScreencopyState::new::<CompState>(&display_handle),
screencopy_pending: Vec::new(),
lock: Default::default(),
+ cursor_status: smithay::input::pointer::CursorImageStatus::default_named(),
+ cursor_buffer: crate::cursor::make_buffer(),
wm: wm.clone(),
surface_to_id: HashMap::new(),
id_to_window: HashMap::new(),
@@ -832,10 +850,30 @@ fn handle_libinput_event(state: &mut CompState, event: InputEvent<LibinputInputB
let pressed = event.state() == BackendButtonState::Pressed;
handle_pointer_button(state, pos, button, pressed, event.time_msec());
}
+ // Laptop lid. libinput reports this as a switch toggle; without
+ // handling it, closing the lid does nothing at all - no lock, no
+ // suspend - which is a genuine problem on a laptop rather than a
+ // missing nicety.
+ InputEvent::SwitchToggle { event } => {
+ // Fully qualified: libinput's own `Switch` is also in scope here.
+ use smithay::backend::input::{SwitchState, SwitchToggleEvent};
+ if matches!(event.switch(), Some(smithay::reexports::input::event::switch::Switch::Lid)) {
+ let closed = event.state() == SwitchState::On;
+ log::info!("lid {}", if closed { "closed" } else { "opened" });
+ state.pending.borrow_mut().push(CoreEvent::LidSwitch { closed });
+ }
+ }
InputEvent::PointerAxis { event } => {
- // Scroll: forwarded to the focused client via the pointer axis
- // frame, no WM-level handling (matches the winit backend, which
- // doesn't handle scroll either).
+ // Modifier+scroll switches workspace instead of reaching the
+ // client - the `bind = SUPER, mouse_down/up, workspace, e+1/e-1`
+ // gesture. Checked first so the client never sees these events;
+ // forwarding them too would scroll the window under the cursor
+ // as a side effect of changing workspace.
+ if crate::input::handle_workspace_scroll(state, &event) {
+ return;
+ }
+ // Otherwise: forwarded to the focused client via the pointer axis
+ // frame, no WM-level handling.
let Some(pointer) = state.seat.get_pointer() else { return };
let source = event.source();
let mut frame = AxisFrame::new(event.time_msec()).source(source);