[DESK] Pass the list of all display modes to extensions 4553/head
authorStanislav Motylkov <x86corez@gmail.com>
Mon, 20 Jun 2022 01:52:04 +0000 (04:52 +0300)
committerStanislav Motylkov <x86corez@gmail.com>
Mon, 20 Jun 2022 11:38:03 +0000 (14:38 +0300)
Also implement mode switching from adapter advanced settings.

dll/cpl/desk/desk.h
dll/cpl/desk/devsett.c
dll/cpl/desk/settings.c
sdk/include/reactos/dll/desk/deskcplx.h

index 3c47925..36470ff 100644 (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,
index dc801f4..d48c949 100644 (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;
 }
index d0b8d12..b161214 100644 (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,61 +755,85 @@ 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)
     {
-        pData->CurrentDisplayDevice->InitialSettings.dmPelsWidth = pData->CurrentDisplayDevice->CurrentSettings->dmPelsWidth;
-        pData->CurrentDisplayDevice->InitialSettings.dmPelsHeight = pData->CurrentDisplayDevice->CurrentSettings->dmPelsHeight;
-        pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
-        pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency = pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency;
+        return TRUE;
     }
     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)
+        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:
-                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;
+                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;
+                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;
         }
     }
 }
 
+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;
+        pData->CurrentDisplayDevice->InitialSettings.dmBitsPerPel = pData->CurrentDisplayDevice->CurrentSettings->dmBitsPerPel;
+        pData->CurrentDisplayDevice->InitialSettings.dmDisplayFrequency = pData->CurrentDisplayDevice->CurrentSettings->dmDisplayFrequency;
+    }
+    else
+    {
+        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);
+    }
+}
+
 /* Property page dialog callback */
 INT_PTR CALLBACK
 SettingsPageProc(IN HWND hwndDlg, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
@@ -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;
index 8647191..1b77344 100644 (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);