[DESK] Pass the list of all display modes to extensions

Also implement mode switching from adapter advanced settings.
This commit is contained in:
Stanislav Motylkov 2022-06-20 04:52:04 +03:00
parent fced1c1192
commit 994e2f289e
No known key found for this signature in database
GPG key ID: AFE513258CBA9E92
4 changed files with 266 additions and 62 deletions

View file

@ -122,6 +122,9 @@ HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY,LPCWSTR,UINT,IDataObject*);
INT_PTR CALLBACK
AdvGeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL
SwitchDisplayMode(HWND hwndDlg, PWSTR DeviceName, PSETTINGS_ENTRY seInit, PSETTINGS_ENTRY seNew, OUT PLONG rc);
LONG
RegLoadMUIStringW(IN HKEY hKey,
IN LPCWSTR pszValue OPTIONAL,

View file

@ -38,6 +38,10 @@ typedef struct _CDevSettings
DESK_EXT_INTERFACE ExtInterface;
PDEVMODEW lpOrigDevMode;
PDEVMODEW lpCurDevMode;
PDEVMODEW * DevModes;
DWORD nDevModes;
DWORD StateFlags;
union
@ -285,28 +289,63 @@ PDEVMODEW DESK_EXT_CALLBACK
CDevSettings_EnumAllModes(PVOID Context,
DWORD Index)
{
//PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
/* FIXME: Implement */
PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
DWORD i, idx = 0;
DPRINT1("CDevSettings::EnumAllModes(%u)\n", Index);
if (!This->DevModes)
return NULL;
for (i = 0; i < This->nDevModes; i++)
{
/* FIXME: Add more sanity checks */
if (!This->DevModes[i])
continue;
if (idx == Index)
return This->DevModes[i];
idx++;
}
return NULL;
}
PDEVMODEW DESK_EXT_CALLBACK
CDevSettings_GetCurrentMode(PVOID Context)
{
//PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
/* FIXME: Implement */
PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
DPRINT1("CDevSettings::GetCurrentMode\n");
return NULL;
return This->lpCurDevMode;
}
BOOL DESK_EXT_CALLBACK
CDevSettings_SetCurrentMode(PVOID Context,
const DEVMODEW *pDevMode)
DEVMODEW *pDevMode)
{
//PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
/* FIXME: Implement */
PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
DWORD i;
DPRINT1("CDevSettings::SetCurrentMode(0x%p)\n", pDevMode);
if (!This->DevModes)
return FALSE;
for (i = 0; i < This->nDevModes; i++)
{
/* FIXME: Add more sanity checks */
if (!This->DevModes[i])
continue;
if (This->DevModes[i] == pDevMode)
{
This->lpCurDevMode = pDevMode;
return TRUE;
}
}
return FALSE;
}
@ -455,7 +494,13 @@ pCDevSettings_Initialize(PCDevSettings This,
PDISPLAY_DEVICE_ENTRY DisplayDeviceInfo)
{
HKEY hKey;
DWORD i = 0, dwSize;
DEVMODEW devmode;
This->lpOrigDevMode = NULL;
This->lpCurDevMode = NULL;
This->DevModes = NULL;
This->nDevModes = 0;
This->Flags = 0;
This->StateFlags = DisplayDeviceInfo->DeviceStateFlags;
DPRINT1("This->StateFlags: %x\n", This->StateFlags);
@ -498,7 +543,7 @@ pCDevSettings_Initialize(PCDevSettings This,
if (hKey != NULL)
{
DWORD dw = 0;
DWORD dwType, dwSize;
DWORD dwType;
dwSize = sizeof(dw);
if (RegQueryValueEx(hKey,
@ -515,6 +560,80 @@ pCDevSettings_Initialize(PCDevSettings This,
RegCloseKey(hKey);
}
/* Initialize display modes */
ZeroMemory(&devmode, sizeof(devmode));
devmode.dmSize = (WORD)sizeof(devmode);
while (EnumDisplaySettingsExW(This->pDisplayDevice, i, &devmode, EDS_RAWMODE))
{
dwSize = devmode.dmSize + devmode.dmDriverExtra;
PDEVMODEW pDevMode = LocalAlloc(LMEM_FIXED, dwSize);
PDEVMODEW * DevModesNew = NULL;
if (pDevMode)
{
CopyMemory(pDevMode,
&devmode,
dwSize);
dwSize = (This->nDevModes + 1) * sizeof(pDevMode);
DevModesNew = LocalAlloc(LMEM_FIXED, dwSize);
if (DevModesNew)
{
if (This->DevModes)
{
CopyMemory(DevModesNew,
This->DevModes,
This->nDevModes * sizeof(pDevMode));
LocalFree(This->DevModes);
}
This->DevModes = DevModesNew;
This->DevModes[This->nDevModes++] = pDevMode;
}
else
{
DPRINT1("LocalAlloc failed to allocate %d bytes\n", dwSize);
return E_OUTOFMEMORY;
}
}
else
{
DPRINT1("LocalAlloc failed to allocate %d bytes\n", dwSize);
return E_OUTOFMEMORY;
}
devmode.dmDriverExtra = 0;
i++;
}
/* FIXME: Detect duplicated modes and mark them.
* Enumeration functions should check these marks
* and skip corresponding array entries. */
/* Get current display mode */
ZeroMemory(&devmode, sizeof(devmode));
devmode.dmSize = (WORD)sizeof(devmode);
if (EnumDisplaySettingsExW(This->pDisplayDevice, ENUM_CURRENT_SETTINGS, &devmode, 0))
{
for (i = 0; i < This->nDevModes; i++)
{
PDEVMODEW CurMode = This->DevModes[i];
if (!CurMode)
continue;
if (((CurMode->dmFields & DM_PELSWIDTH) && devmode.dmPelsWidth == CurMode->dmPelsWidth) &&
((CurMode->dmFields & DM_PELSHEIGHT) && devmode.dmPelsHeight == CurMode->dmPelsHeight) &&
((CurMode->dmFields & DM_BITSPERPEL) && devmode.dmBitsPerPel == CurMode->dmBitsPerPel) &&
((CurMode->dmFields & DM_DISPLAYFREQUENCY) && devmode.dmDisplayFrequency == CurMode->dmDisplayFrequency))
{
This->lpOrigDevMode = This->lpCurDevMode = CurMode;
break;
}
}
}
/* Initialize the shell extension interface */
pCDevSettings_InitializeExtInterface(This);
@ -524,6 +643,15 @@ pCDevSettings_Initialize(PCDevSettings This,
static VOID
pCDevSettings_Free(PCDevSettings This)
{
This->lpOrigDevMode = NULL;
This->lpCurDevMode = NULL;
while (This->nDevModes)
{
LocalFree(This->DevModes[--This->nDevModes]);
}
LocalFree(This->DevModes);
This->DevModes = NULL;
pCDevSettings_FreeString(&This->pDisplayDevice);
pCDevSettings_FreeString(&This->pDisplayName);
pCDevSettings_FreeString(&This->pDisplayKey);
@ -942,7 +1070,38 @@ LONG WINAPI
DisplaySaveSettings(PVOID pContext,
HWND hwndPropSheet)
{
//PCDevSettings This = impl_from_IDataObject((IDataObject *)Context);
DPRINT("DisplaySaveSettings() UNIMPLEMENTED!\n");
return DISP_CHANGE_BADPARAM;
PCDevSettings This = impl_from_IDataObject((IDataObject *)pContext);
LONG rc = DISP_CHANGE_SUCCESSFUL;
if (This->lpCurDevMode != This->lpOrigDevMode)
{
SETTINGS_ENTRY seOrig, seCur;
BOOL Ret;
seOrig.dmPelsWidth = This->lpOrigDevMode->dmPelsWidth;
seOrig.dmPelsHeight = This->lpOrigDevMode->dmPelsHeight;
seOrig.dmBitsPerPel = This->lpOrigDevMode->dmBitsPerPel;
seOrig.dmDisplayFrequency = This->lpOrigDevMode->dmDisplayFrequency;
seCur.dmPelsWidth = This->lpCurDevMode->dmPelsWidth;
seCur.dmPelsHeight = This->lpCurDevMode->dmPelsHeight;
seCur.dmBitsPerPel = This->lpCurDevMode->dmBitsPerPel;
seCur.dmDisplayFrequency = This->lpCurDevMode->dmDisplayFrequency;
Ret = SwitchDisplayMode(hwndPropSheet,
This->pDisplayDevice,
&seOrig,
&seCur,
&rc);
if (rc == DISP_CHANGE_SUCCESSFUL)
{
if (Ret)
This->lpOrigDevMode = This->lpCurDevMode;
else
This->lpCurDevMode = This->lpOrigDevMode;
}
}
return rc;
}

View file

@ -727,27 +727,26 @@ ConfirmDlgProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam
return FALSE;
}
static VOID
ApplyDisplaySettings(HWND hwndDlg, PSETTINGS_DATA pData)
BOOL
SwitchDisplayMode(HWND hwndDlg, PWSTR DeviceName, PSETTINGS_ENTRY seInit, PSETTINGS_ENTRY seNew, OUT PLONG rc)
{
TCHAR Message[1024], Title[256];
DEVMODE devmode;
LONG rc;
RtlZeroMemory(&devmode, sizeof(devmode));
devmode.dmSize = (WORD)sizeof(devmode);
devmode.dmPelsWidth = pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
devmode.dmPelsHeight = pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
devmode.dmBitsPerPel = pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
devmode.dmDisplayFrequency = pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency;
devmode.dmPelsWidth = seNew->dmPelsWidth;
devmode.dmPelsHeight = seNew->dmPelsHeight;
devmode.dmBitsPerPel = seNew->dmBitsPerPel;
devmode.dmDisplayFrequency = seNew->dmDisplayFrequency;
devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
rc = ChangeDisplaySettingsEx(pData->CurrentDisplayDevice->DeviceName,
&devmode,
NULL,
CDS_UPDATEREGISTRY,
NULL);
switch (rc)
*rc = ChangeDisplaySettingsEx(DeviceName,
&devmode,
NULL,
CDS_UPDATEREGISTRY,
NULL);
switch (*rc)
{
case DISP_CHANGE_SUCCESSFUL:
break;
@ -756,17 +755,69 @@ ApplyDisplaySettings(HWND hwndDlg, PSETTINGS_DATA pData)
LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, sizeof(Message) / sizeof (TCHAR));
MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION);
return;
return FALSE;
case DISP_CHANGE_FAILED:
default:
LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
LoadString(hApplet, IDS_APPLY_FAILED, Message, sizeof(Message) / sizeof (TCHAR));
MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP);
return;
return FALSE;
}
if (DialogBox(hApplet, MAKEINTRESOURCE(IDD_CONFIRMSETTINGS), hwndDlg, ConfirmDlgProc) == IDYES)
{
return TRUE;
}
else
{
devmode.dmPelsWidth = seInit->dmPelsWidth;
devmode.dmPelsHeight = seInit->dmPelsHeight;
devmode.dmBitsPerPel = seInit->dmBitsPerPel;
devmode.dmDisplayFrequency = seInit->dmDisplayFrequency;
*rc = ChangeDisplaySettingsEx(DeviceName,
&devmode,
NULL,
CDS_UPDATEREGISTRY,
NULL);
switch (*rc)
{
case DISP_CHANGE_SUCCESSFUL:
return FALSE;
case DISP_CHANGE_RESTART:
LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, sizeof(Message) / sizeof (TCHAR));
MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION);
return FALSE;
case DISP_CHANGE_FAILED:
default:
LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
LoadString(hApplet, IDS_APPLY_FAILED, Message, sizeof(Message) / sizeof (TCHAR));
MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP);
return FALSE;
}
}
}
static VOID
ApplyDisplaySettings(HWND hwndDlg, PSETTINGS_DATA pData)
{
BOOL Ret;
LONG rc;
Ret = SwitchDisplayMode(hwndDlg,
pData->CurrentDisplayDevice->DeviceName,
&pData->CurrentDisplayDevice->InitialSettings,
pData->CurrentDisplayDevice->CurrentSettings,
&rc);
if (rc != DISP_CHANGE_SUCCESSFUL)
return;
if (Ret)
{
pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
@ -775,39 +826,11 @@ ApplyDisplaySettings(HWND hwndDlg, PSETTINGS_DATA pData)
}
else
{
devmode.dmPelsWidth = pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth;
devmode.dmPelsHeight = pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight;
devmode.dmBitsPerPel = pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel;
devmode.dmDisplayFrequency = pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency;
rc = ChangeDisplaySettingsEx(pData->CurrentDisplayDevice->DeviceName,
&devmode,
NULL,
CDS_UPDATEREGISTRY,
NULL);
switch (rc)
{
case DISP_CHANGE_SUCCESSFUL:
pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth = pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth;
pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight = pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight;
pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel = pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel;
pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency = pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency;
UpdateDisplay(hwndDlg, pData, TRUE);
break;
case DISP_CHANGE_RESTART:
LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
LoadString(hApplet, IDS_APPLY_NEEDS_RESTART, Message, sizeof(Message) / sizeof (TCHAR));
MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONINFORMATION);
return;
case DISP_CHANGE_FAILED:
default:
LoadString(hApplet, IDS_DISPLAY_SETTINGS, Title, sizeof(Title) / sizeof(TCHAR));
LoadString(hApplet, IDS_APPLY_FAILED, Message, sizeof(Message) / sizeof (TCHAR));
MessageBox(hwndDlg, Message, Title, MB_OK | MB_ICONSTOP);
return;
}
pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth = pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth;
pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight = pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight;
pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel = pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel;
pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency = pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency;
UpdateDisplay(hwndDlg, pData, TRUE);
}
}
@ -841,7 +864,26 @@ SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lPar
DWORD command = HIWORD(wParam);
if (controlId == IDC_SETTINGS_ADVANCED && command == BN_CLICKED)
DisplayAdvancedSettings(hwndDlg, pData->CurrentDisplayDevice);
{
if (DisplayAdvancedSettings(hwndDlg, pData->CurrentDisplayDevice))
{
DEVMODE devmode;
ZeroMemory(&devmode, sizeof(devmode));
devmode.dmSize = (WORD)sizeof(devmode);
if (EnumDisplaySettingsExW(pData->CurrentDisplayDevice->DeviceName, ENUM_CURRENT_SETTINGS, &devmode, 0))
{
pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = devmode.dmPelsWidth;
pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = devmode.dmPelsHeight;
pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = devmode.dmBitsPerPel;
pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency = devmode.dmDisplayFrequency;
pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth = pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth;
pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight = pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight;
pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel = pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel;
pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency = pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency;
UpdateDisplay(hwndDlg, pData, TRUE);
}
}
}
else if (controlId == IDC_SETTINGS_BPP && command == CBN_SELCHANGE)
OnBPPChanged(hwndDlg, pData);
break;

View file

@ -15,7 +15,7 @@
typedef PDEVMODEW (DESK_EXT_CALLBACK *PDESK_EXT_ENUMALLMODES)(PVOID Context, DWORD Index);
typedef PDEVMODEW (DESK_EXT_CALLBACK *PDESK_EXT_GETCURRENTMODE)(PVOID Context);
typedef BOOL (DESK_EXT_CALLBACK *PDESK_EXT_SETCURRENTMODE)(PVOID Context, const DEVMODEW *pDevMode);
typedef BOOL (DESK_EXT_CALLBACK *PDESK_EXT_SETCURRENTMODE)(PVOID Context, DEVMODEW *pDevMode);
typedef VOID (DESK_EXT_CALLBACK *PDESK_EXT_GETPRUNINGMODE)(PVOID Context, PBOOL pbModesPruned, PBOOL pbKeyIsReadOnly, PBOOL pbPruningOn);
typedef VOID (DESK_EXT_CALLBACK *PDESK_EXT_SETPRUNINGMODE)(PVOID Context, BOOL PruningOn);