Created new infrastructure for SystemParametersInfo function. Used it
to implement processing for SPI_GET/SETBEEP, SPI_GET/SETBORDER,
SPI_GET/SETSHOWSOUNDS system parameters.
diff --git a/windows/sysmetrics.c b/windows/sysmetrics.c
index c94ca37..302bdd3 100644
--- a/windows/sysmetrics.c
+++ b/windows/sysmetrics.c
@@ -105,6 +105,8 @@
{
HDC hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
HKEY hkey; /* key to the window metrics area of the registry */
+ INT dummy;
+
assert(hdc);
if (RegOpenKeyExA (HKEY_CURRENT_USER, "Control Panel\\desktop\\WindowMetrics",
@@ -126,14 +128,8 @@
sysMetrics[SM_CXDLGFRAME] = 3;
sysMetrics[SM_CYDLGFRAME] = sysMetrics[SM_CXDLGFRAME];
- sysMetrics[SM_CXFRAME] = SYSMETRICS_GetRegistryMetric(hkey, "BorderWidth", 1)
- + sysMetrics[SM_CXDLGFRAME];
- sysMetrics[SM_CYFRAME] = sysMetrics[SM_CXFRAME];
- /* Since I am unable to get SM_CXDLGFRAME to be anything other than 3 on
- * my Win95 computer I cannot proved the above assumption that the frame
- * size is dependent on it. However the above relationship is assumed in
- * the painting of the Windows 95 frames (currently in nonclient.c)
- */
+ /* force setting of SM_CXFRAME/SM_CYFRAME */
+ SystemParametersInfoA( SPI_GETBORDER, 0, &dummy, 0 );
}
else
{
@@ -234,7 +230,6 @@
sysMetrics[SM_CXDRAG] = 2;
sysMetrics[SM_CYDRAG] = 2;
- sysMetrics[SM_SHOWSOUNDS] = 0;
sysMetrics[SM_CXMENUCHECK] = 14;
sysMetrics[SM_CYMENUCHECK] = 14;
@@ -254,6 +249,8 @@
sysMetrics[SM_SAMEDISPLAYFORMAT] = 1;
sysMetrics[SM_CMETRICS] = SM_CMETRICS;
+ SystemParametersInfoA( SPI_GETSHOWSOUNDS, 0, &sysMetrics[SM_SHOWSOUNDS], FALSE );
+
if (hkey) RegCloseKey (hkey);
DeleteDC( hdc );
}
diff --git a/windows/sysparams.c b/windows/sysparams.c
index 531ef6c..79440ca 100644
--- a/windows/sysparams.c
+++ b/windows/sysparams.c
@@ -6,6 +6,7 @@
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "windef.h"
@@ -23,7 +24,38 @@
DEFAULT_DEBUG_CHANNEL(system);
+/* System parameter indexes */
+#define SPI_SETBEEP_IDX 0
+#define SPI_SETBORDER_IDX 1
+#define SPI_SETSHOWSOUNDS_IDX 2
+#define SPI_WINE_IDX SPI_SETSHOWSOUNDS_IDX
+
+/**
+ * Names of the registry subkeys of HKEY_CURRENT_USER key and value names
+ * for the system parameters.
+ * Names of the keys are created by adding string "_REGKEY" to
+ * "SET" action names, value names are created by adding "_REG_NAME"
+ * to the "SET" action name.
+ */
+#define SPI_SETBEEP_REGKEY "Control Panel\\Sound"
+#define SPI_SETBEEP_VALNAME "Beep"
+#define SPI_SETSHOWSOUNDS_REGKEY "Control Panel\\Accessibility\\ShowSounds"
+#define SPI_SETSHOWSOUNDS_VALNAME "On"
+#define SPI_SETBORDER_REGKEY "Control Panel\\Desktop"
+#define SPI_SETBORDER_VALNAME "BorderWidth"
+
+/* volatile registry branch under CURRENT_USER_REGKEY for temporary values storage */
+#define WINE_CURRENT_USER_REGKEY "Wine"
+
+/* Indicators whether system parameter value is loaded */
+static char spi_loaded[SPI_WINE_IDX + 1];
+
+static BOOL notify_change = TRUE;
+
+/* System parameters storage */
static BOOL beep_active = TRUE;
+static int border = 1;
+
/***********************************************************************
* GetTimerResolution (USER.14)
@@ -116,7 +148,199 @@
}
/***********************************************************************
+ * SYSPARAMS_Reset
+ *
+ * Sets the system parameter which should be always loaded to
+ * current value stored in registry.
+ * Invalidates lazy loaded parameter, so it will be loaded the next time
+ * it is requested.
+ *
+ * Parameters:
+ * uiAction - system parameter to reload value for.
+ * Note, only "SET" values can be used for this parameter.
+ * If uiAction is 0 all system parameters are reset.
+ */
+void SYSPARAMS_Reset( UINT uiAction )
+{
+#define WINE_RELOAD_SPI(x) \
+ case x: \
+ spi_loaded[x##_IDX] = FALSE; \
+ SystemParametersInfoA( x, 0, dummy_buf, 0 );\
+ if (uiAction) \
+ break
+
+#define WINE_INVALIDATE_SPI(x) \
+ case x: \
+ spi_loaded[x##_IDX] = FALSE; \
+ break
+
+ BOOL not_all_processed = TRUE;
+ char dummy_buf[10];
+
+ /* Execution falls through all the branches for uiAction == 0 */
+ switch (uiAction)
+ {
+ case 0:
+ memset( spi_loaded, 0, sizeof(spi_loaded) );
+
+ WINE_RELOAD_SPI(SPI_SETBORDER);
+ WINE_RELOAD_SPI(SPI_SETSHOWSOUNDS);
+
+ default:
+ if (uiAction)
+ {
+ /* lazy loaded parameters */
+ switch (uiAction)
+ {
+ WINE_INVALIDATE_SPI(SPI_SETBEEP);
+ default:
+ FIXME( "Unknown action reset: %u\n", uiAction );
+ break;
+ }
+ }
+ else
+ not_all_processed = FALSE;
+ break;
+ }
+
+ if (!uiAction && not_all_processed)
+ ERR( "Incorrect implementation of SYSPARAMS_Reset. "
+ "Not all params are reloaded.\n" );
+#undef WINE_INVALIDATE_SPI
+#undef WINE_RELOAD_SPI
+}
+
+/***********************************************************************
+ * get_volatile_regkey
+ *
+ * Return a handle to the volatile registry key used to store
+ * non-permanently modified parameters.
+ */
+static HKEY get_volatile_regkey(void)
+{
+ static HKEY volatile_key;
+
+ if (!volatile_key)
+ {
+ /* FIXME - check whether the key exists
+ notify_change = FALSE;
+ if (WINE_CURRENT_USER_REGKEY does not exist)
+ {
+ initialize system parameters info which take values from X settings,
+ if(current settings differ from X)
+ change current setting and save it;
+ }
+ notify_change = TRUE;
+ */
+
+ if (RegCreateKeyExA( HKEY_CURRENT_USER, WINE_CURRENT_USER_REGKEY,
+ 0, 0, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, 0,
+ &volatile_key, 0 ) != ERROR_SUCCESS)
+ ERR("Can't create wine configuration registry branch");
+ }
+ return volatile_key;
+}
+
+/***********************************************************************
+ * SYSPARAMS_NotifyChange
+ *
+ * Sends notification about system parameter update.
+ */
+void SYSPARAMS_NotifyChange( UINT uiAction, UINT fWinIni )
+{
+ if (notify_change)
+ {
+ if (fWinIni & SPIF_UPDATEINIFILE)
+ {
+ if (fWinIni & (SPIF_SENDWININICHANGE | SPIF_SENDCHANGE))
+ SendMessageA(HWND_BROADCAST, WM_SETTINGCHANGE,
+ uiAction, (LPARAM) "");
+ }
+ else
+ {
+ /* FIXME notify other wine processes with internal message */
+ }
+ }
+}
+
+
+/***********************************************************************
+ * Loads system parameter from user profile.
+ */
+BOOL SYSPARAMS_Load( LPSTR lpRegKey, LPSTR lpValName, LPSTR lpBuf )
+{
+ BOOL ret = FALSE;
+ DWORD type;
+ HKEY hKey;
+ DWORD count;
+
+ if ((RegOpenKeyA( get_volatile_regkey(), lpRegKey,
+ &hKey ) == ERROR_SUCCESS) ||
+ (RegOpenKeyA( HKEY_CURRENT_USER, lpRegKey,
+ &hKey ) == ERROR_SUCCESS))
+ {
+ ret = !RegQueryValueExA( hKey, lpValName, NULL, &type, lpBuf, &count );
+ RegCloseKey( hKey );
+ }
+ return ret;
+}
+
+/***********************************************************************
+ * Saves system parameter to user profile.
+ */
+BOOL SYSPARAMS_Save( LPSTR lpRegKey, LPSTR lpValName, LPSTR lpValue,
+ UINT fWinIni )
+{
+ HKEY hKey;
+ HKEY hBaseKey;
+ DWORD dwOptions;
+ BOOL ret = FALSE;
+
+ if (fWinIni & SPIF_UPDATEINIFILE)
+ {
+ hBaseKey = HKEY_CURRENT_USER;
+ dwOptions = 0;
+ }
+ else
+ {
+ hBaseKey = get_volatile_regkey();
+ dwOptions = REG_OPTION_VOLATILE;
+ }
+
+ if (RegCreateKeyExA( hBaseKey, lpRegKey,
+ 0, 0, dwOptions, KEY_ALL_ACCESS,
+ 0, &hKey, 0 ) == ERROR_SUCCESS)
+ {
+ if (RegSetValueExA( hKey, lpValName, 0, REG_SZ,
+ lpValue, strlen(lpValue) + 1 ) == ERROR_SUCCESS)
+ {
+ ret = TRUE;
+ if (hBaseKey == HKEY_CURRENT_USER)
+ RegDeleteKeyA( get_volatile_regkey(), lpRegKey );
+ }
+ RegCloseKey( hKey );
+ }
+ return ret;
+}
+
+/***********************************************************************
* SystemParametersInfoA (USER32.@)
+ *
+ * Each system parameter has flag which shows whether the parameter
+ * is loaded or not. Parameters, stored directly in SysParametersInfo are
+ * loaded from registry only when they are requested and the flag is
+ * "false", after the loading the flag is set to "true". On interprocess
+ * notification of the parameter change the corresponding parameter flag is
+ * set to "false". The parameter value will be reloaded when it is requested
+ * the next time.
+ * Parameters, backed by or depend on GetSystemMetrics are processed
+ * differently. These parameters are always loaded. They are reloaded right
+ * away on interprocess change notification. We can't do lazy loading because
+ * we don't want to complicate GetSystemMetrics.
+ * When parameter value is updated the changed value is stored in permanent
+ * registry branch if saving is requested. Otherwise it is stored
+ * in temporary branch
+ *
*/
BOOL WINAPI SystemParametersInfoA( UINT uiAction, UINT uiParam,
PVOID pvParam, UINT fWinIni )
@@ -133,25 +357,87 @@
break
BOOL ret = TRUE;
+ unsigned spi_idx = 0;
TRACE("(%u, %u, %p, %u)\n", uiAction, uiParam, pvParam, fWinIni);
switch (uiAction)
{
case SPI_GETBEEP: /* 1 */
+ spi_idx = SPI_SETBEEP_IDX;
+ if (!spi_loaded[spi_idx])
+ {
+ char buf[5];
+
+ if (SYSPARAMS_Load( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME, buf ))
+ beep_active = !strcasecmp( "Yes", buf );
+ spi_loaded[spi_idx] = TRUE;
+ }
+
*(BOOL *)pvParam = beep_active;
break;
case SPI_SETBEEP: /* 2 */
- beep_active = uiParam;
- break;
+ spi_idx = SPI_SETBEEP_IDX;
+ if (SYSPARAMS_Save( SPI_SETBEEP_REGKEY, SPI_SETBEEP_VALNAME,
+ (uiParam ? "Yes" : "No"), fWinIni ))
+ {
+ beep_active = uiParam;
+ spi_loaded[spi_idx] = TRUE;
+ }
+ else
+ ret = FALSE;
+ break;
WINE_SPI_FIXME(SPI_GETMOUSE); /* 3 */
WINE_SPI_FIXME(SPI_SETMOUSE); /* 4 */
case SPI_GETBORDER: /* 5 */
- *(INT *)pvParam = GetSystemMetrics( SM_CXFRAME );
+ spi_idx = SPI_SETBORDER_IDX;
+ if (!spi_loaded[spi_idx])
+ {
+ char buf[10];
+
+ if (SYSPARAMS_Load( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
+ buf ))
+ {
+ int i = atoi( buf );
+ if (i > 0) border = i;
+ }
+ spi_loaded[spi_idx] = TRUE;
+ if (TWEAK_WineLook > WIN31_LOOK)
+ {
+ SYSMETRICS_Set( SM_CXFRAME, border + GetSystemMetrics( SM_CXDLGFRAME ) );
+ SYSMETRICS_Set( SM_CYFRAME, border + GetSystemMetrics( SM_CXDLGFRAME ) );
+ }
+ }
+ *(INT *)pvParam = border;
break;
- WINE_SPI_WARN(SPI_SETBORDER); /* 6 */
+
+ case SPI_SETBORDER: /* 6 */
+ {
+ char buf[10];
+
+ spi_idx = SPI_SETBORDER_IDX;
+ sprintf(buf, "%u", uiParam);
+
+ if (SYSPARAMS_Save( SPI_SETBORDER_REGKEY, SPI_SETBORDER_VALNAME,
+ buf, fWinIni ))
+ {
+ if (uiParam > 0)
+ {
+ border = uiParam;
+ spi_loaded[spi_idx] = TRUE;
+ if (TWEAK_WineLook > WIN31_LOOK)
+ {
+ SYSMETRICS_Set( SM_CXFRAME, uiParam + GetSystemMetrics( SM_CXDLGFRAME ) );
+ SYSMETRICS_Set( SM_CYFRAME, uiParam + GetSystemMetrics( SM_CXDLGFRAME ) );
+ }
+ }
+ }
+ else
+ ret = FALSE;
+ break;
+ }
case SPI_GETKEYBOARDSPEED: /* 10 */
*(DWORD *)pvParam = GetProfileIntA( "keyboard", "KeyboardSpeed", 30 );
@@ -404,11 +690,41 @@
WINE_SPI_FIXME(SPI_GETMOUSEKEYS); /* 54 */
WINE_SPI_FIXME(SPI_SETMOUSEKEYS); /* 55 */
case SPI_GETSHOWSOUNDS: /* 56 */
+ spi_idx = SPI_SETSHOWSOUNDS_IDX;
+
+ if (!spi_loaded[spi_idx])
+ {
+ char buf[10];
+
+ if (SYSPARAMS_Load( SPI_SETSHOWSOUNDS_REGKEY,
+ SPI_SETSHOWSOUNDS_VALNAME, buf ))
+ {
+ SYSMETRICS_Set( SM_SHOWSOUNDS, atoi( buf ) );
+ }
+ spi_loaded[spi_idx] = TRUE;
+ }
+
+
*(INT *)pvParam = GetSystemMetrics( SM_SHOWSOUNDS );
break;
+
case SPI_SETSHOWSOUNDS: /* 57 */
- SYSMETRICS_Set(SM_SHOWSOUNDS, uiParam);
+ {
+ char buf[10];
+ spi_idx = SPI_SETSHOWSOUNDS_IDX;
+
+ sprintf(buf, "%u", uiParam);
+ if (SYSPARAMS_Save( SPI_SETSHOWSOUNDS_REGKEY,
+ SPI_SETSHOWSOUNDS_VALNAME,
+ buf, fWinIni ))
+ {
+ SYSMETRICS_Set( SM_SHOWSOUNDS, uiParam );
+ spi_loaded[spi_idx] = TRUE;
+ }
+ else
+ ret = FALSE;
break;
+ }
WINE_SPI_FIXME(SPI_GETSTICKYKEYS); /* 58 */
WINE_SPI_FIXME(SPI_SETSTICKYKEYS); /* 59 */
WINE_SPI_FIXME(SPI_GETACCESSTIMEOUT); /* 60 */
@@ -534,6 +850,8 @@
break;
}
+ if (ret)
+ SYSPARAMS_NotifyChange( uiAction, fWinIni );
return ret;
#undef WINE_SPI_FIXME
@@ -732,8 +1050,8 @@
}
default:
- ret = SystemParametersInfoA( uiAction, uiParam, pvParam, fuWinIni );
+ ret = SystemParametersInfoA( uiAction, uiParam, pvParam, fuWinIni );
+ break;
}
-
return ret;
}