xref: /reactos/dll/cpl/main/keyboard.c (revision c2c66aff)
1 /*
2  *  ReactOS
3  *  Copyright (C) 2004, 2007 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 /*
20  * PROJECT:         ReactOS Main Control Panel
21  * FILE:            dll/cpl/main/keyboard.c
22  * PURPOSE:         Keyboard Control Panel
23  * PROGRAMMER:      Eric Kohl
24  */
25 
26 #include "main.h"
27 
28 #define ID_BLINK_TIMER 345
29 
30 typedef struct _SPEED_DATA
31 {
32     INT nKeyboardDelay;
33     INT nOrigKeyboardDelay;
34     DWORD dwKeyboardSpeed;
35     DWORD dwOrigKeyboardSpeed;
36     UINT uCaretBlinkTime;
37     UINT uOrigCaretBlinkTime;
38     BOOL fShowCursor;
39     RECT rcCursor;
40 } SPEED_DATA, *PSPEED_DATA;
41 
42 /* Property page dialog callback */
43 static INT_PTR CALLBACK
44 KeyboardSpeedProc(IN HWND hwndDlg,
45                   IN UINT uMsg,
46                   IN WPARAM wParam,
47                   IN LPARAM lParam)
48 {
49     PSPEED_DATA pSpeedData;
50 
51     pSpeedData = (PSPEED_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
52 
53     switch (uMsg)
54     {
55         case WM_INITDIALOG:
56             pSpeedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SPEED_DATA));
57             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSpeedData);
58 
59             /* Get current keyboard delay */
60             if (!SystemParametersInfo(SPI_GETKEYBOARDDELAY,
61                                       sizeof(INT),
62                                       &pSpeedData->nKeyboardDelay,
63                                       0))
64             {
65                 pSpeedData->nKeyboardDelay = 2;
66             }
67 
68             pSpeedData->nOrigKeyboardDelay = pSpeedData->nKeyboardDelay;
69 
70             /* Get current keyboard delay */
71             if (!SystemParametersInfo(SPI_GETKEYBOARDSPEED,
72                                       sizeof(DWORD),
73                                       &pSpeedData->dwKeyboardSpeed,
74                                       0))
75             {
76                 pSpeedData->dwKeyboardSpeed = 31;
77             }
78 
79             pSpeedData->dwOrigKeyboardSpeed = pSpeedData->dwKeyboardSpeed;
80 
81             pSpeedData->fShowCursor = TRUE;
82             GetWindowRect(GetDlgItem(hwndDlg, IDC_TEXT_CURSOR_BLINK), &pSpeedData->rcCursor);
83             ScreenToClient(hwndDlg, (LPPOINT)&pSpeedData->rcCursor.left);
84             ScreenToClient(hwndDlg, (LPPOINT)&pSpeedData->rcCursor.right);
85 
86             /* Get the caret blink time and save its original value */
87             pSpeedData->uOrigCaretBlinkTime = GetCaretBlinkTime();
88             pSpeedData->uCaretBlinkTime = pSpeedData->uOrigCaretBlinkTime;
89 
90             SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_DELAY, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 3));
91             SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_DELAY, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(3 - pSpeedData->nKeyboardDelay));
92 
93             SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_RATE, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 31));
94             SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_RATE, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pSpeedData->dwKeyboardSpeed);
95 
96             SendDlgItemMessage(hwndDlg, IDC_SLIDER_CURSOR_BLINK, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 10));
97             SendDlgItemMessage(hwndDlg, IDC_SLIDER_CURSOR_BLINK, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)(12 - (pSpeedData->uCaretBlinkTime / 100)));
98 
99             /* Start the blink timer */
100             SetTimer(hwndDlg, ID_BLINK_TIMER, pSpeedData->uCaretBlinkTime, NULL);
101             break;
102 
103         case WM_HSCROLL:
104             if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_REPEAT_DELAY))
105             {
106                 switch (LOWORD(wParam))
107                 {
108                         case TB_LINEUP:
109                         case TB_LINEDOWN:
110                         case TB_PAGEUP:
111                         case TB_PAGEDOWN:
112                         case TB_TOP:
113                         case TB_BOTTOM:
114                         case TB_ENDTRACK:
115                             pSpeedData->nKeyboardDelay = 3 - (INT)SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_DELAY, TBM_GETPOS, 0, 0);
116                             SystemParametersInfo(SPI_SETKEYBOARDDELAY,
117                                                  pSpeedData->nKeyboardDelay,
118                                                  0,
119                                                  0);
120                             PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
121                             break;
122 
123                         case TB_THUMBTRACK:
124                             pSpeedData->nKeyboardDelay = 3 - (INT)HIWORD(wParam);
125                             SystemParametersInfo(SPI_SETKEYBOARDDELAY,
126                                                  pSpeedData->nKeyboardDelay,
127                                                  0,
128                                                  0);
129                             PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
130                             break;
131                 }
132             }
133             else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_REPEAT_RATE))
134             {
135                 switch (LOWORD(wParam))
136                 {
137                         case TB_LINEUP:
138                         case TB_LINEDOWN:
139                         case TB_PAGEUP:
140                         case TB_PAGEDOWN:
141                         case TB_TOP:
142                         case TB_BOTTOM:
143                         case TB_ENDTRACK:
144                             pSpeedData->dwKeyboardSpeed = (DWORD)SendDlgItemMessage(hwndDlg, IDC_SLIDER_REPEAT_RATE, TBM_GETPOS, 0, 0);
145                             SystemParametersInfo(SPI_SETKEYBOARDSPEED,
146                                                  pSpeedData->dwKeyboardSpeed,
147                                                  0,
148                                                  0);
149                             PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
150                             break;
151 
152                         case TB_THUMBTRACK:
153                             pSpeedData->dwKeyboardSpeed = (DWORD)HIWORD(wParam);
154                             SystemParametersInfo(SPI_SETKEYBOARDSPEED,
155                                                  pSpeedData->dwKeyboardSpeed,
156                                                  0,
157                                                  0);
158                             PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
159                             break;
160                 }
161             }
162             else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SLIDER_CURSOR_BLINK))
163             {
164                 switch (LOWORD(wParam))
165                 {
166                         case TB_LINEUP:
167                         case TB_LINEDOWN:
168                         case TB_PAGEUP:
169                         case TB_PAGEDOWN:
170                         case TB_TOP:
171                         case TB_BOTTOM:
172                         case TB_ENDTRACK:
173                             pSpeedData->uCaretBlinkTime = (12 - (UINT)SendDlgItemMessage(hwndDlg, IDC_SLIDER_CURSOR_BLINK, TBM_GETPOS, 0, 0)) * 100;
174                             KillTimer(hwndDlg, ID_BLINK_TIMER);
175                             SetTimer(hwndDlg, ID_BLINK_TIMER, pSpeedData->uCaretBlinkTime, NULL);
176                             SetCaretBlinkTime(pSpeedData->uCaretBlinkTime);
177                             PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
178                             break;
179 
180                         case TB_THUMBTRACK:
181                             pSpeedData->uCaretBlinkTime = (12 - (UINT)HIWORD(wParam)) * 100;
182                             KillTimer(hwndDlg, ID_BLINK_TIMER);
183                             SetTimer(hwndDlg, ID_BLINK_TIMER, pSpeedData->uCaretBlinkTime, NULL);
184                             SetCaretBlinkTime(pSpeedData->uCaretBlinkTime);
185                             PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
186                             break;
187                 }
188             }
189             break;
190 
191         case WM_TIMER:
192             if (wParam == ID_BLINK_TIMER)
193             {
194                 if (pSpeedData->fShowCursor)
195                 {
196                     HDC hDC = GetDC(hwndDlg);
197                     HBRUSH hBrush = GetSysColorBrush(COLOR_BTNTEXT);
198                     FillRect(hDC, &pSpeedData->rcCursor, hBrush);
199                     DeleteObject(hBrush);
200                     ReleaseDC(hwndDlg, hDC);
201                 }
202                 else
203                 {
204                     InvalidateRect(hwndDlg, &pSpeedData->rcCursor, TRUE);
205                 }
206 
207                 pSpeedData->fShowCursor = !pSpeedData->fShowCursor;
208             }
209             break;
210 
211         case WM_NOTIFY:
212         {
213             LPNMHDR lpnm = (LPNMHDR)lParam;
214 
215             switch(lpnm->code)
216             {
217                 case PSN_APPLY:
218                     /* Set the new keyboard settings */
219                     SystemParametersInfo(SPI_SETKEYBOARDDELAY,
220                                          pSpeedData->nKeyboardDelay,
221                                          0,
222                                          0);
223                     SystemParametersInfo(SPI_SETKEYBOARDSPEED,
224                                          pSpeedData->dwKeyboardSpeed,
225                                          0,
226                                          SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
227                     return TRUE;
228 
229                 case PSN_RESET:
230                     /* Restore the original settings */
231                     SetCaretBlinkTime(pSpeedData->uOrigCaretBlinkTime);
232                     SystemParametersInfo(SPI_SETKEYBOARDDELAY,
233                                          pSpeedData->nOrigKeyboardDelay,
234                                          0,
235                                          0);
236                     SystemParametersInfo(SPI_SETKEYBOARDSPEED,
237                                          pSpeedData->dwOrigKeyboardSpeed,
238                                          0,
239                                          0);
240                     break;
241 
242                 default:
243                     break;
244             }
245         }
246         break;
247 
248         case WM_DESTROY:
249             KillTimer(hwndDlg, ID_BLINK_TIMER);
250             HeapFree(GetProcessHeap(), 0, pSpeedData);
251             break;
252     }
253 
254     return FALSE;
255 }
256 
257 
258 /* Property page dialog callback */
259 static INT_PTR CALLBACK
260 KeybHardwareProc(IN HWND hwndDlg,
261                  IN UINT uMsg,
262                  IN WPARAM wParam,
263                  IN LPARAM lParam)
264 {
265     GUID Guids[1];
266     Guids[0] = GUID_DEVCLASS_KEYBOARD;
267 
268     UNREFERENCED_PARAMETER(lParam);
269     UNREFERENCED_PARAMETER(wParam);
270 
271     switch(uMsg)
272     {
273         case WM_INITDIALOG:
274             /* Create the hardware page */
275             DeviceCreateHardwarePageEx(hwndDlg,
276                                        Guids,
277                                        sizeof(Guids) / sizeof(Guids[0]),
278                                        HWPD_STANDARDLIST);
279             break;
280     }
281 
282     return FALSE;
283 }
284 
285 
286 LONG APIENTRY
287 KeyboardApplet(HWND hwnd, UINT uMsg, LPARAM wParam, LPARAM lParam)
288 {
289     HPROPSHEETPAGE hpsp[MAX_CPL_PAGES];
290     PROPSHEETHEADER psh;
291     HPSXA hpsxa;
292     TCHAR szCaption[256];
293     LONG ret;
294 
295     UNREFERENCED_PARAMETER(lParam);
296     UNREFERENCED_PARAMETER(wParam);
297     UNREFERENCED_PARAMETER(uMsg);
298     UNREFERENCED_PARAMETER(hwnd);
299 
300     LoadString(hApplet, IDS_CPLNAME_2, szCaption, sizeof(szCaption) / sizeof(TCHAR));
301 
302     ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
303     psh.dwSize = sizeof(PROPSHEETHEADER);
304     psh.dwFlags =  PSH_PROPTITLE;
305     psh.hwndParent = hwnd;
306     psh.hInstance = hApplet;
307     psh.hIcon = LoadIcon(hApplet, MAKEINTRESOURCE(IDC_CPLICON_2));
308     psh.pszCaption = szCaption;
309     psh.nStartPage = 0;
310     psh.phpage = hpsp;
311 
312     /* Load additional pages provided by shell extensions */
313     hpsxa = SHCreatePropSheetExtArray(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTROLSFOLDER TEXT("\\Keyboard"), MAX_CPL_PAGES - psh.nPages);
314 
315     /* NOTE: The speed page (CPLPAGE_KEYBOARD_SPEED) cannot be replaced by
316              shell extensions since Win2k! */
317     InitPropSheetPage(&psh, IDD_KEYBSPEED, KeyboardSpeedProc);
318     InitPropSheetPage(&psh, IDD_HARDWARE, KeybHardwareProc);
319 
320     if (hpsxa != NULL)
321         SHAddFromPropSheetExtArray(hpsxa, PropSheetAddPage, (LPARAM)&psh);
322 
323     ret = (LONG)(PropertySheet(&psh) != -1);
324 
325     if (hpsxa != NULL)
326         SHDestroyPropSheetExtArray(hpsxa);
327 
328     return ret;
329 }
330 
331 /* EOF */
332