source: trunk/src/user32/winmouse.cpp@ 7788

Last change on this file since 7788 was 7620, checked in by sandervl, 24 years ago

SendInput fix + handle Alt-F4 in default window handler

File size: 12.3 KB
Line 
1/* $Id: winmouse.cpp,v 1.20 2001-12-12 16:40:45 sandervl Exp $ */
2/*
3 * Mouse handler for DINPUT
4 *
5 * Copyright 1999-2001 Sander van Leeuwen
6 *
7 * TODO: SwapMouseButton:
8 * We shouldn't let win32 apps change this for the whole system
9 * better to change mouse button message translation instead
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14
15#include <odin.h>
16#include <odinwrap.h>
17#include <os2sel.h>
18
19#include <os2win.h>
20#include <misc.h>
21#include "win32wbase.h"
22#include <winuser32.h>
23#include <winuser.h>
24#include <win\mouse.h>
25#include "winmouse.h"
26#include "oslibmsg.h"
27#include "pmwindow.h"
28#include "oslibwin.h"
29
30#define DBG_LOCALLOG DBG_winmouse
31#include "dbglocal.h"
32
33
34ODINDEBUGCHANNEL(USER32-WINMOUSE)
35
36
37/****************************************************************************
38 * local variables
39 ****************************************************************************/
40
41LPMOUSE_EVENT_PROC mouseHandler = NULL;
42WNDPROC keyboardHandler = NULL;
43
44
45//******************************************************************************
46//******************************************************************************
47ODINPROCEDURE1(MOUSE_Enable,
48 LPMOUSE_EVENT_PROC, lpMouseEventProc)
49{
50 if(lpMouseEventProc == (LPMOUSE_EVENT_PROC)-1)
51 mouseHandler = NULL;
52 else
53 mouseHandler = lpMouseEventProc;
54}
55//******************************************************************************
56//******************************************************************************
57ODINPROCEDURE1(KEYBOARD_Enable,
58 WNDPROC, handler)
59{
60 keyboardHandler = handler;
61}
62//******************************************************************************
63//******************************************************************************
64BOOL DInputKeyBoardHandler(MSG *msg)
65{
66 if(!ISKDB_CAPTURED())
67 return FALSE;
68
69 return keyboardHandler(msg->hwnd, msg->message, msg->wParam, msg->lParam);
70}
71//******************************************************************************
72//******************************************************************************
73BOOL DInputMouseHandler(HWND hwnd, ULONG msg, ULONG x, ULONG y)
74{
75 WINE_MOUSEEVENT mouseEvent;
76 DWORD dwFlags = MOUSEEVENTF_ABSOLUTE;
77
78 if(!ISMOUSE_CAPTURED())
79 return FALSE;
80
81 mouseEvent.magic = WINE_MOUSEEVENT_MAGIC;
82 mouseEvent.hWnd = hwnd;
83 mouseEvent.time = OSLibWinQueryMsgTime();
84 mouseEvent.keyState = 0; //not used in dinput right now
85 switch(msg)
86 {
87 case WM_NCLBUTTONDOWN:
88 case WM_LBUTTONDOWN:
89 dwFlags |= MOUSEEVENTF_LEFTDOWN;
90 break;
91 case WM_NCLBUTTONUP:
92 case WM_LBUTTONUP:
93 dwFlags |= MOUSEEVENTF_LEFTUP;
94 break;
95 case WM_NCRBUTTONUP:
96 case WM_RBUTTONUP:
97 dwFlags |= MOUSEEVENTF_RIGHTUP;
98 break;
99 case WM_NCRBUTTONDOWN:
100 case WM_RBUTTONDOWN:
101 dwFlags |= MOUSEEVENTF_RIGHTDOWN;
102 break;
103 case WM_NCMBUTTONUP:
104 case WM_MBUTTONUP:
105 dwFlags |= MOUSEEVENTF_MIDDLEUP;
106 break;
107 case WM_NCMBUTTONDOWN:
108 case WM_MBUTTONDOWN:
109 dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
110 break;
111 case WM_MOUSEMOVE:
112 case WM_NCMOUSEMOVE:
113 dwFlags |= MOUSEEVENTF_MOVE;
114 break;
115 default:
116 //TODO: handle double clicks???
117 return FALSE;
118 }
119
120 x = (((long)x << 16) + ScreenWidth-1) / ScreenWidth;
121 y = (((long)y << 16) + ScreenHeight-1) / ScreenHeight;
122
123 return mouseHandler(dwFlags, x, y, 0, (DWORD)&mouseEvent);
124}
125//******************************************************************************
126//******************************************************************************
127
128// capture handle "cache"
129static HWND hwndWin32Capture = 0;
130
131ODINFUNCTION0(HWND, GetCapture)
132{
133 if (0 == hwndWin32Capture)
134 hwndWin32Capture = OS2ToWin32Handle(OSLibWinQueryCapture());
135
136 return hwndWin32Capture;
137}
138//******************************************************************************
139//******************************************************************************
140ODINFUNCTION1(HWND, SetCapture,
141 HWND, hwnd)
142{
143 HWND hwndPrev = GetCapture();
144 BOOL rc;
145
146 // invalidate capture "cache"
147 hwndWin32Capture = 0;
148
149 if(hwnd == 0)
150 {
151 ReleaseCapture();
152 return hwndPrev;
153 }
154
155 if(hwnd == hwndPrev)
156 {
157 dprintf(("USER32: SetCapture %x; already set to that window; ignore", hwnd));
158 return hwndPrev;
159 }
160
161 if(hwndPrev != NULL)
162 {
163 //SvL: WinSetCapture returns an error if mouse is already captured
164 OSLibWinSetCapture(0);
165 }
166
167 rc = OSLibWinSetCapture(Win32ToOS2Handle(hwnd));
168 dprintf(("USER32: SetCapture %x (prev %x) returned %d", hwnd, hwndPrev, rc));
169 if(hwndPrev)
170 {
171 SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, hwnd);
172 }
173 return hwndPrev;
174}
175//******************************************************************************
176//******************************************************************************
177ODINFUNCTION0(BOOL, ReleaseCapture)
178{
179 HWND hwndPrev;
180 BOOL ret;
181
182 hwndPrev = GetCapture();
183
184 // invalidate capture "cache"
185 hwndWin32Capture = 0;
186
187 ret = OSLibWinSetCapture(0);
188 if(hwndPrev)
189 {
190 SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, 0L);
191 }
192 return ret;
193}
194//******************************************************************************
195//******************************************************************************
196ODINFUNCTION0(UINT, GetDoubleClickTime)
197{
198 UINT result = OSLibWinQuerySysValue(SVOS_DBLCLKTIME);
199 if(result == 0)
200 SetLastError(ERROR_INVALID_PARAMETER); //TODO: ????
201
202 return result;
203}
204//******************************************************************************
205//******************************************************************************
206ODINFUNCTION1(BOOL, SetDoubleClickTime,
207 UINT, uInterval)
208{
209 BOOL ret = TRUE;
210
211 ret = OSLibWinSetSysValue(SVOS_DBLCLKTIME, uInterval);
212 if(ret == FALSE )
213 {
214 SetLastError(ERROR_INVALID_PARAMETER); //TODO: ????
215 }
216 return (ret);
217}
218//******************************************************************************
219//TODO: we shouldn't let win32 apps change this for the whole system
220// better to change mouse button message translation instead
221BOOL OPEN32API __SwapMouseButton(BOOL swapFlag);
222
223inline BOOL _SwapMouseButton(BOOL swapFlag)
224{
225 BOOL yyrc;
226 USHORT sel = RestoreOS2FS();
227
228 yyrc = __SwapMouseButton(swapFlag);
229 SetFS(sel);
230
231 return yyrc;
232}
233
234//******************************************************************************
235ODINFUNCTION1(BOOL, SwapMouseButton,
236 BOOL, fSwap)
237{
238 return _SwapMouseButton(fSwap);
239}
240
241/*****************************************************************************
242 * Name : VOID WIN32API mouse_event
243 * Purpose : The mouse_event function synthesizes mouse motion and button clicks.
244 * Parameters: DWORD dwFlags flags specifying various motion/click variants
245 * DWORD dx horizontal mouse position or position change
246 * DWORD dy vertical mouse position or position change
247 * DWORD cButtons unused, reserved for future use, set to zero
248 * DWORD dwExtraInfo 32 bits of application-defined information
249 * Variables :
250 * Result :
251 * Remark :
252 * Status : UNTESTED STUB
253 *
254 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
255 *****************************************************************************/
256
257ODINPROCEDURE5(mouse_event,
258 DWORD, dwFlags,
259 DWORD, dx,
260 DWORD, dy,
261 DWORD, cButtons,
262 DWORD, dwExtraInfo)
263{
264 INPUT i;
265
266 // format input packet
267 i.type = INPUT_MOUSE;
268 i.mi.dx = dx;
269 i.mi.dy = dy;
270 i.mi.mouseData = cButtons; // PH: is this really correct?
271 i.mi.dwFlags = dwFlags;
272 i.mi.dwExtraInfo = dwExtraInfo;
273
274 // forward to more modern API
275 SendInput(1, &i, sizeof(i) );
276}
277
278
279ODINFUNCTION1(DWORD, TrackMouseEvent,
280 DWORD, param1)
281{
282 dprintf(("not implemented"));
283 return 0;
284}
285
286
287/*****************************************************************************
288 * Name : UINT SendInput
289 * Purpose : The SendInput function synthesizes keystrokes, mouse motions,
290 * and button clicks
291 * Parameters: UINT nInputs // count if input events
292 * LPINPUT pInputs // array of input structures
293 * int chSize // size of structure
294 * Variables :
295 * Result : number of events successfully inserted,
296 * 0 if the input was already blocked by another thread
297 * Remark :
298 * Status : UNTESTED STUB
299 *
300 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
301 *****************************************************************************/
302
303ODINFUNCTION3(UINT, SendInput,
304 UINT, nInputs,
305 LPINPUT, pInputs,
306 int, chSize)
307{
308 dprintf(("not correctly implemented"));
309
310 // The simulated input is sent to the
311 // foreground thread's message queue.
312 // (WM_KEYUP, WM_KEYDOWN)
313 // After GetMessage or PeekMessage,
314 // TranslateMessage posts an appropriate
315 // WM_CHAR message.
316 HWND hwnd = GetForegroundWindow();
317
318 LPINPUT piBase = pInputs;
319 for (int i = 0;
320 i < nInputs;
321 i++,
322 piBase++)
323 {
324 switch(piBase->type)
325 {
326 case INPUT_MOUSE:
327 {
328 PMOUSEINPUT p = (PMOUSEINPUT)&piBase->mi;
329 MSG msg;
330
331 // simulate mouse input message
332 // @@@PH
333 }
334 break;
335
336 // compose a keyboard input message
337 case INPUT_KEYBOARD:
338 {
339 PKEYBDINPUT p = (PKEYBDINPUT)&piBase->ki;
340 MSG msg;
341 BOOL fUnicode = (p->dwFlags & KEYEVENTF_UNICODE) == KEYEVENTF_UNICODE;
342 DWORD extrainfo = GetMessageExtraInfo();
343
344 // build keyboard message
345 msg.message = (p->dwFlags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
346
347 if (p->dwFlags & KEYEVENTF_SCANCODE)
348 {
349 // keystroke is identified by the scancode
350 if (fUnicode)
351 msg.wParam = MapVirtualKeyW(p->wScan, 1);
352 else
353 msg.wParam = MapVirtualKeyA(p->wScan, 1);
354 }
355 else
356 msg.wParam = p->wVk;
357
358 msg.lParam = 0x0000001 | // repeat count
359 ( (p->wScan & 0xff) << 16); // scan code
360
361 if (p->dwFlags & KEYEVENTF_EXTENDEDKEY)
362 msg.lParam |= (1 << 24);
363
364 // set additional message flags
365 if (msg.message == WM_KEYDOWN)
366 {
367 // @@@PH
368 // bit 30 - previous key state cannot be set, how to determine?
369 }
370 else
371 {
372 // WM_KEYUP -> previous key is always 1, transistion state
373 // always 1
374 msg.lParam |= (1 << 30);
375 msg.lParam |= (1 << 31);
376 }
377
378 msg.time = p->time;
379
380 // @@@PH
381 // unknown: do we have to post or to send the message?
382
383 SetMessageExtraInfo( (LPARAM)p->dwExtraInfo );
384
385 if (fUnicode)
386 SendMessageW(hwnd, msg.message, msg.wParam, msg.lParam);
387 else
388 SendMessageA(hwnd, msg.message, msg.wParam, msg.lParam);
389
390 //restore extra info
391 SetMessageExtraInfo(extrainfo);
392 break;
393 }
394
395 case INPUT_HARDWARE:
396 {
397 PHARDWAREINPUT p = (PHARDWAREINPUT)&piBase->hi;
398
399 // @@@PH
400 // not supported for the time being
401 }
402 break;
403
404 default:
405 dprintf(("unsupported input packet type %d",
406 piBase->type));
407 break;
408 }
409 }
410
411 return 0;
412}
413
414/*****************************************************************************
415 * Name : BOOL WIN32API DragDetect
416 * Purpose : The DragDetect function captures the mouse and tracks its movement
417 * Parameters: HWND hwnd
418 * POINT pt
419 * Variables :
420 * Result : If the user moved the mouse outside of the drag rectangle while
421 * holding the left button down, the return value is TRUE.
422 * If the user did not move the mouse outside of the drag rectangle
423 * while holding the left button down, the return value is FALSE.
424 * Remark :
425 * Status : UNTESTED STUB
426 *
427 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
428 *****************************************************************************/
429ODINFUNCTION2(BOOL, DragDetect,
430 HWND, hwnd,
431 POINT, pt)
432{
433 dprintf(("not implemented"));
434
435 return (FALSE);
436}
437//******************************************************************************
438//******************************************************************************
Note: See TracBrowser for help on using the repository browser.