From: Rémi Bernon rbernon@codeweavers.com
When the window manager moves windows offscreen, the Win32 config is explicitly kept out of sync. We need to handle that case when the Win32 config changes, to avoid forcefully moving the windows back on screen.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57652 --- dlls/winex11.drv/window.c | 22 +++++++++------------- include/wine/gdi_driver.h | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 9c92f9e8a7f..194e41e674e 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1773,12 +1773,12 @@ void make_window_embedded( struct x11drv_win_data *data ) * * Synchronize the X window position with the Windows one */ -static void sync_window_position( struct x11drv_win_data *data, UINT swp_flags ) +static void sync_window_position( struct x11drv_win_data *data, UINT swp_flags, const struct window_rects *old_rects ) { DWORD style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ); DWORD ex_style = NtUserGetWindowLongW( data->hwnd, GWL_EXSTYLE ); + RECT new_rect, window_rect; BOOL above = FALSE; - RECT new_rect;
if (data->managed && data->desired_state.wm_state == IconicState) return;
@@ -1798,16 +1798,12 @@ static void sync_window_position( struct x11drv_win_data *data, UINT swp_flags ) update_net_wm_states( data );
new_rect = data->rects.visible; - if (swp_flags & SWP_NOSIZE) - { - new_rect.right = new_rect.left + data->desired_state.rect.right - data->desired_state.rect.left; - new_rect.bottom = new_rect.top + data->desired_state.rect.bottom - data->desired_state.rect.top; - } - if (swp_flags & SWP_NOMOVE) - { - OffsetRect( &new_rect, data->desired_state.rect.left - new_rect.left, - data->desired_state.rect.top - new_rect.top ); - } + + /* if the window has been moved offscreen by the window manager, we didn't tell the Win32 side about it */ + window_rect = window_rect_from_visible( old_rects, data->desired_state.rect ); + if (!is_window_rect_mapped( &window_rect )) OffsetRect( &new_rect, window_rect.left - old_rects->window.left, + window_rect.top - old_rects->window.top ); + window_set_config( data, &new_rect, above ); }
@@ -2985,7 +2981,7 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UIN /* don't change position if we are about to minimize or maximize a managed window */ if (!(data->managed && (swp_flags & SWP_STATECHANGED) && (new_style & (WS_MINIMIZE|WS_MAXIMIZE)))) { - sync_window_position( data, swp_flags ); + sync_window_position( data, swp_flags, &old_rects ); #ifdef HAVE_LIBXSHAPE if (IsRectEmpty( &old_rects.window ) != IsRectEmpty( &new_rects->window )) sync_empty_window_shape( data, surface ); diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 38ce9b81f14..51a095fd2b0 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -59,7 +59,7 @@ static inline const char *debugstr_window_rects( const struct window_rects *rect }
/* convert a visible rect to the corresponding window rect, using the window_rects offsets */ -static inline RECT window_rect_from_visible( struct window_rects *rects, RECT visible_rect ) +static inline RECT window_rect_from_visible( const struct window_rects *rects, RECT visible_rect ) { RECT rect = visible_rect;