Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

winmouse.cpp

Go to the documentation of this file.
00001 /* $Id: winmouse.cpp,v 1.20 2001/12/12 16:40:45 sandervl Exp $ */
00002 /*
00003  * Mouse handler for DINPUT
00004  *
00005  * Copyright 1999-2001 Sander van Leeuwen
00006  *
00007  * TODO: SwapMouseButton: 
00008  *       We shouldn't let win32 apps change this for the whole system
00009  *       better to change mouse button message translation instead
00010  *
00011  * Project Odin Software License can be found in LICENSE.TXT
00012  *
00013  */
00014 
00015 #include <odin.h>
00016 #include <odinwrap.h>
00017 #include <os2sel.h>
00018 
00019 #include <os2win.h>
00020 #include <misc.h>
00021 #include "win32wbase.h"
00022 #include <winuser32.h>
00023 #include <winuser.h>
00024 #include <win\mouse.h>
00025 #include "winmouse.h"
00026 #include "oslibmsg.h"
00027 #include "pmwindow.h"
00028 #include "oslibwin.h"
00029 
00030 #define DBG_LOCALLOG    DBG_winmouse
00031 #include "dbglocal.h"
00032 
00033 
00034 ODINDEBUGCHANNEL(USER32-WINMOUSE)
00035 
00036 
00037 /****************************************************************************
00038  * local variables
00039  ****************************************************************************/
00040 
00041 LPMOUSE_EVENT_PROC mouseHandler = NULL;
00042 WNDPROC            keyboardHandler = NULL;
00043 
00044 
00045 //******************************************************************************
00046 //******************************************************************************
00047 ODINPROCEDURE1(MOUSE_Enable,
00048                LPMOUSE_EVENT_PROC, lpMouseEventProc)
00049 {
00050   if(lpMouseEventProc == (LPMOUSE_EVENT_PROC)-1)
00051     mouseHandler = NULL;
00052   else  
00053     mouseHandler = lpMouseEventProc;
00054 }
00055 //******************************************************************************
00056 //******************************************************************************
00057 ODINPROCEDURE1(KEYBOARD_Enable,
00058                WNDPROC, handler)
00059 {
00060   keyboardHandler = handler;
00061 }
00062 //******************************************************************************
00063 //******************************************************************************
00064 BOOL DInputKeyBoardHandler(MSG *msg)
00065 {
00066   if(!ISKDB_CAPTURED())
00067         return FALSE;
00068 
00069   return keyboardHandler(msg->hwnd, msg->message, msg->wParam, msg->lParam);
00070 }
00071 //******************************************************************************
00072 //******************************************************************************
00073 BOOL DInputMouseHandler(HWND hwnd, ULONG msg, ULONG x, ULONG y)
00074 {
00075  WINE_MOUSEEVENT mouseEvent;
00076  DWORD dwFlags = MOUSEEVENTF_ABSOLUTE;
00077 
00078   if(!ISMOUSE_CAPTURED())
00079         return FALSE;
00080 
00081   mouseEvent.magic = WINE_MOUSEEVENT_MAGIC;
00082   mouseEvent.hWnd  = hwnd;
00083   mouseEvent.time  = OSLibWinQueryMsgTime();
00084   mouseEvent.keyState = 0; //not used in dinput right now
00085   switch(msg) 
00086   {
00087   case WM_NCLBUTTONDOWN:
00088   case WM_LBUTTONDOWN:
00089         dwFlags |= MOUSEEVENTF_LEFTDOWN;
00090         break;
00091   case WM_NCLBUTTONUP:
00092   case WM_LBUTTONUP:
00093         dwFlags |= MOUSEEVENTF_LEFTUP;
00094         break;
00095   case WM_NCRBUTTONUP:
00096   case WM_RBUTTONUP:
00097         dwFlags |= MOUSEEVENTF_RIGHTUP;
00098         break;
00099   case WM_NCRBUTTONDOWN:
00100   case WM_RBUTTONDOWN:
00101         dwFlags |= MOUSEEVENTF_RIGHTDOWN;
00102         break;
00103   case WM_NCMBUTTONUP:
00104   case WM_MBUTTONUP:
00105         dwFlags |= MOUSEEVENTF_MIDDLEUP;
00106         break;
00107   case WM_NCMBUTTONDOWN:
00108   case WM_MBUTTONDOWN:
00109         dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
00110         break;
00111   case WM_MOUSEMOVE:
00112   case WM_NCMOUSEMOVE:
00113         dwFlags |= MOUSEEVENTF_MOVE;
00114         break;
00115   default:
00116         //TODO: handle double clicks???
00117         return FALSE;
00118   }
00119 
00120   x = (((long)x << 16) + ScreenWidth-1)  / ScreenWidth;
00121   y = (((long)y << 16) + ScreenHeight-1) / ScreenHeight;
00122 
00123   return mouseHandler(dwFlags, x, y, 0, (DWORD)&mouseEvent);
00124 }
00125 //******************************************************************************
00126 //******************************************************************************
00127 
00128 // capture handle "cache"
00129 static HWND hwndWin32Capture = 0;
00130 
00131 ODINFUNCTION0(HWND, GetCapture)
00132 {
00133   if (0 == hwndWin32Capture)
00134     hwndWin32Capture = OS2ToWin32Handle(OSLibWinQueryCapture());
00135   
00136   return hwndWin32Capture;
00137 }
00138 //******************************************************************************
00139 //******************************************************************************
00140 ODINFUNCTION1(HWND, SetCapture,
00141               HWND, hwnd)
00142 {
00143   HWND hwndPrev = GetCapture();
00144   BOOL rc;
00145   
00146   // invalidate capture "cache"
00147   hwndWin32Capture = 0;
00148   
00149   if(hwnd == 0) 
00150   {
00151     ReleaseCapture();
00152     return hwndPrev;
00153   }
00154   
00155   if(hwnd == hwndPrev) 
00156   {
00157     dprintf(("USER32: SetCapture %x; already set to that window; ignore", hwnd));
00158     return hwndPrev;
00159   }
00160   
00161   if(hwndPrev != NULL) 
00162   {
00163     //SvL: WinSetCapture returns an error if mouse is already captured
00164     OSLibWinSetCapture(0);
00165   }
00166   
00167   rc = OSLibWinSetCapture(Win32ToOS2Handle(hwnd));
00168   dprintf(("USER32: SetCapture %x (prev %x) returned %d", hwnd, hwndPrev, rc));
00169   if(hwndPrev) 
00170   {
00171     SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, hwnd);
00172   }
00173   return hwndPrev;
00174 }
00175 //******************************************************************************
00176 //******************************************************************************
00177 ODINFUNCTION0(BOOL, ReleaseCapture)
00178 {
00179   HWND hwndPrev;
00180   BOOL ret;
00181 
00182   hwndPrev = GetCapture();
00183   
00184   // invalidate capture "cache"
00185   hwndWin32Capture = 0;
00186   
00187   ret = OSLibWinSetCapture(0);
00188   if(hwndPrev) 
00189   {
00190     SendMessageA(hwndPrev, WM_CAPTURECHANGED, 0L, 0L);
00191   }
00192   return ret;
00193 }
00194 //******************************************************************************
00195 //******************************************************************************
00196 ODINFUNCTION0(UINT, GetDoubleClickTime)
00197 {
00198   UINT result = OSLibWinQuerySysValue(SVOS_DBLCLKTIME);
00199   if(result == 0)
00200     SetLastError(ERROR_INVALID_PARAMETER); //TODO: ????
00201 
00202   return result;
00203 }
00204 //******************************************************************************
00205 //******************************************************************************
00206 ODINFUNCTION1(BOOL, SetDoubleClickTime,
00207               UINT, uInterval)
00208 {
00209   BOOL ret = TRUE;
00210 
00211   ret = OSLibWinSetSysValue(SVOS_DBLCLKTIME, uInterval);
00212   if(ret == FALSE )
00213   {
00214     SetLastError(ERROR_INVALID_PARAMETER); //TODO: ????
00215   }
00216   return (ret);
00217 }
00218 //******************************************************************************
00219 //TODO: we shouldn't let win32 apps change this for the whole system
00220 //      better to change mouse button message translation instead
00221 BOOL OPEN32API __SwapMouseButton(BOOL swapFlag);
00222 
00223 inline BOOL _SwapMouseButton(BOOL swapFlag)
00224 {
00225  BOOL yyrc;
00226  USHORT sel = RestoreOS2FS();
00227 
00228     yyrc = __SwapMouseButton(swapFlag);
00229     SetFS(sel);
00230 
00231     return yyrc;
00232 }
00233 
00234 //******************************************************************************
00235 ODINFUNCTION1(BOOL, SwapMouseButton,
00236               BOOL, fSwap)
00237 {
00238   return _SwapMouseButton(fSwap);
00239 }
00240 
00241 /*****************************************************************************
00242  * Name      : VOID WIN32API mouse_event
00243  * Purpose   : The mouse_event function synthesizes mouse motion and button clicks.
00244  * Parameters: DWORD dwFlags     flags specifying various motion/click variants
00245  *             DWORD dx          horizontal mouse position or position change
00246  *             DWORD dy          vertical mouse position or position change
00247  *             DWORD cButtons    unused, reserved for future use, set to zero
00248  *             DWORD dwExtraInfo 32 bits of application-defined information
00249  * Variables :
00250  * Result    :
00251  * Remark    :
00252  * Status    : UNTESTED STUB
00253  *
00254  * Author    : Patrick Haller [Thu, 1998/02/26 11:55]
00255  *****************************************************************************/
00256 
00257 ODINPROCEDURE5(mouse_event,
00258                DWORD, dwFlags, 
00259                DWORD, dx,
00260                DWORD, dy,
00261                DWORD, cButtons,
00262                DWORD, dwExtraInfo)
00263 {
00264   INPUT i;
00265   
00266   // format input packet
00267   i.type           = INPUT_MOUSE;
00268   i.mi.dx          = dx;
00269   i.mi.dy          = dy;
00270   i.mi.mouseData   = cButtons; // PH: is this really correct?
00271   i.mi.dwFlags     = dwFlags;
00272   i.mi.dwExtraInfo = dwExtraInfo;
00273   
00274   // forward to more modern API
00275   SendInput(1, &i, sizeof(i) );
00276 }
00277 
00278 
00279 ODINFUNCTION1(DWORD, TrackMouseEvent,
00280               DWORD, param1)
00281 {
00282   dprintf(("not implemented"));
00283   return 0;
00284 }
00285 
00286 
00287 /*****************************************************************************
00288  * Name      : UINT SendInput
00289  * Purpose   : The SendInput function synthesizes keystrokes, mouse motions, 
00290  *             and button clicks
00291  * Parameters: UINT    nInputs // count if input events
00292  *             LPINPUT pInputs // array of input structures
00293  *             int     chSize  // size of structure
00294  * Variables :
00295  * Result    : number of events successfully inserted,
00296  *             0 if the input was already blocked by another thread
00297  * Remark    :
00298  * Status    : UNTESTED STUB
00299  *
00300  * Author    : Patrick Haller [Thu, 1998/02/26 11:55]
00301  *****************************************************************************/
00302 
00303 ODINFUNCTION3(UINT,    SendInput,
00304               UINT,    nInputs,
00305               LPINPUT, pInputs,
00306               int,     chSize)
00307 {
00308   dprintf(("not correctly implemented"));
00309   
00310   // The simulated input is sent to the
00311   // foreground thread's message queue.
00312   // (WM_KEYUP, WM_KEYDOWN)
00313   // After GetMessage or PeekMessage,
00314   // TranslateMessage posts an appropriate
00315   // WM_CHAR message.
00316   HWND hwnd = GetForegroundWindow();
00317   
00318   LPINPUT piBase = pInputs;
00319   for (int i = 0;
00320        i < nInputs;
00321        i++,
00322        piBase++)
00323   {
00324     switch(piBase->type)
00325     {
00326       case INPUT_MOUSE:
00327       {
00328         PMOUSEINPUT p = (PMOUSEINPUT)&piBase->mi;
00329         MSG msg;
00330         
00331         // simulate mouse input message
00332         // @@@PH
00333       }  
00334       break;
00335       
00336       // compose a keyboard input message
00337       case INPUT_KEYBOARD:
00338       {
00339         PKEYBDINPUT p = (PKEYBDINPUT)&piBase->ki;
00340         MSG msg;
00341         BOOL fUnicode = (p->dwFlags & KEYEVENTF_UNICODE) == KEYEVENTF_UNICODE;
00342         DWORD extrainfo = GetMessageExtraInfo();
00343         
00344         // build keyboard message
00345         msg.message = (p->dwFlags & KEYEVENTF_KEYUP) ? WM_KEYUP : WM_KEYDOWN;
00346         
00347         if (p->dwFlags & KEYEVENTF_SCANCODE)
00348         {
00349           // keystroke is identified by the scancode
00350           if (fUnicode)
00351             msg.wParam = MapVirtualKeyW(p->wScan, 1);
00352           else
00353             msg.wParam = MapVirtualKeyA(p->wScan, 1);
00354         }
00355         else
00356           msg.wParam = p->wVk;
00357         
00358         msg.lParam = 0x0000001 |                    // repeat count
00359                       ( (p->wScan & 0xff) << 16);   // scan code
00360         
00361         if (p->dwFlags & KEYEVENTF_EXTENDEDKEY)
00362           msg.lParam |= (1 << 24);
00363         
00364         // set additional message flags
00365         if (msg.message == WM_KEYDOWN)
00366         {
00367           // @@@PH
00368           // bit 30 - previous key state cannot be set, how to determine?
00369         }
00370         else
00371         {
00372           // WM_KEYUP -> previous key is always 1, transistion state
00373           // always 1
00374           msg.lParam |= (1 << 30);
00375           msg.lParam |= (1 << 31);
00376         }
00377         
00378         msg.time   = p->time;
00379         
00380         // @@@PH
00381         // unknown: do we have to post or to send the message?
00382 
00383         SetMessageExtraInfo( (LPARAM)p->dwExtraInfo );
00384         
00385         if (fUnicode)
00386           SendMessageW(hwnd, msg.message, msg.wParam, msg.lParam);
00387         else
00388           SendMessageA(hwnd, msg.message, msg.wParam, msg.lParam);
00389         
00390         //restore extra info
00391         SetMessageExtraInfo(extrainfo);
00392         break;
00393       }  
00394       
00395       case INPUT_HARDWARE:
00396       {
00397         PHARDWAREINPUT p = (PHARDWAREINPUT)&piBase->hi;
00398         
00399         // @@@PH
00400         // not supported for the time being
00401       }  
00402       break;
00403       
00404       default:
00405         dprintf(("unsupported input packet type %d",
00406                 piBase->type));
00407         break;
00408     }
00409   }
00410   
00411   return 0;
00412 }
00413 
00414 /*****************************************************************************
00415  * Name      : BOOL WIN32API DragDetect
00416  * Purpose   : The DragDetect function captures the mouse and tracks its movement
00417  * Parameters: HWND  hwnd
00418  *             POINT pt
00419  * Variables :
00420  * Result    : If the user moved the mouse outside of the drag rectangle while
00421  *               holding the left button down, the return value is TRUE.
00422  *             If the user did not move the mouse outside of the drag rectangle
00423  *               while holding the left button down, the return value is FALSE.
00424  * Remark    :
00425  * Status    : UNTESTED STUB
00426  *
00427  * Author    : Patrick Haller [Thu, 1998/02/26 11:55]
00428  *****************************************************************************/
00429 ODINFUNCTION2(BOOL,  DragDetect,
00430               HWND,  hwnd,
00431               POINT, pt)
00432 {
00433   dprintf(("not implemented"));
00434 
00435   return (FALSE);
00436 }
00437 //******************************************************************************
00438 //******************************************************************************

Generated on Wed Jan 23 23:17:55 2002 for ODIN-user32 by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001