Instead of checking for monitor rect.
Similar purpose as https://gitlab.winehq.org/wine/wine/-/merge_requests/7362
-- v3: winewayland: Pass fullscreen flag to is_window_managed. winex11: Pass fullscreen flag to is_window_managed. winex11: Check managed window changes in WindowPosChanged. winex11: Request managed/embedded in a new window_set_managed helper. winex11: Initialize window managed flag in create_whole_window.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 7ae1d8ef66a..ac967906646 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2110,12 +2110,6 @@ static void create_whole_window( struct x11drv_win_data *data ) HRGN win_rgn; POINT pos;
- if (!data->managed && is_window_managed( data->hwnd, SWP_NOACTIVATE, &data->rects.window )) - { - TRACE( "making win %p/%lx managed\n", data->hwnd, data->whole_window ); - data->managed = TRUE; - } - if ((win_rgn = NtGdiCreateRectRgn( 0, 0, 0, 0 )) && NtUserGetWindowRgnEx( data->hwnd, win_rgn, 0 ) == ERROR) { @@ -2127,6 +2121,7 @@ static void create_whole_window( struct x11drv_win_data *data ) if (data->vis.visualid != default_visual.visualid) data->whole_colormap = XCreateColormap( data->display, root_window, data->vis.visual, AllocNone );
+ data->managed = is_window_managed( data->hwnd, SWP_NOACTIVATE, &data->rects.window ); mask = get_window_attributes( data, &attr );
if (!(cx = data->rects.visible.right - data->rects.visible.left)) cx = 1;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 51 +++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 18 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index ac967906646..40179965676 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -470,7 +470,6 @@ static unsigned long get_mwm_decorations( struct x11drv_win_data *data, DWORD st */ static int get_window_attributes( struct x11drv_win_data *data, XSetWindowAttributes *attr ) { - attr->override_redirect = !data->managed; attr->colormap = data->whole_colormap ? data->whole_colormap : default_colormap; attr->save_under = ((NtUserGetClassLongW( data->hwnd, GCL_STYLE ) & CS_SAVEBITS) != 0); attr->bit_gravity = NorthWestGravity; @@ -482,7 +481,7 @@ static int get_window_attributes( struct x11drv_win_data *data, XSetWindowAttrib KeyPressMask | KeyReleaseMask | FocusChangeMask | KeymapStateMask | StructureNotifyMask | PropertyChangeMask);
- return (CWOverrideRedirect | CWSaveUnder | CWColormap | CWBorderPixel | CWBackPixel | + return (CWSaveUnder | CWColormap | CWBorderPixel | CWBackPixel | CWEventMask | CWBitGravity | CWBackingStore); }
@@ -1508,6 +1507,31 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state ) XFlush( data->display ); }
+static void window_set_managed( struct x11drv_win_data *data, BOOL new_managed, BOOL new_embedded ) +{ + XSetWindowAttributes attr = {.override_redirect = !new_managed}; + BOOL old_managed = data->managed, old_embedded = data->embedded; + UINT wm_state = data->desired_state.wm_state; + + if (!data->whole_window) return; /* no window, nothing to update */ + if (old_managed == new_managed && old_embedded == new_embedded) return; /* states are the same, nothing to update */ + if (!new_managed) + { + ERR( "Changing window to unmanaged is not supported\n" ); + return; + } + + window_set_wm_state( data, WithdrawnState ); /* no WM_STATE is pending, requested immediately */ + + data->managed = new_managed; + data->embedded = new_embedded; + TRACE( "window %p/%lx, requesting override-redirect %u -> %u serial %lu\n", data->hwnd, data->whole_window, + !old_managed, !new_managed, NextRequest( data->display ) ); + XChangeWindowAttributes( data->display, data->whole_window, CWOverrideRedirect, &attr ); + + window_set_wm_state( data, wm_state ); /* queue another WM_STATE request with the desired state */ +} +
/*********************************************************************** * map_window @@ -1775,11 +1799,7 @@ BOOL window_has_pending_wm_state( HWND hwnd, UINT state ) */ void make_window_embedded( struct x11drv_win_data *data ) { - /* the window cannot be mapped before being embedded */ - window_set_wm_state( data, WithdrawnState ); - data->embedded = TRUE; - data->managed = TRUE; - window_set_wm_state( data, NormalState ); + window_set_managed( data, TRUE, TRUE ); }
@@ -2122,7 +2142,8 @@ static void create_whole_window( struct x11drv_win_data *data ) data->whole_colormap = XCreateColormap( data->display, root_window, data->vis.visual, AllocNone );
data->managed = is_window_managed( data->hwnd, SWP_NOACTIVATE, &data->rects.window ); - mask = get_window_attributes( data, &attr ); + mask = get_window_attributes( data, &attr ) | CWOverrideRedirect; + attr.override_redirect = !data->managed;
if (!(cx = data->rects.visible.right - data->rects.visible.left)) cx = 1; else if (cx > 65535) cx = 65535; @@ -2191,6 +2212,8 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des if (data->whole_colormap) XFreeColormap( data->display, data->whole_colormap ); data->whole_window = data->client_window = 0; data->whole_colormap = 0; + data->managed = FALSE; + data->embedded = FALSE;
memset( &data->desired_state, 0, sizeof(data->desired_state) ); memset( &data->pending_state, 0, sizeof(data->pending_state) ); @@ -2342,7 +2365,7 @@ static BOOL create_desktop_win_data( Window win, HWND hwnd )
if (!(data = alloc_win_data( display, hwnd ))) return FALSE; data->whole_window = win; - data->managed = TRUE; + window_set_managed( data, TRUE, FALSE ); NtUserSetProp( data->hwnd, whole_window_prop, (HANDLE)win ); set_initial_wm_hints( display, win ); release_win_data( data ); @@ -2837,7 +2860,6 @@ void X11DRV_SetParent( HWND hwnd, HWND parent, HWND old_parent ) { /* destroy the old X windows */ destroy_whole_window( data, FALSE ); - data->managed = FALSE; } } else /* new top level window */ @@ -2871,14 +2893,7 @@ BOOL X11DRV_WindowPosChanging( HWND hwnd, UINT swp_flags, BOOL shaped, const str data->shaped = shaped;
/* check if we need to switch the window to managed */ - if (!data->managed && data->whole_window && is_window_managed( hwnd, swp_flags, &rects->window )) - { - TRACE( "making win %p/%lx managed\n", hwnd, data->whole_window ); - release_win_data( data ); - unmap_window( hwnd ); - if (!(data = get_win_data( hwnd ))) return FALSE; /* use default surface */ - data->managed = TRUE; - } + if (is_window_managed( hwnd, swp_flags, &rects->window )) window_set_managed( data, TRUE, FALSE );
ret = !!data->whole_window; /* use default surface if we don't have a window */ release_win_data( data );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 40179965676..129b0070a45 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2892,9 +2892,6 @@ BOOL X11DRV_WindowPosChanging( HWND hwnd, UINT swp_flags, BOOL shaped, const str if (!data && !(data = X11DRV_create_win_data( hwnd, rects ))) return FALSE; /* use default surface */ data->shaped = shaped;
- /* check if we need to switch the window to managed */ - if (is_window_managed( hwnd, swp_flags, &rects->window )) window_set_managed( data, TRUE, FALSE ); - ret = !!data->whole_window; /* use default surface if we don't have a window */ release_win_data( data );
@@ -2967,6 +2964,7 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UIN sync_gl_drawable( hwnd, FALSE );
if (!(data = get_win_data( hwnd ))) return; + if (is_window_managed( hwnd, swp_flags, &rects->window )) window_set_managed( data, TRUE, FALSE );
old_style = new_style & ~(WS_VISIBLE | WS_MINIMIZE | WS_MAXIMIZE); if (data->desired_state.wm_state != WithdrawnState) old_style |= WS_VISIBLE;
From: Rémi Bernon rbernon@codeweavers.com
Instead of checking for monitor rect. --- dlls/winex11.drv/window.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 129b0070a45..853acb5aa9e 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -376,7 +376,7 @@ static struct x11drv_win_data *alloc_win_data( Display *display, HWND hwnd ) * * Check if a given window should be managed */ -static BOOL is_window_managed( HWND hwnd, UINT swp_flags, const RECT *window_rect ) +static BOOL is_window_managed( HWND hwnd, UINT swp_flags, BOOL fullscreen ) { DWORD style, ex_style;
@@ -394,18 +394,10 @@ static BOOL is_window_managed( HWND hwnd, UINT swp_flags, const RECT *window_rec if (style & WS_THICKFRAME) return TRUE; if (style & WS_POPUP) { - HMONITOR hmon; - MONITORINFO mi; - /* popup with sysmenu == caption are managed */ if (style & WS_SYSMENU) return TRUE; /* full-screen popup windows are managed */ - hmon = NtUserMonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY ); - mi.cbSize = sizeof( mi ); - NtUserGetMonitorInfo( hmon, &mi ); - if (window_rect->left <= mi.rcWork.left && window_rect->right >= mi.rcWork.right && - window_rect->top <= mi.rcWork.top && window_rect->bottom >= mi.rcWork.bottom) - return TRUE; + if (fullscreen) return TRUE; } /* application windows are managed */ ex_style = NtUserGetWindowLongW( hwnd, GWL_EXSTYLE ); @@ -2141,7 +2133,7 @@ static void create_whole_window( struct x11drv_win_data *data ) if (data->vis.visualid != default_visual.visualid) data->whole_colormap = XCreateColormap( data->display, root_window, data->vis.visual, AllocNone );
- data->managed = is_window_managed( data->hwnd, SWP_NOACTIVATE, &data->rects.window ); + data->managed = is_window_managed( data->hwnd, SWP_NOACTIVATE, FALSE ); mask = get_window_attributes( data, &attr ) | CWOverrideRedirect; attr.override_redirect = !data->managed;
@@ -2964,7 +2956,7 @@ void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UIN sync_gl_drawable( hwnd, FALSE );
if (!(data = get_win_data( hwnd ))) return; - if (is_window_managed( hwnd, swp_flags, &rects->window )) window_set_managed( data, TRUE, FALSE ); + if (is_window_managed( hwnd, swp_flags, fullscreen )) window_set_managed( data, TRUE, FALSE );
old_style = new_style & ~(WS_VISIBLE | WS_MINIMIZE | WS_MAXIMIZE); if (data->desired_state.wm_state != WithdrawnState) old_style |= WS_VISIBLE;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/window.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-)
diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 67718936b53..e80bebdc042 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -362,7 +362,7 @@ static inline HWND get_active_window(void) * * Check if a given window should be managed */ -static BOOL is_window_managed(HWND hwnd, UINT swp_flags, const RECT *window_rect) +static BOOL is_window_managed(HWND hwnd, UINT swp_flags, BOOL fullscreen) { DWORD style, ex_style;
@@ -378,18 +378,10 @@ static BOOL is_window_managed(HWND hwnd, UINT swp_flags, const RECT *window_rect if (style & WS_THICKFRAME) return TRUE; if (style & WS_POPUP) { - HMONITOR hmon; - MONITORINFO mi; - /* popup with sysmenu == caption are managed */ if (style & WS_SYSMENU) return TRUE; /* full-screen popup windows are managed */ - hmon = NtUserMonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); - mi.cbSize = sizeof(mi); - NtUserGetMonitorInfo(hmon, &mi); - if (window_rect->left <= mi.rcWork.left && window_rect->right >= mi.rcWork.right && - window_rect->top <= mi.rcWork.top && window_rect->bottom >= mi.rcWork.bottom) - return TRUE; + if (fullscreen) return TRUE; } /* application windows are managed */ ex_style = NtUserGetWindowLongW(hwnd, GWL_EXSTYLE); @@ -448,7 +440,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, HWND owner_hint, UIN /* Get the managed state with win_data unlocked, as is_window_managed * may need to query win_data information about other HWNDs and thus * acquire the lock itself internally. */ - if (!(managed = is_window_managed(hwnd, swp_flags, &new_rects->window)) && surface) toplevel = owner_hint; + if (!(managed = is_window_managed(hwnd, swp_flags, fullscreen)) && surface) toplevel = owner_hint;
if (!(data = wayland_win_data_get(hwnd))) return; toplevel_data = toplevel && toplevel != hwnd ? wayland_win_data_get_nolock(toplevel) : NULL;
v3: Keep things simpler, only introduce the helper that can change from unmanaged to managed but forbid changes the other way around for now. Include the embedded flag changes within it too, as it need to be changed *after* window has been withdrawn.
Note that it may not be 100% correct: if an already managed window is changed to be embedded while it has WM_STATE changes inflight the Withdrawn request will be delayed. This is a preexisting issue though, and to address it we'd need to make the managed/embedded async like v2, which can be done later.