<feed xmlns='http://www.w3.org/2005/Atom'>
<title>srdwm/crates/wayland/src/input.rs, branch main</title>
<subtitle>Cross-platform window manager written in Rust.
</subtitle>
<id>https://srdusr.com/git/srdwm/atom?h=main</id>
<link rel='self' href='https://srdusr.com/git/srdwm/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/'/>
<updated>2025-02-15T12:56:00+00:00</updated>
<entry>
<title>Checkpoint: preserve all uncommitted rust-rewrite worktree work</title>
<updated>2025-02-15T12:56:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-02-15T12:56:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=0a4c4b5941fe982ccb3d3175e26d9d83f0025ffd'/>
<id>urn:sha1:0a4c4b5941fe982ccb3d3175e26d9d83f0025ffd</id>
<content type='text'>
Safety commit before reconciling this worktree with main, which has
diverged with its own separate fixes today. Nothing here is reviewed
or curated yet - this exists purely so none of this work can be lost
to a git operation, disk issue, or worktree cleanup while that
reconciliation happens.
</content>
</entry>
<entry>
<title>Implement the Wayland implicit pointer grab</title>
<updated>2025-02-12T23:14:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-02-12T23:14:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=ed0b8ecf6c08d920ffd1b52c9dc6a24a436ce977'/>
<id>urn:sha1:ed0b8ecf6c08d920ffd1b52c9dc6a24a436ce977</id>
<content type='text'>
Every pointer motion event re-ran the same popup/layer/content hit-test
from scratch and delivered focus to whatever it found right now - there
was no notion of "a button is held, keep delivering to the surface that
received the press" at all, which is standard, expected Wayland
compositor behavior (every real compositor does this; it's how dragging,
text selection, and scrollbar-thumb dragging all stay coherent even when
the pointer briefly leaves the widget's bounds mid-gesture).

Without it, a real human's hand drifting even slightly outside the
pressed surface mid-drag - trivially easy during a fast, non-perfectly-
straight mouse motion - sent that client an unrequested `leave` event in
the middle of its own gesture. GTK's drag recognizers (a GtkHeaderBar's
move-the-window gesture, concretely) treat a mid-gesture leave as "this
isn't coherent, abort," which reads as "dragging this window by its
title bar does nothing at all" - live-reproduced this work on Nemo,
and consistent with move_request never having fired once all session
despite real attempts.

pointer_button_grab captures the (surface, origin) resolved on a button
press once the held-button count goes from 0 to 1, and every event under
the grab - motion or button, this press's or a later one overlapping
it - is delivered there instead of wherever a fresh hit-test lands,
until every held button is back up.
</content>
</entry>
<entry>
<title>Fix layer surfaces spuriously hiding/re-showing on their own realization</title>
<updated>2025-02-06T07:28:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-02-06T07:28:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=ef2eff8f654884406c8989baf1ad345a2da43a58'/>
<id>urn:sha1:ef2eff8f654884406c8989baf1ad345a2da43a58</id>
<content type='text'>
sync_layer_visibility could not tell a real hide (null-buffer commit on
an already-visible surface) apart from a layer-shell client's ordinary
realization sequence (commit with no buffer -&gt; configure -&gt; ack-commit
with no buffer again -&gt; attach real content): both look like "committed,
no buffer" from has_buffer alone. Every layer surface's first realization
was spuriously unmapped and immediately remapped, doubling LayerMap
arrange() passes on every single popup open.

Live-reproduced via an AGS peer session: a full-monitor click-outside-to-
close popup surface came back from a hit-test with geometry wider than
the real output after several open/close cycles on a wl_surface GTK had
reused across role destroy/recreate, and sat in the Top layer above every
real window with no input region set - silently swallowing clicks meant
for windows, dropdowns, and CSD title bars alike.

layer_surfaces_shown_once now gates the hide path on a surface having
actually shown a buffer at least once, and is cleared in layer_destroyed
so a reused wl_surface's next role starts clean rather than inheriting
the previous role's flag.
</content>
</entry>
<entry>
<title>Add temporary tracing to layer-surface hit-testing for a live dock-input report</title>
<updated>2025-02-05T07:46:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-02-05T07:46:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=d25f28c5a779438bef01106ba2b28874e24d5029'/>
<id>urn:sha1:d25f28c5a779438bef01106ba2b28874e24d5029</id>
<content type='text'>
Logs the layer kind, namespace, arranged geometry, surface-local hit
point, and the surface's actual committed input region for every
candidate the hit-test walks. Answers two open questions from a live
report of a dock receiving zero pointer input despite a correctly-set
input region as measured from the client side: whether arrange() is
giving the surface its full requested size or clamping it to the
exclusive zone, and whether this compositor's own view of the
committed input region actually matches what the client set. Remove
once that's settled.
</content>
</entry>
<entry>
<title>Fix layer-surface hit-testing giving up after the topmost bbox match fails</title>
<updated>2025-02-04T21:56:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-02-04T21:56:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=379466fe866f006700df9ace16c12ad78adb9a83'/>
<id>urn:sha1:379466fe866f006700df9ace16c12ad78adb9a83</id>
<content type='text'>
layer_surface_under_layers used smithay's LayerMap::layer_under(),
which returns only the single topmost surface (by z-order) whose
*bounding box* contains the point - not its real input region. If
that one surface's input region excluded the point, the old code gave
up on the whole layer-kind instead of falling through to whatever real
surface is stacked underneath it.

Concretely: any other surface on the same layer-kind with a bbox
overlapping the target - a mapped-but-mostly-transparent
backdrop/dismiss popup, concretely - would silently swallow every
hover and click meant for whatever's underneath, with no way to reach
it at all. Same failure shape as an already-fixed AGS-side bug
(Overview's own bbox-wide input-region fallback), just compositor-side
and not limited to that one instance.

Now walks every candidate on a layer-kind topmost-first and tries the
next one down when a candidate's actual input region doesn't cover the
point, instead of stopping at the first bounding-box match.
</content>
</entry>
<entry>
<title>Accumulate wayland-crate additions: capture rendering, focus/Space sync, VT resume, plumbing</title>
<updated>2024-12-24T18:44:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2024-12-24T18:44:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=3d73ed0f057a555ded67ad58dbe02b36cd4d2d1f'/>
<id>urn:sha1:3d73ed0f057a555ded67ad58dbe02b36cd4d2d1f</id>
<content type='text'>
Bundles the remaining wayland-crate changes built up here,
touching both backends (udev and winit) and the shared input/rendering
code:
- udev/capture.rs: off-screen Pixman render of an arbitrary (not
  necessarily on-screen) workspace's window content to a PPM file --
  what crates/core's capture-request queue drives, for a workspace
  switcher's thumbnail previews. wlr-screencopy structurally can't do
  this (it can only see what an output is presenting), which is why
  this exists as a separate render path rather than reusing it.
- input::focus_window now also raises the window in smithay's own
  Space, not just core's stacking order - Space is what actually
  renders on top and what pointer hit-testing reads, so any focus path
  that skipped this (an IPC "focus" dispatch, concretely) left a
  window genuinely focused while still rendering, and receiving
  clicks, underneath whatever was already topmost. Both backends'
  poll loops now re-sync this after any IPC mutation.
- udev/session.rs's VT-switch resume fix (drains a stale pending page
  flip before reasserting CRTCs) already has its own earlier, cleanly
  isolated commit - not duplicated here.
- Assorted decoration/cursor/rounded-corners/output-management/
  screencopy/XWayland changes and their cross-backend wiring.

Coarser than the repo's usual one-purpose-per-commit convention,
deliberately - see the core-crate sweep commit's own message for why.
</content>
</entry>
<entry>
<title>Add Monitor::maximize_geometry: maximize covers a dock, still stops at a top bar</title>
<updated>2024-11-26T21:16:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2024-11-26T21:16:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=87f5c04b2593dc49409644e69e7962b73d26b9d8'/>
<id>urn:sha1:87f5c04b2593dc49409644e69e7962b73d26b9d8</id>
<content type='text'>
toggle_maximize previously targeted full_geometry outright (past every
reserved zone), on an earlier request specifically about the dock -
which also silently let it extend behind a top bar's zone, reported
back as its own bug once live-tested. maximize_geometry is a third
rect distinct from geometry (every zone) and full_geometry (none):
full_geometry with only a top-anchored bar's exclusive zone subtracted
back out. New test locks in dock-covered/bar-respected together.
</content>
</entry>
<entry>
<title>Implement general.focus_follows_mouse/auto_raise; remove the rest as dead</title>
<updated>2024-08-24T07:11:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2024-08-24T07:11:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=adc1a56982c70c06a0f8549c2c1b3bddd17930c2'/>
<id>urn:sha1:adc1a56982c70c06a0f8549c2c1b3bddd17930c2</id>
<content type='text'>
Auditing "clicking behavior and basics": general.focus_follows_mouse,
general.mouse_follows_focus, general.auto_raise, general.auto_focus,
the entire window.* namespace (8 more keys, a full duplicate of the
same four plus remember_position/size/state), and general.
smart_placement/border_width were all seeded into default_config() and
documented in DEFAULTS.md, but none were read anywhere - srd.set()/
srd.get() on any of them silently succeeded while doing nothing.

focus_follows_mouse is real, well-defined, and directly relevant to
clicking basics - implemented it plus auto_raise (raise, not just
focus, on hover) rather than just deleting the promise like the
others. WindowManager gained focus_follows_mouse/auto_raise bools,
wired from apply_general_settings the same way every other general.*
flag is. handle_pointer_position now tracks whichever window (content
or decoration) is under the pointer and, when the setting is on and
that differs from the currently-focused window, focuses it through the
same focus_window() free function every click-driven focus change
already uses (real keyboard focus, not just core state) - skipped
entirely while dragging/resizing or over a layer-shell surface, so the
pointer sweeping over other windows mid-drag or hovering a bar can't
steal focus from what's actually being manipulated.

mouse_follows_focus (pointer warp on keybinding-driven focus change)
and auto_focus (no clear distinct meaning beyond click-to-focus) stay
unimplemented and are now undocumented rather than promised.
</content>
</entry>
<entry>
<title>Fix decoration drift during animated transitions; checkpoint IPC/global-menu/output-management work</title>
<updated>2024-05-30T14:10:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2024-05-30T14:10:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=1c175642d073689ca11b9252411ea5f8446007d0'/>
<id>urn:sha1:1c175642d073689ca11b9252411ea5f8446007d0</id>
<content type='text'>
Border/titlebar decoration was built from Window.geometry (the animation's
final target) in both wayland backends' render loops, while sync_geometry
already draws a window's actual content at window_anims' interpolated rect
during any maximize/fullscreen/open-slide tween. Border and content read two
different rectangles for the whole transition, so the border visibly
detached from the window it was outlining - reported as "borders aren't
flush." Both udev.rs and winit.rs now read the same animated rect for
titlebar placement, border-strip placement, and the occlusion test against
later windows in stacking order. Verified: cargo build --workspace, cargo
clippy (0 new warnings), cargo test -p srdwm-core (111/111).

Also checkpoints substantial protocol/IPC work from prior sessions that had
accumulated uncommitted: gtk-shell1 support (gtk_shell.rs, the vendored
gtk-shell.xml, xwayland.rs's X11-side mirror) backing the global app menu;
zwlr_foreign_toplevel_manager_v1 (foreign_toplevel.rs) broadcasting distinct
maximized/minimized/fullscreen/activated state per window; output_management
(ext-output-management + layer-shell exclusive-zone reservation tracking);
workspace.rs and context_menu.rs; a Unix-socket IPC crate (platform/src/
ipc.rs) and a `srd` control-CLI crate (crates/ctl); xkb_config.rs; and a
theme module (core/src/theme.rs). A peer session working the AGS shell
concurrently verified several of these live against a running srdwm: the
global menu rendering a real app's File/Edit menu over gtk-shell1, and
foreign-toplevel correctly reporting maximized and fullscreen as independent,
non-simultaneous states with the geometry each implies (maximize stops at a
reserved top bar and past a dock; fullscreen reaches the true monitor edge).
</content>
</entry>
<entry>
<title>Config at ~/.config/srd; cursor shapes, key repeat, pin, mouse defaults</title>
<updated>2024-05-29T12:40:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2024-05-29T12:40:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=3d3057ae384ef7389284af8988410889e99c6bb9'/>
<id>urn:sha1:3d3057ae384ef7389284af8988410889e99c6bb9</id>
<content type='text'>
Config path drops a level: ~/.config/srd, not ~/.config/srdwm/srd, which
said the same thing twice. No other user-facing path had the same problem --
srdwm reads the config dir and writes nothing else.

Cursor shapes. A client's own cursor surface is now rendered with the
hotspot it declared, so an I-beam over text or a hand over a link shows the
app's image instead of srdwm's arrow. The built-in arrow stays as the
fallback when no client has set one, over decorations and the desktop.
Named shapes still fall back to the arrow; most toolkits set a surface.
Decorations and cursors now share one OverlayElement type, since
render_output takes a single custom-element slice.

Key repeat (srd.bind_repeat, Hyprland's binde). Held volume, brightness and
switcher keys repeat at the seat's own rate rather than firing once. Driven
from the poll loop, not a timer source: the winit backend has no calloop
loop of its own, and poll_events already runs continuously in both backends.
Repeat stops when *that* key is released, not when any key is.

Always-on-top / pin, for the picture-in-picture and HUD rules that used it.
Window::always_on_top was another declared-but-never-read field. Enforced in
WindowManager's stacking order rather than at render time, so every consumer
of stacking_order gets it and none can forget to honour it.

Mouse-only window management, checked end to end: drag the titlebar to move,
drag any edge or corner to resize, titlebar buttons to close/maximise/
minimise, click to focus, drag to a screen edge to snap, and now
double-click the titlebar to maximise. The resize grab band went from 6px to
10px - a hairline is genuinely hard to hit with a mouse, which is why
Hyprland ships extend_border_grab_area.

Also removed the emoji status markers from docs/IMPLEMENTATION_STATUS.md.
</content>
</entry>
</feed>
