From dd31bf5ac2a692617d478478d36c733586b93cf8 Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Tue, 14 May 2024 00:42:00 +0200 Subject: Draw a cursor, handle the lid, and everything a real config needs Groundwork for actually daily-driving this: porting the user's Hyprland config exposed what srdwm couldn't yet express, and testing on a bare TTY exposed something worse. A visible mouse cursor. Nothing drew a pointer at all - on a bare TTY the mouse was simply invisible. It hid because the nested backend runs inside another compositor, which draws a cursor over srdwm's window; only the DRM backend, i.e. the actual session path, was affected. A built-in arrow is now composited above everything on the output the pointer is on. It's a reviewable ASCII bitmap rather than an XCursor theme: a cursor that is always present beats a prettier one that sometimes isn't, the same reasoning as decoration.rs's font fallback. Client-set cursor surfaces and named shapes are still not rendered, so an app asking for an I-beam gets the arrow. Lid switch. libinput switch events are handled and surfaced to config as srd.on("lid_closed"/"lid_open", fn), so closing the lid can lock and suspend instead of doing nothing. Config-driven additions, each needed by a binding in the ported config and none of which existed: fullscreen (Window.fullscreen was a dead field -- declared, never read or written), directional window move that swaps with the neighbour and reorders the stack so tiling follows, focus cycling, modifier+drag to move/resize anywhere in a window rather than only by the titlebar, modifier+scroll to change workspace, and 8 XF86 media/power keysyms taken from the system's own XF86keysym.h. The keysym tables are hand-maintained in both directions and a key missing from either fails silently, so a round-trip test now covers every one the configs bind. Verified in the QEMU VM: a bare-TTY screendump shows a recognisable arrow at the pointer position (113 white fill + 58 black outline pixels at screen centre, where the pointer starts). --- crates/wayland/src/input.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'crates/wayland/src/input.rs') diff --git a/crates/wayland/src/input.rs b/crates/wayland/src/input.rs index 76607ee..6959c8f 100644 --- a/crates/wayland/src/input.rs +++ b/crates/wayland/src/input.rs @@ -20,6 +20,11 @@ use smithay::wayland::shell::wlr_layer::{KeyboardInteractivity, Layer}; use srdwm_core::{Event as CoreEvent, Modifiers, TitlebarHit, WindowId}; +/// Modifier that turns a drag anywhere in a window into move/resize. +/// Matches the `SUPER` the shipped and ported configs use for +/// `bindm ... movewindow` / `resizewindow`. +const DRAG_MODIFIER: Modifiers = Modifiers::SUPER; + use crate::state::CompState; pub(crate) fn last_pointer_pos(state: &CompState) -> Point { @@ -134,6 +139,7 @@ pub(crate) fn focus_window(state: &mut CompState, id: WindowId) { pub(crate) fn handle_pointer_button(state: &mut CompState, pos: Point, button: u32, pressed: bool, time: u32) { const BTN_LEFT: u32 = 0x110; + const BTN_RIGHT: u32 = 0x111; let serial = SERIAL_COUNTER.next_serial(); // Locked: forward the click to the lock surface (it may have a button or @@ -146,6 +152,33 @@ pub(crate) fn handle_pointer_button(state: &mut CompState, pos: Point(state: &mut CompState, event: &E) -> bool +where + B: smithay::backend::input::InputBackend, + E: smithay::backend::input::PointerAxisEvent, +{ + use smithay::backend::input::Axis; + + if state.lock.locked { + return false; + } + let mods = state.seat.get_keyboard().map(|k| core_modifiers_from_xkb(&k.modifier_state())); + if !mods.is_some_and(|m| m.contains(DRAG_MODIFIER)) { + return false; + } + let Some(v) = event.amount(Axis::Vertical).filter(|v| *v != 0.0) else { return false }; + + let mut wm = state.wm.borrow_mut(); + let ids: Vec<_> = wm.workspaces().iter().map(|w| w.id).collect(); + if ids.is_empty() { + return false; + } + let current = ids.iter().position(|&id| id == wm.current_workspace()).unwrap_or(0); + // Scrolling down (positive) advances, matching `workspace, e+1`. + let next = if v > 0.0 { (current + 1) % ids.len() } else { (current + ids.len() - 1) % ids.len() }; + wm.switch_workspace(ids[next]); + true +} -- cgit v1.2.3