<feed xmlns='http://www.w3.org/2005/Atom'>
<title>srdwm/crates/wayland/src/xwayland.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>2026-08-30T18:41:00+00:00</updated>
<entry>
<title>Indent doc list continuations</title>
<updated>2026-08-30T18:41:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2026-08-30T18:41:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=f2f9ed1b3f9c49b323ce591eb72a406058d324a4'/>
<id>urn:sha1:f2f9ed1b3f9c49b323ce591eb72a406058d324a4</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Fix window memory never saving on close, and split-screen icon/primary bugs</title>
<updated>2025-11-04T09:55:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-11-04T09:55:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=a8991f65602abc5ecee740c443c58fa96ecd15e1'/>
<id>urn:sha1:a8991f65602abc5ecee740c443c58fa96ecd15e1</id>
<content type='text'>
Screenshotted the just-split display on request rather than guessing --
it showed why windows never seem to remember placement/size, plus two
real split-screen bugs.

Window memory (WindowManager::remembered_geometry) was correctly wired
on the read side, but the only writes came from end_drag/end_resize in
dragresize.rs - a real drag or resize. A window the user opens, looks
at, and closes without ever touching its edges had nothing recorded, so
reopening it always fell back to a fresh cascade placement, for what is
probably most ordinary window lifecycles. remove_window now also
snapshots geometry (same app_id-non-empty gate the drag/resize sites
use), persisted at both of its wayland-side call sites the same way the
drag/resize-release site already does.

desktop_icon_origins mirrored the full icon set onto every Monitor entry
when general.desktop_icons_all_monitors is on - which, after a
srd.monitor.split, is one entry per split part of the same physical
screen, not one per real monitor. Extracted into a separately-tested
icon_origins_for that collapses split parts of the same connector back
to one origin, keeping a genuinely separate monitor's own origin intact.

Found while fixing that: every split part also reported primary: true
(computed from the connector's name, which doesn't vary per part) --
fixed by gating on part == 0 too.
</content>
</entry>
<entry>
<title>Wayland backend: desktop icons v2, menu rebuild, layer-shell/scale fixes,</title>
<updated>2025-09-10T09:24:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-09-10T09:24:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=5ee627928d0cb017e59d796c71793c35d5b65d33'/>
<id>urn:sha1:5ee627928d0cb017e59d796c71793c35d5b65d33</id>
<content type='text'>
XWayland stability, GPU rendering, and multi-cursor Phase 2

The bulk of a multi-session shift's real work landed in crates/wayland.
Full root-cause/verification narrative for every item below lives in
docs/TODO.md (each has its own dated entry); this is the summary:

Desktop shell:
- Real desktop icons v2 (state/desktop_icons.rs, desktop_icons.rs):
  fixed origin-baked-before-the-bar-connects, fixed-icon sort order, and
  a proper Rename/Delete-to-Trash menu (window_memory.rs backs the
  rename-persistence side). Rubber-band marquee multi-select.
- icon_theme.rs: real freedesktop icon-theme lookup (inherits chain,
  hicolor fallback) rendering actual theme SVGs via resvg/tiny-skia,
  replacing the hand-drawn placeholder glyphs.
- Context/desktop menus (decoration.rs, desktop_menu.rs, state/menu.rs)
  rebuilt to match the project's own AGS panel styling: rounded floating
  panel, tinted-fill row highlight, real separators, a much fuller
  titlebar window-menu action set.

Layer-shell / multi-monitor:
- Layer-shell hit-testing and render positioning (input/pointer.rs,
  udev/render.rs's element placement) now correctly convert LayerMap's
  logical geometry into physical pixels on a fractionally-scaled output
  - root cause of a bottom-anchored dock being unclickable and
  unpainted while a top-anchored bar on the same output worked.
  udev/outputs.rs's relayout_outputs gained the same physical/logical
  split for cross-output positioning, now backed by a real unit test
  (next_logical_x) built from the original measured incident numbers.
- state/geometry.rs: a window's border/decoration no longer briefly
  clips when moved between differently-scaled monitors mid-drag.

XWayland / stability:
- xwayland.rs, udev/session.rs, udev/platform.rs: fixed a 100%-
  reproducible cold-start XKEYBOARD crash-loop (XWayland's own stdin
  inherited a real, already-owned VT; env passthrough and idle-callback
  spawn timing were both real, independent gaps) that had silently taken
  down all X11-app support and the global-menu registrar every session.
- state/toplevel.rs, state/lifecycle.rs: XWayland dialog detection via
  WM_TRANSIENT_FOR, not just a native xdg_toplevel parent.

Rendering:
- udev/render.rs, decoration.rs: real GPU (GBM+EGL+DrmCompositor)
  window-content and cursor rendering on the udev backend, falling back
  to the untouched Pixman path automatically on any init failure.
- decoration/tests.rs, state/mod.rs: rounded-corner/border fixes for
  interactive resize lag and cross-monitor moves.

Multi-cursor Phase 2 (virtual_pointer.rs, new; state/mod.rs, udev/
platform.rs, winit/nested_platform.rs): pins a zwlr_virtual_pointer_
unstable_v1 object to a specific window, bypassing the shared seat/
focus/pointer_pos path entirely via hand-rolled wl_pointer.enter/motion/
button/frame/leave against every WlPointer the target client has bound
(PointerHandle::client_pointers). Lets an agent operate one window while
a human uses another, genuinely simultaneously, with zero client
cooperation and no second wl_seat (confirmed a dead end: real clients
only ever bind the first seat advertised).

Full workspace build/test/clippy clean.
</content>
</entry>
<entry>
<title>Detect XWayland dialogs via WM_TRANSIENT_FOR, not just native xdg_toplevel parent</title>
<updated>2025-05-29T23:12:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2025-05-29T23:12:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=3f2ac4d85c4e66c2f1ae6622bf3c2f302abe93b9'/>
<id>urn:sha1:3f2ac4d85c4e66c2f1ae6622bf3c2f302abe93b9</id>
<content type='text'>
Window::is_dialog (close-button-only titlebar, no traffic lights) was
only ever set from a native xdg_toplevel's own parent() - redraw_
decoration_buffer's is_dialog computation called dw.toplevel(), which
is always None for an XWayland-backed DWindow (X11Surface's own
accessor is x11_surface(), a different method), so the .unwrap_or(false)
fallback made every XWayland dialog - a GTK "Save As", an app's own
"About" box, anything setting the ICCCM transient-for hint - always
draw with the full three-button titlebar and traffic-light colours,
even though the feature this was built for explicitly wanted the
opposite. Documented as a known gap at the time; now closed.

redraw_decoration_buffer now also checks X11Surface::is_transient_for()
for an XWayland window. property_notify gained a WmWindowProperty::
TransientFor arm that re-runs redraw_decoration_buffer, for a client
that sets the hint slightly after its own initial map - the same
"read fresh every call" pattern the existing xdg_toplevel::parent()
check already relied on, extended to catch a late X11 property the way
the Wayland equivalent (set_parent, any time) already was.
</content>
</entry>
<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>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>Fix global-menu source misclassification for appmenu-gtk-module's shim</title>
<updated>2024-08-25T19:34:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2024-08-25T19:34:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=4fb537aa4cfe52e364dbcd9a97078f0206ada54b'/>
<id>urn:sha1:4fb537aa4cfe52e364dbcd9a97078f0206ada54b</id>
<content type='text'>
read_global_menu unconditionally preferred MenuSource::Gtk whenever a
GTK menubar path resolved - but appmenu-gtk-module exports a plain
Gtk.Window's menu (no GtkApplication, so no _GTK_APPLICATION_OBJECT_
PATH/_GTK_WINDOW_OBJECT_PATH) through its Unity-compatibility shim,
unity.-prefixed actions and all, while still setting _GTK_MENUBAR_
OBJECT_PATH. Labeling that Gtk meant a consumer inserted app/win
action groups the app never populated instead of a unity one it did --
every menu item rendered, but permanently insensitive, since none of
them resolved against a group that existed. This was flagged as a
known risk in this function's own doc comment when `source` was first
added, but the priority logic itself never got the fix.

Root-caused live by an AGS peer session: read the actual exported menu
content off the bus for a real appmenu-gtk-module app and found
unity.-prefixed actions at the GTK atom's own path, with app_path/
window_path both empty - confirming that emptiness is the reliable
tell, not which atom happened to resolve.

Fixed by preferring Unity whenever app_path/window_path are both
absent, even if a GTK menubar path resolved - the path itself doesn't
change, only the label. Pulled the decision out into a standalone
classify_menu_source function so it's unit-testable without a real X
connection, with the exact live case as a regression test.
</content>
</entry>
<entry>
<title>Handle late title/class updates on XWayland windows</title>
<updated>2024-08-14T14:55:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2024-08-14T14:55:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=380c4d90f63ac9c82455206072c2deac246a4fdc'/>
<id>urn:sha1:380c4d90f63ac9c82455206072c2deac246a4fdc</id>
<content type='text'>
map_window_request only ever read window.title()/.class() once, at
MapRequest - for a client whose managed window doesn't carry
WM_NAME/WM_CLASS at that exact moment (or the properties simply arrive
later), Window.title/app_id stayed permanently empty. That reaches
srd.rule's class matching, this compositor's own titlebar text, and
every wlr-foreign-toplevel-management listener (a dock's running
indicator, an app switcher, icon lookup) - confirmed live via a peer
session's AGS instance rendering blank rows for Spotify and OpenSnitch.

Implements XwmHandler::property_notify (previously unhandled, a
no-op default) to re-read title/class on WmWindowProperty::Title/Class
and update Window plus notify rule/decoration/foreign-toplevel
listeners on an actual change - the XWayland-side mirror of
sync_toplevel_metadata, which already exists for exactly this problem
on the native xdg-shell path (see its own doc comment).

Not fully verified against the specific live case that surfaced this:
whether XWayland's X11Wm delivers property_notify for a *managed*
window whose real WM_NAME/WM_CLASS live only on an unmanaged sibling/
child (rather than arriving late on the same window) is still an open
question - this fixes the well-documented "arrives late" case with
certainty, and may or may not cover that harder case too.
</content>
</entry>
<entry>
<title>Fix doc-comment file references left stale by today's six module splits</title>
<updated>2024-08-03T18:07:00+00:00</updated>
<author>
<name>srdusr</name>
<email>99972264+srdusr@users.noreply.github.com</email>
</author>
<published>2024-08-03T18:07:00+00:00</published>
<link rel='alternate' type='text/html' href='https://srdusr.com/git/srdwm/commit/?id=35a28a257644483495ac2bd6a5fb1e109e8c1f26'/>
<id>urn:sha1:35a28a257644483495ac2bd6a5fb1e109e8c1f26</id>
<content type='text'>
~17 comments across the codebase still pointed at udev.rs/winit.rs/
state.rs by their old flat-file names after those became udev/,
winit/, state/ directories - found while auditing what this work
rushed, since the split verification (function/struct-name diffing,
full test suite) checked structural correctness but never comment
accuracy. Updated each to either the specific new file (e.g. "see
state.rs's REPEAT_DELAY" -&gt; "see state/mod.rs's REPEAT_DELAY",
"udev.rs's monitors()" -&gt; "udev/platform.rs's monitors()") or the bare
module name where the reference was already generic ("the udev/winit
backends", not a specific location).
</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>
</feed>
