moved desktop code to desktop.c
[reactos.git] / reactos / subsys / win32k / ntuser / input.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: input.c,v 1.24 2003/12/07 19:29:33 weiden Exp $
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window classes
24 * FILE: subsys/win32k/ntuser/class.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * REVISION HISTORY:
27 * 06-06-2001 CSH Created
28 */
29
30 /* INCLUDES ******************************************************************/
31
32 #include <ddk/ntddk.h>
33 #include <win32k/win32k.h>
34 #include <include/class.h>
35 #include <include/error.h>
36 #include <include/winsta.h>
37 #include <include/desktop.h>
38 #include <include/msgqueue.h>
39 #include <ddk/ntddmou.h>
40 #include <include/mouse.h>
41 #include <include/input.h>
42 #include <include/hotkey.h>
43 #include <rosrtl/string.h>
44
45 #define NDEBUG
46 #include <debug.h>
47
48 /* GLOBALS *******************************************************************/
49
50 static HANDLE MouseDeviceHandle;
51 static HANDLE KeyboardThreadHandle;
52 static CLIENT_ID KeyboardThreadId;
53 static HANDLE KeyboardDeviceHandle;
54 static KEVENT InputThreadsStart;
55 static BOOLEAN InputThreadsRunning = FALSE;
56 PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue = 0;
57
58 /* FUNCTIONS *****************************************************************/
59
60 VOID STDCALL_FUNC STATIC
61 KeyboardThreadMain(PVOID StartContext)
62 {
63 UNICODE_STRING KeyboardDeviceName;
64 OBJECT_ATTRIBUTES KeyboardObjectAttributes;
65 IO_STATUS_BLOCK Iosb;
66 NTSTATUS Status;
67 MSG msg;
68 PUSER_MESSAGE_QUEUE FocusQueue;
69 struct _ETHREAD *FocusThread;
70
71 RtlRosInitUnicodeStringFromLiteral(&KeyboardDeviceName, L"\\??\\Keyboard");
72 InitializeObjectAttributes(&KeyboardObjectAttributes,
73 &KeyboardDeviceName,
74 0,
75 NULL,
76 NULL);
77 Status = NtOpenFile(&KeyboardDeviceHandle,
78 FILE_ALL_ACCESS,
79 &KeyboardObjectAttributes,
80 &Iosb,
81 0,
82 FILE_SYNCHRONOUS_IO_ALERT);
83 if (!NT_SUCCESS(Status))
84 {
85 DPRINT1("Win32K: Failed to open keyboard.\n");
86 return; //(Status);
87 }
88
89 for (;;)
90 {
91 /*
92 * Wait to start input.
93 */
94 DPRINT( "Input Thread Waiting for start event\n" );
95 Status = KeWaitForSingleObject(&InputThreadsStart,
96 0,
97 UserMode,
98 TRUE,
99 NULL);
100 DPRINT( "Input Thread Starting...\n" );
101
102 /*
103 * Receive and process keyboard input.
104 */
105 while (InputThreadsRunning)
106 {
107 KEY_EVENT_RECORD KeyEvent;
108 LPARAM lParam = 0;
109 UINT fsModifiers;
110 struct _ETHREAD *Thread;
111 HWND hWnd;
112 int id;
113
114 Status = NtReadFile (KeyboardDeviceHandle,
115 NULL,
116 NULL,
117 NULL,
118 &Iosb,
119 &KeyEvent,
120 sizeof(KEY_EVENT_RECORD),
121 NULL,
122 NULL);
123 DPRINT( "KeyRaw: %s %04x\n",
124 KeyEvent.bKeyDown ? "down" : "up",
125 KeyEvent.wVirtualScanCode );
126
127 if (Status == STATUS_ALERTED && !InputThreadsRunning)
128 {
129 break;
130 }
131 if (!NT_SUCCESS(Status))
132 {
133 DPRINT1("Win32K: Failed to read from keyboard.\n");
134 return; //(Status);
135 }
136
137 DPRINT( "Key: %s\n", KeyEvent.bKeyDown ? "down" : "up" );
138
139 fsModifiers = 0;
140 if (KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
141 fsModifiers |= MOD_ALT;
142
143 if (KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
144 fsModifiers |= MOD_CONTROL;
145
146 if (KeyEvent.dwControlKeyState & SHIFT_PRESSED)
147 fsModifiers |= MOD_SHIFT;
148
149 /* FIXME: Support MOD_WIN */
150
151 lParam = KeyEvent.wRepeatCount |
152 ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0x40000000;
153
154 /* Bit 24 indicates if this is an extended key */
155 if (KeyEvent.dwControlKeyState & ENHANCED_KEY)
156 {
157 lParam |= (1 << 24);
158 }
159
160 if (fsModifiers & MOD_ALT)
161 {
162 /* Context mode. 1 if ALT if pressed while the key is pressed */
163 lParam |= (1 << 29);
164 }
165
166 if(KeyEvent.bKeyDown && (fsModifiers & MOD_ALT))
167 msg.message = WM_SYSKEYDOWN;
168 else if(KeyEvent.bKeyDown)
169 msg.message = WM_KEYDOWN;
170 else if(fsModifiers & MOD_ALT)
171 msg.message = WM_SYSKEYUP;
172 else
173 msg.message = WM_KEYUP;
174
175 /* Find the target thread whose locale is in effect */
176 if (!IntGetScreenDC())
177 {
178 FocusQueue = W32kGetPrimitiveMessageQueue();
179 }
180 else
181 {
182 FocusQueue = IntGetFocusMessageQueue();
183 }
184
185 if (!FocusQueue) continue;
186
187 msg.wParam = KeyEvent.wVirtualKeyCode;
188 msg.lParam = lParam;
189 msg.hwnd = FocusQueue->FocusWindow;
190
191 FocusThread = FocusQueue->Thread;
192
193 if (FocusThread && FocusThread->Win32Thread &&
194 FocusThread->Win32Thread->KeyboardLayout)
195 {
196 W32kKeyProcessMessage(&msg,
197 FocusThread->Win32Thread->KeyboardLayout);
198 }
199 else
200 continue;
201
202 if (GetHotKey(InputWindowStation,
203 fsModifiers,
204 msg.wParam,
205 &Thread,
206 &hWnd,
207 &id))
208 {
209 if (KeyEvent.bKeyDown)
210 {
211 DPRINT("Hot key pressed (hWnd %lx, id %d)\n", hWnd, id);
212 MsqPostHotKeyMessage (Thread,
213 hWnd,
214 (WPARAM)id,
215 MAKELPARAM((WORD)fsModifiers,
216 (WORD)msg.wParam));
217 }
218 }
219 else
220 {
221 /*
222 * Post a keyboard message.
223 */
224 MsqPostKeyboardMessage(msg.message,msg.wParam,msg.lParam);
225 }
226 }
227 DPRINT( "Input Thread Stopped...\n" );
228 }
229 }
230
231
232 NTSTATUS STDCALL
233 NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release)
234 {
235 if (Release && InputThreadsRunning && !pmPrimitiveMessageQueue)
236 {
237 DPRINT( "Releasing input: PM = %08x\n", pmPrimitiveMessageQueue );
238 KeClearEvent(&InputThreadsStart);
239 InputThreadsRunning = FALSE;
240
241 NtAlertThread(KeyboardThreadHandle);
242 }
243 else if (!Release && !InputThreadsRunning)
244 {
245 InputThreadsRunning = TRUE;
246 KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE);
247 }
248
249 return(STATUS_SUCCESS);
250 }
251
252 NTSTATUS FASTCALL
253 InitInputImpl(VOID)
254 {
255 NTSTATUS Status;
256 UNICODE_STRING MouseDeviceName;
257 OBJECT_ATTRIBUTES MouseObjectAttributes;
258 IO_STATUS_BLOCK Iosb;
259 PIRP Irp;
260 PFILE_OBJECT FileObject;
261 GDI_INFORMATION GdiInfo;
262 KEVENT IoEvent;
263 PIO_STACK_LOCATION StackPtr;
264
265 KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
266
267 Status = PsCreateSystemThread(&KeyboardThreadHandle,
268 THREAD_ALL_ACCESS,
269 NULL,
270 NULL,
271 &KeyboardThreadId,
272 KeyboardThreadMain,
273 NULL);
274 if (!NT_SUCCESS(Status))
275 {
276 DPRINT1("Win32K: Failed to create keyboard thread.\n");
277 }
278
279 /*
280 * Connect to the mouse class driver.
281 * Failures here don't result in a failure return, the system must be
282 * able to operate without mouse
283 */
284 RtlRosInitUnicodeStringFromLiteral(&MouseDeviceName, L"\\??\\MouseClass");
285 InitializeObjectAttributes(&MouseObjectAttributes,
286 &MouseDeviceName,
287 0,
288 NULL,
289 NULL);
290 Status = NtOpenFile(&MouseDeviceHandle,
291 FILE_ALL_ACCESS,
292 &MouseObjectAttributes,
293 &Iosb,
294 0,
295 0);
296 if (!NT_SUCCESS(Status))
297 {
298 DPRINT1("Win32K: Failed to open mouse.\n");
299 return STATUS_SUCCESS;
300 }
301 Status = ObReferenceObjectByHandle(MouseDeviceHandle,
302 FILE_READ_DATA | FILE_WRITE_DATA,
303 IoFileObjectType,
304 KernelMode,
305 (PVOID *) &FileObject,
306 NULL);
307
308 if (!NT_SUCCESS(Status))
309 {
310 DPRINT1("Win32K: Failed to reference mouse file object.\n");
311 NtClose(MouseDeviceHandle);
312 return STATUS_SUCCESS;
313 }
314 KeInitializeEvent(&IoEvent, FALSE, NotificationEvent);
315 GdiInfo.CallBack = MouseGDICallBack;
316 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
317 FileObject->DeviceObject,
318 &GdiInfo,
319 sizeof(GdiInfo),
320 NULL,
321 0,
322 TRUE,
323 &FileObject->Event,
324 &Iosb);
325
326 //trigger FileObject/Event dereferencing
327 Irp->Tail.Overlay.OriginalFileObject = FileObject;
328
329 StackPtr = IoGetNextIrpStackLocation(Irp);
330 StackPtr->FileObject = FileObject;
331 StackPtr->DeviceObject = FileObject->DeviceObject;
332 StackPtr->Parameters.DeviceIoControl.InputBufferLength = sizeof(GdiInfo);
333 StackPtr->Parameters.DeviceIoControl.OutputBufferLength = 0;
334
335 Status = IoCallDriver(FileObject->DeviceObject, Irp);
336 if (Status == STATUS_PENDING)
337 {
338 KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE,
339 NULL);
340 Status = Iosb.Status;
341 }
342 if (!NT_SUCCESS(Status))
343 {
344 DPRINT1("Win32K: Failed to connect to mouse driver.\n");
345 ObDereferenceObject(&FileObject);
346 NtClose(MouseDeviceHandle);
347 return STATUS_SUCCESS;
348 }
349
350 /* Initialize the default keyboard layout */
351 (VOID)W32kGetDefaultKeyLayout();
352
353 return STATUS_SUCCESS;
354 }
355
356 NTSTATUS FASTCALL
357 CleanupInputImp(VOID)
358 {
359 return(STATUS_SUCCESS);
360 }
361
362 BOOL
363 STDCALL
364 NtUserDragDetect(
365 HWND hWnd,
366 LONG x,
367 LONG y)
368 {
369 UNIMPLEMENTED
370 return 0;
371 }
372
373 /* EOF */