source: trunk/src/user32/winmouse.cpp

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 23.3 KB
RevLine 
[10185]1/* $Id: winmouse.cpp,v 1.27 2003-07-28 11:27:50 sandervl Exp $ */
[2469]2/*
[7807]3 * Win32 mouse functions
[2469]4 *
[7807]5 * Copyright 1999-2002 Sander van Leeuwen
[2469]6 *
[7807]7 * Parts based on Wine code (windows\input.c) (TrackMouseEvent)
8 *
9 * Copyright 1993 Bob Amstadt
[21502]10 * Copyright 1996 Albrecht Kleine
[7807]11 * Copyright 1997 David Faure
12 * Copyright 1998 Morten Welinder
13 * Copyright 1998 Ulrich Weigand
14 *
[21502]15 * TODO: SwapMouseButton:
[6395]16 * We shouldn't let win32 apps change this for the whole system
17 * better to change mouse button message translation instead
[2469]18 *
19 * Project Odin Software License can be found in LICENSE.TXT
20 *
21 */
[6846]22
23#include <odin.h>
24#include <odinwrap.h>
25#include <os2sel.h>
26
[2469]27#include <os2win.h>
28#include <misc.h>
29#include "win32wbase.h"
[4848]30#include <winuser32.h>
[6846]31#include <winuser.h>
[7807]32#include <commctrl.h>
33#include <debugtools.h>
[21916]34#include <win/mouse.h>
[2469]35#include "winmouse.h"
36#include "oslibmsg.h"
[8533]37#include "oslibres.h"
[2469]38#include "pmwindow.h"
[3488]39#include "oslibwin.h"
[8533]40#include "hook.h"
[2469]41
[10185]42#include <winkeyboard.h>
43
[2803]44#define DBG_LOCALLOG DBG_winmouse
45#include "dbglocal.h"
46
[6846]47
48ODINDEBUGCHANNEL(USER32-WINMOUSE)
49
50
51/****************************************************************************
52 * local variables
53 ****************************************************************************/
54
[2469]55//******************************************************************************
56//******************************************************************************
[8533]57BOOL WIN32API GetCursorPos( PPOINT lpPoint)
58{
59 if (!lpPoint) return FALSE;
[3007]60
[8533]61 if (OSLibWinQueryPointerPos(lpPoint)) //POINT == POINTL
62 {
63 mapScreenPoint((OSLIBPOINT*)lpPoint);
64 dprintf2(("USER32: GetCursorPos (%d,%d)", lpPoint->x, lpPoint->y));
65 return TRUE;
66 }
67 else return FALSE;
68}
69//******************************************************************************
70//******************************************************************************
71BOOL WIN32API SetCursorPos( int X, int Y)
72{
[9019]73 BOOL ret;
74 POINT point;
75 MSLLHOOKSTRUCT hook;
[8533]76
[9019]77 GetCursorPos(&point);
78 dprintf(("USER32: SetCursorPos (%d,%d)->(%d,%d)", point.x, point.y, X,Y));
79
80 //The current cursor position may not have been passed to the application
81 //just yet. The position change discards any previous events which may
82 //lead to inconsistent mouse behaviour (like in DirectInput).
83 //To fix this, we pass down a mouse move event to any hook handlers.
84 hook.pt.x = point.x;
85 hook.pt.y = point.y;
86 hook.mouseData = 0;
87 hook.flags = 0;
88 hook.time = GetCurrentTime();
89 hook.dwExtraInfo = 0;
90 HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WM_MOUSEMOVE, (LPARAM)&hook);
91
[8533]92 ret = OSLibWinSetPointerPos(X, mapScreenY(Y));
93 if(ret == TRUE) {
94 hook.pt.x = X;
95 hook.pt.y = Y;
96 hook.mouseData = 0;
97 //signal to dinput hook that it only needs to modify the last
98 //known position (not treat it as a new event)
99 hook.flags = LLMHF_INJECTED;
100 hook.time = GetCurrentTime();
101 hook.dwExtraInfo = 0;
102
103 HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WM_MOUSEMOVE, (LPARAM)&hook);
104 }
105 return ret;
106}
107//******************************************************************************
108//******************************************************************************
109BOOL WIN32API ClipCursor(const RECT * lpRect)
110{
111 if(lpRect) {
112 dprintf(("USER32: ClipCursor (%d,%d)(%d,%d)", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom));
113 }
114 else dprintf(("USER32: ClipCursor NULL"));
115 return OSLibWinClipCursor(lpRect);
116}
117//******************************************************************************
118//******************************************************************************
119BOOL WIN32API GetClipCursor( LPRECT lpRect)
120{
121 dprintf(("USER32: GetClipCursor %x", lpRect));
122 return OSLibWinGetClipCursor(lpRect);
123}
124//******************************************************************************
[7028]125// capture handle "cache"
126static HWND hwndWin32Capture = 0;
[8533]127//******************************************************************************
[7875]128HWND WIN32API GetCapture()
[3488]129{
[7028]130 if (0 == hwndWin32Capture)
131 hwndWin32Capture = OS2ToWin32Handle(OSLibWinQueryCapture());
[21502]132
[7028]133 return hwndWin32Capture;
[3488]134}
135//******************************************************************************
136//******************************************************************************
[7875]137HWND WIN32API SetCapture(HWND hwnd)
[3488]138{
[6846]139 HWND hwndPrev = GetCapture();
140 BOOL rc;
[21502]141
[7028]142 // invalidate capture "cache"
143 hwndWin32Capture = 0;
[21502]144
145 if(hwnd == 0)
[6846]146 {
147 ReleaseCapture();
[3488]148 return hwndPrev;
[6846]149 }
[21502]150
151 if(hwnd == hwndPrev)
[6846]152 {
153 dprintf(("USER32: SetCapture %x; already set to that window; ignore", hwnd));
[10185]154 //TODO: NT4 SP6 sends this message even now
155//////// SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, hwnd);
[6846]156 return hwndPrev;
157 }
[21502]158
159 if(hwndPrev != NULL)
[6846]160 {
161 //SvL: WinSetCapture returns an error if mouse is already captured
162 OSLibWinSetCapture(0);
163 }
[21502]164
[6846]165 rc = OSLibWinSetCapture(Win32ToOS2Handle(hwnd));
166 dprintf(("USER32: SetCapture %x (prev %x) returned %d", hwnd, hwndPrev, rc));
[21502]167 if(hwndPrev)
[6846]168 {
169 SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, hwnd);
170 }
171 return hwndPrev;
[3488]172}
173//******************************************************************************
174//******************************************************************************
[7875]175BOOL WIN32API ReleaseCapture()
[3488]176{
[6846]177 HWND hwndPrev;
178 BOOL ret;
[3488]179
[6846]180 hwndPrev = GetCapture();
[21502]181
[7028]182 // invalidate capture "cache"
183 hwndWin32Capture = 0;
[21502]184
[6846]185 ret = OSLibWinSetCapture(0);
[21502]186 if(hwndPrev)
[6846]187 {
188 SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, 0L);
189 }
190 return ret;
[3488]191}
192//******************************************************************************
193//******************************************************************************
[7875]194UINT WIN32API GetDoubleClickTime()
[5606]195{
[6846]196 UINT result = OSLibWinQuerySysValue(SVOS_DBLCLKTIME);
197 if(result == 0)
198 SetLastError(ERROR_INVALID_PARAMETER); //TODO: ????
[6395]199
[6846]200 return result;
[5606]201}
202//******************************************************************************
203//******************************************************************************
[7875]204BOOL WIN32API SetDoubleClickTime(UINT uInterval)
[5606]205{
[6846]206 BOOL ret = TRUE;
[6395]207
[6846]208 ret = OSLibWinSetSysValue(SVOS_DBLCLKTIME, uInterval);
209 if(ret == FALSE )
210 {
211 SetLastError(ERROR_INVALID_PARAMETER); //TODO: ????
212 }
213 return (ret);
[5606]214}
215//******************************************************************************
[6395]216//TODO: we shouldn't let win32 apps change this for the whole system
217// better to change mouse button message translation instead
218BOOL OPEN32API __SwapMouseButton(BOOL swapFlag);
219
220inline BOOL _SwapMouseButton(BOOL swapFlag)
221{
222 BOOL yyrc;
223 USHORT sel = RestoreOS2FS();
224
225 yyrc = __SwapMouseButton(swapFlag);
226 SetFS(sel);
227
228 return yyrc;
229}
230
[5606]231//******************************************************************************
[7875]232BOOL WIN32API SwapMouseButton(BOOL fSwap)
[5606]233{
[6846]234 return _SwapMouseButton(fSwap);
[5606]235}
[6846]236
[5606]237/*****************************************************************************
238 * Name : VOID WIN32API mouse_event
239 * Purpose : The mouse_event function synthesizes mouse motion and button clicks.
240 * Parameters: DWORD dwFlags flags specifying various motion/click variants
241 * DWORD dx horizontal mouse position or position change
242 * DWORD dy vertical mouse position or position change
243 * DWORD cButtons unused, reserved for future use, set to zero
244 * DWORD dwExtraInfo 32 bits of application-defined information
245 * Variables :
246 * Result :
247 * Remark :
248 * Status : UNTESTED STUB
249 *
250 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
251 *****************************************************************************/
[6846]252
[7875]253VOID WIN32API mouse_event(DWORD dwFlags, DWORD dx, DWORD dy, DWORD cButtons,
254 DWORD dwExtraInfo)
[5606]255{
[6972]256 INPUT i;
[21502]257
[6972]258 i.type = INPUT_MOUSE;
259 i.mi.dx = dx;
260 i.mi.dy = dy;
261 i.mi.mouseData = cButtons; // PH: is this really correct?
262 i.mi.dwFlags = dwFlags;
263 i.mi.dwExtraInfo = dwExtraInfo;
[21502]264
[6972]265 // forward to more modern API
266 SendInput(1, &i, sizeof(i) );
[5606]267}
[5751]268
[6846]269
270/*****************************************************************************
271 * Name : UINT SendInput
[21502]272 * Purpose : The SendInput function synthesizes keystrokes, mouse motions,
[6846]273 * and button clicks
274 * Parameters: UINT nInputs // count if input events
275 * LPINPUT pInputs // array of input structures
276 * int chSize // size of structure
277 * Variables :
278 * Result : number of events successfully inserted,
279 * 0 if the input was already blocked by another thread
280 * Remark :
281 * Status : UNTESTED STUB
[8347]282 * TODO: call hooks!!
[6846]283 *
284 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
285 *****************************************************************************/
286
[7875]287UINT WIN32API SendInput(UINT nInputs, LPINPUT pInputs, int chSize)
[5751]288{
[6846]289 dprintf(("not correctly implemented"));
[21502]290
[6846]291 // The simulated input is sent to the
292 // foreground thread's message queue.
293 // (WM_KEYUP, WM_KEYDOWN)
294 // After GetMessage or PeekMessage,
295 // TranslateMessage posts an appropriate
296 // WM_CHAR message.
[10185]297
[6846]298 HWND hwnd = GetForegroundWindow();
[21502]299
[6846]300 LPINPUT piBase = pInputs;
301 for (int i = 0;
302 i < nInputs;
303 i++,
304 piBase++)
305 {
306 switch(piBase->type)
307 {
308 case INPUT_MOUSE:
309 {
310 PMOUSEINPUT p = (PMOUSEINPUT)&piBase->mi;
[21502]311 MSG msg;
[10185]312 HWND hwndCapture;
313
314 hwndCapture = GetCapture();
315 if(hwndCapture) hwnd = hwndCapture;
[21502]316
317 if(p->dwFlags & MOUSEEVENTF_MOVE)
[10185]318 {
319 if(!(p->dwFlags & MOUSEEVENTF_ABSOLUTE)) {
320 POINT pt;
321
322 if(GetCursorPos(&pt) == TRUE) {
323 LONG relx = (LONG)p->dx;
324 LONG rely = (LONG)p->dy;
325
326 p->dx = pt.x + relx;
327 p->dy = pt.y + rely;
328 }
329 else {
330 DebugInt3();
331 return 0;
332 }
333 }
[21502]334 SetCursorPos(p->dx, p->dy);
[10185]335 OSLibSendWinMessage(hwnd, WM_MOUSEMOVE);
336 }
337
[21502]338 if(p->dwFlags & MOUSEEVENTF_LEFTDOWN)
[10185]339 {
340 KeySetOverlayKeyState(VK_LBUTTON, KEYOVERLAYSTATE_DOWN);
341 OSLibSendWinMessage(hwnd, WM_LBUTTONDOWN);
342 }
[21502]343 if(p->dwFlags & MOUSEEVENTF_LEFTUP)
[10185]344 {
345 KeySetOverlayKeyState(VK_LBUTTON, KEYOVERLAYSTATE_DONTCARE);
346 OSLibSendWinMessage(hwnd, WM_LBUTTONUP);
347 }
[21502]348 if(p->dwFlags & MOUSEEVENTF_RIGHTDOWN)
[10185]349 {
350 KeySetOverlayKeyState(VK_RBUTTON, KEYOVERLAYSTATE_DOWN);
351 OSLibSendWinMessage(hwnd, WM_RBUTTONDOWN);
352 }
[21502]353 if(p->dwFlags & MOUSEEVENTF_RIGHTUP)
[10185]354 {
355 KeySetOverlayKeyState(VK_RBUTTON, KEYOVERLAYSTATE_DONTCARE);
356 OSLibSendWinMessage(hwnd, WM_RBUTTONUP);
357 }
[21502]358 if(p->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
[10185]359 {
360 KeySetOverlayKeyState(VK_MBUTTON, KEYOVERLAYSTATE_DOWN);
361 OSLibSendWinMessage(hwnd, WM_MBUTTONDOWN);
362 }
[21502]363 if(p->dwFlags & MOUSEEVENTF_MIDDLEUP)
[10185]364 {
365 KeySetOverlayKeyState(VK_MBUTTON, KEYOVERLAYSTATE_DONTCARE);
366 OSLibSendWinMessage(hwnd, WM_MBUTTONUP);
367 }
[21502]368 if(p->dwFlags & MOUSEEVENTF_WHEEL)
369 {
370 OSLibSendWinMessage(hwnd, WM_MOUSEWHEEL, p->mouseData);
371 }
372 }
[6846]373 break;
[21502]374
[6846]375 // compose a keyboard input message
376 case INPUT_KEYBOARD:
377 {
378 PKEYBDINPUT p = (PKEYBDINPUT)&piBase->ki;
379 MSG msg;
380 BOOL fUnicode = (p->dwFlags & KEYEVENTF_UNICODE) == KEYEVENTF_UNICODE;
[7620]381 DWORD extrainfo = GetMessageExtraInfo();
[10185]382
383 //TODO: We should really send an OS/2 WM_CHAR message here and let
384 // our existing code handle everything (WM_CHAR generation)
385 // This is a quick and dirty implementation. Not entirely correct.
[21502]386
[6846]387 // build keyboard message
388 msg.message = (p->dwFlags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
[21502]389
[6846]390 if (p->dwFlags & KEYEVENTF_SCANCODE)
391 {
392 // keystroke is identified by the scancode
393 if (fUnicode)
394 msg.wParam = MapVirtualKeyW(p->wScan, 1);
395 else
396 msg.wParam = MapVirtualKeyA(p->wScan, 1);
397 }
398 else
399 msg.wParam = p->wVk;
[21502]400
[6846]401 msg.lParam = 0x0000001 | // repeat count
402 ( (p->wScan & 0xff) << 16); // scan code
[21502]403
[6846]404 if (p->dwFlags & KEYEVENTF_EXTENDEDKEY)
405 msg.lParam |= (1 << 24);
[21502]406
[6846]407 // set additional message flags
408 if (msg.message == WM_KEYDOWN)
409 {
410 // @@@PH
411 // bit 30 - previous key state cannot be set, how to determine?
412 }
413 else
414 {
415 // WM_KEYUP -> previous key is always 1, transistion state
416 // always 1
417 msg.lParam |= (1 << 30);
418 msg.lParam |= (1 << 31);
419 }
[21502]420
[6846]421 msg.time = p->time;
[21502]422
[6846]423 // @@@PH
424 // unknown: do we have to post or to send the message?
[7620]425
426 SetMessageExtraInfo( (LPARAM)p->dwExtraInfo );
[10185]427
428 KeySetOverlayKeyState(msg.wParam, (msg.message == WM_KEYDOWN) ? KEYOVERLAYSTATE_DOWN : KEYOVERLAYSTATE_DONTCARE);
[21502]429
[6846]430 if (fUnicode)
[7620]431 SendMessageW(hwnd, msg.message, msg.wParam, msg.lParam);
[6846]432 else
[7620]433 SendMessageA(hwnd, msg.message, msg.wParam, msg.lParam);
[10185]434
435 if(msg.message == WM_KEYDOWN) {
436 char keybstate[256];
437 WORD key = 0;
438
439 GetKeyboardState((LPBYTE)&keybstate[0]);
440 if(ToAscii(p->wVk, p->wScan, (LPBYTE)&keybstate[0], &key, 0) != 0) {
441 SendMessageA(hwnd, WM_CHAR, key, msg.lParam);
442 }
443 }
444
[7620]445 //restore extra info
446 SetMessageExtraInfo(extrainfo);
447 break;
[21502]448 }
449
[6846]450 case INPUT_HARDWARE:
451 {
452 PHARDWAREINPUT p = (PHARDWAREINPUT)&piBase->hi;
[21502]453
[6846]454 // @@@PH
455 // not supported for the time being
[21502]456 }
[6846]457 break;
[21502]458
[6846]459 default:
460 dprintf(("unsupported input packet type %d",
461 piBase->type));
462 break;
463 }
464 }
[21502]465
[5751]466 return 0;
467}
468
[5606]469/*****************************************************************************
470 * Name : BOOL WIN32API DragDetect
471 * Purpose : The DragDetect function captures the mouse and tracks its movement
472 * Parameters: HWND hwnd
473 * POINT pt
474 * Variables :
475 * Result : If the user moved the mouse outside of the drag rectangle while
476 * holding the left button down, the return value is TRUE.
477 * If the user did not move the mouse outside of the drag rectangle
478 * while holding the left button down, the return value is FALSE.
479 * Remark :
480 * Status : UNTESTED STUB
481 *
482 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
483 *****************************************************************************/
[7875]484BOOL WIN32API DragDetect(HWND hwnd, POINT pt)
[5606]485{
[6846]486 dprintf(("not implemented"));
[5606]487
488 return (FALSE);
489}
490//******************************************************************************
491//******************************************************************************
[7807]492typedef struct __TRACKINGLIST {
493 TRACKMOUSEEVENT tme;
494 POINT pos; /* center of hover rectangle */
495 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
[21502]496} _TRACKINGLIST;
[7807]497
[21502]498#define UINT_PTR UINT
[7807]499static _TRACKINGLIST TrackingList[10];
500static int iTrackMax = 0;
501static UINT_PTR timer;
502static const INT iTimerInterval = 50; /* msec for timer interval */
503
504/* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
505/* TrackMouseEventProc and _TrackMouseEvent */
506static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
507 DWORD dwTime)
508{
509 int i = 0;
510 POINT pos;
511 HWND hwnd;
512 INT hoverwidth = 0, hoverheight = 0;
513
514 GetCursorPos(&pos);
515 hwnd = WindowFromPoint(pos);
516
517 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
518 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
519
520 /* loop through tracking events we are processing */
521 while (i < iTrackMax) {
522 /* see if this tracking event is looking for TME_LEAVE and that the */
523 /* mouse has left the window */
524 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
525 (TrackingList[i].tme.hwndTrack != hwnd)) {
526 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
527
528 /* remove the TME_LEAVE flag */
529 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
530 }
531
532 /* see if we are tracking hovering for this hwnd */
533 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
534 /* add the timer interval to the hovering time */
[21502]535 TrackingList[i].iHoverTime+=iTimerInterval;
536
[7807]537 /* has the cursor moved outside the rectangle centered around pos? */
538 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
539 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
540 {
541 /* record this new position as the current position and reset */
542 /* the iHoverTime variable to 0 */
543 TrackingList[i].pos = pos;
544 TrackingList[i].iHoverTime = 0;
545 }
546
547 /* has the mouse hovered long enough? */
548 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
549 {
550 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
551
552 /* stop tracking mouse hover */
553 TrackingList[i].tme.dwFlags ^= TME_HOVER;
554 }
555 }
556
557 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
558 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
559 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
560 i++;
561 } else { /* remove this entry from the tracking list */
562 TrackingList[i] = TrackingList[--iTrackMax];
563 }
564 }
[21502]565
[7807]566 /* stop the timer if the tracking list is empty */
567 if(iTrackMax == 0) {
568 KillTimer(0, timer);
569 timer = 0;
570 }
571}
572
573
574/***********************************************************************
575 * TrackMouseEvent [USER32]
576 *
577 * Requests notification of mouse events
578 *
579 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
580 * to the hwnd specified in the ptme structure. After the event message
581 * is posted to the hwnd, the entry in the queue is removed.
582 *
583 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
584 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
585 * immediately and the TME_LEAVE flag being ignored.
586 *
587 * PARAMS
588 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
589 *
590 * RETURNS
591 * Success: non-zero
592 * Failure: zero
593 *
594 */
595
596BOOL WINAPI
597TrackMouseEvent (TRACKMOUSEEVENT *ptme)
598{
599 DWORD flags = 0;
600 int i = 0;
601 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
602 HWND hwnd;
603 POINT pos;
604
605 pos.x = 0;
606 pos.y = 0;
607
608 dprintf(("TrackMouseEvent: %lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime));
609
610 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
611 WARN("wrong TRACKMOUSEEVENT size from app\n");
612 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
613 return FALSE;
614 }
615
616 flags = ptme->dwFlags;
[21502]617
[7807]618 /* if HOVER_DEFAULT was specified replace this with the systems current value */
619 if(ptme->dwHoverTime == HOVER_DEFAULT)
620 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
621
622 GetCursorPos(&pos);
[21502]623 hwnd = WindowFromPoint(pos);
[7807]624
625 if ( flags & TME_CANCEL ) {
626 flags &= ~ TME_CANCEL;
627 cancel = 1;
628 }
[21502]629
[7807]630 if ( flags & TME_HOVER ) {
631 flags &= ~ TME_HOVER;
632 hover = 1;
633 }
[21502]634
[7807]635 if ( flags & TME_LEAVE ) {
636 flags &= ~ TME_LEAVE;
637 leave = 1;
638 }
639
640 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
641 if ( flags & TME_QUERY ) {
642 flags &= ~ TME_QUERY;
643 query = 1;
644 i = 0;
645
646 /* Find the tracking list entry with the matching hwnd */
647 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
648 i++;
649 }
650
651 /* hwnd found, fill in the ptme struct */
652 if(i < iTrackMax)
653 *ptme = TrackingList[i].tme;
654 else
655 ptme->dwFlags = 0;
[21502]656
[7807]657 return TRUE; /* return here, TME_QUERY is retrieving information */
658 }
659
660 if ( flags )
661 FIXME("Unknown flag(s) %08lx\n", flags );
662
663 if(cancel) {
664 /* find a matching hwnd if one exists */
665 i = 0;
666
667 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
668 i++;
669 }
670
671 if(i < iTrackMax) {
672 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
673
674 /* if we aren't tracking on hover or leave remove this entry */
675 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
676 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
677 {
678 TrackingList[i] = TrackingList[--iTrackMax];
[21502]679
[7807]680 if(iTrackMax == 0) {
681 KillTimer(0, timer);
682 timer = 0;
683 }
684 }
685 }
686 } else {
687 /* see if hwndTrack isn't the current window */
688 if(ptme->hwndTrack != hwnd) {
689 if(leave) {
690 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
691 }
692 } else {
693 /* See if this hwnd is already being tracked and update the tracking flags */
694 for(i = 0; i < iTrackMax; i++) {
695 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
696 if(hover) {
697 TrackingList[i].tme.dwFlags |= TME_HOVER;
698 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
699 }
[21502]700
[7807]701 if(leave)
702 TrackingList[i].tme.dwFlags |= TME_LEAVE;
703
704 /* reset iHoverTime as per winapi specs */
[21502]705 TrackingList[i].iHoverTime = 0;
706
[7807]707 return TRUE;
708 }
[21502]709 }
[7807]710
711 /* if the tracking list is full return FALSE */
712 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
713 return FALSE;
714 }
715
716 /* Adding new mouse event to the tracking list */
717 TrackingList[iTrackMax].tme = *ptme;
718
719 /* Initialize HoverInfo variables even if not hover tracking */
720 TrackingList[iTrackMax].iHoverTime = 0;
721 TrackingList[iTrackMax].pos = pos;
722
723 iTrackMax++;
724
725 if (!timer) {
726 timer = SetTimer(0, 0, iTimerInterval, (TIMERPROC)TrackMouseEventProc);
727 }
728 }
729 }
730
731 return TRUE;
732}
733//******************************************************************************
734//******************************************************************************
[10185]735ULONG GetMouseKeyState()
736{
737 ULONG keystate = 0;
738
739 if(GetKeyState(VK_LBUTTON) & 0x8000)
740 keystate |= MK_LBUTTON;
741 if(GetKeyState(VK_RBUTTON) & 0x8000)
742 keystate |= MK_RBUTTON;
743 if(GetKeyState(VK_MBUTTON) & 0x8000)
744 keystate |= MK_MBUTTON;
745 if(GetKeyState(VK_SHIFT) & 0x8000)
746 keystate |= MK_SHIFT;
747 if(GetKeyState(VK_CONTROL) & 0x8000)
748 keystate |= MK_CONTROL;
749
750 return keystate;
751}
752//******************************************************************************
753//******************************************************************************
Note: See TracBrowser for help on using the repository browser.