diff --git a/reactos/lib/dinput/keyboard.c b/reactos/lib/dinput/keyboard.c new file mode 100644 index 00000000000..2d14f389e2b --- /dev/null +++ b/reactos/lib/dinput/keyboard.c @@ -0,0 +1,827 @@ +/* DirectInput Keyboard device + * + * 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winerror.h" +#include "dinput.h" + +#include "dinput_private.h" +#include "device_private.h" +#include "wine/debug.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dinput); + +#define WINE_DINPUT_KEYBOARD_MAX_KEYS 256 + +static IDirectInputDevice8AVtbl SysKeyboardAvt; +static IDirectInputDevice8WVtbl SysKeyboardWvt; + +typedef struct SysKeyboardImpl SysKeyboardImpl; +struct SysKeyboardImpl +{ + LPVOID lpVtbl; + DWORD ref; + GUID guid; + + IDirectInputImpl* dinput; + + HANDLE hEvent; + /* SysKeyboardAImpl */ + int acquired; + int buffersize; /* set in 'SetProperty' */ + LPDIDEVICEOBJECTDATA buffer; /* buffer for 'GetDeviceData'. + Alloc at 'Acquire', Free at + 'Unacquire' */ + int count; /* number of objects in use in + 'buffer' */ + int start; /* 'buffer' rotates. This is the + first in use (if count > 0) */ + BOOL overflow; /* return DI_BUFFEROVERFLOW in + 'GetDeviceData' */ + CRITICAL_SECTION crit; +}; + +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[WINE_DINPUT_KEYBOARD_MAX_KEYS]; /* array for 'GetDeviceState' */ + +static CRITICAL_SECTION keyboard_crit; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &keyboard_crit, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { 0, (DWORD)(__FILE__ ": keyboard_crit") } +}; +static CRITICAL_SECTION keyboard_crit = { &critsect_debug, -1, 0, 0, 0, 0 }; + +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); + + /** 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)); + + n = (current_lock->start + current_lock->count) % current_lock->buffersize; + + 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); +} + +static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */ + 0x0ab8648a, + 0x7735, + 0x11d2, + {0x8c, 0x73, 0x71, 0xdf, 0x54, 0xa9, 0x64, 0x41} +}; + +static void fill_keyboard_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, int version) { + DWORD dwSize; + DIDEVICEINSTANCEA ddi; + + dwSize = lpddi->dwSize; + + TRACE("%ld %p\n", dwSize, lpddi); + + memset(lpddi, 0, dwSize); + memset(&ddi, 0, sizeof(ddi)); + + ddi.dwSize = dwSize; + ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */ + ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */ + if (version >= 8) + ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8); + else + ddi.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); + strcpy(ddi.tszInstanceName, "Keyboard"); + strcpy(ddi.tszProductName, "Wine Keyboard"); + + memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi))); +} + +static void fill_keyboard_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, int version) { + DWORD dwSize; + DIDEVICEINSTANCEW ddi; + + dwSize = lpddi->dwSize; + + TRACE("%ld %p\n", dwSize, lpddi); + + memset(lpddi, 0, dwSize); + memset(&ddi, 0, sizeof(ddi)); + + ddi.dwSize = dwSize; + ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */ + ddi.guidProduct = DInput_Wine_Keyboard_GUID; /* Vendor's GUID */ + if (version >= 8) + ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8); + else + ddi.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); + MultiByteToWideChar(CP_ACP, 0, "Keyboard", -1, ddi.tszInstanceName, MAX_PATH); + MultiByteToWideChar(CP_ACP, 0, "Wine Keyboard", -1, ddi.tszProductName, MAX_PATH); + + memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi))); +} + +static BOOL keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, int version, int id) +{ + if (id != 0) + return FALSE; + + if ((dwDevType == 0) || + ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 8)) || + (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 8))) { + TRACE("Enumerating the Keyboard device\n"); + + fill_keyboard_dideviceinstanceA(lpddi, version); + + return TRUE; + } + + return FALSE; +} + +static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, int version, int id) +{ + if (id != 0) + return FALSE; + + if ((dwDevType == 0) || + ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 8)) || + (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 8))) { + TRACE("Enumerating the Keyboard device\n"); + + fill_keyboard_dideviceinstanceW(lpddi, version); + + return TRUE; + } + + return FALSE; +} + +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); + kbd_users = InterlockedIncrement(&keyboard_users); + if (1 == kbd_users) { + keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 ); + } + LeaveCriticalSection(&keyboard_crit); + + return newDevice; +} + + +static HRESULT keyboarddev_create_deviceA(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEA* pdev) +{ + if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) || /* Generic Keyboard */ + (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */ + if ((riid == NULL) || + IsEqualGUID(&IID_IDirectInputDeviceA,riid) || + IsEqualGUID(&IID_IDirectInputDevice2A,riid) || + IsEqualGUID(&IID_IDirectInputDevice7A,riid) || + IsEqualGUID(&IID_IDirectInputDevice8A,riid)) { + *pdev = (IDirectInputDeviceA*) alloc_device(rguid, &SysKeyboardAvt, dinput); + TRACE("Creating a Keyboard device (%p)\n", *pdev); + return DI_OK; + } else + return DIERR_NOINTERFACE; + } + return DIERR_DEVICENOTREG; +} + +static HRESULT keyboarddev_create_deviceW(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPDIRECTINPUTDEVICEW* pdev) +{ + if ((IsEqualGUID(&GUID_SysKeyboard,rguid)) || /* Generic Keyboard */ + (IsEqualGUID(&DInput_Wine_Keyboard_GUID,rguid))) { /* Wine Keyboard */ + if ((riid == NULL) || + IsEqualGUID(&IID_IDirectInputDeviceW,riid) || + IsEqualGUID(&IID_IDirectInputDevice2W,riid) || + IsEqualGUID(&IID_IDirectInputDevice7W,riid) || + IsEqualGUID(&IID_IDirectInputDevice8W,riid)) { + *pdev = (IDirectInputDeviceW*) alloc_device(rguid, &SysKeyboardWvt, dinput); + TRACE("Creating a Keyboard device (%p)\n", *pdev); + return DI_OK; + } else + return DIERR_NOINTERFACE; + } + return DIERR_DEVICENOTREG; +} + +const struct dinput_device keyboard_device = { + "Wine keyboard driver", + keyboarddev_enum_deviceA, + keyboarddev_enum_deviceW, + keyboarddev_create_deviceA, + keyboarddev_create_deviceW +}; + +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); + kbd_users = InterlockedDecrement(&keyboard_users); + if (0 == kbd_users) { + UnhookWindowsHookEx( keyboard_hook ); + keyboard_hook = 0; + } + LeaveCriticalSection(&keyboard_crit); + + /* Free the data queue */ + HeapFree(GetProcessHeap(),0,This->buffer); + + DeleteCriticalSection(&(This->crit)); + + HeapFree(GetProcessHeap(),0,This); + return DI_OK; +} + +static HRESULT WINAPI SysKeyboardAImpl_SetProperty( + LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPCDIPROPHEADER ph +) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + + TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph); + TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n", + ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow); + if (!HIWORD(rguid)) { + switch ((DWORD)rguid) { + case (DWORD) DIPROP_BUFFERSIZE: { + LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; + + TRACE("(buffersize=%ld)\n",pd->dwData); + + if (This->acquired) + return DIERR_INVALIDPARAM; + + This->buffersize = pd->dwData; + + break; + } + default: + WARN("Unknown type %ld\n",(DWORD)rguid); + break; + } + } + return DI_OK; +} + +static HRESULT WINAPI SysKeyboardAImpl_GetProperty( + LPDIRECTINPUTDEVICE8A iface,REFGUID rguid,LPDIPROPHEADER ph +) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + + TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph); + TRACE("(size=%ld,headersize=%ld,obj=%ld,how=%ld\n", + ph->dwSize,ph->dwHeaderSize,ph->dwObj,ph->dwHow); + if (!HIWORD(rguid)) { + switch ((DWORD)rguid) { + case (DWORD) DIPROP_BUFFERSIZE: { + LPDIPROPDWORD pd = (LPDIPROPDWORD)ph; + + TRACE("(buffersize=%ld)\n",pd->dwData); + + if (This->acquired) + return DIERR_INVALIDPARAM; + + pd->dwData = This->buffersize; + + break; + } + default: + WARN("Unknown type %ld\n",(DWORD)rguid); + break; + } + } + return DI_OK; +} + +static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState( + LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr +) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + TRACE("(%p)->(%ld,%p)\n", This, len, ptr); + + /* Note: device does not need to be acquired */ + 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 < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) { + if (DInputKeyState[i] != 0x00) { + TRACE(" - %02X: %02x\n", i, DInputKeyState[i]); + } + } + } + + memcpy(ptr, DInputKeyState, WINE_DINPUT_KEYBOARD_MAX_KEYS); + LeaveCriticalSection(&(This->crit)); + + return DI_OK; +} + +static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData( + LPDIRECTINPUTDEVICE8A iface,DWORD dodsize,LPDIDEVICEOBJECTDATA dod, + LPDWORD entries,DWORD flags +) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + int ret = DI_OK, i = 0; + + TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n", + This,dodsize,dod,entries,entries?*entries:0,flags); + + if (This->acquired == 0) + return DIERR_NOTACQUIRED; + + if (This->buffer == NULL) + return DIERR_NOTBUFFERED; + + if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) + return DIERR_INVALIDPARAM; + + MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0); + + EnterCriticalSection(&(This->crit)); + + /* Copy item at a time for the case dodsize > sizeof(buffer[n]) */ + while ((i < *entries || *entries == INFINITE) && i < This->count) + { + if (dod != NULL) + { + int n = (This->start + i) % This->buffersize; + LPDIDEVICEOBJECTDATA pd + = (LPDIDEVICEOBJECTDATA)((BYTE *)dod + dodsize * i); + pd->dwOfs = This->buffer[n].dwOfs; + pd->dwData = This->buffer[n].dwData; + pd->dwTimeStamp = This->buffer[n].dwTimeStamp; + pd->dwSequence = This->buffer[n].dwSequence; + } + i++; + } + + *entries = i; + + if (This->overflow) + ret = DI_BUFFEROVERFLOW; + + if (!(flags & DIGDD_PEEK)) + { + /* Empty buffer */ + This->count -= i; + This->start = (This->start + i) % This->buffersize; + This->overflow = FALSE; + } + + LeaveCriticalSection(&(This->crit)); + + TRACE("Returning %ld events queued\n", *entries); + + return ret; +} + +static HRESULT WINAPI SysKeyboardAImpl_EnumObjects( + LPDIRECTINPUTDEVICE8A iface, + LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, + LPVOID lpvRef, + DWORD dwFlags) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + DIDEVICEOBJECTINSTANCEA ddoi; + int i; + + TRACE("(this=%p,%p,%p,%08lx)\n", This, lpCallback, lpvRef, dwFlags); + if (TRACE_ON(dinput)) { + TRACE(" - flags = "); + _dump_EnumObjects_flags(dwFlags); + TRACE("\n"); + } + + /* Only the fields till dwFFMaxForce are relevant */ + memset(&ddoi, 0, sizeof(ddoi)); + ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce); + + for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) { + /* Report 255 keys :-) */ + ddoi.guidType = GUID_Key; + ddoi.dwOfs = i; + ddoi.dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_BUTTON; + GetKeyNameTextA(((i & 0x7f) << 16) | ((i & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName)); + _dump_OBJECTINSTANCEA(&ddoi); + if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) return DI_OK; + } + + return DI_OK; +} + +static HRESULT WINAPI SysKeyboardWImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface, + LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, + LPVOID lpvRef, + DWORD dwFlags) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + + device_enumobjects_AtoWcb_data data; + + data.lpCallBack = lpCallback; + data.lpvRef = lpvRef; + + return SysKeyboardAImpl_EnumObjects((LPDIRECTINPUTDEVICE8A) This, (LPDIENUMDEVICEOBJECTSCALLBACKA) DIEnumDevicesCallbackAtoW, (LPVOID) &data, dwFlags); +} + +static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface); + +static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + + TRACE("(this=%p)\n",This); + + if (This->acquired) + return S_FALSE; + + This->acquired = 1; + + 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; +} + +static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + TRACE("(this=%p)\n",This); + + if (This->acquired == 0) + return DI_NOEFFECT; + + /* No more locks */ + if (current_lock == This) + current_lock = NULL; + else + ERR("this != current_lock\n"); + + /* Unacquire device */ + This->acquired = 0; + + if (This->buffersize >= 0) { + HeapFree(GetProcessHeap(), 0, This->buffer); + This->buffer = NULL; + } + + return DI_OK; +} + +static HRESULT WINAPI SysKeyboardAImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface, + HANDLE hnd) { + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + + TRACE("(this=%p,0x%08lx)\n",This,(DWORD)hnd); + + This->hEvent = hnd; + return DI_OK; +} + +/****************************************************************************** + * GetCapabilities : get the device capablitites + */ +static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities( + LPDIRECTINPUTDEVICE8A iface, + LPDIDEVCAPS lpDIDevCaps) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + DIDEVCAPS devcaps; + + TRACE("(this=%p,%p)\n",This,lpDIDevCaps); + + if ((lpDIDevCaps->dwSize != sizeof(DIDEVCAPS)) && (lpDIDevCaps->dwSize != sizeof(DIDEVCAPS_DX3))) { + WARN("invalid parameter\n"); + return DIERR_INVALIDPARAM; + } + + devcaps.dwSize = lpDIDevCaps->dwSize; + devcaps.dwFlags = DIDC_ATTACHED; + if (This->dinput->version >= 8) + devcaps.dwDevType = DI8DEVTYPE_KEYBOARD | (DI8DEVTYPEKEYBOARD_UNKNOWN << 8); + else + devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); + devcaps.dwAxes = 0; + devcaps.dwButtons = WINE_DINPUT_KEYBOARD_MAX_KEYS; + devcaps.dwPOVs = 0; + devcaps.dwFFSamplePeriod = 0; + devcaps.dwFFMinTimeResolution = 0; + devcaps.dwFirmwareRevision = 100; + devcaps.dwHardwareRevision = 100; + devcaps.dwFFDriverVersion = 0; + + memcpy(lpDIDevCaps, &devcaps, lpDIDevCaps->dwSize); + + return DI_OK; +} + +/****************************************************************************** + * GetObjectInfo : get information about a device object such as a button + * or axis + */ +static HRESULT WINAPI +SysKeyboardAImpl_GetObjectInfo( + LPDIRECTINPUTDEVICE8A iface, + LPDIDEVICEOBJECTINSTANCEA pdidoi, + DWORD dwObj, + DWORD dwHow) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + DIDEVICEOBJECTINSTANCEA ddoi; + DWORD dwSize = pdidoi->dwSize; + + TRACE("(this=%p,%p,%ld,0x%08lx)\n", This, pdidoi, dwObj, dwHow); + + if (dwHow == DIPH_BYID) { + WARN(" querying by id not supported yet...\n"); + return DI_OK; + } + + memset(pdidoi, 0, dwSize); + memset(&ddoi, 0, sizeof(ddoi)); + + ddoi.dwSize = dwSize; + ddoi.guidType = GUID_Key; + ddoi.dwOfs = dwObj; + ddoi.dwType = DIDFT_MAKEINSTANCE(dwObj) | DIDFT_BUTTON; + GetKeyNameTextA(((dwObj & 0x7f) << 16) | ((dwObj & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName)); + + /* And return our just filled device object instance structure */ + memcpy(pdidoi, &ddoi, (dwSize < sizeof(ddoi) ? dwSize : sizeof(ddoi))); + + _dump_OBJECTINSTANCEA(pdidoi); + + return DI_OK; +} + +static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, + LPDIDEVICEOBJECTINSTANCEW pdidoi, + DWORD dwObj, + DWORD dwHow) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + DIDEVICEOBJECTINSTANCEW ddoi; + DWORD dwSize = pdidoi->dwSize; + + TRACE("(this=%p,%p,%ld,0x%08lx)\n", This, pdidoi, dwObj, dwHow); + + if (dwHow == DIPH_BYID) { + WARN(" querying by id not supported yet...\n"); + return DI_OK; + } + + memset(pdidoi, 0, dwSize); + memset(&ddoi, 0, sizeof(ddoi)); + + ddoi.dwSize = dwSize; + ddoi.guidType = GUID_Key; + ddoi.dwOfs = dwObj; + ddoi.dwType = DIDFT_MAKEINSTANCE(dwObj) | DIDFT_BUTTON; + GetKeyNameTextW(((dwObj & 0x7f) << 16) | ((dwObj & 0x80) << 17), ddoi.tszName, sizeof(ddoi.tszName)); + + /* And return our just filled device object instance structure */ + memcpy(pdidoi, &ddoi, (dwSize < sizeof(ddoi) ? dwSize : sizeof(ddoi))); + + _dump_OBJECTINSTANCEW(pdidoi); + + return DI_OK; +} + +/****************************************************************************** + * GetDeviceInfo : get information about a device's identity + */ +static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo( + LPDIRECTINPUTDEVICE8A iface, + LPDIDEVICEINSTANCEA pdidi) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + TRACE("(this=%p,%p)\n", This, pdidi); + + if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) { + WARN(" dinput3 not supported yet...\n"); + return DI_OK; + } + + fill_keyboard_dideviceinstanceA(pdidi, This->dinput->version); + + return DI_OK; +} + +static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi) +{ + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + TRACE("(this=%p,%p)\n", This, pdidi); + + if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) { + WARN(" dinput3 not supported yet...\n"); + return DI_OK; + } + + fill_keyboard_dideviceinstanceW(pdidi, This->dinput->version); + + return DI_OK; +} + +static IDirectInputDevice8AVtbl SysKeyboardAvt = +{ + IDirectInputDevice2AImpl_QueryInterface, + IDirectInputDevice2AImpl_AddRef, + SysKeyboardAImpl_Release, + SysKeyboardAImpl_GetCapabilities, + SysKeyboardAImpl_EnumObjects, + SysKeyboardAImpl_GetProperty, + SysKeyboardAImpl_SetProperty, + SysKeyboardAImpl_Acquire, + SysKeyboardAImpl_Unacquire, + SysKeyboardAImpl_GetDeviceState, + SysKeyboardAImpl_GetDeviceData, + IDirectInputDevice2AImpl_SetDataFormat, + SysKeyboardAImpl_SetEventNotification, + IDirectInputDevice2AImpl_SetCooperativeLevel, + SysKeyboardAImpl_GetObjectInfo, + SysKeyboardAImpl_GetDeviceInfo, + IDirectInputDevice2AImpl_RunControlPanel, + IDirectInputDevice2AImpl_Initialize, + IDirectInputDevice2AImpl_CreateEffect, + IDirectInputDevice2AImpl_EnumEffects, + IDirectInputDevice2AImpl_GetEffectInfo, + IDirectInputDevice2AImpl_GetForceFeedbackState, + IDirectInputDevice2AImpl_SendForceFeedbackCommand, + IDirectInputDevice2AImpl_EnumCreatedEffectObjects, + IDirectInputDevice2AImpl_Escape, + IDirectInputDevice2AImpl_Poll, + IDirectInputDevice2AImpl_SendDeviceData, + IDirectInputDevice7AImpl_EnumEffectsInFile, + IDirectInputDevice7AImpl_WriteEffectToFile, + IDirectInputDevice8AImpl_BuildActionMap, + IDirectInputDevice8AImpl_SetActionMap, + IDirectInputDevice8AImpl_GetImageInfo +}; + +#if !defined(__STRICT_ANSI__) && defined(__GNUC__) +# define XCAST(fun) (typeof(SysKeyboardWvt.fun)) +#else +# define XCAST(fun) (void*) +#endif + +static IDirectInputDevice8WVtbl SysKeyboardWvt = +{ + IDirectInputDevice2WImpl_QueryInterface, + XCAST(AddRef)IDirectInputDevice2AImpl_AddRef, + XCAST(Release)SysKeyboardAImpl_Release, + XCAST(GetCapabilities)SysKeyboardAImpl_GetCapabilities, + SysKeyboardWImpl_EnumObjects, + XCAST(GetProperty)SysKeyboardAImpl_GetProperty, + XCAST(SetProperty)SysKeyboardAImpl_SetProperty, + XCAST(Acquire)SysKeyboardAImpl_Acquire, + XCAST(Unacquire)SysKeyboardAImpl_Unacquire, + XCAST(GetDeviceState)SysKeyboardAImpl_GetDeviceState, + XCAST(GetDeviceData)SysKeyboardAImpl_GetDeviceData, + XCAST(SetDataFormat)IDirectInputDevice2AImpl_SetDataFormat, + XCAST(SetEventNotification)SysKeyboardAImpl_SetEventNotification, + XCAST(SetCooperativeLevel)IDirectInputDevice2AImpl_SetCooperativeLevel, + SysKeyboardWImpl_GetObjectInfo, + SysKeyboardWImpl_GetDeviceInfo, + XCAST(RunControlPanel)IDirectInputDevice2AImpl_RunControlPanel, + XCAST(Initialize)IDirectInputDevice2AImpl_Initialize, + XCAST(CreateEffect)IDirectInputDevice2AImpl_CreateEffect, + IDirectInputDevice2WImpl_EnumEffects, + IDirectInputDevice2WImpl_GetEffectInfo, + XCAST(GetForceFeedbackState)IDirectInputDevice2AImpl_GetForceFeedbackState, + XCAST(SendForceFeedbackCommand)IDirectInputDevice2AImpl_SendForceFeedbackCommand, + XCAST(EnumCreatedEffectObjects)IDirectInputDevice2AImpl_EnumCreatedEffectObjects, + XCAST(Escape)IDirectInputDevice2AImpl_Escape, + XCAST(Poll)IDirectInputDevice2AImpl_Poll, + XCAST(SendDeviceData)IDirectInputDevice2AImpl_SendDeviceData, + IDirectInputDevice7WImpl_EnumEffectsInFile, + IDirectInputDevice7WImpl_WriteEffectToFile, + IDirectInputDevice8WImpl_BuildActionMap, + IDirectInputDevice8WImpl_SetActionMap, + IDirectInputDevice8WImpl_GetImageInfo +}; +#undef XCAST diff --git a/reactos/lib/dinput/mouse.c b/reactos/lib/dinput/mouse.c index 47dc282f51a..aa5a50aff91 100644 --- a/reactos/lib/dinput/mouse.c +++ b/reactos/lib/dinput/mouse.c @@ -256,9 +256,9 @@ static SysMouseImpl *alloc_device_mouse(REFGUID rguid, LPVOID mvt, IDirectInputI newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseImpl)); newDevice->ref = 1; newDevice->lpVtbl = mvt; -#ifndef __REACTOS__ + InitializeCriticalSection(&(newDevice->crit)); -#endif + memcpy(&(newDevice->guid),rguid,sizeof(*rguid)); /* Per default, Wine uses its internal data format */ @@ -338,20 +338,15 @@ static ULONG WINAPI SysMouseAImpl_Release(LPDIRECTINPUTDEVICE8A iface) /* Free the data queue */ HeapFree(GetProcessHeap(),0,This->data_queue); -#ifndef __REACTOS__ + if (This->hook) { UnhookWindowsHookEx( This->hook ); if (This->dwCoopLevel & DISCL_EXCLUSIVE) ShowCursor(TRUE); /* show cursor */ } DeleteCriticalSection(&(This->crit)); -#endif -#ifdef __REACTOS__ -if (This->dwCoopLevel & DISCL_EXCLUSIVE) - ShowCursor(TRUE); /* show cursor */ - -#endif + /* Free the DataFormat */ if (This->df != &(Wine_InternalMouseFormat)) { HeapFree(GetProcessHeap(), 0, This->df->rgodf); @@ -443,8 +438,9 @@ static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lpara * This is to allow the cursor to start acceleration before * the warps happen. But if it involves a mouse button event we * allow it since we don't want to lose the clicks. + * in reactos 1ms instead for 10ms */ - if (((GetCurrentTime() - last_event) < 10) + if (((GetCurrentTime() - last_event) < 1) && wparam == WM_MOUSEMOVE) goto end; else last_event = GetCurrentTime(); @@ -583,7 +579,9 @@ static void dinput_window_check(SysMouseImpl* This) { MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1); } - +#ifdef __REACTOS__ +int poll_mouse=0; +#endif /****************************************************************************** * Acquire : gets exclusive control of the mouse */ @@ -623,15 +621,15 @@ static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) /* Install our mouse hook */ if (This->dwCoopLevel & DISCL_EXCLUSIVE) ShowCursor(FALSE); /* hide cursor */ -#ifndef __REACTOS__ + This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 ); -#endif - - /* Get the window dimension and find the center */ - GetWindowRect(This->win, &rect); + + /* 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; @@ -664,17 +662,12 @@ static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) /* Reinstall previous mouse event handler */ if (This->hook) { -#ifndef __REACTOS__ + UnhookWindowsHookEx( This->hook ); This->hook = 0; if (This->dwCoopLevel & DISCL_EXCLUSIVE) ShowCursor(TRUE); /* show cursor */ -#endif -#ifdef __REACTOS__ - if (This->dwCoopLevel & DISCL_EXCLUSIVE) - ShowCursor(TRUE); /* show cursor */ -#endif } /* No more locks */ @@ -697,70 +690,25 @@ static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) // if you call poll then to getdevicestate // it did not send back right value in windows -int poll_mouse=0; -#ifdef __REACTOS__ -void getmousesvalue(LPDIRECTINPUTDEVICE8A iface); -int filp=0; -void getmousesvalue(LPDIRECTINPUTDEVICE8A iface) -{ - static long last_event = 0; - POINT point; - SysMouseImpl *This = (SysMouseImpl *)iface; - - 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); - This->m_state.rgbButtons[3] = ((GetKeyState(VK_XBUTTON1) & 0x80) ? 0xFF : 0x00); - This->m_state.rgbButtons[4] = ((GetKeyState(VK_XBUTTON2) & 0x80) ? 0xFF : 0x00); - - - - - if (poll_mouse==1) filp=0; - if (filp==2) filp=0; - if (filp==0) { - GetCursorPos( &point ); - - if (This->prevX == point.x) This->m_state.lX = 0; - else { - This->prevX = point.x; - This->m_state.lX = point.x - This->org_coords.x; - } - - if (This->prevY == point.y) This->m_state.lY = 0; - else { - This->prevY = point.y; - This->m_state.lY = point.y - This->org_coords.y; - } - - } - else - { - This->m_state.lX = 0; - This->m_state.lY = 0; - } - filp++; - -// check see if buffer have been set - -} - -#endif +/* wine does not implement poll but we do, this is from GDI patch from the mouse */ static HRESULT WINAPI SysMouseAImpl_Poll(LPDIRECTINPUTDEVICE8A iface) { int retValue = DI_OK; + SysMouseImpl *This = (SysMouseImpl *)iface; - if (poll_mouse==0) { - retValue=SysMouseAImpl_Acquire(iface); + + + if (poll_mouse==0) { poll_mouse=1; + retValue=SysMouseAImpl_Acquire(iface); if (retValue!=DI_OK) retValue=DIERR_NOTACQUIRED; else retValue = DI_OK; } - + return retValue; } @@ -777,13 +725,9 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceState( SysMouseImpl *This = (SysMouseImpl *)iface; POINT point; -#ifndef __REACTOS__ EnterCriticalSection(&(This->crit)); -#endif -#ifdef __REACTOS__ -getmousesvalue(iface); -#endif + TRACE("(this=%p,0x%08lx,%p): \n",This,len,ptr); /* Copy the current mouse state */ @@ -818,9 +762,9 @@ getmousesvalue(iface); #endif } -#ifndef __REACTOS__ + LeaveCriticalSection(&(This->crit)); -#endif + TRACE("(X: %ld - Y: %ld - Z: %ld L: %02x M: %02x R: %02x)\n", This->m_state.lX, This->m_state.lY, This->m_state.lZ, @@ -843,44 +787,10 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface, SysMouseImpl *This = (SysMouseImpl *)iface; DWORD len; int nqtail; -#ifdef __REACTOS__ -static int last_event=0; -const int size = sizeof(DIDEVICEOBJECTDATA) * 1; -int count=0; -DWORD count_ent=0; -static DWORD time=0; -static POINT save_point; -static int save_b[5]; -static int b[5]; -static POINT point; -int calc; -int count_button; -int add = 0; -#endif TRACE("(%p)->(dods=%ld,entries=%ld,fl=0x%08lx)\n",This,dodsize,*entries,flags); - -#ifdef __REACTOS__ - -if (flags != DIGDD_PEEK) -{ -b[0] = ((GetKeyState(VK_LBUTTON) & 0x80) ? 0xFF : 0x00); -b[1] = ((GetKeyState(VK_RBUTTON) & 0x80) ? 0xFF : 0x00); -b[2] = ((GetKeyState(VK_MBUTTON) & 0x80) ? 0xFF : 0x00); -b[3] = ((GetKeyState(VK_XBUTTON1) & 0x80) ? 0xFF : 0x00); -b[4] = ((GetKeyState(VK_XBUTTON2) & 0x80) ? 0xFF : 0x00); -GetCursorPos( &point ); -} - -#endif - - - - - - - + if (This->acquired == 0) { WARN(" application tries to get data from an unacquired device !\n"); return DIERR_NOTACQUIRED; @@ -892,117 +802,6 @@ GetCursorPos( &point ); // then return it. } - - - - -#ifdef __REACTOS__ - - - if (*entries == 0) return DIERR_INVALIDPARAM; - - if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) { - ERR("Wrong structure size !\n"); - return DIERR_INVALIDPARAM; - } - if (This->data_queue==NULL) { - WARN("No buffer have been set up !\n"); - return DIERR_NOTINITIALIZED; - } - -/* this code are not need it but if we want 100% compatible - with ms we should keep it. but the mouse will be choppy - in Unreal 2004 Demo - - if (GetTickCount()-time <50) { - *entries=0; - return DI_OK; - } - time = GetTickCount(); -*/ - if (GetTickCount()-time <50) - { - add=0; - } - else - { - add=1; - time = GetTickCount(); - } - - - for (count=0;count<*entries;count++) { - - - if (save_point.x != point.x) { - dod[count_ent].dwOfs = DIMOFS_X; - - dod[count_ent].dwData = point.x - save_point.x; - dod[count_ent].dwTimeStamp = GetTickCount(); - dod[count_ent].dwSequence = last_event+=add; - count_ent++; - save_point.x = point.x; - } - - else if (save_point.y != point.y) { - dod[count_ent].dwOfs = DIMOFS_Y; - dod[count_ent].dwData = point.y - save_point.y; - - dod[count_ent].dwTimeStamp = GetTickCount(); - dod[count_ent].dwSequence = last_event+=add; - count_ent++; - save_point.y = point.y; - } - - else if (save_b[0] != b[0]) { - dod[count_ent].dwOfs = DIMOFS_BUTTON0; - - dod[count_ent].dwData = b[0]; - dod[count_ent].dwTimeStamp = GetTickCount(); - dod[count_ent].dwSequence = last_event+=add; - count_ent++; - save_b[0] = b[0]; - } - - else if (save_b[1] != b[1]) { - dod[count_ent].dwOfs = DIMOFS_BUTTON1; - - dod[count_ent].dwData = b[1]; - dod[count_ent].dwTimeStamp = GetTickCount(); - dod[count_ent].dwSequence = last_event+=add; - count_ent++; - save_b[1] = b[1]; - } - - else if (save_b[2] != b[2]) { - dod[count_ent].dwOfs = DIMOFS_BUTTON2; - - dod[count_ent].dwData = b[2]; - dod[count_ent].dwTimeStamp = GetTickCount(); - dod[count_ent].dwSequence = last_event+=add; - count_ent++; - save_b[2] = b[2]; - } - - else if (save_b[3] != b[3]) { - dod[count_ent].dwOfs = DIMOFS_BUTTON3; - - dod[count_ent].dwData = b[3]; - dod[count_ent].dwTimeStamp = GetTickCount(); - dod[count_ent].dwSequence = last_event+=add; - count_ent++; - save_b[3] = b[3]; - } - - - } // end for - - -SetCursorPos(point.x, point.y); -*entries = count_ent; -#endif - -#ifndef __REACTOS__ EnterCriticalSection(&(This->crit)); @@ -1067,7 +866,7 @@ SetCursorPos(point.x, point.y); This->need_warp = WARP_STARTED; #endif } -#endif + return DI_OK; }