WayfireWM / WayfireWM/wayfire

xdg-shell: Send XDG_TOPLEVEL_STATE_RESIZING during interactive resize

Open
#3,101 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
C++
Stars
3.1k
Forks
237
Avg merge
1h 43m
Merged PRs (30d)
1

Description

Description

xdg-shell: Send XDG_TOPLEVEL_STATE_RESIZING state during interactive resize

Use Case

Problem

Currently, Wayfire does not send the XDG_TOPLEVEL_STATE_RESIZING state to clients when the user initiates an interactive resize (e.g., dragging a window border).
According to the xdg-shell protocol, compositors SHOULD send the RESIZING state to inform the client that an interactive resize is happening, allowing the toolkit to pause heavy rendering or suppress focus changes.

Furthermore, because Wayfire changes the keyboard focus (sending wl_keyboard_leave) immediately upon starting the resize grab, toolkits like GTK3 receive a focus-out-event before or without knowing that a resize is in progress.

This causes significant issues for applications that rely on window focus. For example, utilities designed to close when they lose focus (notify::is-active or focus-out-event) will incorrectly close while the user is simply trying to resize the window.

Solution

This FR adds the missing xdg-shell state notifications by hooking into the on_request_resize callback in xdg-toplevel-view.cpp:

  1. When a resize is requested, it calls
wlr_xdg_toplevel_set_resizing(this->xdg_toplevel, true).
  1. It dynamically connects a listener to the pointer_button signal to detect when the user releases the mouse button WL_POINTER_BUTTON_STATE_RELEASED. Once released, it sets the resizing state to false and disconnects the listeners.
  2. To prevent memory leaks if the view is destroyed during a resize grab, it also connects to the view-disappeared signal to safely reset the state and disconnect.

Benefits

This allows clients (like GTK3) to know exactly when an interactive resize starts and ends, restoring compatibility with standard Wayland behavior seen in compositors like Mutter and KWin.

Testing

Tested with a custom GTK3 application that closes on notify::is-active loss.
Before patch: The application closes immediately upon clicking the window border to resize.
After patch: The application remains open during the resize, as the toolkit can now properly intercept the focus loss using the RESIZING state.

Additional context

Code Changes
--- a/src/view/xdg-shell/xdg-toplevel-view.hpp  2026-06-30 16:45:46.503000000 +0200
+++ b/src/view/xdg-shell/xdg-toplevel-view.hpp  2026-08-04 21:34:11.085741111 +0200
@@ -11,6 +11,7 @@
 #include <wayfire/toplevel-view.hpp>
 #include "wayfire/toplevel.hpp"
 #include "wayfire/util.hpp"
+#include <wayfire/signal-definitions.hpp>
 #include "xdg-toplevel.hpp"

 namespace wf
@@ -48,6 +49,10 @@

     std::shared_ptr<wf::xdg_toplevel_t> wtoplevel;
     wf::signal::connection_t<xdg_toplevel_applied_state_signal> on_toplevel_applied;
+    /* ------------------------------- */
+    wf::signal::connection_t<wf::input_event_signal<wlr_pointer_button_event>> on_pointer_button;
+    wf::signal::connection_t<wf::view_disappeared_signal> on_view_disappeared_during_resize;
+    /* ------------------------------- */

     void map() override;
     void destroy() override;
--- a/src/view/xdg-shell/xdg-toplevel-view.cpp  2026-06-30 16:45:46.502657991 +0200
+++ b/src/view/xdg-shell/xdg-toplevel-view.cpp  2026-08-05 09:00:58.699021823 +0200
@@ -218,6 +218,42 @@
         if (ev->serial == wf::get_core().seat->priv->last_press_release_serial)
         {
             wf::get_core().default_wm->resize_request({this}, ev->edges);
+
+            // 1. Turn ON resize flag
+            // LOGI("Resize ON");
+            wlr_xdg_toplevel_set_resizing(this->xdg_toplevel, true);
+
+            // 2. Listen for button release
+            on_pointer_button.set_callback([&] (wf::input_event_signal<wlr_pointer_button_event> *ev)
+            {
+                if (ev->event->state == WL_POINTER_BUTTON_STATE_RELEASED)
+                {
+                    // LOGI("Button released. Resize OFF");
+                    // Button released — turn OFF resize flag
+                    wlr_xdg_toplevel_set_resizing(this->xdg_toplevel, false);
+
+                    // Disconnect signals
+                    on_pointer_button.disconnect();
+                    on_view_disappeared_during_resize.disconnect();
+                }
+            });
+            wf::get_core().connect(&on_pointer_button);
+
+            // 3. Prevent memory leak on view destruction during resize 
+            on_view_disappeared_during_resize.set_callback([&] (wf::view_disappeared_signal *ev)
+            {
+                if (ev->view == self())
+                {
+                    // LOGI("View disappeared. Resize OFF");
+                    wlr_xdg_toplevel_set_resizing(this->xdg_toplevel, false);
+                    on_pointer_button.disconnect();
+                    on_view_disappeared_during_resize.disconnect();
+                }
+            });
+            wf::get_core().connect(&on_view_disappeared_during_resize);
+            //wf::get_core().connect_signal("view-disappeared", &on_view_disappeared_during_resize);
         }
     });
     on_request_minimize.set_callback([&] (void*)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/view/xdg-shell/xdg-toplevel-view.cpp and its header, then inspect on_request_resize and existing signal connection patterns. Exercise interactive resizing with the GTK3 focus-loss test described in the issue; done when clients receive the resizing state during the grab and it is cleared on release or view disappearance.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
desktop-dev
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.