Server: implement per-device display mode override

This commit is contained in:
Yukino Song
2025-02-25 05:11:59 +08:00
parent 1cdd309cfd
commit c6127ed0e5
7 changed files with 115 additions and 25 deletions

View File

@@ -27,21 +27,75 @@ LONG getDeviceSettings(const wchar_t* deviceName, DEVMODEW& devMode) {
}
LONG changeDisplaySettings(const wchar_t* deviceName, int width, int height, int refresh_rate) {
DEVMODEW devMode = {0};
devMode.dmSize = sizeof(devMode);
if (EnumDisplaySettingsW(deviceName, ENUM_CURRENT_SETTINGS, &devMode)) {
devMode.dmPelsWidth = width;
devMode.dmPelsHeight = height;
devMode.dmDisplayFrequency = refresh_rate;
devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
return ChangeDisplaySettingsExW(deviceName, &devMode, NULL, CDS_UPDATEREGISTRY, NULL);
UINT32 pathCount = 0;
UINT32 modeCount = 0;
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount)) {
wprintf(L"[SUDOVDA] Failed to query display configuration size.\n");
return ERROR_INVALID_PARAMETER;
}
return 0;
std::vector<DISPLAYCONFIG_PATH_INFO> pathArray(pathCount);
std::vector<DISPLAYCONFIG_MODE_INFO> modeArray(modeCount);
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, pathArray.data(), &modeCount, modeArray.data(), nullptr) != ERROR_SUCCESS) {
wprintf(L"[SUDOVDA] Failed to query display configuration.\n");
return ERROR_INVALID_PARAMETER;
}
for (UINT32 i = 0; i < pathCount; i++) {
DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {};
sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
sourceName.header.size = sizeof(sourceName);
sourceName.header.adapterId = pathArray[i].sourceInfo.adapterId;
sourceName.header.id = pathArray[i].sourceInfo.id;
if (DisplayConfigGetDeviceInfo(&sourceName.header) != ERROR_SUCCESS) {
continue;
}
auto* sourceInfo = &pathArray[i].sourceInfo;
auto* targetInfo = &pathArray[i].targetInfo;
if (std::wstring_view(sourceName.viewGdiDeviceName) == std::wstring_view(deviceName)) {
wprintf(L"[SUDOVDA] Display found: %ls\n", deviceName);
for (UINT32 j = 0; j < modeCount; j++) {
if (
modeArray[j].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE &&
modeArray[j].adapterId.HighPart == sourceInfo->adapterId.HighPart &&
modeArray[j].adapterId.LowPart == sourceInfo->adapterId.LowPart &&
modeArray[j].id == sourceInfo->id
) {
auto* sourceMode = &modeArray[j].sourceMode;
wprintf(L"[SUDOVDA] Current mode found: %dx%dx%d\n", sourceMode->width, sourceMode->height, targetInfo->refreshRate);
sourceMode->width = width;
sourceMode->height = height;
targetInfo->refreshRate = {(UINT32)refresh_rate, 1000};
// Apply the changes
LONG status = SetDisplayConfig(pathCount, pathArray.data(), modeCount, modeArray.data(), SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG | SDC_SAVE_TO_DATABASE | SDC_ALLOW_CHANGES);
if (status != ERROR_SUCCESS) {
wprintf(L"[SUDOVDA] Failed to apply display settings.\n");
} else {
wprintf(L"[SUDOVDA] Display settings updated successfully.\n");
}
return status;
}
}
wprintf(L"[SUDOVDA] Mode %dx%dx%d not found for display: %ls\n", width, height, refresh_rate, deviceName);
return ERROR_INVALID_PARAMETER;
}
}
wprintf(L"[SUDOVDA] Display not found: %ls\n", deviceName);
return ERROR_DEVICE_NOT_CONNECTED;
}
std::wstring getPrimaryDisplay() {
DISPLAY_DEVICEW displayDevice;
displayDevice.cb = sizeof(DISPLAY_DEVICE);
@@ -117,8 +171,8 @@ bool setPrimaryDisplay(const wchar_t* primaryDeviceName) {
}
bool findDisplayIds(const wchar_t* displayName, LUID& adapterId, uint32_t& targetId) {
UINT pathCount;
UINT modeCount;
UINT32 pathCount;
UINT32 modeCount;
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount)) {
return false;
}
@@ -132,17 +186,17 @@ bool findDisplayIds(const wchar_t* displayName, LUID& adapterId, uint32_t& targe
auto path = std::find_if(paths.begin(), paths.end(), [&displayName](DISPLAYCONFIG_PATH_INFO _path) {
DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo = _path.sourceInfo;
DISPLAYCONFIG_SOURCE_DEVICE_NAME deviceName = {};
deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
deviceName.header.size = sizeof(deviceName);
deviceName.header.adapterId = sourceInfo.adapterId;
deviceName.header.id = sourceInfo.id;
DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {};
sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
sourceName.header.size = sizeof(sourceName);
sourceName.header.adapterId = sourceInfo.adapterId;
sourceName.header.id = sourceInfo.id;
if (DisplayConfigGetDeviceInfo(&deviceName.header) != ERROR_SUCCESS) {
if (DisplayConfigGetDeviceInfo(&sourceName.header) != ERROR_SUCCESS) {
return false;
}
return std::wstring_view(displayName) == deviceName.viewGdiDeviceName;
return std::wstring_view(displayName) == sourceName.viewGdiDeviceName;
});
if (path == paths.end()) {