From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 4 +- dlls/winex11.drv/window.c | 79 ++++++++++++++++++++++++--------------- dlls/winex11.drv/x11drv.h | 2 +- 3 files changed, 51 insertions(+), 34 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 428dcb7b8b7..a0555e0e6e5 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -1024,7 +1024,7 @@ static BOOL X11DRV_MapNotify( HWND hwnd, XEvent *event )
if (!(data = get_win_data( hwnd ))) return FALSE;
- if (!data->managed && !data->embedded && data->desired_state.wm_state != WithdrawnState) + if (!data->pending_state.managed && !data->embedded && data->desired_state.wm_state != WithdrawnState) { HWND hwndFocus = get_focus(); if (hwndFocus && NtUserIsChild( hwnd, hwndFocus )) @@ -1299,7 +1299,7 @@ void X11DRV_SetFocus( HWND hwnd ) release_win_data( data ); hwnd = parent; } - if (!data->managed || data->embedder) set_input_focus( data ); + if (!data->pending_state.managed || data->embedder) set_input_focus( data ); release_win_data( data ); }
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index ac967906646..932fc7494e7 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -311,7 +311,7 @@ static void remove_startup_notification(Display *display, Window window) static BOOL is_managed( HWND hwnd ) { struct x11drv_win_data *data = get_win_data( hwnd ); - BOOL ret = data && data->managed; + BOOL ret = data && data->desired_state.managed; release_win_data( data ); return ret; } @@ -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); }
@@ -1308,7 +1307,7 @@ static void window_set_config( struct x11drv_win_data *data, const RECT *new_rec /* resizing a managed maximized window is not allowed */ if ((old_rect->right - old_rect->left != new_rect->right - new_rect->left || old_rect->bottom - old_rect->top != new_rect->bottom - new_rect->top) && - (!(style & WS_MAXIMIZE) || !data->managed)) + (!(style & WS_MAXIMIZE) || !data->pending_state.managed)) { changes.width = new_rect->right - new_rect->left; changes.height = new_rect->bottom - new_rect->top; @@ -1349,7 +1348,7 @@ static void update_net_wm_states( struct x11drv_win_data *data ) { UINT style, ex_style, new_state = 0;
- if (!data->managed || data->embedded) return; + if (!data->pending_state.managed || data->embedded) return; if (data->whole_window == root_window) { update_desktop_fullscreen(data->display); @@ -1454,7 +1453,7 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state ) * Mutter, a window can be both iconic and mapped. If the window is mapped, then XMapWindow() * will have no effect according to the XMapWindow() documentation. Thus we have to transition * to WithdrawnState first, then to NormalState */ - if (data->managed && MAKELONG(old_state, new_state) == MAKELONG(IconicState, NormalState)) + if (data->pending_state.managed && MAKELONG(old_state, new_state) == MAKELONG(IconicState, NormalState)) { WARN( "window %p/%lx is iconic, remapping to workaround Mutter issues.\n", data->hwnd, data->whole_window ); window_set_wm_state( data, WithdrawnState ); @@ -1494,7 +1493,7 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state ) case MAKELONG(NormalState, WithdrawnState): case MAKELONG(IconicState, WithdrawnState): if (data->embedded) set_xembed_flags( data, 0 ); - else if (!data->managed) XUnmapWindow( data->display, data->whole_window ); + else if (!data->pending_state.managed) XUnmapWindow( data->display, data->whole_window ); else XWithdrawWindow( data->display, data->whole_window, data->vis.screen ); break; case MAKELONG(NormalState, IconicState): @@ -1503,11 +1502,32 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state ) }
/* override redirect windows won't receive WM_STATE property changes */ - if (!data->managed) data->wm_state_serial = 0; + if (!data->pending_state.managed) data->wm_state_serial = 0;
XFlush( data->display ); }
+static void window_set_managed( struct x11drv_win_data *data, UINT new_managed ) +{ + UINT wm_state = data->desired_state.wm_state, old_managed = data->pending_state.managed; + XSetWindowAttributes attr = {.override_redirect = !new_managed}; + + data->desired_state.managed = new_managed; + if (!data->whole_window) return; /* no window, nothing to update */ + if (data->wm_state_serial) return; /* another WM_STATE update is pending, wait for it to complete */ + if (old_managed == new_managed) return; /* states are the same, nothing to update */ + + window_set_wm_state( data, WithdrawnState ); /* no WM_STATE is pending, requested immediately */ + + data->pending_state.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 ); + data->current_state.managed = new_managed; /* assume it takes effect immediately */ + + window_set_wm_state( data, wm_state ); /* queue another WM_STATE request with the desired state */ +} +
/*********************************************************************** * map_window @@ -1542,7 +1562,7 @@ static UINT window_update_client_state( struct x11drv_win_data *data ) { UINT old_style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ), new_style;
- if (!data->managed) return 0; /* unmanaged windows are managed by the Win32 side */ + if (!data->desired_state.managed) return 0; /* unmanaged windows are managed by the Win32 side */ if (data->desired_state.wm_state == WithdrawnState) return 0; /* ignore state changes on invisible windows */
if (data->wm_state_serial) return 0; /* another WM_STATE update is pending, wait for it to complete */ @@ -1589,7 +1609,7 @@ static UINT window_update_client_config( struct x11drv_win_data *data ) UINT old_style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ), flags; RECT rect, old_rect = data->rects.window, new_rect;
- if (!data->managed) return 0; /* unmanaged windows are managed by the Win32 side */ + if (!data->desired_state.managed) return 0; /* unmanaged windows are managed by the Win32 side */ if (data->desired_state.wm_state != NormalState) return 0; /* ignore config changes on invisible/minimized windows */
if (data->wm_state_serial) return 0; /* another WM_STATE update is pending, wait for it to complete */ @@ -1683,6 +1703,7 @@ void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, *expect_serial = 0;
/* send any pending changes from the desired state */ + window_set_managed( data, data->desired_state.managed ); window_set_wm_state( data, data->desired_state.wm_state ); window_set_net_wm_state( data, data->desired_state.net_wm_state ); window_set_config( data, &data->desired_state.rect, FALSE ); @@ -1720,6 +1741,7 @@ void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long ser *expect_serial = 0;
/* send any pending changes from the desired state */ + window_set_managed( data, data->desired_state.managed ); window_set_wm_state( data, data->desired_state.wm_state ); window_set_net_wm_state( data, data->desired_state.net_wm_state ); window_set_config( data, &data->desired_state.rect, FALSE ); @@ -1776,10 +1798,8 @@ 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 ); }
@@ -1795,7 +1815,7 @@ static void sync_window_position( struct x11drv_win_data *data, UINT swp_flags, RECT new_rect, window_rect; BOOL above = FALSE;
- if (data->managed && data->desired_state.wm_state == IconicState) return; + if (data->desired_state.managed && data->desired_state.wm_state == IconicState) return;
if (!(swp_flags & SWP_NOZORDER) || (swp_flags & SWP_SHOWWINDOW)) { @@ -2121,8 +2141,12 @@ 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 ); + data->current_state.managed = is_window_managed( data->hwnd, SWP_NOACTIVATE, &data->rects.window ); + data->pending_state.managed = data->current_state.managed; + data->desired_state.managed = data->current_state.managed; + + mask = get_window_attributes( data, &attr ) | CWOverrideRedirect; + attr.override_redirect = !data->current_state.managed;
if (!(cx = data->rects.visible.right - data->rects.visible.left)) cx = 1; else if (cx > 65535) cx = 65535; @@ -2342,7 +2366,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 +2861,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 +2894,8 @@ 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 (!data->desired_state.managed && data->whole_window && 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 ); @@ -2922,7 +2939,7 @@ BOOL X11DRV_GetWindowStyleMasks( HWND hwnd, UINT style, UINT ex_style, UINT *sty
if ((data = get_win_data( hwnd ))) { - if (!data->managed) decor = 0; + if (!data->desired_state.managed) decor = 0; release_win_data( data ); }
@@ -2989,7 +3006,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)))) + if (!(data->pending_state.managed && (swp_flags & SWP_STATECHANGED) && (new_style & (WS_MINIMIZE|WS_MAXIMIZE)))) { sync_window_position( data, swp_flags, &old_rects ); #ifdef HAVE_LIBXSHAPE @@ -3046,7 +3063,7 @@ static BOOL hide_icon( struct x11drv_win_data *data ) static const WCHAR trayW[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0}; UNICODE_STRING str = RTL_CONSTANT_STRING( trayW );
- if (data->managed) return TRUE; + if (data->desired_state.managed) return TRUE; /* hide icons in desktop mode when the taskbar is active */ if (!is_virtual_desktop()) return FALSE; return NtUserIsWindowVisible( NtUserFindWindowEx( 0, 0, &str, NULL, 0 )); @@ -3075,7 +3092,7 @@ UINT X11DRV_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ) } goto done; } - if (!data->managed || data->desired_state.wm_state != NormalState) goto done; + if (!data->desired_state.managed || data->desired_state.wm_state != NormalState) goto done;
/* only fetch the new rectangle if the ShowWindow was a result of a window manager event */
@@ -3342,7 +3359,7 @@ LRESULT X11DRV_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam, const POINT if (wparam == SC_SCREENSAVE && hwnd == NtUserGetDesktopWindow()) return start_screensaver(); return -1; } - if (!data->whole_window || !data->managed || data->desired_state.wm_state == WithdrawnState) goto failed; + if (!data->whole_window || !data->desired_state.managed || data->desired_state.wm_state == WithdrawnState) goto failed;
switch (wparam & 0xfff0) { diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 8e383ae4c48..1b20479521b 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -611,6 +611,7 @@ struct window_state { UINT wm_state; UINT net_wm_state; + UINT managed; RECT rect; };
@@ -626,7 +627,6 @@ struct x11drv_win_data struct window_rects rects; /* window rects in monitor DPI, relative to parent client area */ struct host_window *parent; /* the host window parent, frame or embedder, NULL if root_window */ XIC xic; /* X input context */ - UINT managed : 1; /* is window managed? */ UINT embedded : 1; /* is window an XEMBED client? */ UINT shaped : 1; /* is window using a custom region shape? */ UINT layered : 1; /* is window layered and with valid attributes? */