Changeset 9016 for trunk/src/dinput/keyboard.c
- Timestamp:
- Aug 16, 2002, 5:08:25 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/dinput/keyboard.c
r8346 r9016 3 3 * Copyright 1998 Marcus Meissner 4 4 * Copyright 1998,1999 Lionel Ulmer 5 * Copyright 2000-2001 TransGaming Technologies Inc. 5 6 * 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 6 20 */ 7 21 8 22 #include "config.h" 23 #include "wine/port.h" 24 9 25 #include <string.h> 10 26 #ifdef HAVE_SYS_ERRNO_H … … 19 35 #include "dinput_private.h" 20 36 #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 39 WINE_DEFAULT_DEBUG_CHANNEL(dinput); 40 41 static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt; 42 28 43 typedef struct SysKeyboardAImpl SysKeyboardAImpl; 29 44 struct SysKeyboardAImpl 30 45 { 31 /* IDirectInputDevice2AImpl */ 32 ICOM_VFIELD(IDirectInputDevice2A); 46 LPVOID lpVtbl; 33 47 DWORD ref; 34 48 GUID guid; 35 49 36 50 IDirectInputAImpl *dinput; 37 51 52 HANDLE hEvent; 38 53 /* SysKeyboardAImpl */ 39 BYTE keystate[256];40 54 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; 41 66 }; 67 68 SysKeyboardAImpl *current; /* Today's acquired device 69 FIXME: currently this can be only one. 70 Maybe this should be a linked list or st. 71 I don't know what the rules are for multiple acquired keyboards, 72 but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason. 73 */ 74 75 static BYTE DInputKeyState[256]; /* array for 'GetDeviceState' */ 76 77 HHOOK keyboard_hook; 78 79 LRESULT 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 } 42 135 43 136 static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */ … … 48 141 }; 49 142 50 static BOOL keyboarddev_enum_device(DWORD dwDevType, DWORD dwFlags, LP CDIDEVICEINSTANCEA lpddi)143 static BOOL keyboarddev_enum_device(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi) 51 144 { 52 145 if ((dwDevType == 0) || (dwDevType == DIDEVTYPE_KEYBOARD)) { 53 146 TRACE("Enumerating the Keyboard device\n"); 54 147 55 148 lpddi->guidInstance = GUID_SysKeyboard;/* DInput's GUID */ 56 149 lpddi->guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */ … … 58 151 strcpy(lpddi->tszInstanceName, "Keyboard"); 59 152 strcpy(lpddi->tszProductName, "Wine Keyboard"); 60 153 61 154 return TRUE; 62 155 } … … 65 158 } 66 159 67 static SysKeyboardAImpl *alloc_device(REFGUID rguid, ICOM_VTABLE(IDirectInputDevice2A) *kvt, IDirectInputAImpl *dinput)160 static SysKeyboardAImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputAImpl *dinput) 68 161 { 69 162 SysKeyboardAImpl* newDevice; 70 163 newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardAImpl)); 164 newDevice->lpVtbl = kvt; 71 165 newDevice->ref = 1; 72 ICOM_VTBL(newDevice) = kvt;73 166 memcpy(&(newDevice->guid),rguid,sizeof(*rguid)); 74 memset(newDevice->keystate,0,256);75 167 newDevice->dinput = dinput; 76 168 … … 83 175 if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) || /* Generic Keyboard */ 84 176 (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)) { 86 182 *pdev=(IDirectInputDeviceA*) alloc_device(rguid, &SysKeyboardAvt, dinput); 87 88 183 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);94 184 return DI_OK; 95 185 } else … … 109 199 110 200 static HRESULT WINAPI SysKeyboardAImpl_SetProperty( 111 LPDIRECTINPUTDEVICE 2A iface,REFGUID rguid,LPCDIPROPHEADER ph201 LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPCDIPROPHEADER ph 112 202 ) 113 203 { … … 123 213 124 214 TRACE("(buffersize=%ld)\n",pd->dwData); 215 216 if (This->acquired) 217 return DIERR_INVALIDPARAM; 218 219 This->buffersize = pd->dwData; 220 125 221 break; 126 222 } … … 134 230 135 231 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState( 136 LPDIRECTINPUTDEVICE 2A iface,DWORD len,LPVOID ptr232 LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr 137 233 ) 138 234 { 139 DWORD i; 140 141 memset( ptr, 0, len ); 235 /* Note: device does not need to be acquired */ 142 236 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); 156 240 return DI_OK; 157 241 } 158 242 159 243 static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData( 160 LPDIRECTINPUTDEVICE 2A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod,244 LPDIRECTINPUTDEVICE8A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod, 161 245 LPDWORD entries,DWORD flags 162 246 ) 163 247 { 164 248 ICOM_THIS(SysKeyboardAImpl,iface); 165 int i, n;249 int ret = DI_OK, i = 0; 166 250 167 251 TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n", 168 252 This,dodsize,dod,entries,entries?*entries:0,flags); 169 253 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 301 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface); 302 303 static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) 196 304 { 197 305 ICOM_THIS(SysKeyboardAImpl,iface); 198 306 199 307 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 205 334 return DI_OK; 206 335 } 207 336 208 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE 2A iface)337 static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) 209 338 { 210 339 ICOM_THIS(SysKeyboardAImpl,iface); 211 340 TRACE("(this=%p)\n",This); 212 341 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 } 218 358 219 359 return DI_OK; 360 } 361 362 static 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; 220 370 } 221 371 … … 224 374 */ 225 375 static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities( 226 LPDIRECTINPUTDEVICE 2A iface,376 LPDIRECTINPUTDEVICE8A iface, 227 377 LPDIDEVCAPS lpDIDevCaps) 228 378 { … … 246 396 FIXME("DirectX 3.0 not supported....\n"); 247 397 } 248 398 249 399 return DI_OK; 250 400 } 251 401 252 static ICOM_VTABLE(IDirectInputDevice 2A) SysKeyboardAvt =402 static ICOM_VTABLE(IDirectInputDevice8A) SysKeyboardAvt = 253 403 { 254 404 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE … … 265 415 SysKeyboardAImpl_GetDeviceData, 266 416 IDirectInputDevice2AImpl_SetDataFormat, 267 IDirectInputDevice2AImpl_SetEventNotification,417 SysKeyboardAImpl_SetEventNotification, 268 418 IDirectInputDevice2AImpl_SetCooperativeLevel, 269 419 IDirectInputDevice2AImpl_GetObjectInfo, … … 279 429 IDirectInputDevice2AImpl_Escape, 280 430 IDirectInputDevice2AImpl_Poll, 281 IDirectInputDevice2AImpl_SendDeviceData 431 IDirectInputDevice2AImpl_SendDeviceData, 432 IDirectInputDevice7AImpl_EnumEffectsInFile, 433 IDirectInputDevice7AImpl_WriteEffectToFile, 434 IDirectInputDevice8AImpl_BuildActionMap, 435 IDirectInputDevice8AImpl_SetActionMap, 436 IDirectInputDevice8AImpl_GetImageInfo 282 437 }; 283 284 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)285 # define XCAST(fun) (typeof(SysKeyboard7Avt.fun))286 #else287 # define XCAST(fun) (void*)288 #endif289 290 static ICOM_VTABLE(IDirectInputDevice7A) SysKeyboard7Avt =291 {292 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE293 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_WriteEffectToFile322 };323 324 #undef XCAST
Note:
See TracChangeset
for help on using the changeset viewer.