winex11.drv: Fixing an issue where the window size was not saved after switching from full-screen mode
When switching from maximized window to windowed mode, the window retains the size of the entire screen. This bug is reproducible in xfce. Upon closer examination of the logs, I noticed that xfce was duplicating ConfigureNotify requests. The duplicate requests had the send_event=TRUE flag. These requests caused the window to resize incorrectly. The current implementation of wine uses the asynchronous ConfigureNotify event notification method - NtUserPosteMessage with the WM_WINE_WINDOW_STATE_CHANGED flag. I suggest returning to the synchronous method using Send_message. This bug is a regression. This issue first appeared in commit 0f1d999b, which moved the handling of GetWindowStateUpdates in win32u/message.c to the handle_internal_message function via NtUserPostMessage. I decided to revert the handling logic to before this patch was applied, adapting it to the current handling of GetWindowStateUpdates in win32u/message.c
This solution was tested in xfce, mate, and a number of different programs. Everything worked correctly
From: Ivan Lyugaev valy@etersoft.ru
When switching from maximized window to windowed mode, the window retains the size of the entire screen. This bug is reproducible in xfce. Upon closer examination of the logs, I noticed that xfce was duplicating ConfigureNotify requests. The duplicate requests had the send_event=TRUE flag. These requests caused the window to resize incorrectly. The current implementation of wine uses the asynchronous ConfigureNotify event notification method - NtUserPosteMessage with the WM_WINE_WINDOW_STATE_CHANGED flag. I suggest returning to the synchronous method using Send_message. This bug is a regression. This issue first appeared in commit 0f1d999b, which moved the handling of GetWindowStateUpdates in win32u/message.c to the handle_internal_message function via NtUserPostMessage. I decided to revert the handling logic to before this patch was applied, adapting it to the current handling of GetWindowStateUpdates in win32u/message.c --- dlls/winex11.drv/event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index d2cf9e55977..9aba3a22f1d 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1133,7 +1133,7 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
release_win_data( data );
- return NtUserPostMessage( hwnd, WM_WINE_WINDOW_STATE_CHANGED, 0, 0 ); + return send_message( hwnd, WM_WINE_WINDOW_STATE_CHANGED, 0, 0 ); }
/***********************************************************************
The state change is done asynchronously on purpose. If we're not tracking WM state changes correctly we should debug and fix that.
Restoring the synchronous processing is not really going to fix the issue, but rather hide it because it will discard the pending events by forcing the win32 state to change earlier.
On Mon Sep 8 15:02:52 2025 +0000, Rémi Bernon wrote:
The state change is done asynchronously on purpose. If we're not tracking WM state changes correctly we should debug and fix that. Restoring the synchronous processing is not really going to fix the issue, but rather hide it because it will discard the pending events by forcing the win32 state to change earlier.
The whole problem lies in the change of rcNormalRect in win32u/window.c in the NtUserGetWindowPlacement function. When the mode is changed in the first ConfigureNotify request with the send_event=FALSE parameter, the win->normal_rect = win->rects.window is changed, and in the next ConfigureNotify request with the send_event=TRUE parameter, the SC_RESTORE flag is received. In the NtUserGetWindowPlacement function, the win->normal_rect dimensions correspond to the size of the entire screen, while the win->rects.window dimensions correspond to the correct window dimensions in windowed mode. That is, there is a certain desynchronization in the process of changing the window mode.
I had the idea to add a flag that would track the type of event (the Send_event flag) and change the logic in the NtUserGetWindowPlacement function accordingly.
Due to the asynchronous execution of the request, incorrect processing occurs
On Mon Sep 8 15:02:52 2025 +0000, Ivan Lyugaev wrote:
The whole problem lies in the change of rcNormalRect in win32u/window.c in the NtUserGetWindowPlacement function. When the mode is changed in the first ConfigureNotify request with the send_event=FALSE parameter, the win->normal_rect = win->rects.window is changed, and in the next ConfigureNotify request with the send_event=TRUE parameter, the SC_RESTORE flag is received. In the NtUserGetWindowPlacement function, the win->normal_rect dimensions correspond to the size of the entire screen, while the win->rects.window dimensions correspond to the correct window dimensions in windowed mode. That is, there is a certain desynchronization in the process of changing the window mode. I had the idea to add a flag that would track the type of event (the Send_event flag) and change the logic in the NtUserGetWindowPlacement function accordingly. Due to the asynchronous execution of the request, incorrect processing occurs
Do I understand correctly that you are suggesting to add synchronization of such requests when passing them through NtUserPostMessage ?
Will the option described above be suitable?
On Wed Sep 10 14:18:30 2025 +0000, Ivan Lyugaev wrote:
Do I understand correctly that you are suggesting to add synchronization of such requests when passing them through NtUserPostMessage ? Will the option described above be suitable?
No, I don't think this needs more synchronization. Maybe the window normal rect should not be updated here. If the window is still maximized at that point (before sending SC_RESTORE) then it shouldn't.