Skip to content

fix: don't toggle fullscreen/maximize on client request (GTK windows exploding)#70

Merged
ebenali merged 1 commit into
masterfrom
fix-csd-fullscreen-toggle
Jun 21, 2026
Merged

fix: don't toggle fullscreen/maximize on client request (GTK windows exploding)#70
ebenali merged 1 commit into
masterfrom
fix-csd-fullscreen-toggle

Conversation

@ebenali

@ebenali ebenali commented Jun 21, 2026

Copy link
Copy Markdown
Member

Properly diagnosed and reproduced the "GTK windows (wbconf, awf-gtk4) explode/expand and lose their titlebar when dragged" bug — apologies it took several wrong turns to get to the actual root cause.

Root cause

xdg_toplevel_request_fullscreen toggled fullscreen based on current state:

set_toplevel_fullscreen(toplevel, !toplevel->xdg_toplevel->current.fullscreen);

wlroots raises request_fullscreen for both set and unset, with the wanted value in requested.fullscreen. GTK proactively sends unset_fullscreen while managing its window state — so a GTK window being dragged emitted request_fullscreen with requested=false on a non-fullscreen window, and the toggle turned it into fullscreen. The window blows up to fill the screen and GTK hides its titlebar (fullscreen has no decorations) — exactly the "explode + lose titlebar" symptom. request_maximize had the identical toggle bug.

Fix: honour requested.fullscreen / requested.maximized instead of toggling; make set_toplevel_fullscreen a no-op when unchanged and skip redundant maximize requests (so a redundant unset can't corrupt geometry by restoring an unset restore-rect). The keybinding actions (ToggleMaximize / Fullscreen) still toggle, as intended.

Second bug (found while building a reproduction)

Virtual pointers never advertised seat pointer capability: the virtual-pointer protocol attaches its device via handle_new_pointer directly, bypassing new_input_notify — the only caller of wlr_seat_set_capabilities. So with only a virtual pointer (the headless backend the tests use), no client ever received pointer events (compositor-handled input like SSD buttons still worked, which masked it). Factored the capability update into a helper and call it from the virtual-pointer/keyboard paths. This also makes client input scriptable from the command line (answering the earlier "drive a seat from cmdline" question).

How it was reproduced (deterministically)

  • A toolkit-free xdg-shell client (shadow-offset window geometry like GTK) proved the generic move path is correct — no growth.
  • A zwlr_virtual_pointer_v1 press/move/release CLI drove a real GTK header-bar drag. Before the fix: wb-geom fullscreen-on 1280x720. After: the window stays put (only mapped logged).

Testing

  • Full suite 27 green (g++/ASan/UBSan), including the maximize/fullscreen window_state integration test (keybinding toggles still work); clang + release clean.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

…inter caps

Two bugs, the first explaining the "wbconf/GTK windows explode and lose their
titlebar when dragged" report.

1) Client fullscreen/maximize requests were TOGGLED instead of applied.
   xdg_toplevel_request_fullscreen did `set_fullscreen(!current)` and
   request_maximize did `set_maximized(!full)`. wlroots raises these events for
   BOTH set and unset, with the wanted value in requested.{fullscreen,maximized}.
   GTK proactively sends unset_fullscreen while managing its window state, so a
   GTK window being dragged emitted `request_fullscreen` with requested=false on
   a non-fullscreen window — which the toggle turned INTO fullscreen. The window
   blew up to fill the screen and GTK hid its titlebar (fullscreen). Reproduced
   deterministically (see below).

   Honour requested.fullscreen / requested.maximized instead of toggling, and
   make set_toplevel_fullscreen a no-op when the state is unchanged + skip
   redundant maximize requests, so a redundant unset can't corrupt geometry by
   restoring an unset restore-rect. The keybinding actions (ToggleMaximize /
   Fullscreen) still toggle, as intended.

2) Virtual pointers never advertised seat pointer capability. The
   virtual-pointer protocol attaches its device via handle_new_pointer directly,
   bypassing new_input_notify — the only place that called
   wlr_seat_set_capabilities. So with only a virtual pointer (e.g. the headless
   backend the tests use), the seat advertised no pointer and NO client ever
   received pointer events (compositor-handled input like SSD buttons still
   worked, which masked it). Factor the capability update into a helper and call
   it from the virtual-pointer and virtual-keyboard paths too. This also makes
   client input scriptable from the command line via the virtual-pointer
   protocol, which is how bug #1 was finally reproduced.

Verified: built a toolkit-free xdg client and a zwlr_virtual_pointer drag tool;
before the fix, dragging a GTK header bar logged `fullscreen-on 1280x720`; after,
the window stays put. Full suite 27 green (g++/ASan, incl. the maximize/
fullscreen window_state integration test); clang + release clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ebenali
ebenali merged commit 3deafc4 into master Jun 21, 2026
4 checks passed
@ebenali
ebenali deleted the fix-csd-fullscreen-toggle branch June 21, 2026 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant