Bug 489983 - Incorrect window size when restoring from a maximized state
Summary: Incorrect window size when restoring from a maximized state
Status: RESOLVED FIXED
Alias: None
Product: kwin
Classification: Plasma
Component: wayland-generic (show other bugs)
Version: 6.1.1
Platform: Fedora RPMs Linux
: NOR normal
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-07-09 16:22 UTC by Frank Praznik
Modified: 2024-07-18 14:13 UTC (History)
4 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
WAYLAND_DEBUG=1 output (235.34 KB, text/plain)
2024-07-09 16:22 UTC, Frank Praznik
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Frank Praznik 2024-07-09 16:22:01 UTC
Created attachment 171504 [details]
WAYLAND_DEBUG=1 output

Upstream SDL bug: https://github.com/libsdl-org/SDL/issues/10203

Windows will shrink in size by few pixels after being maximized and restored. In some cases this can allow the window to have zero area, causing a crash.

STEPS TO REPRODUCE
1. Build the main branch of SDL3 with the tests enabled (cmake -DSDL_TESTS=on)
2. Run testsprite with the --resizable flag
3. Click the maximize button in the title bar, followed by the restore button

OBSERVED RESULT

The 640x480 window becomes 637x478

EXPECTED RESULT

The 640x480 window remains 640x480

SOFTWARE/OS VERSIONS
Linux/KDE Plasma: Fedora 40 with KDE 6.1.1

ADDITIONAL INFORMATION

The WAYLAND_DEBUG=1 output shows the following when restoring from maximized:

1. KWin sends a configure event for the floating window with a size of 643x482 (???)
2. The SDL application ignores the size hint in this case, because it knows that the floating window size should be 640x480
3. The window is configured to be 640x480 and a buffer of that size is attached
4. KWin then sends a 'corrected' configure event with current dimensions offset by -3,-2, in what appears to be an attempt to fix the previously requested (incorrect) window size, but that ends up making the window 637x478, since the geometry was already corrected by SDL.

The window size sent in the configure event for floating windows is just a hint, so I don't think that SDL is in the wrong here by ignoring it in favor of what it knows to be correct, which it has historically had to do since some older compositors would send incorrectly resize the window when transitioning from non-floating to floating states.
Comment 1 Frank Praznik 2024-07-09 20:08:27 UTC
Also to note, this behavior occurs with the scale factor at both 100% and 150%.
Comment 2 Frank Praznik 2024-07-10 18:15:09 UTC
A case where this causes a crash can be reproduced by running ./testsprite --resizable --geometry 1x1

1. Press ctrl+m to maximize with window, since the window controls are too small to use
2. Un-maximize the window with the button in the title bar
3. A crash occurs after KWin sends a configure request with a size hint of -2,-1
Comment 3 Zamundaaa 2024-07-17 14:07:55 UTC
This intermediate resize is because of changes in the decoration size; it should ideally be atomic but right now it sadly just isn't, and fixing that isn't trivial.

> The window size sent in the configure event for floating windows is just a hint, so I don't think that SDL is in the wrong here by ignoring it in favor of what it knows to be correct
It's not just a hint. It's a maximum to allow resizing to a specific aspect ratio, but it is not meant to allow clients to decide an arbitrary size. If the client is supposed to pick a size, the compositor will send a configure event with size 0.
In practice, doing this on the client side will break our placement tracker restoring window state after display hotplug events.

> which it has historically had to do since some older compositors would send incorrectly resize the window when transitioning from non-floating to floating states
Is that causing practical issues, or is it just making the size wrong? If it's the latter, please just drop that workaround. If the compositor is doing things that users don't like, it's up to the compositor to stop doing that.

> A case where this causes a crash can be reproduced
Ack, we're missing a guard there.
Comment 4 Bug Janitor Service 2024-07-17 14:56:36 UTC
A possibly relevant merge request was started @ https://invent.kde.org/plasma/kwin/-/merge_requests/6125
Comment 5 Frank Praznik 2024-07-17 15:22:50 UTC
(In reply to Zamundaaa from comment #3)
> > The window size sent in the configure event for floating windows is just a hint, so I don't think that SDL is in the wrong here by ignoring it in favor of what it knows to be correct
> It's not just a hint. It's a maximum to allow resizing to a specific aspect
> ratio, but it is not meant to allow clients to decide an arbitrary size. If
> the client is supposed to pick a size, the compositor will send a configure
> event with size 0.
> In practice, doing this on the client side will break our placement tracker
> restoring window state after display hotplug events.
> 

The spec only states that the width/height are a maximum if  the window is fullscreen or being interactively resized, and must be precisely obeyed in the maximized state. Otherwise, it says "The width and height arguments specify a hint to the window about how its surface should be resized in window geometry coordinates"

Nothing in the spec states that the size must be considered a maximum in the floating state, and even if it was, a client sending a smaller size, as in this case, shouldn't be an issue.

There is always the option to not ack the configure event if the requested floating size is not precisely obeyed, but that results in the window not being placed back where it was when leaving the maximized state.

> > which it has historically had to do since some older compositors would send incorrectly resize the window when transitioning from non-floating to floating states
> Is that causing practical issues, or is it just making the size wrong? If
> it's the latter, please just drop that workaround. If the compositor is
> doing things that users don't like, it's up to the compositor to stop doing
> that.

If I remember correctly, the workaround was originally introduced years ago due to Mutter shrinking the floating window when leaving fullscreen. That seems to be fixed in 46.2, but I'll have to check on the versions in LTS distros. But yes, it was solving a practical problem. The SDL automated tests also check that the proper size is restored upon leaving a fixed-size state such as maximized or fullscreen.

Even if SDL always obeys and passes through the size it receives, the client app/game can arbitrarily resize itself at any point, and if it does so between the initial restored configure event and the correction, the current behavior will cause the window to shrink and overwrite the client requested size.
Comment 6 Zamundaaa 2024-07-17 15:43:26 UTC
> The spec only states that the width/height are a maximum if  the window is fullscreen or being interactively resized, and must be precisely obeyed in the maximized state. Otherwise, it says "The width and height arguments specify a hint to the window about how its surface should be resized in window geometry coordinates"
Technically that's correct, but that's not the intention of the spec. It's just left out because some toolkits won't resize down below their minimum size, and that shouldn't cause protocol errors.

> Nothing in the spec states that the size must be considered a maximum in the floating state, and even if it was, a client sending a smaller size, as in this case, shouldn't be an issue.
It's not a protocol error, but it is very much an issue.

> There is always the option to not ack the configure event if the requested floating size is not precisely obeyed, but that results in the window not being placed back where it was when leaving the maximized state.
No, unless the requested size is 0, you should simply resize to the requested size, with no exceptions.

> If I remember correctly, the workaround was originally introduced years ago due to Mutter shrinking the floating window when leaving fullscreen. That seems to be fixed in 46.2, but I'll have to check on the versions in LTS distros. But yes, it was solving a practical problem. The SDL automated tests also check that the proper size is restored upon leaving a fixed-size state such as maximized or fullscreen.
That autotest is testing for Mutter's behavior then, and not SDL itself. You can fix that by starting the window maximized, and only then un-maximizing it; in that case the compositor doesn't know the un-maximized size and will request a size of zero / that SDL should choose.

> Even if SDL always obeys and passes through the size it receives, the client app/game can arbitrarily resize itself at any point, and if it does so between the initial restored configure event and the correction, the current behavior will cause the window to shrink and overwrite the client requested size.
The compositor resizing the window is not a bug, it's intentional. KWin keeps a record of what sizes windows should go to in various window and display states, and the application should never attempt to overwrite that.
Comment 7 Frank Praznik 2024-07-17 16:59:30 UTC
(In reply to Zamundaaa from comment #6)
> > There is always the option to not ack the configure event if the requested floating size is not precisely obeyed, but that results in the window not being placed back where it was when leaving the maximized state.
> No, unless the requested size is 0, you should simply resize to the
> requested size, with no exceptions.
> 

This is very much a problem if, say, a client resizes itself, and the compositor sends a configure event with an old size due to a state change (https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/199).

It's also saying that there is no way that a client can un-maximize and immediately request a new floating size.
Comment 8 Zamundaaa 2024-07-18 13:49:14 UTC
> This is very much a problem if, say, a client resizes itself, and the compositor sends a configure event with an old size due to a state change
That problem does not go away unless the client always completely ignores configure events, which is not acceptable.

> It's also saying that there is no way that a client can un-maximize and immediately request a new floating size
Yes, that is not really supported by the protocol right now, unless the compositor sends a configure event with size 0. If you'd like to have that supported, it would need changes in the protocol to bundle unset_maximized with a desired size hint. In practice it's never been an issue though.
Comment 9 Zamundaaa 2024-07-18 13:57:58 UTC
Git commit 01d9393e80e6b6672961134ec32fe55bddb96669 by Xaver Hugl.
Committed on 18/07/2024 at 13:41.
Pushed by zamundaaa into branch 'master'.

xdgshellwindow: never request clients to resize to a negative size

Doing that can cause clients to crash

M  +2    -2    src/xdgshellwindow.cpp

https://invent.kde.org/plasma/kwin/-/commit/01d9393e80e6b6672961134ec32fe55bddb96669
Comment 10 Zamundaaa 2024-07-18 14:13:38 UTC
Git commit 52b8a0bb7c29732a44cf2710db4481ba926aebc2 by Xaver Hugl.
Committed on 18/07/2024 at 13:58.
Pushed by zamundaaa into branch 'Plasma/6.1'.

xdgshellwindow: never request clients to resize to a negative size

Doing that can cause clients to crash


(cherry picked from commit 01d9393e80e6b6672961134ec32fe55bddb96669)

Co-authored-by: Xaver Hugl <xaver.hugl@gmail.com>

M  +2    -2    src/xdgshellwindow.cpp

https://invent.kde.org/plasma/kwin/-/commit/52b8a0bb7c29732a44cf2710db4481ba926aebc2