Ignore:
Timestamp:
Aug 16, 2002, 5:08:25 PM (23 years ago)
Author:
sandervl
Message:

Wine resync; added missing bugfix

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/dinput/keyboard.c

    r8346 r9016  
    33 * Copyright 1998 Marcus Meissner
    44 * Copyright 1998,1999 Lionel Ulmer
     5 * Copyright 2000-2001 TransGaming Technologies Inc.
    56 *
     7 * This library is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU Lesser General Public
     9 * License as published by the Free Software Foundation; either
     10 * version 2.1 of the License, or (at your option) any later version.
     11 *
     12 * This library is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15 * Lesser General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU Lesser General Public
     18 * License along with this library; if not, write to the Free Software
     19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    620 */
    721
    822#include "config.h"
     23#include "wine/port.h"
     24
    925#include <string.h>
    1026#ifdef HAVE_SYS_ERRNO_H
     
    1935#include "dinput_private.h"
    2036#include "device_private.h"
    21 #include "debugtools.h"
    22 
    23 DEFAULT_DEBUG_CHANNEL(dinput);
    24 
    25 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt;
    26 static ICOM_VTABLE(IDirectInputDevice7A) SysKeyboard7Avt;
    27      
     37#include "wine/debug.h"
     38
     39WINE_DEFAULT_DEBUG_CHANNEL(dinput);
     40
     41static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt;
     42
    2843typedef struct SysKeyboardAImpl SysKeyboardAImpl;
    2944struct SysKeyboardAImpl
    3045{
    31         /* IDirectInputDevice2AImpl */
    32         ICOM_VFIELD(IDirectInputDevice2A);
     46        LPVOID                          lpVtbl;
    3347        DWORD                           ref;
    3448        GUID                            guid;
    3549
    3650        IDirectInputAImpl *dinput;
    37        
     51
     52        HANDLE  hEvent;
    3853        /* SysKeyboardAImpl */
    39         BYTE                            keystate[256];
    4054        int                             acquired;
     55        int                             buffersize;  /* set in 'SetProperty'         */
     56        LPDIDEVICEOBJECTDATA            buffer;      /* buffer for 'GetDeviceData'.
     57                                                        Alloc at 'Acquire', Free at
     58                                                        'Unacquire'                  */
     59        int                             count;       /* number of objects in use in
     60                                                        'buffer'                     */
     61        int                             start;       /* 'buffer' rotates. This is the
     62                                                        first in use (if count > 0)  */
     63        BOOL                            overflow;    /* return DI_BUFFEROVERFLOW in
     64                                                        'GetDeviceData'              */
     65        CRITICAL_SECTION                crit;
    4166};
     67
     68SysKeyboardAImpl *current; /* Today's acquired device
     69FIXME: currently this can be only one.
     70Maybe this should be a linked list or st.
     71I don't know what the rules are for multiple acquired keyboards,
     72but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason.
     73*/
     74
     75static BYTE DInputKeyState[256]; /* array for 'GetDeviceState' */
     76
     77HHOOK keyboard_hook;
     78
     79LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
     80{
     81  TRACE("(%d,%d,%ld)\n", code, wparam, lparam);
     82
     83  if (code == HC_ACTION)
     84    {
     85      BYTE dik_code;
     86      BOOL down;
     87      DWORD timestamp;
     88
     89      {
     90        KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
     91        dik_code = hook->scanCode;
     92        if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
     93        down = !(hook->flags & LLKHF_UP);
     94        timestamp = hook->time;
     95      }
     96
     97      DInputKeyState[dik_code] = (down ? 0x80 : 0);
     98
     99      if (current != NULL)
     100        {
     101          if (current->hEvent)
     102            SetEvent(current->hEvent);
     103
     104          if (current->buffer != NULL)
     105            {
     106              int n;
     107
     108              EnterCriticalSection(&(current->crit));
     109
     110              n = (current->start + current->count) % current->buffersize;
     111
     112              current->buffer[n].dwOfs = dik_code;
     113              current->buffer[n].dwData = down ? 0x80 : 0;
     114              current->buffer[n].dwTimeStamp = timestamp;
     115              current->buffer[n].dwSequence = current->dinput->evsequence++;
     116
     117              TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n,
     118                    current->buffer[n].dwOfs, current->buffer[n].dwData, current->buffer[n].dwTimeStamp, current->buffer[n].dwSequence);
     119
     120              if (current->count == current->buffersize)
     121                {
     122                  current->start++;
     123                  current->overflow = TRUE;
     124                }
     125              else
     126                current->count++;
     127
     128              LeaveCriticalSection(&(current->crit));
     129            }
     130        }
     131    }
     132
     133  return CallNextHookEx(keyboard_hook, code, wparam, lparam);
     134}
    42135
    43136static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
     
    48141};
    49142
    50 static BOOL keyboarddev_enum_device(DWORD dwDevType, DWORD dwFlags, LPCDIDEVICEINSTANCEA lpddi)
     143static BOOL keyboarddev_enum_device(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi)
    51144{
    52145  if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) {
    53146    TRACE("Enumerating the Keyboard device\n");
    54    
     147
    55148    lpddi->guidInstance = GUID_SysKeyboard;/* DInput's GUID */
    56149    lpddi->guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */
     
    58151    strcpy(lpddi->tszInstanceName, "Keyboard");
    59152    strcpy(lpddi->tszProductName, "Wine Keyboard");
    60    
     153
    61154    return TRUE;
    62155  }
     
    65158}
    66159
    67 static SysKeyboardAImpl *alloc_device(REFGUID rguid, ICOM_VTABLE(IDirectInputDevice2A) *kvt, IDirectInputAImpl *dinput)
     160static SysKeyboardAImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputAImpl *dinput)
    68161{
    69162    SysKeyboardAImpl* newDevice;
    70163    newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl));
     164    newDevice->lpVtbl = kvt;
    71165    newDevice->ref = 1;
    72     ICOM_VTBL(newDevice) = kvt;
    73166    memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
    74     memset(newDevice->keystate,0,256);
    75167    newDevice->dinput = dinput;
    76168
     
    83175  if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) ||          /* Generic Keyboard */
    84176      (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */
    85     if ((riid == NULL) || (IsEqualGUID(&IID_IDirectInputDevice2A,riid)) || (IsEqualGUID(&IID_IDirectInputDevice2A,riid))) {
     177    if ((riid == NULL) ||
     178        IsEqualGUID(&IID_IDirectInputDeviceA,riid) ||
     179        IsEqualGUID(&IID_IDirectInputDevice2A,riid) ||
     180        IsEqualGUID(&IID_IDirectInputDevice7A,riid) ||
     181        IsEqualGUID(&IID_IDirectInputDevice8A,riid)) {
    86182      *pdev=(IDirectInputDeviceA*) alloc_device(rguid, &SysKeyboardAvt, dinput);
    87    
    88183      TRACE("Creating a Keyboard device (%p)\n", *pdev);
    89       return DI_OK;
    90     } else if (IsEqualGUID(&IID_IDirectInputDevice7A,riid)) {
    91       *pdev=(IDirectInputDeviceA*) alloc_device(rguid, (ICOM_VTABLE(IDirectInputDevice2A) *) &SysKeyboard7Avt, dinput);
    92    
    93       TRACE("Creating a Keyboard DInput7A device (%p)\n", *pdev);
    94184      return DI_OK;
    95185    } else
     
    109199
    110200static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
    111         LPDIRECTINPUTDEVICE2A iface,REFGUID rguid,LPCDIPROPHEADER ph
     201        LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPCDIPROPHEADER ph
    112202)
    113203{
     
    123213
    124214                        TRACE("(buffersize=%ld)\n",pd->dwData);
     215
     216                        if (This->acquired)
     217                           return DIERR_INVALIDPARAM;
     218
     219                        This->buffersize = pd->dwData;
     220
    125221                        break;
    126222                }
     
    134230
    135231static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
    136         LPDIRECTINPUTDEVICE2A iface,DWORD len,LPVOID ptr
     232        LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr
    137233)
    138234{
    139     DWORD i;
    140 
    141     memset( ptr, 0, len );
     235    /* Note: device does not need to be acquired */
    142236    if (len != 256)
    143     {
    144         WARN("whoops, got len %ld?\n", len);
    145         return DI_OK;
    146     }
    147     for (i = 0; i < 0x80; i++)
    148     {
    149         WORD vkey = MapVirtualKeyA( i, 1 );
    150         if (vkey && (GetAsyncKeyState( vkey ) & 0x8000))
    151         {
    152             ((LPBYTE)ptr)[i] = 0x80;
    153             ((LPBYTE)ptr)[i | 0x80] = 0x80;
    154         }
    155     }
     237      return DIERR_INVALIDPARAM;
     238
     239    memcpy(ptr, DInputKeyState, 256);
    156240    return DI_OK;
    157241}
    158242
    159243static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
    160         LPDIRECTINPUTDEVICE2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
     244        LPDIRECTINPUTDEVICE8A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,
    161245        LPDWORD entries,DWORD flags
    162246)
    163247{
    164248        ICOM_THIS(SysKeyboardAImpl,iface);
    165         int i, n;
     249        int ret = DI_OK, i = 0;
    166250
    167251        TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n",
    168252              This,dodsize,dod,entries,entries?*entries:0,flags);
    169253
    170 
    171         for (i = n = 0; (i < 0x80) && (n < *entries); i++)
    172         {
    173             WORD state, vkey = MapVirtualKeyA( i, 1 );
    174             if (!vkey) continue;
    175             state = (GetAsyncKeyState( vkey ) >> 8) & 0x80;
    176             if (state != This->keystate[vkey])
    177             {
    178                 if (dod)
    179                 {
    180                     /* add an entry */
    181                     dod[n].dwOfs       = i; /* scancode */
    182                     dod[n].dwData      = state;
    183                     dod[n].dwTimeStamp = GetCurrentTime(); /* umm */
    184                     dod[n].dwSequence  = This->dinput->evsequence++;
    185                     n++;
    186                 }
    187                 if (!(flags & DIGDD_PEEK)) This->keystate[vkey] = state;
    188             }
    189         }
    190         if (n) TRACE_(dinput)("%d entries\n",n);
    191         *entries = n;
    192         return DI_OK;
    193 }
    194 
    195 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE2A iface)
     254        if (This->acquired == 0)
     255          return DIERR_NOTACQUIRED;
     256
     257        if (This->buffer == NULL)
     258          return DIERR_NOTBUFFERED;
     259
     260        if (dodsize < sizeof(*dod))
     261          return DIERR_INVALIDPARAM;
     262
     263        EnterCriticalSection(&(This->crit));
     264
     265        /* Copy item at a time for the case dodsize > sizeof(buffer[n]) */
     266        while ((i < *entries || *entries == INFINITE) && i < This->count)
     267          {
     268            if (dod != NULL)
     269              {
     270                int n = (This->start + i) % This->buffersize;
     271                LPDIDEVICEOBJECTDATA pd
     272                   = (LPDIDEVICEOBJECTDATA)((BYTE *)dod + dodsize * i);
     273                pd->dwOfs       = This->buffer[n].dwOfs;
     274                pd->dwData      = This->buffer[n].dwData;
     275                pd->dwTimeStamp = This->buffer[n].dwTimeStamp;
     276                pd->dwSequence  = This->buffer[n].dwSequence;
     277              }
     278            i++;
     279          }
     280
     281        *entries = i;
     282
     283        if (This->overflow)
     284          ret = DI_BUFFEROVERFLOW;
     285
     286        if (!(flags & DIGDD_PEEK))
     287          {
     288            /* Empty buffer */
     289            This->count -= i;
     290            This->start = (This->start + i) % This->buffersize;
     291            This->overflow = FALSE;
     292          }
     293
     294        LeaveCriticalSection(&(This->crit));
     295
     296        TRACE("Returning %ld events queued\n", *entries);
     297
     298        return ret;
     299}
     300
     301static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface);
     302
     303static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
    196304{
    197305        ICOM_THIS(SysKeyboardAImpl,iface);
    198        
     306
    199307        TRACE("(this=%p)\n",This);
    200        
    201         if (This->acquired == 0) {
    202           This->acquired = 1;
    203         }
    204        
     308
     309        if (This->acquired)
     310          return S_FALSE;
     311
     312        This->acquired = 1;
     313
     314        if (current != NULL)
     315          {
     316            FIXME("Not more than one keyboard can be acquired at the same time.\n");
     317            SysKeyboardAImpl_Unacquire(iface);
     318          }
     319
     320        current = This;
     321
     322        if (This->buffersize > 0)
     323          {
     324            This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
     325                                     This->buffersize * sizeof(*(This->buffer)));
     326            This->start = 0;
     327            This->count = 0;
     328            This->overflow = FALSE;
     329            InitializeCriticalSection(&(This->crit));
     330          }
     331        else
     332          This->buffer = NULL;
     333
    205334        return DI_OK;
    206335}
    207336
    208 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE2A iface)
     337static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
    209338{
    210339        ICOM_THIS(SysKeyboardAImpl,iface);
    211340        TRACE("(this=%p)\n",This);
    212341
    213         if (This->acquired == 1) {
    214           This->acquired = 0;
    215         } else {
    216           ERR("Unacquiring a not-acquired device !!!\n");
    217         }
     342        if (This->acquired == 0)
     343          return DI_NOEFFECT;
     344
     345        if (current == This)
     346          current = NULL;
     347        else
     348          ERR("this != current\n");
     349
     350        This->acquired = 0;
     351
     352        if (This->buffersize >= 0)
     353          {
     354            HeapFree(GetProcessHeap(), 0, This->buffer);
     355            This->buffer = NULL;
     356            DeleteCriticalSection(&(This->crit));
     357          }
    218358
    219359        return DI_OK;
     360}
     361
     362static HRESULT WINAPI SysKeyboardAImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface,
     363                                                            HANDLE hnd) {
     364  ICOM_THIS(SysKeyboardAImpl,iface);
     365
     366  TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd);
     367
     368  This->hEvent = hnd;
     369  return DI_OK;
    220370}
    221371
     
    224374  */
    225375static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
    226         LPDIRECTINPUTDEVICE2A iface,
     376        LPDIRECTINPUTDEVICE8A iface,
    227377        LPDIDEVCAPS lpDIDevCaps)
    228378{
     
    246396    FIXME("DirectX 3.0 not supported....\n");
    247397  }
    248  
     398
    249399  return DI_OK;
    250400}
    251401
    252 static ICOM_VTABLE(IDirectInputDevice2A) SysKeyboardAvt =
     402static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt =
    253403{
    254404        ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
     
    265415        SysKeyboardAImpl_GetDeviceData,
    266416        IDirectInputDevice2AImpl_SetDataFormat,
    267         IDirectInputDevice2AImpl_SetEventNotification,
     417        SysKeyboardAImpl_SetEventNotification,
    268418        IDirectInputDevice2AImpl_SetCooperativeLevel,
    269419        IDirectInputDevice2AImpl_GetObjectInfo,
     
    279429        IDirectInputDevice2AImpl_Escape,
    280430        IDirectInputDevice2AImpl_Poll,
    281         IDirectInputDevice2AImpl_SendDeviceData
     431        IDirectInputDevice2AImpl_SendDeviceData,
     432        IDirectInputDevice7AImpl_EnumEffectsInFile,
     433        IDirectInputDevice7AImpl_WriteEffectToFile,
     434        IDirectInputDevice8AImpl_BuildActionMap,
     435        IDirectInputDevice8AImpl_SetActionMap,
     436        IDirectInputDevice8AImpl_GetImageInfo
    282437};
    283 
    284 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
    285 # define XCAST(fun)     (typeof(SysKeyboard7Avt.fun))
    286 #else
    287 # define XCAST(fun)     (void*)
    288 #endif
    289 
    290 static ICOM_VTABLE(IDirectInputDevice7A) SysKeyboard7Avt =
    291 {
    292         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    293         XCAST(QueryInterface)IDirectInputDevice2AImpl_QueryInterface,
    294         XCAST(AddRef)IDirectInputDevice2AImpl_AddRef,
    295         XCAST(Release)IDirectInputDevice2AImpl_Release,
    296         XCAST(GetCapabilities)SysKeyboardAImpl_GetCapabilities,
    297         XCAST(EnumObjects)IDirectInputDevice2AImpl_EnumObjects,
    298         XCAST(GetProperty)IDirectInputDevice2AImpl_GetProperty,
    299         XCAST(SetProperty)SysKeyboardAImpl_SetProperty,
    300         XCAST(Acquire)SysKeyboardAImpl_Acquire,
    301         XCAST(Unacquire)SysKeyboardAImpl_Unacquire,
    302         XCAST(GetDeviceState)SysKeyboardAImpl_GetDeviceState,
    303         XCAST(GetDeviceData)SysKeyboardAImpl_GetDeviceData,
    304         XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat,
    305         XCAST(SetEventNotification)IDirectInputDevice2AImpl_SetEventNotification,
    306         XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel,
    307         XCAST(GetObjectInfo)IDirectInputDevice2AImpl_GetObjectInfo,
    308         XCAST(GetDeviceInfo)IDirectInputDevice2AImpl_GetDeviceInfo,
    309         XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel,
    310         XCAST(Initialize)IDirectInputDevice2AImpl_Initialize,
    311         XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect,
    312         XCAST(EnumEffects)IDirectInputDevice2AImpl_EnumEffects,
    313         XCAST(GetEffectInfo)IDirectInputDevice2AImpl_GetEffectInfo,
    314         XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState,
    315         XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand,
    316         XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
    317         XCAST(Escape)IDirectInputDevice2AImpl_Escape,
    318         XCAST(Poll)IDirectInputDevice2AImpl_Poll,
    319         XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData,
    320         IDirectInputDevice7AImpl_EnumEffectsInFile,
    321         IDirectInputDevice7AImpl_WriteEffectToFile
    322 };
    323 
    324 #undef XCAST
Note: See TracChangeset for help on using the changeset viewer.