diff --git a/dll/shellext/stobject/CMakeLists.txt b/dll/shellext/stobject/CMakeLists.txt index b8b18915cab..7604c3caecf 100644 --- a/dll/shellext/stobject/CMakeLists.txt +++ b/dll/shellext/stobject/CMakeLists.txt @@ -10,6 +10,7 @@ list(APPEND SOURCE csystray.cpp stobject.cpp hotplug.cpp + mouse.cpp power.cpp volume.cpp precomp.h) diff --git a/dll/shellext/stobject/csystray.cpp b/dll/shellext/stobject/csystray.cpp index 93d17406115..bab008c0d01 100644 --- a/dll/shellext/stobject/csystray.cpp +++ b/dll/shellext/stobject/csystray.cpp @@ -22,6 +22,7 @@ const int g_NumIcons = _countof(g_IconHandlers); CSysTray::CSysTray() : dwServicesEnabled(0) { + wm_SHELLHOOK = RegisterWindowMessageW(L"SHELLHOOK"); wm_DESTROYWINDOW = RegisterWindowMessageW(L"CSysTray_DESTROY"); } @@ -128,6 +129,8 @@ HRESULT CSysTray::InitIcons() } } + MouseKeys_Init(this); + return InitNetShell(); } @@ -144,6 +147,8 @@ HRESULT CSysTray::ShutdownIcons() } } + MouseKeys_Shutdown(this); + return ShutdownNetShell(); } @@ -318,6 +323,17 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM { return DestroyWindow(); } + + if (wm_SHELLHOOK && uMsg == wm_SHELLHOOK) + { + if (wParam == HSHELL_ACCESSIBILITYSTATE && lParam == ACCESS_MOUSEKEYS) + { + MouseKeys_Update(this); + } + lResult = 0L; + return TRUE; + } + switch (uMsg) { case WM_NCCREATE: @@ -328,6 +344,7 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM GetServicesEnabled(); InitIcons(); SetTimer(1, 2000, NULL); + RegisterShellHookWindow(hWnd); return TRUE; case WM_TIMER: @@ -337,8 +354,16 @@ BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM ProcessIconMessage(uMsg, wParam, lParam, lResult); return TRUE; + case WM_SETTINGCHANGE: + if (wParam == SPI_SETMOUSEKEYS) + { + MouseKeys_Update(this); + } + break; + case WM_DESTROY: KillTimer(1); + DeregisterShellHookWindow(hWnd); ShutdownIcons(); PostQuitMessage(0); return TRUE; diff --git a/dll/shellext/stobject/csystray.h b/dll/shellext/stobject/csystray.h index 692948efcbf..059e7047f0b 100644 --- a/dll/shellext/stobject/csystray.h +++ b/dll/shellext/stobject/csystray.h @@ -29,6 +29,7 @@ class CSysTray : // TODO: keep icon handlers here DWORD dwServicesEnabled; + UINT wm_SHELLHOOK; UINT wm_DESTROYWINDOW; static DWORD WINAPI s_SysTrayThreadProc(PVOID param); diff --git a/dll/shellext/stobject/mouse.cpp b/dll/shellext/stobject/mouse.cpp new file mode 100644 index 00000000000..103b1235503 --- /dev/null +++ b/dll/shellext/stobject/mouse.cpp @@ -0,0 +1,125 @@ +/* + * PROJECT: ReactOS system libraries + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Mouse keys notification icon handler + * COPYRIGHT: Copyright 2022 Mark Jansen + */ + +#include "precomp.h" + +static MOUSEKEYS g_Mk; +static UINT g_MkState; +static HICON g_MkStateIcon; + +HRESULT STDMETHODCALLTYPE +MouseKeys_Init(_In_ CSysTray *pSysTray) +{ + TRACE("MouseKeys_Init!\n"); + + return MouseKeys_Update(pSysTray); +} + +HRESULT STDMETHODCALLTYPE +MouseKeys_Shutdown(_In_ CSysTray *pSysTray) +{ + TRACE("MouseKeys_Shutdown!\n"); + + if (g_MkStateIcon) + { + DestroyIcon(g_MkStateIcon); + g_MkStateIcon = NULL; + } + + if (g_MkState) + { + g_MkState = 0; + pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_MOUSE, g_MkStateIcon, L"MouseKeys"); + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +MouseKeys_Update(_In_ CSysTray *pSysTray) +{ + TRACE("MouseKeys_Update!\n"); + + g_Mk.cbSize = sizeof(g_Mk); + SystemParametersInfoW(SPI_GETMOUSEKEYS, sizeof(g_Mk), &g_Mk, 0); + + UINT state = 0; + if ((g_Mk.dwFlags & (MKF_INDICATOR | MKF_MOUSEKEYSON)) == (MKF_INDICATOR | MKF_MOUSEKEYSON)) + { + if (g_Mk.dwFlags & MKF_MOUSEMODE) + { + switch (g_Mk.dwFlags & (MKF_LEFTBUTTONDOWN | MKF_LEFTBUTTONSEL | MKF_RIGHTBUTTONDOWN | MKF_RIGHTBUTTONSEL)) + { + case 0: + default: + state = IDI_MOUSE_NOBTN; + break; + case MKF_LEFTBUTTONSEL: + state = IDI_MOUSE_L_ACTIVE; + break; + case MKF_LEFTBUTTONDOWN: + case MKF_LEFTBUTTONDOWN | MKF_LEFTBUTTONSEL: + state = IDI_MOUSE_L_DOWN; + break; + case MKF_RIGHTBUTTONSEL: + state = IDI_MOUSE_R_ACTIVE; + break; + case MKF_RIGHTBUTTONDOWN: + case MKF_RIGHTBUTTONDOWN | MKF_RIGHTBUTTONSEL: + state = IDI_MOUSE_R_DOWN; + break; + case MKF_LEFTBUTTONSEL | MKF_RIGHTBUTTONSEL: + state = IDI_MOUSE_LR_ACTIVE; + break; + case MKF_RIGHTBUTTONDOWN | MKF_LEFTBUTTONDOWN: + case MKF_RIGHTBUTTONDOWN | MKF_LEFTBUTTONDOWN | MKF_LEFTBUTTONSEL: + case MKF_RIGHTBUTTONDOWN | MKF_LEFTBUTTONDOWN | MKF_LEFTBUTTONSEL | MKF_RIGHTBUTTONSEL: + case MKF_RIGHTBUTTONDOWN | MKF_LEFTBUTTONDOWN | MKF_RIGHTBUTTONSEL: + state = IDI_MOUSE_LR_DOWN; + break; + case MKF_LEFTBUTTONSEL | MKF_RIGHTBUTTONDOWN: + case MKF_LEFTBUTTONSEL | MKF_RIGHTBUTTONDOWN | MKF_RIGHTBUTTONSEL: + state = IDI_MOUSE_L_ACTIVE_R_DOWN; + break; + case MKF_LEFTBUTTONDOWN | MKF_RIGHTBUTTONSEL: + case MKF_LEFTBUTTONDOWN | MKF_RIGHTBUTTONSEL | MKF_LEFTBUTTONSEL: + state = IDI_MOUSE_R_ACTIVE_L_DOWN; + break; + } + } + else + { + state = IDI_MOUSE_DISABLED; + } + } + + UINT uId = NIM_MODIFY; + if (state != g_MkState) + { + if (g_MkStateIcon) + { + DestroyIcon(g_MkStateIcon); + g_MkStateIcon = NULL; + } + + if (g_MkState == 0) + uId = NIM_ADD; + + g_MkState = state; + if (g_MkState) + { + g_MkStateIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(g_MkState)); + } + } + + if (g_MkState == 0) + { + uId = NIM_DELETE; + } + + return pSysTray->NotifyIcon(uId, ID_ICON_MOUSE, g_MkStateIcon, L"MouseKeys"); +} diff --git a/dll/shellext/stobject/precomp.h b/dll/shellext/stobject/precomp.h index e60b0a265b8..3d891af31b6 100644 --- a/dll/shellext/stobject/precomp.h +++ b/dll/shellext/stobject/precomp.h @@ -33,6 +33,7 @@ extern HINSTANCE g_hInstance; #define ID_ICON_VOLUME (WM_APP + 0x4CB) #define ID_ICON_HOTPLUG (WM_APP + 0x4CC) #define ID_ICON_POWER (WM_APP + 0x4CD) +#define ID_ICON_MOUSE (WM_APP + 0x4CE) #define POWER_SERVICE_FLAG 0x00000001 #define HOTPLUG_SERVICE_FLAG 0x00000002 @@ -74,6 +75,11 @@ extern HRESULT STDMETHODCALLTYPE Power_Shutdown(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Power_Update(_In_ CSysTray * pSysTray); extern HRESULT STDMETHODCALLTYPE Power_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult); +extern HRESULT STDMETHODCALLTYPE MouseKeys_Init(_In_ CSysTray * pSysTray); +extern HRESULT STDMETHODCALLTYPE MouseKeys_Shutdown(_In_ CSysTray * pSysTray); +extern HRESULT STDMETHODCALLTYPE MouseKeys_Update(_In_ CSysTray * pSysTray); + + #define POWER_TIMER_ID 2 #define VOLUME_TIMER_ID 3 #define HOTPLUG_TIMER_ID 4 diff --git a/dll/shellext/stobject/resource.h b/dll/shellext/stobject/resource.h index 71d500ec25b..66e6aed204f 100644 --- a/dll/shellext/stobject/resource.h +++ b/dll/shellext/stobject/resource.h @@ -56,4 +56,16 @@ #define IDI_HOTPLUG_ERR 420 #define IDI_HOTPLUG_OK 421 +#define IDI_MOUSE_DISABLED 440 +#define IDI_MOUSE_NOBTN 441 +#define IDI_MOUSE_L_ACTIVE 442 +#define IDI_MOUSE_L_DOWN 443 +#define IDI_MOUSE_R_ACTIVE 444 +#define IDI_MOUSE_R_DOWN 445 +#define IDI_MOUSE_LR_ACTIVE 446 +#define IDI_MOUSE_LR_DOWN 447 +#define IDI_MOUSE_L_ACTIVE_R_DOWN 448 +#define IDI_MOUSE_R_ACTIVE_L_DOWN 449 + + #define IDR_SYSTRAY 11001 diff --git a/dll/shellext/stobject/resources/mouse/disabled.ico b/dll/shellext/stobject/resources/mouse/disabled.ico new file mode 100644 index 00000000000..e5b51a6d65b Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/disabled.ico differ diff --git a/dll/shellext/stobject/resources/mouse/left_active.ico b/dll/shellext/stobject/resources/mouse/left_active.ico new file mode 100644 index 00000000000..d87b21b3d36 Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/left_active.ico differ diff --git a/dll/shellext/stobject/resources/mouse/left_active_right_down.ico b/dll/shellext/stobject/resources/mouse/left_active_right_down.ico new file mode 100644 index 00000000000..ee977316081 Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/left_active_right_down.ico differ diff --git a/dll/shellext/stobject/resources/mouse/left_down.ico b/dll/shellext/stobject/resources/mouse/left_down.ico new file mode 100644 index 00000000000..97346434deb Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/left_down.ico differ diff --git a/dll/shellext/stobject/resources/mouse/left_down_right_active.ico b/dll/shellext/stobject/resources/mouse/left_down_right_active.ico new file mode 100644 index 00000000000..95899121b79 Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/left_down_right_active.ico differ diff --git a/dll/shellext/stobject/resources/mouse/left_right_active.ico b/dll/shellext/stobject/resources/mouse/left_right_active.ico new file mode 100644 index 00000000000..4964f037312 Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/left_right_active.ico differ diff --git a/dll/shellext/stobject/resources/mouse/left_right_down.ico b/dll/shellext/stobject/resources/mouse/left_right_down.ico new file mode 100644 index 00000000000..0283f66338a Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/left_right_down.ico differ diff --git a/dll/shellext/stobject/resources/mouse/none.ico b/dll/shellext/stobject/resources/mouse/none.ico new file mode 100644 index 00000000000..0c84cf292e1 Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/none.ico differ diff --git a/dll/shellext/stobject/resources/mouse/right_active.ico b/dll/shellext/stobject/resources/mouse/right_active.ico new file mode 100644 index 00000000000..b2dcfe6fa2d Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/right_active.ico differ diff --git a/dll/shellext/stobject/resources/mouse/right_down.ico b/dll/shellext/stobject/resources/mouse/right_down.ico new file mode 100644 index 00000000000..624999a41c9 Binary files /dev/null and b/dll/shellext/stobject/resources/mouse/right_down.ico differ diff --git a/dll/shellext/stobject/stobject.rc b/dll/shellext/stobject/stobject.rc index f9b6e1bcf3d..bf310d7b95d 100644 --- a/dll/shellext/stobject/stobject.rc +++ b/dll/shellext/stobject/stobject.rc @@ -31,6 +31,18 @@ IDI_HOTPLUG_ERR ICON "resources/hotplug/0.ico" IDI_HOTPLUG_OK ICON "resources/hotplug/1.ico" +IDI_MOUSE_DISABLED ICON "resources/mouse/disabled.ico" +IDI_MOUSE_NOBTN ICON "resources/mouse/none.ico" +IDI_MOUSE_L_ACTIVE ICON "resources/mouse/left_active.ico" +IDI_MOUSE_L_DOWN ICON "resources/mouse/left_down.ico" +IDI_MOUSE_R_ACTIVE ICON "resources/mouse/right_active.ico" +IDI_MOUSE_R_DOWN ICON "resources/mouse/right_down.ico" +IDI_MOUSE_LR_ACTIVE ICON "resources/mouse/left_right_active.ico" +IDI_MOUSE_LR_DOWN ICON "resources/mouse/left_right_down.ico" +IDI_MOUSE_L_ACTIVE_R_DOWN ICON "resources/mouse/left_active_right_down.ico" +IDI_MOUSE_R_ACTIVE_L_DOWN ICON "resources/mouse/left_down_right_active.ico" + + IDR_SYSTRAY REGISTRY "resources/rgs/systray.rgs" #include