From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 46 +++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 14 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index ac967906646..53903954b17 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,30 @@ 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 ) +{ + XSetWindowAttributes attr = {.override_redirect = !new_managed}; + UINT wm_state = data->desired_state.wm_state; + BOOL old_managed = data->managed; + + if (!data->whole_window) return; /* no window, nothing to update */ + if (old_managed == new_managed) 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; + 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 @@ -1777,8 +1800,9 @@ void make_window_embedded( struct x11drv_win_data *data ) { /* the window cannot be mapped before being embedded */ window_set_wm_state( data, WithdrawnState ); + if (data->managed) WARN( "Window is already managed, should wait for WithdrawnState\n" ); + else window_set_managed( data, TRUE ); data->embedded = TRUE; - data->managed = TRUE; window_set_wm_state( data, NormalState ); }
@@ -2122,7 +2146,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 +2216,7 @@ 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;
memset( &data->desired_state, 0, sizeof(data->desired_state) ); memset( &data->pending_state, 0, sizeof(data->pending_state) ); @@ -2342,7 +2368,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 ); NtUserSetProp( data->hwnd, whole_window_prop, (HANDLE)win ); set_initial_wm_hints( display, win ); release_win_data( data ); @@ -2837,7 +2863,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 +2896,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 );
ret = !!data->whole_window; /* use default surface if we don't have a window */ release_win_data( data );