- use WINE_DINPUT_KEYBOARD_MAX_KEYS instead hard-coded 256 value
authorRaphael Junqueira <fenix@club-internet.fr>
Thu, 24 Mar 2005 15:08:27 +0000 (15:08 +0000)
committerAlexandre Julliard <julliard@winehq.org>
Thu, 24 Mar 2005 15:08:27 +0000 (15:08 +0000)
- better use of critical section
- some cleanup to better understand code paths
- logic correction on SetWindowsHookExA/UnhookWindowsHookEx on
  keyboard.

dlls/dinput/keyboard.c
dlls/dinput/mouse.c

index ceee1f591d4980f0c9481d0ee9ad66fbbf45763b..1114d5f87272e7e8098720d09d63d44a30c83be4 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright 1998 Marcus Meissner
  * Copyright 1998,1999 Lionel Ulmer
  * Copyright 2000-2001 TransGaming Technologies Inc.
+ * Copyright 2005 Raphael Junqueira
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -37,6 +38,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
+#define WINE_DINPUT_KEYBOARD_MAX_KEYS 256
+
 static IDirectInputDevice8AVtbl SysKeyboardAvt;
 static IDirectInputDevice8WVtbl SysKeyboardWvt;
 
@@ -65,14 +68,15 @@ struct SysKeyboardImpl
         CRITICAL_SECTION                crit;
 };
 
-SysKeyboardImpl *current; /* Today's acquired device
-FIXME: currently this can be only one.
-Maybe this should be a linked list or st.
-I don't know what the rules are for multiple acquired keyboards,
-but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason.
+static SysKeyboardImpl* current_lock = NULL; 
+/* Today's acquired device
+ * FIXME: currently this can be only one.
+ * Maybe this should be a linked list or st.
+ * I don't know what the rules are for multiple acquired keyboards,
+ * but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason.
 */
 
-static BYTE DInputKeyState[256]; /* array for 'GetDeviceState' */
+static BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; /* array for 'GetDeviceState' */
 
 static CRITICAL_SECTION keyboard_crit;
 static CRITICAL_SECTION_DEBUG critsect_debug =
@@ -83,64 +87,63 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
 };
 static CRITICAL_SECTION keyboard_crit = { &critsect_debug, -1, 0, 0, 0, 0 };
 
-static DWORD keyboard_users;
-static HHOOK keyboard_hook;
+static DWORD keyboard_users = 0;
+static HHOOK keyboard_hook = NULL;
 
 LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
 {
+  BYTE dik_code;
+  BOOL down;
+  DWORD timestamp;
+  KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
+  BYTE new_diks;
+
   TRACE("(%d,%d,%ld)\n", code, wparam, lparam);
 
-  if (code == HC_ACTION)
-    {
-      BYTE dik_code;
-      BOOL down;
-      DWORD timestamp;
+  /** returns now if not HC_ACTION */
+  if (code != HC_ACTION) return CallNextHookEx(keyboard_hook, code, wparam, lparam);
+  
+  {
+    dik_code = hook->scanCode;
+    if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
+    down = !(hook->flags & LLKHF_UP);
+    timestamp = hook->time;
+  }
+
+  /** returns now if key event already known */
+  new_diks = (down ? 0x80 : 0);
+  /*if (new_diks != DInputKeyState[dik_code]) return CallNextHookEx(keyboard_hook, code, wparam, lparam); TO BE FIXED */
+
+  DInputKeyState[dik_code] = new_diks;
+  TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]);
+      
+  if (current_lock != NULL) {
+    if (current_lock->hEvent) SetEvent(current_lock->hEvent);
+    
+    if (current_lock->buffer != NULL) {
+      int n;
+      
+      EnterCriticalSection(&(current_lock->crit));
       
-      {
-        KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
-        dik_code = hook->scanCode;
-        if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
-        down = !(hook->flags & LLKHF_UP);
-        timestamp = hook->time;
-      }
-
-      DInputKeyState[dik_code] = (down ? 0x80 : 0);
-      TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]);
+      n = (current_lock->start + current_lock->count) % current_lock->buffersize;
       
-      if (current != NULL)
-        {
-          if (current->hEvent)
-            SetEvent(current->hEvent);
-
-          if (current->buffer != NULL)
-            {
-              int n;
-
-              EnterCriticalSection(&(current->crit));
-
-              n = (current->start + current->count) % current->buffersize;
-
-              current->buffer[n].dwOfs = dik_code;
-              current->buffer[n].dwData = down ? 0x80 : 0;
-              current->buffer[n].dwTimeStamp = timestamp;
-              current->buffer[n].dwSequence = current->dinput->evsequence++;
-
-             TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n,
-                   current->buffer[n].dwOfs, current->buffer[n].dwData, current->buffer[n].dwTimeStamp, current->buffer[n].dwSequence);
-
-              if (current->count == current->buffersize)
-                {
-                  current->start = ++current->start % current->buffersize;
-                  current->overflow = TRUE;
-                }
-              else
-                current->count++;
-
-              LeaveCriticalSection(&(current->crit));
-            }
-        }
+      current_lock->buffer[n].dwOfs = dik_code;
+      current_lock->buffer[n].dwData = down ? 0x80 : 0;
+      current_lock->buffer[n].dwTimeStamp = timestamp;
+      current_lock->buffer[n].dwSequence = current_lock->dinput->evsequence++;
+      
+      TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n,
+           current_lock->buffer[n].dwOfs, current_lock->buffer[n].dwData, current_lock->buffer[n].dwTimeStamp, current_lock->buffer[n].dwSequence);
+      
+      if (current_lock->count == current_lock->buffersize) {
+       current_lock->start = ++current_lock->start % current_lock->buffersize;
+       current_lock->overflow = TRUE;
+      } else
+       current_lock->count++;
+      
+      LeaveCriticalSection(&(current_lock->crit));
     }
-
+  }
   return CallNextHookEx(keyboard_hook, code, wparam, lparam);
 }
 
@@ -238,15 +241,20 @@ static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI
 static SysKeyboardImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputImpl *dinput)
 {
     SysKeyboardImpl* newDevice;
+    DWORD kbd_users;
+
     newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl));
     newDevice->lpVtbl = kvt;
     newDevice->ref = 1;
     memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
     newDevice->dinput = dinput;
+    InitializeCriticalSection(&(newDevice->crit));
 
     EnterCriticalSection(&keyboard_crit);
-    if (!keyboard_users++)
-        keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );
+    kbd_users = InterlockedIncrement(&keyboard_users);
+    if (1 == kbd_users) {
+      keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );
+    }
     LeaveCriticalSection(&keyboard_crit);
 
     return newDevice;
@@ -301,13 +309,15 @@ static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
 {
        SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
        ULONG ref;
+       DWORD kbd_users;
 
        ref = InterlockedDecrement(&(This->ref));
        if (ref)
                return ref;
 
-       EnterCriticalSection(&keyboard_crit);
-       if (!--keyboard_users) {
+       EnterCriticalSection(&keyboard_crit);   
+       kbd_users = InterlockedDecrement(&keyboard_users);
+       if (0 == kbd_users) {
            UnhookWindowsHookEx( keyboard_hook );
            keyboard_hook = 0;
        }
@@ -388,24 +398,29 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
        LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
 )
 {
-    TRACE("(%p)->(%ld,%p)\n", iface, len, ptr);
+    SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+    TRACE("(%p)->(%ld,%p)\n", This, len, ptr);
 
     /* Note: device does not need to be acquired */
-    if (len != 256)
+    if (len != WINE_DINPUT_KEYBOARD_MAX_KEYS)
       return DIERR_INVALIDPARAM;
 
     MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
 
+    EnterCriticalSection(&(This->crit));
+
     if (TRACE_ON(dinput)) {
        int i;
-       for (i = 0; i < 256; i++) {
+       for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) {
            if (DInputKeyState[i] != 0x00) {
                TRACE(" - %02X: %02x\n", i, DInputKeyState[i]);
            }
        }
     }
     
-    memcpy(ptr, DInputKeyState, 256);
+    memcpy(ptr, DInputKeyState, WINE_DINPUT_KEYBOARD_MAX_KEYS);
+    LeaveCriticalSection(&(This->crit));
+
     return DI_OK;
 }
 
@@ -490,7 +505,7 @@ static HRESULT WINAPI SysKeyboardAImpl_EnumObjects(
     memset(&ddoi, 0, sizeof(ddoi));
     ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
 
-    for (i = 0; i < 256; i++) {
+    for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) {
         /* Report 255 keys :-) */
         ddoi.guidType = GUID_Key;
        ddoi.dwOfs = i;
@@ -531,25 +546,24 @@ static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
 
         This->acquired = 1;
 
-        if (current != NULL)
-          {
-            FIXME("Not more than one keyboard can be acquired at the same time.\n");
-            SysKeyboardAImpl_Unacquire(iface);
-          }
-
-        current = This;
-
-        if (This->buffersize > 0)
-          {
-            This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
-                                     This->buffersize * sizeof(*(This->buffer)));
-            This->start = 0;
-            This->count = 0;
-            This->overflow = FALSE;
-            InitializeCriticalSection(&(This->crit));
-          }
-        else
+        if (current_lock != NULL) {
+         FIXME("Not more than one keyboard can be acquired at the same time.\n");
+         SysKeyboardAImpl_Unacquire(iface);
+       }
+       
+        current_lock = This;
+
+        if (This->buffersize > 0) {
+         This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                  This->buffersize * sizeof(*(This->buffer)));
+         This->start = 0;
+         This->count = 0;
+         This->overflow = FALSE;
+       } else {
           This->buffer = NULL;
+       }
+
+       /*keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );*/
 
        return DI_OK;
 }
@@ -562,19 +576,19 @@ static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
         if (This->acquired == 0)
           return DI_NOEFFECT;
 
-        if (current == This)
-          current = NULL;
+       /* No more locks */
+        if (current_lock == This)
+          current_lock = NULL;
         else
-          ERR("this != current\n");
+          ERR("this != current_lock\n");
 
+       /* Unacquire device */
         This->acquired = 0;
 
-        if (This->buffersize >= 0)
-          {
-            HeapFree(GetProcessHeap(), 0, This->buffer);
-            This->buffer = NULL;
-            DeleteCriticalSection(&(This->crit));
-          }
+        if (This->buffersize >= 0) {
+         HeapFree(GetProcessHeap(), 0, This->buffer);
+         This->buffer = NULL;
+       }
 
        return DI_OK;
 }
@@ -613,7 +627,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
     else
        devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
     devcaps.dwAxes = 0;
-    devcaps.dwButtons = 256;
+    devcaps.dwButtons = WINE_DINPUT_KEYBOARD_MAX_KEYS;
     devcaps.dwPOVs = 0;
     devcaps.dwFFSamplePeriod = 0;
     devcaps.dwFFMinTimeResolution = 0;
@@ -709,7 +723,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo(
     TRACE("(this=%p,%p)\n", This, pdidi);
 
     if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
-        WARN(" dinput3 not supporte yet...\n");
+        WARN(" dinput3 not supported yet...\n");
        return DI_OK;
     }
 
@@ -724,7 +738,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface
     TRACE("(this=%p,%p)\n", This, pdidi);
 
     if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
-        WARN(" dinput3 not supporte yet...\n");
+        WARN(" dinput3 not supported yet...\n");
        return DI_OK;
     }
 
index 3394142b3b5229ade119b153168b162bb95a1c06..162bcbdad67f7f641f993f8574d7d5aae7fc6f9d 100644 (file)
@@ -578,61 +578,61 @@ static void dinput_window_check(SysMouseImpl* This) {
 static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
 {
     SysMouseImpl *This = (SysMouseImpl *)iface;
-    RECT       rect;
+    RECT  rect;
+    POINT point;
     
     TRACE("(this=%p)\n",This);
     
-    if (This->acquired == 0) {
-       POINT point;
-       
-       /* Store (in a global variable) the current lock */
-       current_lock = (IDirectInputDevice8A*)This;
-       
-       /* Init the mouse state */
-       GetCursorPos( &point );
-       if (This->absolute) {
-           This->m_state.lX = point.x;
-           This->m_state.lY = point.y;
-           This->prevX = point.x;
-           This->prevY = point.y;
-       } else {
-           This->m_state.lX = 0;
-           This->m_state.lY = 0;
-           This->org_coords = point;
-       }
-       This->m_state.lZ = 0;
-       This->m_state.rgbButtons[0] = ((GetKeyState(VK_LBUTTON) & 0x80) ? 0xFF : 0x00);
-       This->m_state.rgbButtons[1] = ((GetKeyState(VK_RBUTTON) & 0x80) ? 0xFF : 0x00);
-       This->m_state.rgbButtons[2] = ((GetKeyState(VK_MBUTTON) & 0x80) ? 0xFF : 0x00);
-       
-       /* Install our mouse hook */
-       if (This->dwCoopLevel & DISCL_EXCLUSIVE)
-           ShowCursor(FALSE); /* hide cursor */
-       This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 );
-       
-       /* Get the window dimension and find the center */
-       GetWindowRect(This->win, &rect);
-       This->win_centerX = (rect.right  - rect.left) / 2;
-       This->win_centerY = (rect.bottom - rect.top ) / 2;
-       
-       /* Warp the mouse to the center of the window */
-       if (This->absolute == 0) {
-           This->mapped_center.x = This->win_centerX;
-           This->mapped_center.y = This->win_centerY;
-           MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
-           TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
-           SetCursorPos( This->mapped_center.x, This->mapped_center.y );
+    if (This->acquired)
+      return S_FALSE;
+    
+    This->acquired = 1;
+
+    /* Store (in a global variable) the current lock */
+    current_lock = (IDirectInputDevice8A*)This;
+    
+    /* Init the mouse state */
+    GetCursorPos( &point );
+    if (This->absolute) {
+      This->m_state.lX = point.x;
+      This->m_state.lY = point.y;
+      This->prevX = point.x;
+      This->prevY = point.y;
+    } else {
+      This->m_state.lX = 0;
+      This->m_state.lY = 0;
+      This->org_coords = point;
+    }
+    This->m_state.lZ = 0;
+    This->m_state.rgbButtons[0] = ((GetKeyState(VK_LBUTTON) & 0x80) ? 0xFF : 0x00);
+    This->m_state.rgbButtons[1] = ((GetKeyState(VK_RBUTTON) & 0x80) ? 0xFF : 0x00);
+    This->m_state.rgbButtons[2] = ((GetKeyState(VK_MBUTTON) & 0x80) ? 0xFF : 0x00);
+    
+    /* Install our mouse hook */
+    if (This->dwCoopLevel & DISCL_EXCLUSIVE)
+      ShowCursor(FALSE); /* hide cursor */
+    This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 );
+    
+    /* Get the window dimension and find the center */
+    GetWindowRect(This->win, &rect);
+    This->win_centerX = (rect.right  - rect.left) / 2;
+    This->win_centerY = (rect.bottom - rect.top ) / 2;
+    
+    /* Warp the mouse to the center of the window */
+    if (This->absolute == 0) {
+      This->mapped_center.x = This->win_centerX;
+      This->mapped_center.y = This->win_centerY;
+      MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1);
+      TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y);
+      SetCursorPos( This->mapped_center.x, This->mapped_center.y );
 #ifdef MOUSE_HACK
-           This->need_warp = WARP_DONE;
+      This->need_warp = WARP_DONE;
 #else
-           This->need_warp = WARP_STARTED;
+      This->need_warp = WARP_STARTED;
 #endif
-       }
-       
-       This->acquired = 1;
-       return DI_OK;
     }
-    return S_FALSE;
+       
+    return DI_OK;
 }
 
 /******************************************************************************
@@ -644,29 +644,32 @@ static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
     
     TRACE("(this=%p)\n",This);
     
-    if (This->acquired) {
-       /* Reinstall previous mouse event handler */
-       if (This->hook) {
-           UnhookWindowsHookEx( This->hook );
-           This->hook = 0;
-
-           if (This->dwCoopLevel & DISCL_EXCLUSIVE)
-               ShowCursor(TRUE); /* show cursor */
-        }
+    if (0 == This->acquired) {
+       return DI_NOEFFECT;
+    }
        
-        /* No more locks */
-        current_lock = NULL;
+    /* Reinstall previous mouse event handler */
+    if (This->hook) {
+      UnhookWindowsHookEx( This->hook );
+      This->hook = 0;
+      
+      if (This->dwCoopLevel & DISCL_EXCLUSIVE)
+       ShowCursor(TRUE); /* show cursor */
+    }
        
-        /* Unacquire device */
-        This->acquired = 0;
+    /* No more locks */
+    if (current_lock == (IDirectInputDevice8A*) This)
+      current_lock = NULL;
+    else
+      ERR("this(%p) != current_lock(%p)\n", This, current_lock);
 
-       /* And put the mouse cursor back where it was at acquire time */
-       if (This->absolute == 0) {
-           TRACE(" warping mouse back to (%ld , %ld)\n", This->org_coords.x, This->org_coords.y);
-           SetCursorPos(This->org_coords.x, This->org_coords.y);
-       }
-    } else {
-       return DI_NOEFFECT;
+    /* Unacquire device */
+    This->acquired = 0;
+    
+    /* And put the mouse cursor back where it was at acquire time */
+    if (This->absolute == 0) {
+      TRACE(" warping mouse back to (%ld , %ld)\n", This->org_coords.x, This->org_coords.y);
+      SetCursorPos(This->org_coords.x, This->org_coords.y);
     }
        
     return DI_OK;