From: Zhiyi Zhang zzhang@codeweavers.com
Fix a regression from 31fda1f4, which allowed the visible rect to be larger than the monitor rect. After 31fda1f4, CHRONO TRIGGER (613830) sets a window rect slightly larger than the monitor rect and will change the window rect to the rect it previously set if the game detects a different window rect. Adding __NET_WM_STATE_FULLSCREEN will cause WMs to move the window to cover exactly the monitor rect. So the window rect will be repeatedly changed by the WM and the game, causing a flickering effect. Limit fullscreen visible rects to the virtual screen rect so that the visible rects in winex11.drv are of the same size as the monitor rect. Thus, adding __NET_WM_STATE_FULLSCREEN won't trigger a size change. --- dlls/winex11.drv/window.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index b9055791a60..a22bf699169 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -3158,8 +3158,9 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UIN { struct x11drv_win_data *data; UINT new_style = NtUserGetWindowLongW( hwnd, GWL_STYLE ), old_style; - struct window_rects old_rects; + struct window_rects old_rects, tmp_rects; BOOL was_fullscreen, activate = !(swp_flags & SWP_NOACTIVATE); + RECT virtual;
if (!(data = get_win_data( hwnd ))) return; if (is_window_managed( hwnd, swp_flags, fullscreen )) window_set_managed( data, TRUE ); @@ -3169,6 +3170,20 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UIN if (data->desired_state.wm_state == IconicState) old_style |= WS_MINIMIZE; if (data->desired_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) old_style |= WS_MAXIMIZE;
+ /* If the visible rect is fullscreen on any one of the monitors, limit the visible rect to the + * virtual screen rect. This is needed because adding __NET_WM_STATE_FULLSCREEN will make WMs + * move the window to cover exactly the monitor rect. If the application sets a visible rect + * slightly larger than the monitor rect and insists on changing to the rect that it previously + * set when the rect is changed by the WM, then the window rect will be repeatedly changed by + * the WM and the application, causing a flickering effect */ + if (fullscreen) + { + virtual = NtUserGetVirtualScreenRect( MDT_RAW_DPI ); + tmp_rects = *new_rects; + intersect_rect( &tmp_rects.visible, &tmp_rects.visible, &virtual ); + new_rects = &tmp_rects; + } + old_rects = data->rects; was_fullscreen = data->is_fullscreen; data->rects = *new_rects;