[STOBJECT][NTUSER][ACCESS] Don't use a systray timer when not needed (#7917)

This commit is contained in:
Whindmar Saksit 2025-04-24 21:27:36 +02:00 committed by GitHub
parent 78e04c07b8
commit 7eb8535edf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 124 additions and 36 deletions

View file

@ -189,11 +189,11 @@ SystemApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
PGLOBAL_DATA pGlobalData;
PROPSHEETPAGE psp[5];
PROPSHEETHEADER psh;
INT nPage = 0;
UINT nPage = 0; // This is unsigned so we don't have to deal with negative numbers
INT ret;
if (uMsg == CPL_STARTWPARMSW && lParam != 0)
nPage = _wtoi((PWSTR)lParam);
nPage = (*(PWSTR)lParam) - '1'; // Convert from 1-based to 0-based.
pGlobalData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLOBAL_DATA));
if (pGlobalData == NULL)

View file

@ -162,6 +162,11 @@ MousePageProc(HWND hwndDlg,
CheckDlgButton(hwndDlg,
IDC_MOUSE_BOX,
pGlobalData->mouseKeys.dwFlags & MKF_MOUSEKEYSON ? BST_CHECKED : BST_UNCHECKED);
#if 1 // FIXME: Feature not implemented, disable the UI
EnableWindow(GetDlgItem(hwndDlg, IDC_MOUSE_BOX), pGlobalData->mouseKeys.dwFlags & MKF_MOUSEKEYSON);
EnableWindow(GetDlgItem(hwndDlg, IDC_MOUSE_BUTTON), pGlobalData->mouseKeys.dwFlags & MKF_MOUSEKEYSON);
#endif
return TRUE;

View file

@ -12,6 +12,7 @@
#include <regstr.h>
#include <undocshell.h>
#include <shellutils.h>
#include <shlwapi.h>
SysTrayIconHandlers_t g_IconHandlers [] = {
{ VOLUME_SERVICE_FLAG, Volume_Init, Volume_Shutdown, Volume_Update, Volume_Message },
@ -20,10 +21,13 @@ SysTrayIconHandlers_t g_IconHandlers [] = {
};
const int g_NumIcons = _countof(g_IconHandlers);
SysTrayIconHandlers_t g_StandaloneHandlers[] = {
{ MOUSE_SERVICE_FLAG, MouseKeys_Init, MouseKeys_Shutdown, MouseKeys_Update, MouseKeys_Message },
};
CSysTray::CSysTray() : dwServicesEnabled(0)
{
wm_SHELLHOOK = RegisterWindowMessageW(L"SHELLHOOK");
wm_DESTROYWINDOW = RegisterWindowMessageW(L"CSysTray_DESTROY");
}
CSysTray::~CSysTray()
@ -69,7 +73,7 @@ VOID CSysTray::EnableService(DWORD dwServiceFlag, BOOL bEnable)
this->dwServicesEnabled &= ~dwServiceFlag;
if (RegCreateKeyExW(HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\SysTray",
REGSTR_PATH_SYSTRAY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
@ -78,15 +82,18 @@ VOID CSysTray::EnableService(DWORD dwServiceFlag, BOOL bEnable)
&hKey,
NULL) == ERROR_SUCCESS)
{
DWORD dwConfig = this->dwServicesEnabled & ~STANDALONESERVICEMASK;
RegSetValueExW(hKey,
L"Services",
0,
REG_DWORD,
(LPBYTE)&this->dwServicesEnabled,
sizeof(DWORD));
(LPBYTE)&dwConfig,
sizeof(dwConfig));
RegCloseKey(hKey);
}
ConfigurePollTimer();
}
BOOL CSysTray::IsServiceEnabled(DWORD dwServiceFlag)
@ -94,6 +101,18 @@ BOOL CSysTray::IsServiceEnabled(DWORD dwServiceFlag)
return (this->dwServicesEnabled & dwServiceFlag);
}
void CSysTray::ConfigurePollTimer()
{
// FIXME: VOLUME_SERVICE_FLAG should use mixerOpen(CALLBACK_WINDOW)
// FIXME: POWER_SERVICE_FLAG should use WM_DEVICECHANGE, WM_POWERBROADCAST
DWORD fNeedsTimer = VOLUME_SERVICE_FLAG | POWER_SERVICE_FLAG;
if (this->dwServicesEnabled & fNeedsTimer)
SetTimer(POLL_TIMER_ID, 2000, NULL);
else
KillTimer(POLL_TIMER_ID);
}
HRESULT CSysTray::InitNetShell()
{
HRESULT hr = CoCreateInstance(CLSID_ConnectionTray, 0, 1u, IID_PPV_ARG(IOleCommandTarget, &pctNetShell));
@ -119,7 +138,7 @@ HRESULT CSysTray::ShutdownNetShell()
HRESULT CSysTray::InitIcons()
{
TRACE("Initializing Notification icons...\n");
for (int i = 0; i < g_NumIcons; i++)
for (UINT i = 0; i < g_NumIcons; i++)
{
if (this->dwServicesEnabled & g_IconHandlers[i].dwServiceFlag)
{
@ -128,8 +147,10 @@ HRESULT CSysTray::InitIcons()
return hr;
}
}
MouseKeys_Init(this);
for (UINT i = 0; i < _countof(g_StandaloneHandlers); ++i)
{
g_StandaloneHandlers[i].pfnInit(this);
}
return InitNetShell();
}
@ -137,7 +158,7 @@ HRESULT CSysTray::InitIcons()
HRESULT CSysTray::ShutdownIcons()
{
TRACE("Shutting down Notification icons...\n");
for (int i = 0; i < g_NumIcons; i++)
for (UINT i = 0; i < g_NumIcons; i++)
{
if (this->dwServicesEnabled & g_IconHandlers[i].dwServiceFlag)
{
@ -146,8 +167,10 @@ HRESULT CSysTray::ShutdownIcons()
FAILED_UNEXPECTEDLY(hr);
}
}
MouseKeys_Shutdown(this);
for (UINT i = 0; i < _countof(g_StandaloneHandlers); ++i)
{
g_StandaloneHandlers[i].pfnShutdown(this);
}
return ShutdownNetShell();
}
@ -170,12 +193,19 @@ HRESULT CSysTray::UpdateIcons()
HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult)
{
for (int i = 0; i < g_NumIcons; i++)
for (UINT i = 0; i < g_NumIcons; i++)
{
HRESULT hr = g_IconHandlers[i].pfnMessage(this, uMsg, wParam, lParam, lResult);
if (FAILED(hr))
return hr;
if (hr == S_OK)
return hr;
}
for (UINT i = 0; i < _countof(g_StandaloneHandlers); ++i)
{
HRESULT hr = g_StandaloneHandlers[i].pfnMessage(this, uMsg, wParam, lParam, lResult);
if (FAILED(hr))
return hr;
if (hr == S_OK)
return hr;
}
@ -285,7 +315,7 @@ HRESULT CSysTray::DestroySysTrayWindow()
if (!DestroyWindow())
{
// Window is from another thread, ask it politely to destroy itself:
SendMessage(wm_DESTROYWINDOW);
SendMessage(WM_CLOSE);
}
return S_OK;
}
@ -319,14 +349,13 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
if (hWnd != m_hWnd)
return FALSE;
if (wm_DESTROYWINDOW && uMsg == wm_DESTROYWINDOW)
if (uMsg == wm_SHELLHOOK && wm_SHELLHOOK)
{
return DestroyWindow();
}
if (wm_SHELLHOOK && uMsg == wm_SHELLHOOK)
{
if (wParam == HSHELL_ACCESSIBILITYSTATE && lParam == ACCESS_MOUSEKEYS)
if (wParam == HSHELL_ACCESSIBILITYSTATE && lParam == ACCESS_STICKYKEYS)
{
StickyKeys_Update(this);
}
else if (wParam == HSHELL_ACCESSIBILITYSTATE && lParam == ACCESS_MOUSEKEYS)
{
MouseKeys_Update(this);
}
@ -340,29 +369,32 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
case WM_NCDESTROY:
return FALSE;
case WM_CLOSE:
return DestroyWindow();
case WM_CREATE:
GetServicesEnabled();
InitIcons();
SetTimer(1, 2000, NULL);
RegisterShellHookWindow(hWnd);
ConfigurePollTimer();
return TRUE;
case WM_TIMER:
if (wParam == 1)
if (wParam == POLL_TIMER_ID)
UpdateIcons();
else
ProcessIconMessage(uMsg, wParam, lParam, lResult);
return TRUE;
case WM_SETTINGCHANGE:
if (wParam == SPI_SETSTICKYKEYS)
StickyKeys_Update(this);
if (wParam == SPI_SETMOUSEKEYS)
{
MouseKeys_Update(this);
}
break;
case WM_DESTROY:
KillTimer(1);
KillTimer(POLL_TIMER_ID);
DeregisterShellHookWindow(hWnd);
ShutdownIcons();
PostQuitMessage(0);
@ -377,3 +409,18 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
return (hr == S_OK);
}
void CSysTray::RunDll(PCSTR Dll, PCSTR Parameters)
{
WCHAR buf[400], rundll[MAX_PATH];
GetSystemDirectory(rundll, _countof(rundll));
PathAppendW(rundll, L"rundll32.exe");
wsprintfW(buf, L"%hs %hs%hs", "shell32.dll,Control_RunDLL", Dll, Parameters);
ShellExecuteW(NULL, NULL, rundll, buf, NULL, SW_SHOW);
}
void CSysTray::RunAccessCpl(PCSTR Parameters)
{
RunDll("access.cpl", Parameters);
}

View file

@ -55,6 +55,10 @@ public:
VOID EnableService(DWORD dwServiceFlag, BOOL bEnable);
BOOL IsServiceEnabled(DWORD dwServiceFlag);
void ConfigurePollTimer();
static void RunDll(PCSTR Dll, PCSTR Parameters);
static void RunAccessCpl(PCSTR Parameters);
protected:
BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID = 0);

View file

@ -154,12 +154,7 @@ HRESULT STDMETHODCALLTYPE Hotplug_Shutdown(_In_ CSysTray * pSysTray)
static void _RunHotplug(CSysTray * pSysTray)
{
ShellExecuteW(pSysTray->GetHWnd(),
L"open",
L"rundll32.exe",
L"shell32.dll,Control_RunDLL hotplug.dll",
NULL,
SW_SHOWNORMAL);
pSysTray->RunDll("hotplug.dll", "");
}
static void _ShowContextMenu(CSysTray * pSysTray)

View file

@ -123,3 +123,20 @@ MouseKeys_Update(_In_ CSysTray *pSysTray)
return pSysTray->NotifyIcon(uId, ID_ICON_MOUSE, g_MkStateIcon, L"MouseKeys");
}
HRESULT STDMETHODCALLTYPE MouseKeys_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult)
{
switch (uMsg)
{
case ID_ICON_MOUSE:
switch (lParam)
{
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
pSysTray->RunAccessCpl(",,4");
return S_OK;
}
break;
}
return S_FALSE;
}

View file

@ -171,7 +171,7 @@ HRESULT STDMETHODCALLTYPE Power_Shutdown(_In_ CSysTray * pSysTray)
static void _RunPower()
{
ShellExecuteW(NULL, NULL, L"powercfg.cpl", NULL, NULL, SW_SHOWNORMAL);
CSysTray::RunDll("powercfg.cpl", "");
}
static void _ShowContextMenu(CSysTray * pSysTray)

View file

@ -38,6 +38,10 @@ extern HINSTANCE g_hInstance;
#define POWER_SERVICE_FLAG 0x00000001
#define HOTPLUG_SERVICE_FLAG 0x00000002
#define VOLUME_SERVICE_FLAG 0x00000004
#define SKEYS_SERVICE_FLAG 0x20000000
#define FKEYS_SERVICE_FLAG 0x40000000
#define MOUSE_SERVICE_FLAG 0x80000000
#define STANDALONESERVICEMASK 0xF0000000
#include "csystray.h"
@ -78,8 +82,13 @@ extern HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray, UINT uM
extern HRESULT STDMETHODCALLTYPE MouseKeys_Init(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE MouseKeys_Shutdown(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE MouseKeys_Update(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE MouseKeys_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult);
#define StickyKeys_Update(thisptr) (void)0 // TODO
#define FilterKeys_Update(thisptr) (void)0 // TODO
#define POLL_TIMER_ID 1 // FIXME: Use callbacks instead of polling with this timer
#define POWER_TIMER_ID 2
#define VOLUME_TIMER_ID 3
#define HOTPLUG_TIMER_ID 4

View file

@ -220,7 +220,7 @@ static void _RunVolume(BOOL bTray)
static void _RunMMCpl()
{
ShellExecuteW(NULL, NULL, L"mmsys.cpl", NULL, NULL, SW_NORMAL);
CSysTray::RunDll("mmsys.cpl", "");
}
static void _ShowContextMenu(CSysTray * pSysTray)

View file

@ -101,6 +101,11 @@ static const WCHAR* KEY_KDBPREF = L"Control Panel\\Accessibility\\Keyboard Prefe
static const WCHAR* KEY_SCRREAD = L"Control Panel\\Accessibility\\Blind Access";
static const WCHAR* VAL_ON = L"On";
static const WCHAR* KEY_MOUSEKEYS = L"Control Panel\\Accessibility\\MouseKeys";
static const WCHAR* VAL_MOUSEKEYS_FLAGS = L"Flags";
static const WCHAR* VAL_MOUSEKEYS_MAX = L"MaximumSpeed";
static const WCHAR* VAL_MOUSEKEYS_TIMETOMAX = L"TimeToMaximumSpeed";
/** Loading the settings ******************************************************/
static
@ -336,6 +341,10 @@ SpiUpdatePerUserSystemParameters(VOID)
gspv.filterkeys.cbSize = sizeof(FILTERKEYS);
gspv.togglekeys.cbSize = sizeof(TOGGLEKEYS);
gspv.mousekeys.cbSize = sizeof(MOUSEKEYS);
gspv.mousekeys.dwFlags = SpiLoadInt(KEY_MOUSEKEYS, VAL_MOUSEKEYS_FLAGS, 62);
gspv.mousekeys.iMaxSpeed = SpiLoadInt(KEY_MOUSEKEYS, VAL_MOUSEKEYS_MAX, 80);
gspv.mousekeys.iTimeToMaxSpeed = SpiLoadInt(KEY_MOUSEKEYS, VAL_MOUSEKEYS_TIMETOMAX, 3000);
gspv.mousekeys.iCtrlSpeed = 8; // FIXME
gspv.stickykeys.cbSize = sizeof(STICKYKEYS);
gspv.serialkeys.cbSize = sizeof(SERIALKEYS);
gspv.soundsentry.cbSize = sizeof(SOUNDSENTRYW);
@ -1197,7 +1206,9 @@ SpiGetSet(UINT uiAction, UINT uiParam, PVOID pvParam, FLONG fl)
if (fl & SPIF_UPDATEINIFILE)
{
// FIXME: What to do?
SpiStoreSzInt(KEY_MOUSEKEYS, VAL_MOUSEKEYS_FLAGS, gspv.mousekeys.dwFlags);
SpiStoreSzInt(KEY_MOUSEKEYS, VAL_MOUSEKEYS_MAX, gspv.mousekeys.iMaxSpeed);
SpiStoreSzInt(KEY_MOUSEKEYS, VAL_MOUSEKEYS_TIMETOMAX, gspv.mousekeys.iTimeToMaxSpeed);
}
return (UINT_PTR)KEY_DESKTOP;
}