From: Zhiyi Zhang zzhang@codeweavers.com
This fixes a regression from 6dc9f5e1, which made calling update_net_wm_fullscreen_monitors() before a window is mapped. Thus after a window gets mapped and managed by window managers, _NET_WM_FULLSCREEN_MONITORS may not be set and so windows covering multiple monitors don't function as expected.
Partially fix Project CARS 3 (958400) fails to enter triple screen mode. --- dlls/winex11.drv/window.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index a733d566d4f..1fe96f03897 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -1432,7 +1432,6 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state, B set_wm_hints( data ); update_net_wm_states( data ); sync_window_style( data ); - update_net_wm_fullscreen_monitors( data ); break; case MAKELONG(IconicState, NormalState): case MAKELONG(NormalState, IconicState): @@ -1459,7 +1458,11 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state, B case MAKELONG(WithdrawnState, NormalState): case MAKELONG(IconicState, NormalState): if (data->embedded) set_xembed_flags( data, XEMBED_MAPPED ); - else XMapWindow( data->display, data->whole_window ); + else + { + XMapWindow( data->display, data->whole_window ); + update_net_wm_fullscreen_monitors( data ); + } break; case MAKELONG(NormalState, WithdrawnState): case MAKELONG(IconicState, WithdrawnState):
From: Zhiyi Zhang zzhang@codeweavers.com
Fix a regression from 545073fd, which restricts the visible rect to only one monitor when the original virtual visible rect is spanning multiple monitors.
Fix Project CARS 3 (958400) fails to enter triple screen mode. --- dlls/win32u/sysparams.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index e33ff6e60e5..b7b2c1fc004 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2602,23 +2602,30 @@ RECT map_rect_virt_to_raw( RECT rect, UINT dpi_from ) /* map (absolute) window rects from MDT_DEFAULT to MDT_RAW_DPI coordinates */ struct window_rects map_window_rects_virt_to_raw( struct window_rects rects, UINT dpi_from ) { + RECT rect, monitor_rect, virt_visible_rect = rects.visible; struct monitor *monitor; - RECT rect, monitor_rect; BOOL is_fullscreen;
if (!lock_display_devices( FALSE )) return rects; if ((monitor = get_monitor_from_rect( rects.window, MONITOR_DEFAULTTONEAREST, dpi_from, MDT_DEFAULT ))) { - /* if the visible rect is fullscreen, make it cover the full raw monitor, regardless of aspect ratio */ - monitor_rect = monitor_get_rect( monitor, dpi_from, MDT_DEFAULT ); - - is_fullscreen = intersect_rect( &rect, &monitor_rect, &rects.visible ) && EqualRect( &rect, &monitor_rect ); - if (is_fullscreen) rects.visible = monitor_get_rect( monitor, 0, MDT_RAW_DPI ); - else rects.visible = map_monitor_rect( monitor, rects.visible, dpi_from, MDT_DEFAULT, 0, MDT_RAW_DPI ); - + rects.visible = map_monitor_rect( monitor, rects.visible, dpi_from, MDT_DEFAULT, 0, MDT_RAW_DPI ); rects.window = map_monitor_rect( monitor, rects.window, dpi_from, MDT_DEFAULT, 0, MDT_RAW_DPI ); rects.client = map_monitor_rect( monitor, rects.client, dpi_from, MDT_DEFAULT, 0, MDT_RAW_DPI ); } + /* if the visible rect is fullscreen, make it cover the full raw monitor, regardless of aspect ratio */ + LIST_FOR_EACH_ENTRY(monitor, &monitors, struct monitor, entry) + { + if (!is_monitor_active( monitor ) || monitor->is_clone) continue; + + monitor_rect = monitor_get_rect( monitor, dpi_from, MDT_DEFAULT ); + is_fullscreen = intersect_rect( &rect, &monitor_rect, &virt_visible_rect ) && EqualRect( &rect, &monitor_rect ); + if (is_fullscreen) + { + rect = monitor_get_rect( monitor, 0, MDT_RAW_DPI ); + union_rect( &rects.visible, &rects.visible, &rect ); + } + } unlock_display_devices();
return rects;
Rémi Bernon (@rbernon) commented about dlls/winex11.drv/window.c:
I don't understand what difference it makes, or even how this is better? When the window is mapped, window managers should check whether it has the property set already, (and whether it is fullscreen) and apply the proper changes.
On Thu Apr 3 08:54:07 2025 +0000, Rémi Bernon wrote:
I didn't check the Mutter logs. I am gussing this is what happens regarding a window that covers two monitors.
On Mutter, the _NET_WM_FULLSCREEN_MONITORS property is not checked when a window is mapped. For example, meta_x11_display_init_window_prop_hooks() doesn't load the _NET_WM_FULLSCREEN_MONITORS property. So in meta_window_x11_set_net_wm_state(), window->fullscreen is TRUE, but meta_window_has_fullscreen_monitors(window) is FALSE because window->fullscreen_monitors is not initialized. So _NET_WM_FULLSCREEN_MONITORS then gets deleted at the end of meta_window_x11_set_net_wm_state(). With window->fullscreen being TRUE, the window becomes fullscreen only on one monitor, and then a ConfigureNotify is sent. Then Wine synchronizes the window size with that of the X11 window, which only covers one monitor.
Now that you mentioned it. It's probably Mutter's bug. I will see if I can get it fixed on the Mutter side.