winex11.drv: Support detaching adapters.

Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zhiyi Zhang 2020-07-27 16:01:04 +08:00 committed by Alexandre Julliard
parent 4a24816313
commit d13b61b738
3 changed files with 66 additions and 15 deletions

View file

@ -612,10 +612,10 @@ static void test_ChangeDisplaySettingsEx(void)
dd.cb = sizeof(dd);
res = EnumDisplayDevicesA(NULL, devices[device].index, &dd, 0);
ok(res, "EnumDisplayDevicesA %s failed, error %#x\n", devices[device].name, GetLastError());
todo_wine ok(!(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP), "Expect device %s detached.\n", devices[device].name);
ok(!(dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP), "Expect device %s detached.\n", devices[device].name);
count = GetSystemMetrics(SM_CMONITORS);
todo_wine ok(count == old_count - 1, "Expect monitor count %d, got %d\n", old_count - 1, count);
ok(count == old_count - 1, "Expect monitor count %d, got %d\n", old_count - 1, count);
}
/* Test changing each adapter to every available mode */

View file

@ -805,27 +805,33 @@ static void place_all_displays(struct x11drv_display_setting *displays, INT disp
}
}
static LONG apply_display_settings(struct x11drv_display_setting *displays, INT display_count)
static LONG apply_display_settings(struct x11drv_display_setting *displays, INT display_count, BOOL do_attach)
{
DEVMODEW *full_mode;
BOOL attached_mode;
INT display_idx;
LONG ret;
for (display_idx = 0; display_idx < display_count; ++display_idx)
{
if (is_detached_mode(&displays[display_idx].desired_mode))
{
FIXME("Detaching %s is currently unsupported.\n",
wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName));
attached_mode = !is_detached_mode(&displays[display_idx].desired_mode);
if ((attached_mode && !do_attach) || (!attached_mode && do_attach))
continue;
if (attached_mode)
{
full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode);
if (!full_mode)
return DISP_CHANGE_BADMODE;
full_mode->dmFields |= DM_POSITION;
full_mode->u1.s2.dmPosition = displays[display_idx].desired_mode.u1.s2.dmPosition;
}
else
{
full_mode = &displays[display_idx].desired_mode;
}
full_mode = get_full_mode(displays[display_idx].id, &displays[display_idx].desired_mode);
if (!full_mode)
return DISP_CHANGE_BADMODE;
full_mode->dmFields |= DM_POSITION;
full_mode->u1.s2.dmPosition = displays[display_idx].desired_mode.u1.s2.dmPosition;
TRACE("handler:%s changing %s to position:(%d,%d) resolution:%ux%u frequency:%uHz "
"depth:%ubits orientation:%#x.\n", handler.name,
wine_dbgstr_w(displays[display_idx].desired_mode.dmDeviceName),
@ -834,7 +840,8 @@ static LONG apply_display_settings(struct x11drv_display_setting *displays, INT
full_mode->u1.s2.dmDisplayOrientation);
ret = handler.set_current_mode(displays[display_idx].id, full_mode);
heap_free(full_mode);
if (attached_mode)
heap_free(full_mode);
if (ret != DISP_CHANGE_SUCCESSFUL)
return ret;
}
@ -842,6 +849,19 @@ static LONG apply_display_settings(struct x11drv_display_setting *displays, INT
return DISP_CHANGE_SUCCESSFUL;
}
static BOOL all_detached_settings(const struct x11drv_display_setting *displays, INT display_count)
{
INT display_idx;
for (display_idx = 0; display_idx < display_count; ++display_idx)
{
if (!is_detached_mode(&displays[display_idx].desired_mode))
return FALSE;
}
return TRUE;
}
/***********************************************************************
* ChangeDisplaySettingsEx (X11DRV.@)
*
@ -888,9 +908,19 @@ LONG CDECL X11DRV_ChangeDisplaySettingsEx( LPCWSTR devname, LPDEVMODEW devmode,
return DISP_CHANGE_SUCCESSFUL;
}
if (all_detached_settings(displays, display_count))
{
WARN("Detaching all displays is not permitted.\n");
heap_free(displays);
return DISP_CHANGE_SUCCESSFUL;
}
place_all_displays(displays, display_count);
ret = apply_display_settings(displays, display_count);
/* Detach displays first to free up CRTCs */
ret = apply_display_settings(displays, display_count, FALSE);
if (ret == DISP_CHANGE_SUCCESSFUL)
ret = apply_display_settings(displays, display_count, TRUE);
if (ret == DISP_CHANGE_SUCCESSFUL)
X11DRV_DisplayDevices_Update(TRUE);
heap_free(displays);

View file

@ -1306,6 +1306,27 @@ static LONG xrandr14_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
if (!output_info || output_info->connection != RR_Connected)
goto done;
if (is_detached_mode(mode))
{
/* Already detached */
if (!output_info->crtc)
{
ret = DISP_CHANGE_SUCCESSFUL;
goto done;
}
/* Execute detach operation */
status = pXRRSetCrtcConfig( gdi_display, screen_resources, output_info->crtc,
CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0 );
if (status == RRSetConfigSuccess)
{
get_screen_size( screen_resources, &screen_width, &screen_height );
set_screen_size( screen_width, screen_height );
ret = DISP_CHANGE_SUCCESSFUL;
}
goto done;
}
/* Attached */
if (output_info->crtc)
{