From: Rémi Bernon <rbernon(a)codeweavers.com> Fixes: 065d637e3eebbd0600b48f84447c5249cbea4752 --- dlls/winex11.drv/window.c | 34 ++++++++++++++++++++-------------- dlls/winex11.drv/x11drv.h | 10 ++++++++-- dlls/winex11.drv/xinerama.c | 6 +++++- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index e154db1e23a..066b5313a36 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -111,6 +111,11 @@ static const char *debugstr_mwm_hints( const MwmHints *hints ) return wine_dbg_sprintf( "%lx,%lx", hints->functions, hints->decorations ); } +static const char *debugstr_monitor_indices( const struct monitor_indices *monitors ) +{ + return wine_dbg_sprintf( "%ld,%ld,%ld,%ld", monitors->indices[0], monitors->indices[1], monitors->indices[2], monitors->indices[3] ); +} + static pthread_mutex_t win_data_mutex = PTHREAD_MUTEX_INITIALIZER; static void host_window_add_ref( struct host_window *win ) @@ -1168,7 +1173,7 @@ void window_set_user_time( struct x11drv_win_data *data, Time time, BOOL init ) * windows spanning multiple monitors */ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data ) { - long *old_monitors = data->pending_state.monitors, monitors[4]; + struct monitor_indices *old_monitors = &data->pending_state.monitors, monitors; XEvent xev; if (!(data->pending_state.net_wm_state & (1 << NET_WM_STATE_FULLSCREEN)) || is_virtual_desktop() @@ -1181,18 +1186,19 @@ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data ) if (!X11DRV_DisplayDevices_SupportEventHandlers()) return; - xinerama_get_fullscreen_monitors( &data->rects.visible, monitors ); - memcpy( data->desired_state.monitors, monitors, sizeof(monitors) ); - if (!memcmp( old_monitors, monitors, sizeof(monitors) )) return; /* states are the same, nothing to update */ + xinerama_get_fullscreen_monitors( &data->rects.visible, &monitors.generation, monitors.indices ); + data->desired_state.monitors = monitors; + + if (!memcmp( old_monitors, &monitors, sizeof(monitors) )) return; /* states are the same, nothing to update */ if (data->pending_state.wm_state == WithdrawnState) { - memcpy( data->pending_state.monitors, monitors, sizeof(monitors) ); - TRACE( "window %p/%lx, requesting _NET_WM_FULLSCREEN_MONITORS %ld,%ld,%ld,%ld serial %lu\n", data->hwnd, data->whole_window, - monitors[0], monitors[1], monitors[2], monitors[3], NextRequest( data->display ) ); - if (monitors[0] == -1) XDeleteProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_FULLSCREEN_MONITORS) ); + memcpy( &data->pending_state.monitors, &monitors, sizeof(monitors) ); + TRACE( "window %p/%lx, requesting _NET_WM_FULLSCREEN_MONITORS %s serial %lu\n", data->hwnd, data->whole_window, + debugstr_monitor_indices( &monitors ), NextRequest( data->display ) ); + if (monitors.indices[0] == -1) XDeleteProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_FULLSCREEN_MONITORS) ); else XChangeProperty( data->display, data->whole_window, x11drv_atom(_NET_WM_FULLSCREEN_MONITORS), - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)monitors, 4 ); + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)monitors.indices, 4 ); } else { @@ -1204,17 +1210,17 @@ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data ) xev.xclient.send_event = True; xev.xclient.format = 32; xev.xclient.data.l[4] = 1; - memcpy( xev.xclient.data.l, monitors, sizeof(monitors) ); + memcpy( xev.xclient.data.l, monitors.indices, sizeof(monitors.indices) ); - memcpy( data->pending_state.monitors, monitors, sizeof(monitors) ); - TRACE( "window %p/%lx, requesting _NET_WM_FULLSCREEN_MONITORS %ld,%ld,%ld,%ld serial %lu\n", data->hwnd, data->whole_window, - monitors[0], monitors[1], monitors[2], monitors[3], NextRequest( data->display ) ); + memcpy( &data->pending_state.monitors, &monitors, sizeof(monitors) ); + TRACE( "window %p/%lx, requesting _NET_WM_FULLSCREEN_MONITORS %s serial %lu\n", data->hwnd, data->whole_window, + debugstr_monitor_indices( &monitors ), NextRequest( data->display ) ); XSendEvent( data->display, DefaultRootWindow( data->display ), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev ); } /* assume it changes immediately, we don't track the property for now */ - memcpy( data->current_state.monitors, monitors, sizeof(monitors) ); + memcpy( &data->current_state.monitors, &monitors, sizeof(monitors) ); } static void window_set_net_wm_state( struct x11drv_win_data *data, UINT new_state ) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 1c7282d443d..42a145f9ee1 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -619,13 +619,19 @@ enum x11drv_net_wm_state NB_NET_WM_STATES }; +struct monitor_indices +{ + unsigned int generation; + long indices[4]; +}; + struct window_state { UINT wm_state; BOOL activate; UINT net_wm_state; MwmHints mwm_hints; - long monitors[4]; + struct monitor_indices monitors; RECT rect; }; @@ -737,7 +743,7 @@ extern POINT virtual_screen_to_root( INT x, INT y ); extern POINT root_to_virtual_screen( INT x, INT y ); extern RECT get_host_primary_monitor_rect(void); extern RECT get_work_area( const RECT *monitor_rect ); -extern void xinerama_get_fullscreen_monitors( const RECT *rect, long *indices ); +extern void xinerama_get_fullscreen_monitors( const RECT *rect, unsigned int *generation, long *indices ); extern void xinerama_init( unsigned int width, unsigned int height ); extern void init_recursive_mutex( pthread_mutex_t *mutex ); diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c index 096bd95f04e..5086f3ee766 100644 --- a/dlls/winex11.drv/xinerama.c +++ b/dlls/winex11.drv/xinerama.c @@ -46,6 +46,7 @@ static MONITORINFOEXW default_monitor = }; static pthread_mutex_t xinerama_mutex = PTHREAD_MUTEX_INITIALIZER; +static unsigned long xinerama_generation; static MONITORINFOEXW *monitors; static int nb_monitors; @@ -124,7 +125,7 @@ static inline int query_screens(void) #endif /* SONAME_LIBXINERAMA */ /* Get xinerama monitor indices required for _NET_WM_FULLSCREEN_MONITORS */ -void xinerama_get_fullscreen_monitors( const RECT *rect, long *indices ) +void xinerama_get_fullscreen_monitors( const RECT *rect, unsigned int *generation, long *indices ) { RECT window_rect, intersected_rect, monitor_rect; POINT offset; @@ -134,6 +135,7 @@ void xinerama_get_fullscreen_monitors( const RECT *rect, long *indices ) if (nb_monitors == 1) { memset( indices, 0, sizeof(*indices) * 4 ); + *generation = xinerama_generation; goto done; } @@ -154,6 +156,7 @@ void xinerama_get_fullscreen_monitors( const RECT *rect, long *indices ) } indices[0] = indices[1] = indices[2] = indices[3] = -1; + *generation = xinerama_generation; for (i = 0; i < nb_monitors; ++i) { SetRect( &monitor_rect, monitors[i].rcMonitor.left - offset.x, @@ -354,6 +357,7 @@ void xinerama_init( unsigned int width, unsigned int height ) (monitors[i].dwFlags & MONITORINFOF_PRIMARY) ? " (primary)" : "" ); } + xinerama_generation++; pthread_mutex_unlock( &xinerama_mutex ); handler.name = "Xinerama"; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8130