From: Rémi Bernon rbernon@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";