mirror of
https://github.com/reactos/reactos.git
synced 2024-06-28 08:51:29 +00:00
[DINPUT] Sync with Wine Staging 4.18. CORE-16441
This commit is contained in:
parent
1477b2deb7
commit
41c8c312e1
|
@ -1,5 +1,5 @@
|
|||
|
||||
add_definitions(-D__WINESRC__)
|
||||
add_definitions(-D__WINESRC__ -DDIRECTINPUT_VERSION=0x0700)
|
||||
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
|
||||
spec2def(dinput.dll dinput.spec ADD_IMPORTLIB)
|
||||
|
||||
|
|
|
@ -18,17 +18,23 @@
|
|||
|
||||
#define NONAMELESSUNION
|
||||
|
||||
|
||||
#include "wine/unicode.h"
|
||||
#include "objbase.h"
|
||||
#include "dinput_private.h"
|
||||
#include "device_private.h"
|
||||
#include "resource.h"
|
||||
|
||||
#include "wine/heap.h"
|
||||
|
||||
typedef struct {
|
||||
int nobjects;
|
||||
IDirectInputDevice8W *lpdid;
|
||||
DIDEVICEINSTANCEW ddi;
|
||||
DIDEVICEOBJECTINSTANCEW ddo[256];
|
||||
/* ActionFormat for every user.
|
||||
* In same order as ConfigureDevicesData usernames */
|
||||
DIACTIONFORMATW *user_afs;
|
||||
} DeviceData;
|
||||
|
||||
typedef struct {
|
||||
|
@ -38,10 +44,11 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
IDirectInput8W *lpDI;
|
||||
LPDIACTIONFORMATW lpdiaf;
|
||||
LPDIACTIONFORMATW original_lpdiaf;
|
||||
DIDevicesData devices_data;
|
||||
int display_only;
|
||||
int nusernames;
|
||||
WCHAR **usernames;
|
||||
} ConfigureDevicesData;
|
||||
|
||||
/*
|
||||
|
@ -57,27 +64,43 @@ static BOOL CALLBACK collect_objects(LPCDIDEVICEOBJECTINSTANCEW lpddo, LPVOID pv
|
|||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK count_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef)
|
||||
{
|
||||
DIDevicesData *data = (DIDevicesData*) pvRef;
|
||||
|
||||
data->ndevices++;
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK collect_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef)
|
||||
{
|
||||
DIDevicesData *data = (DIDevicesData*) pvRef;
|
||||
DeviceData *device = &data->devices[data->ndevices];
|
||||
device->lpdid = lpdid;
|
||||
device->ddi = *lpddi;
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) pvRef;
|
||||
DeviceData *device;
|
||||
int i, j;
|
||||
|
||||
IDirectInputDevice_AddRef(lpdid);
|
||||
|
||||
/* alloc array for devices if this is our first device */
|
||||
if (!data->devices_data.ndevices)
|
||||
data->devices_data.devices = HeapAlloc(GetProcessHeap(), 0, sizeof(DeviceData) * (dwRemaining + 1));
|
||||
device = &data->devices_data.devices[data->devices_data.ndevices];
|
||||
device->lpdid = lpdid;
|
||||
device->ddi = *lpddi;
|
||||
|
||||
device->nobjects = 0;
|
||||
IDirectInputDevice_EnumObjects(lpdid, collect_objects, (LPVOID) device, DIDFT_ALL);
|
||||
|
||||
data->ndevices++;
|
||||
device->user_afs = heap_alloc(sizeof(*device->user_afs) * data->nusernames);
|
||||
memset(device->user_afs, 0, sizeof(*device->user_afs) * data->nusernames);
|
||||
for (i = 0; i < data->nusernames; i++)
|
||||
{
|
||||
DIACTIONFORMATW *user_af = &device->user_afs[i];
|
||||
user_af->dwNumActions = data->original_lpdiaf->dwNumActions;
|
||||
user_af->guidActionMap = data->original_lpdiaf->guidActionMap;
|
||||
user_af->rgoAction = heap_alloc(sizeof(DIACTIONW) * data->original_lpdiaf->dwNumActions);
|
||||
memset(user_af->rgoAction, 0, sizeof(DIACTIONW) * data->original_lpdiaf->dwNumActions);
|
||||
for (j = 0; j < user_af->dwNumActions; j++)
|
||||
{
|
||||
user_af->rgoAction[j].dwSemantic = data->original_lpdiaf->rgoAction[j].dwSemantic;
|
||||
user_af->rgoAction[j].dwFlags = data->original_lpdiaf->rgoAction[j].dwFlags;
|
||||
user_af->rgoAction[j].u.lptszActionName = data->original_lpdiaf->rgoAction[j].u.lptszActionName;
|
||||
}
|
||||
IDirectInputDevice8_BuildActionMap(lpdid, user_af, data->usernames[i], 0);
|
||||
}
|
||||
|
||||
data->devices_data.ndevices++;
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -170,10 +193,18 @@ static DeviceData* get_cur_device(HWND dialog)
|
|||
return &data->devices_data.devices[sel];
|
||||
}
|
||||
|
||||
static LPDIACTIONFORMATW get_cur_lpdiaf(HWND dialog)
|
||||
static DIACTIONFORMATW *get_cur_lpdiaf(HWND dialog)
|
||||
{
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
return data->lpdiaf;
|
||||
int controller_sel = SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_GETCURSEL, 0, 0);
|
||||
int player_sel = SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_GETCURSEL, 0, 0);
|
||||
return &data->devices_data.devices[controller_sel].user_afs[player_sel];
|
||||
}
|
||||
|
||||
static DIACTIONFORMATW *get_original_lpdiaf(HWND dialog)
|
||||
{
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
return data->original_lpdiaf;
|
||||
}
|
||||
|
||||
static int dialog_display_only(HWND dialog)
|
||||
|
@ -182,40 +213,36 @@ static int dialog_display_only(HWND dialog)
|
|||
return data->display_only;
|
||||
}
|
||||
|
||||
static void init_devices(HWND dialog, IDirectInput8W *lpDI, DIDevicesData *data, LPDIACTIONFORMATW lpdiaf)
|
||||
static void init_devices(HWND dialog, ConfigureDevicesData *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Count devices */
|
||||
data->ndevices = 0;
|
||||
IDirectInput8_EnumDevicesBySemantics(lpDI, NULL, lpdiaf, count_devices, (LPVOID) data, 0);
|
||||
|
||||
/* Allocate devices */
|
||||
data->devices = HeapAlloc(GetProcessHeap(), 0, sizeof(DeviceData) * data->ndevices);
|
||||
|
||||
/* Collect and insert */
|
||||
data->ndevices = 0;
|
||||
IDirectInput8_EnumDevicesBySemantics(lpDI, NULL, lpdiaf, collect_devices, (LPVOID) data, 0);
|
||||
data->devices_data.ndevices = 0;
|
||||
IDirectInput8_EnumDevicesBySemantics(data->lpDI, NULL, data->original_lpdiaf, collect_devices, (LPVOID) data, 0);
|
||||
|
||||
for (i=0; i < data->ndevices; i++)
|
||||
SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->devices[i].ddi.tszProductName );
|
||||
for (i = 0; i < data->devices_data.ndevices; i++)
|
||||
SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->devices_data.devices[i].ddi.tszProductName );
|
||||
for (i = 0; i < data->nusernames; i++)
|
||||
SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->usernames[i]);
|
||||
}
|
||||
|
||||
static void destroy_data(HWND dialog)
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
DIDevicesData *devices_data = &data->devices_data;
|
||||
|
||||
/* Free the devices */
|
||||
for (i=0; i < devices_data->ndevices; i++)
|
||||
{
|
||||
IDirectInputDevice8_Release(devices_data->devices[i].lpdid);
|
||||
for (j=0; j < data->nusernames; j++)
|
||||
heap_free(devices_data->devices[i].user_afs[j].rgoAction);
|
||||
heap_free(devices_data->devices[i].user_afs);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, devices_data->devices);
|
||||
|
||||
/* Free the backup LPDIACTIONFORMATW */
|
||||
HeapFree(GetProcessHeap(), 0, data->original_lpdiaf->rgoAction);
|
||||
HeapFree(GetProcessHeap(), 0, data->original_lpdiaf);
|
||||
}
|
||||
|
||||
static void fill_device_object_list(HWND dialog)
|
||||
|
@ -231,6 +258,7 @@ static void fill_device_object_list(HWND dialog)
|
|||
/* Add each object */
|
||||
for (i=0; i < device->nobjects; i++)
|
||||
{
|
||||
DWORD ddo_inst, ddo_type;
|
||||
int action = -1;
|
||||
|
||||
item.mask = LVIF_TEXT | LVIF_PARAM;
|
||||
|
@ -241,12 +269,20 @@ static void fill_device_object_list(HWND dialog)
|
|||
|
||||
/* Add the item */
|
||||
SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_INSERTITEMW, 0, (LPARAM) &item);
|
||||
ddo_inst = DIDFT_GETINSTANCE(device->ddo[i].dwType);
|
||||
ddo_type = DIDFT_GETTYPE(device->ddo[i].dwType);
|
||||
|
||||
/* Search for an assigned action for this device */
|
||||
/* Search for an assigned action for this device */
|
||||
for (j=0; j < lpdiaf->dwNumActions; j++)
|
||||
{
|
||||
DWORD af_inst = DIDFT_GETINSTANCE(lpdiaf->rgoAction[j].dwObjID);
|
||||
DWORD af_type = DIDFT_GETTYPE(lpdiaf->rgoAction[j].dwObjID);
|
||||
if (af_type == DIDFT_PSHBUTTON) af_type = DIDFT_BUTTON;
|
||||
if (af_type == DIDFT_RELAXIS) af_type = DIDFT_AXIS;
|
||||
/* NOTE previously compared dwType == dwObjId but default buildActionMap actions
|
||||
* were PSHBUTTON and RELAXS and didnt show up on config */
|
||||
if (IsEqualGUID(&lpdiaf->rgoAction[j].guidInstance, &device->ddi.guidInstance) &&
|
||||
lpdiaf->rgoAction[j].dwObjID == device->ddo[i].dwType)
|
||||
ddo_inst == af_inst && ddo_type & af_type)
|
||||
{
|
||||
action = j;
|
||||
break;
|
||||
|
@ -260,7 +296,7 @@ static void fill_device_object_list(HWND dialog)
|
|||
static void show_suitable_actions(HWND dialog)
|
||||
{
|
||||
DeviceData *device = get_cur_device(dialog);
|
||||
LPDIACTIONFORMATW lpdiaf = get_cur_lpdiaf(dialog);
|
||||
LPDIACTIONFORMATW lpdiaf = get_original_lpdiaf(dialog);
|
||||
int i, added = 0;
|
||||
int obj = lv_get_cur_item(dialog);
|
||||
|
||||
|
@ -298,10 +334,13 @@ static void assign_action(HWND dialog)
|
|||
int obj = lv_get_cur_item(dialog);
|
||||
int old_action = lv_get_item_data(dialog, obj);
|
||||
int used_obj;
|
||||
|
||||
DIDEVICEOBJECTINSTANCEW ddo = device->ddo[obj];
|
||||
DWORD type;
|
||||
|
||||
if (old_action == action) return;
|
||||
if (obj < 0) return;
|
||||
if (lpdiaf->rgoAction[old_action].dwFlags & DIA_APPFIXED) return;
|
||||
|
||||
type = device->ddo[obj].dwType;
|
||||
|
||||
/* Clear old action */
|
||||
if (old_action != -1)
|
||||
|
@ -320,7 +359,7 @@ static void assign_action(HWND dialog)
|
|||
lv_set_action(dialog, used_obj, -1, lpdiaf);
|
||||
|
||||
/* Set new action */
|
||||
lpdiaf->rgoAction[action].dwObjID = ddo.dwType;
|
||||
lpdiaf->rgoAction[action].dwObjID = type;
|
||||
lpdiaf->rgoAction[action].guidInstance = device->ddi.guidInstance;
|
||||
lpdiaf->rgoAction[action].dwHow = DIAH_USERCONFIG;
|
||||
|
||||
|
@ -328,24 +367,35 @@ static void assign_action(HWND dialog)
|
|||
lv_set_action(dialog, obj, action, lpdiaf);
|
||||
}
|
||||
|
||||
static void copy_actions(LPDIACTIONFORMATW to, LPDIACTIONFORMATW from)
|
||||
{
|
||||
DWORD i;
|
||||
for (i=0; i < from->dwNumActions; i++)
|
||||
{
|
||||
to->rgoAction[i].guidInstance = from->rgoAction[i].guidInstance;
|
||||
to->rgoAction[i].dwObjID = from->rgoAction[i].dwObjID;
|
||||
to->rgoAction[i].dwHow = from->rgoAction[i].dwHow;
|
||||
to->rgoAction[i].u.lptszActionName = from->rgoAction[i].u.lptszActionName;
|
||||
}
|
||||
}
|
||||
|
||||
static void reset_actions(HWND dialog)
|
||||
{
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
LPDIACTIONFORMATW to = data->lpdiaf, from = data->original_lpdiaf;
|
||||
DIDevicesData *ddata = (DIDevicesData*) &data->devices_data;
|
||||
unsigned i, j;
|
||||
|
||||
copy_actions(to, from);
|
||||
for (i = 0; i < data->devices_data.ndevices; i++)
|
||||
{
|
||||
DeviceData *device = &ddata->devices[i];
|
||||
for (j = 0; j < data->nusernames; j++)
|
||||
IDirectInputDevice8_BuildActionMap(device->lpdid, &device->user_afs[j], data->usernames[j], DIDBAM_HWDEFAULTS);
|
||||
}
|
||||
}
|
||||
|
||||
static void save_actions(HWND dialog) {
|
||||
ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
|
||||
DIDevicesData *ddata = (DIDevicesData*) &data->devices_data;
|
||||
unsigned i, j;
|
||||
if (!data->display_only) {
|
||||
for (i = 0; i < ddata->ndevices; i++)
|
||||
{
|
||||
DeviceData *device = &ddata->devices[i];
|
||||
for (j = 0; j < data->nusernames; j++)
|
||||
{
|
||||
if (save_mapping_settings(device->lpdid, &device->user_afs[j], data->usernames[j]) != DI_OK)
|
||||
MessageBoxA(dialog, "Could not save settings", 0, MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
|
@ -357,26 +407,27 @@ static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM w
|
|||
ConfigureDevicesData *data = (ConfigureDevicesData*) lParam;
|
||||
|
||||
/* Initialize action format and enumerate devices */
|
||||
init_devices(dialog, data->lpDI, &data->devices_data, data->lpdiaf);
|
||||
init_devices(dialog, data);
|
||||
|
||||
/* Store information in the window */
|
||||
SetWindowLongPtrW(dialog, DWLP_USER, (LONG_PTR) data);
|
||||
|
||||
init_listview_columns(dialog);
|
||||
|
||||
/* Create a backup action format for CANCEL and RESET operations */
|
||||
data->original_lpdiaf = HeapAlloc(GetProcessHeap(), 0, sizeof(*data->original_lpdiaf));
|
||||
data->original_lpdiaf->dwNumActions = data->lpdiaf->dwNumActions;
|
||||
data->original_lpdiaf->rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*data->lpdiaf->dwNumActions);
|
||||
copy_actions(data->original_lpdiaf, data->lpdiaf);
|
||||
|
||||
/* Select the first device and show its actions */
|
||||
SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_SETCURSEL, 0, 0);
|
||||
SendDlgItemMessageW(dialog, IDC_PLAYERCOMBO, CB_SETCURSEL, 0, 0);
|
||||
fill_device_object_list(dialog);
|
||||
|
||||
ShowCursor(TRUE);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
ShowCursor(FALSE);
|
||||
break;
|
||||
|
||||
case WM_NOTIFY:
|
||||
|
||||
switch (((LPNMHDR)lParam)->code)
|
||||
|
@ -407,6 +458,7 @@ static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM w
|
|||
break;
|
||||
|
||||
case IDC_CONTROLLERCOMBO:
|
||||
case IDC_PLAYERCOMBO:
|
||||
|
||||
switch (HIWORD(wParam))
|
||||
{
|
||||
|
@ -417,12 +469,12 @@ static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM w
|
|||
break;
|
||||
|
||||
case IDOK:
|
||||
save_actions(dialog);
|
||||
EndDialog(dialog, 0);
|
||||
destroy_data(dialog);
|
||||
break;
|
||||
|
||||
case IDCANCEL:
|
||||
reset_actions(dialog);
|
||||
EndDialog(dialog, 0);
|
||||
destroy_data(dialog);
|
||||
break;
|
||||
|
@ -445,15 +497,48 @@ HRESULT _configure_devices(IDirectInput8W *iface,
|
|||
LPVOID pvRefData
|
||||
)
|
||||
{
|
||||
int i;
|
||||
DWORD size;
|
||||
WCHAR *username = NULL;
|
||||
ConfigureDevicesData data;
|
||||
data.lpDI = iface;
|
||||
data.lpdiaf = lpdiCDParams->lprgFormats;
|
||||
data.original_lpdiaf = lpdiCDParams->lprgFormats;
|
||||
data.display_only = !(dwFlags & DICD_EDIT);
|
||||
data.nusernames = lpdiCDParams->dwcUsers;
|
||||
if (lpdiCDParams->lptszUserNames == NULL)
|
||||
{
|
||||
/* Get default user name */
|
||||
GetUserNameW(NULL, &size);
|
||||
username = heap_alloc(size * sizeof(WCHAR) );
|
||||
GetUserNameW(username, &size);
|
||||
data.nusernames = 1;
|
||||
data.usernames = heap_alloc(sizeof(WCHAR *));
|
||||
data.usernames[0] = username;
|
||||
}
|
||||
else
|
||||
{
|
||||
WCHAR *p = lpdiCDParams->lptszUserNames;
|
||||
data.usernames = heap_alloc(sizeof(WCHAR *) * data.nusernames);
|
||||
for (i = 0; i < data.nusernames; i++)
|
||||
{
|
||||
if (*p)
|
||||
{
|
||||
data.usernames[i] = p;
|
||||
while (*(p++));
|
||||
}
|
||||
else
|
||||
/* Return if there is an empty string */
|
||||
return DIERR_INVALIDPARAM;
|
||||
}
|
||||
}
|
||||
|
||||
InitCommonControls();
|
||||
|
||||
DialogBoxParamW(DINPUT_instance, (const WCHAR *)MAKEINTRESOURCE(IDD_CONFIGUREDEVICES),
|
||||
lpdiCDParams->hwnd, ConfigureDevicesDlgProc, (LPARAM)&data);
|
||||
|
||||
heap_free(username);
|
||||
heap_free(data.usernames);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <string.h>
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/heap.h"
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winreg.h"
|
||||
|
@ -643,12 +644,29 @@ static DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic)
|
|||
return type | (0x0000ff00 & (obj_instance << 8));
|
||||
}
|
||||
|
||||
static void del_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid) {
|
||||
static const WCHAR subkey[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
'W','i','n','e','\\',
|
||||
'D','i','r','e','c','t','I','n','p','u','t','\\',
|
||||
'M','a','p','p','i','n','g','s','\\','%','s','\\','%','s','\\','%','s','\0'};
|
||||
WCHAR *keyname;
|
||||
|
||||
keyname = heap_alloc(sizeof(WCHAR) * (lstrlenW(subkey) + strlenW(username) + strlenW(device) + strlenW(guid)));
|
||||
sprintfW(keyname, subkey, username, device, guid);
|
||||
|
||||
/* Remove old key mappings so there will be no overlapping mappings */
|
||||
RegDeleteKeyW(HKEY_CURRENT_USER, keyname);
|
||||
|
||||
heap_free(keyname);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_mapping_key
|
||||
* Retrieves an open registry key to save the mapping, parametrized for an username,
|
||||
* specific device and specific action mapping guid.
|
||||
*/
|
||||
static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid)
|
||||
static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid, BOOL create)
|
||||
{
|
||||
static const WCHAR subkey[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
|
@ -663,15 +681,18 @@ static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WC
|
|||
sprintfW(keyname, subkey, username, device, guid);
|
||||
|
||||
/* The key used is HKCU\Software\Wine\DirectInput\Mappings\[username]\[device]\[mapping_guid] */
|
||||
if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey))
|
||||
hkey = 0;
|
||||
if (create) {
|
||||
if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey))
|
||||
hkey = 0;
|
||||
} else if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &hkey))
|
||||
hkey = 0;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, keyname);
|
||||
|
||||
return hkey;
|
||||
}
|
||||
|
||||
static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername)
|
||||
HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername)
|
||||
{
|
||||
WCHAR *guid_str = NULL;
|
||||
DIDEVICEINSTANCEW didev;
|
||||
|
@ -684,7 +705,9 @@ static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORM
|
|||
if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
|
||||
return DI_SETTINGSNOTSAVED;
|
||||
|
||||
hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str);
|
||||
del_mapping_key(didev.tszInstanceName, lpszUsername, guid_str);
|
||||
|
||||
hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str, TRUE);
|
||||
|
||||
if (!hkey)
|
||||
{
|
||||
|
@ -714,12 +737,12 @@ static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORM
|
|||
return DI_OK;
|
||||
}
|
||||
|
||||
static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username)
|
||||
BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username)
|
||||
{
|
||||
HKEY hkey;
|
||||
WCHAR *guid_str;
|
||||
DIDEVICEINSTANCEW didev;
|
||||
int i, mapped = 0;
|
||||
int i;
|
||||
|
||||
didev.dwSize = sizeof(didev);
|
||||
IDirectInputDevice8_GetDeviceInfo(&This->IDirectInputDevice8W_iface, &didev);
|
||||
|
@ -727,7 +750,7 @@ static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMAT
|
|||
if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
|
||||
return FALSE;
|
||||
|
||||
hkey = get_mapping_key(didev.tszInstanceName, username, guid_str);
|
||||
hkey = get_mapping_key(didev.tszInstanceName, username, guid_str, FALSE);
|
||||
|
||||
if (!hkey)
|
||||
{
|
||||
|
@ -748,15 +771,21 @@ static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMAT
|
|||
{
|
||||
lpdiaf->rgoAction[i].dwObjID = id;
|
||||
lpdiaf->rgoAction[i].guidInstance = didev.guidInstance;
|
||||
lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT;
|
||||
mapped += 1;
|
||||
lpdiaf->rgoAction[i].dwHow = DIAH_USERCONFIG;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&lpdiaf->rgoAction[i].guidInstance, 0, sizeof(GUID));
|
||||
lpdiaf->rgoAction[i].dwHow = DIAH_UNMAPPED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RegCloseKey(hkey);
|
||||
CoTaskMemFree(guid_str);
|
||||
|
||||
return mapped > 0;
|
||||
/* On Windows BuildActionMap can open empty mapping, so always return TRUE if get_mapping_key is success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df)
|
||||
|
@ -779,13 +808,18 @@ HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf,
|
|||
load_success = load_mapping_settings(This, lpdiaf, username);
|
||||
}
|
||||
|
||||
if (load_success) return DI_OK;
|
||||
if (load_success) {
|
||||
/* Update dwCRC to track if action format has changed */
|
||||
for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
{
|
||||
lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
|
||||
lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
|
||||
}
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
{
|
||||
/* Don't touch a user configured action */
|
||||
if (lpdiaf->rgoAction[i].dwHow == DIAH_USERCONFIG) continue;
|
||||
|
||||
if ((lpdiaf->rgoAction[i].dwSemantic & devMask) == devMask)
|
||||
{
|
||||
DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic);
|
||||
|
@ -816,6 +850,14 @@ HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf,
|
|||
}
|
||||
}
|
||||
|
||||
/* Update dwCRC to track if action format has changed */
|
||||
lpdiaf->dwCRC = 0;
|
||||
for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
{
|
||||
lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
|
||||
lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
|
||||
}
|
||||
|
||||
if (!has_actions) return DI_NOEFFECT;
|
||||
|
||||
return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags);
|
||||
|
@ -831,6 +873,7 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
|
|||
DIPROPSTRING dps;
|
||||
WCHAR username[MAX_PATH];
|
||||
DWORD username_size = MAX_PATH;
|
||||
DWORD new_crc = 0;
|
||||
int i, action = 0, num_actions = 0;
|
||||
unsigned int offset = 0;
|
||||
|
||||
|
@ -841,12 +884,30 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
|
|||
data_format.dwFlags = DIDF_RELAXIS;
|
||||
data_format.dwDataSize = lpdiaf->dwDataSize;
|
||||
|
||||
/* Calculate checksum for actionformat */
|
||||
for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
{
|
||||
new_crc ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
|
||||
new_crc ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
|
||||
}
|
||||
|
||||
/* Count the actions */
|
||||
for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance))
|
||||
{
|
||||
if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance) ||
|
||||
(IsEqualGUID(&IID_NULL, &lpdiaf->rgoAction[i].guidInstance) &&
|
||||
((lpdiaf->rgoAction[i].dwSemantic & lpdiaf->dwGenre) == lpdiaf->dwGenre ||
|
||||
(lpdiaf->rgoAction[i].dwSemantic & 0xff000000) == 0xff000000 /* Any Axis */) ))
|
||||
{
|
||||
num_actions++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_actions == 0) return DI_NOEFFECT;
|
||||
/* Should return DI_NOEFFECT if we dont have any actions and actionformat has not changed */
|
||||
if (num_actions == 0 && lpdiaf->dwCRC == new_crc && !(dwFlags & DIDSAM_FORCESAVE)) return DI_NOEFFECT;
|
||||
|
||||
/* update dwCRC to track if action format has changed */
|
||||
lpdiaf->dwCRC = new_crc;
|
||||
|
||||
This->num_actions = num_actions;
|
||||
|
||||
|
@ -880,8 +941,40 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
|
|||
|
||||
action++;
|
||||
}
|
||||
else if ((lpdiaf->rgoAction[i].dwSemantic & lpdiaf->dwGenre) == lpdiaf->dwGenre ||
|
||||
(lpdiaf->rgoAction[i].dwSemantic & 0xff000000) == 0xff000000 /* Any Axis */)
|
||||
{
|
||||
DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic);
|
||||
DWORD type = DIDFT_GETTYPE(obj_id);
|
||||
DWORD inst = DIDFT_GETINSTANCE(obj_id);
|
||||
LPDIOBJECTDATAFORMAT obj;
|
||||
|
||||
if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON;
|
||||
else if (type == DIDFT_RELAXIS) type = DIDFT_AXIS;
|
||||
|
||||
obj = dataformat_to_odf_by_type(df, inst, type);
|
||||
TRACE("obj %p, inst 0x%08x, type 0x%08x\n", obj, inst, type);
|
||||
if(obj)
|
||||
{
|
||||
memcpy(&obj_df[action], obj, df->dwObjSize);
|
||||
|
||||
This->action_map[action].uAppData = lpdiaf->rgoAction[i].uAppData;
|
||||
This->action_map[action].offset = offset;
|
||||
obj_df[action].dwOfs = offset;
|
||||
offset += (type & DIDFT_BUTTON) ? 1 : 4;
|
||||
|
||||
action++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (action == 0)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, obj_df);
|
||||
return DI_NOEFFECT;
|
||||
}
|
||||
data_format.dwNumObjs = action;
|
||||
|
||||
IDirectInputDevice8_SetDataFormat(iface, &data_format);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, obj_df);
|
||||
|
@ -1140,7 +1233,7 @@ ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)
|
|||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
ULONG ref = InterlockedDecrement(&(This->ref));
|
||||
|
||||
TRACE("(%p) releasing from %d\n", This, ref + 1);
|
||||
TRACE("(%p) ref %d\n", This, ref);
|
||||
|
||||
if (ref) return ref;
|
||||
|
||||
|
@ -1168,7 +1261,7 @@ ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)
|
|||
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
|
||||
return DI_OK;
|
||||
return ref;
|
||||
}
|
||||
|
||||
ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
|
||||
|
@ -1181,7 +1274,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W ifa
|
|||
{
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
||||
TRACE("(%p this=%p,%s,%p)\n", iface, This, debugstr_guid(riid), ppobj);
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj);
|
||||
if (IsEqualGUID(&IID_IUnknown, riid) ||
|
||||
IsEqualGUID(&IID_IDirectInputDeviceA, riid) ||
|
||||
IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
|
||||
|
@ -1203,7 +1296,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W ifa
|
|||
}
|
||||
|
||||
WARN("Unsupported interface!\n");
|
||||
return E_FAIL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj)
|
||||
|
@ -1215,7 +1308,9 @@ HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A ifa
|
|||
ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface)
|
||||
{
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
return InterlockedIncrement(&This->ref);
|
||||
ULONG ref = InterlockedIncrement(&This->ref);
|
||||
TRACE( "(%p) ref %d\n", This, ref );
|
||||
return ref;
|
||||
}
|
||||
|
||||
ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface)
|
||||
|
@ -1231,7 +1326,7 @@ HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface,
|
|||
DIDEVICEOBJECTINSTANCEA ddoi;
|
||||
int i;
|
||||
|
||||
TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags);
|
||||
TRACE("(%p)->(%p,%p flags:%08x)\n", This, lpCallback, lpvRef, dwFlags);
|
||||
TRACE(" - flags = ");
|
||||
_dump_EnumObjects_flags(dwFlags);
|
||||
TRACE("\n");
|
||||
|
@ -1261,7 +1356,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
|
|||
DIDEVICEOBJECTINSTANCEW ddoi;
|
||||
int i;
|
||||
|
||||
TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags);
|
||||
TRACE("(%p)->(%p,%p flags:%08x)\n", This, lpCallback, lpvRef, dwFlags);
|
||||
TRACE(" - flags = ");
|
||||
_dump_EnumObjects_flags(dwFlags);
|
||||
TRACE("\n");
|
||||
|
@ -1292,7 +1387,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,
|
|||
{
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
||||
TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph);
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
|
||||
_dump_DIPROPHEADER(pdiph);
|
||||
|
||||
if (!IS_DIPROP(rguid)) return DI_OK;
|
||||
|
@ -1357,7 +1452,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(
|
|||
{
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
||||
TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph);
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
|
||||
_dump_DIPROPHEADER(pdiph);
|
||||
|
||||
if (!IS_DIPROP(rguid)) return DI_OK;
|
||||
|
@ -1596,7 +1691,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A ifac
|
|||
|
||||
HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags)
|
||||
{
|
||||
FIXME("(this=%p,%p,0x%08x): stub!\n", iface, hwndOwner, dwFlags);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("%p)->(%p,0x%08x): stub!\n", This, hwndOwner, dwFlags);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
@ -1610,7 +1706,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A if
|
|||
HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion,
|
||||
REFGUID rguid)
|
||||
{
|
||||
FIXME("(this=%p,%p,%d,%s): stub!\n", iface, hinst, dwVersion, debugstr_guid(rguid));
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p,%d,%s): stub!\n", This, hinst, dwVersion, debugstr_guid(rguid));
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
|
@ -1628,7 +1725,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface,
|
|||
HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
|
||||
LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
|
||||
{
|
||||
FIXME("(this=%p,%s,%p,%p,%p): stub!\n", iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%s,%p,%p,%p): stub!\n", This, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
|
||||
|
||||
FIXME("not available in the generic implementation\n");
|
||||
*ppdef = NULL;
|
||||
|
@ -1648,9 +1746,9 @@ HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
|
|||
LPVOID lpvRef,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
|
||||
iface, lpCallback, lpvRef, dwFlags);
|
||||
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
|
||||
FIXME("%p)->(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
|
@ -1660,9 +1758,9 @@ HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
|
|||
LPVOID lpvRef,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
|
||||
iface, lpCallback, lpvRef, dwFlags);
|
||||
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
|
@ -1671,8 +1769,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
|
|||
LPDIEFFECTINFOA lpdei,
|
||||
REFGUID rguid)
|
||||
{
|
||||
FIXME("(this=%p,%p,%s): stub!\n",
|
||||
iface, lpdei, debugstr_guid(rguid));
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
|
||||
FIXME("(%p)->(%p,%s): stub!\n", This, lpdei, debugstr_guid(rguid));
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
|
@ -1681,14 +1779,15 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo(
|
|||
LPDIEFFECTINFOW lpdei,
|
||||
REFGUID rguid)
|
||||
{
|
||||
FIXME("(this=%p,%p,%s): stub!\n",
|
||||
iface, lpdei, debugstr_guid(rguid));
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p,%s): stub!\n", This, lpdei, debugstr_guid(rguid));
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
|
||||
{
|
||||
FIXME("(this=%p,%p): stub!\n", iface, pdwOut);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p): stub!\n", This, pdwOut);
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
|
@ -1700,7 +1799,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(LPDIRECTINPUTDEVIC
|
|||
|
||||
HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
|
||||
{
|
||||
TRACE("(%p) 0x%08x:\n", iface, dwFlags);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
TRACE("(%p)->(0x%08x)\n", This, dwFlags);
|
||||
return DI_NOEFFECT;
|
||||
}
|
||||
|
||||
|
@ -1713,7 +1813,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(LPDIRECTINPUTDE
|
|||
HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
|
||||
LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
|
||||
{
|
||||
FIXME("(this=%p,%p,%p,0x%08x): stub!\n", iface, lpCallback, lpvRef, dwFlags);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)0>(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
|
@ -1726,7 +1827,8 @@ HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDE
|
|||
|
||||
HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc)
|
||||
{
|
||||
FIXME("(this=%p,%p): stub!\n", iface, lpDIEEsc);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p): stub!\n", This, lpDIEEsc);
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
|
@ -1756,7 +1858,8 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W ifa
|
|||
LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(this=%p,0x%08x,%p,%p,0x%08x): stub!\n", iface, cbObjectData, rgdod, pdwInOut, dwFlags);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(0x%08x,%p,%p,0x%08x): stub!\n", This, cbObjectData, rgdod, pdwInOut, dwFlags);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
@ -1776,7 +1879,8 @@ HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A
|
|||
LPVOID pvRef,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
|
||||
FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", This, lpszFileName, pec, pvRef, dwFlags);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
@ -1787,7 +1891,8 @@ HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W
|
|||
LPVOID pvRef,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", This, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
@ -1798,7 +1903,8 @@ HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A
|
|||
LPDIFILEEFFECT rgDiFileEft,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
|
||||
FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", This, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
@ -1809,7 +1915,8 @@ HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W
|
|||
LPDIFILEEFFECT rgDiFileEft,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", This, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
@ -1819,7 +1926,8 @@ HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W ifa
|
|||
LPCWSTR lpszUserName,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
#define X(x) if (dwFlags & x) FIXME("\tdwFlags =|"#x"\n");
|
||||
X(DIDBAM_DEFAULT)
|
||||
X(DIDBAM_PRESERVE)
|
||||
|
@ -1833,7 +1941,8 @@ HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W ifa
|
|||
HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
|
||||
LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
|
||||
{
|
||||
FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
|
||||
FIXME("(%p)->(%p): stub !\n", This, lpdiDevImageInfoHeader);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
@ -1841,7 +1950,8 @@ HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface
|
|||
HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
|
||||
LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
|
||||
{
|
||||
FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
|
||||
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p): stub !\n", This, lpdiDevImageInfoHeader);
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
|
|
@ -114,6 +114,8 @@ typedef struct
|
|||
LPDIRECTINPUTEFFECT ref;
|
||||
} effect_list_item;
|
||||
|
||||
extern const GUID DInput_PIDVID_Product_GUID DECLSPEC_HIDDEN;
|
||||
|
||||
/* Various debug tools */
|
||||
extern void _dump_DIPROPHEADER(LPCDIPROPHEADER diph) DECLSPEC_HIDDEN;
|
||||
extern void _dump_OBJECTINSTANCEA(const DIDEVICEOBJECTINSTANCEA *ddoi) DECLSPEC_HIDDEN;
|
||||
|
@ -123,6 +125,9 @@ extern const char *_dump_dinput_GUID(const GUID *guid) DECLSPEC_HIDDEN;
|
|||
|
||||
extern LPDIOBJECTDATAFORMAT dataformat_to_odf_by_type(LPCDIDATAFORMAT df, int n, DWORD type) DECLSPEC_HIDDEN;
|
||||
|
||||
extern HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername) DECLSPEC_HIDDEN;
|
||||
extern BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username) DECLSPEC_HIDDEN;
|
||||
|
||||
extern HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
|
||||
extern HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
* - Fallout : works great in X and DGA mode
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
@ -39,7 +38,9 @@
|
|||
#define NONAMELESSUNION
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/asm.h"
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winuser.h"
|
||||
|
@ -47,6 +48,7 @@
|
|||
#include "objbase.h"
|
||||
#include "rpcproxy.h"
|
||||
#include "initguid.h"
|
||||
#include "devguid.h"
|
||||
#include "dinput_private.h"
|
||||
#include "device_private.h"
|
||||
#include "dinputd.h"
|
||||
|
@ -289,6 +291,20 @@ static void _dump_EnumDevices_dwFlags(DWORD dwFlags)
|
|||
TRACE("\n");
|
||||
}
|
||||
|
||||
static const char *dump_semantic(DWORD semantic)
|
||||
{
|
||||
if((semantic & 0xff000000) == 0xff000000)
|
||||
return "Any AXIS";
|
||||
else if((semantic & 0x82000000) == 0x82000000)
|
||||
return "Mouse";
|
||||
else if((semantic & 0x81000000) == 0x81000000)
|
||||
return "Keybaord";
|
||||
else if((semantic & DIVIRTUAL_FLYING_HELICOPTER) == DIVIRTUAL_FLYING_HELICOPTER)
|
||||
return "Helicopter";
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static void _dump_diactionformatA(LPDIACTIONFORMATA lpdiActionFormat)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -311,7 +327,7 @@ static void _dump_diactionformatA(LPDIACTIONFORMATA lpdiActionFormat)
|
|||
{
|
||||
TRACE("diaf.rgoAction[%u]:\n", i);
|
||||
TRACE("\tuAppData=0x%lx\n", lpdiActionFormat->rgoAction[i].uAppData);
|
||||
TRACE("\tdwSemantic=0x%08x\n", lpdiActionFormat->rgoAction[i].dwSemantic);
|
||||
TRACE("\tdwSemantic=0x%08x (%s)\n", lpdiActionFormat->rgoAction[i].dwSemantic, dump_semantic(lpdiActionFormat->rgoAction[i].dwSemantic));
|
||||
TRACE("\tdwFlags=0x%x\n", lpdiActionFormat->rgoAction[i].dwFlags);
|
||||
TRACE("\tszActionName=%s\n", debugstr_a(lpdiActionFormat->rgoAction[i].u.lptszActionName));
|
||||
TRACE("\tguidInstance=%s\n", debugstr_guid(&lpdiActionFormat->rgoAction[i].guidInstance));
|
||||
|
@ -467,9 +483,10 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(dinput_devices); i++) {
|
||||
if (!dinput_devices[i]->enum_deviceA) continue;
|
||||
|
||||
TRACE(" Checking device %u ('%s')\n", i, dinput_devices[i]->name);
|
||||
for (j = 0, r = S_OK; SUCCEEDED(r); j++) {
|
||||
devInstance.dwSize = sizeof(devInstance);
|
||||
TRACE(" - checking device %u ('%s')\n", i, dinput_devices[i]->name);
|
||||
r = dinput_devices[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->dwVersion, j);
|
||||
if (r == S_OK)
|
||||
if (enum_callback_wrapper(lpCallback, &devInstance, pvRef) == DIENUM_STOP)
|
||||
|
@ -525,7 +542,7 @@ static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)
|
|||
IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
|
||||
ULONG ref = InterlockedIncrement(&This->ref);
|
||||
|
||||
TRACE( "(%p) incrementing from %d\n", This, ref - 1);
|
||||
TRACE( "(%p) ref %d\n", This, ref );
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
@ -540,7 +557,7 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
|
|||
IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
|
||||
ULONG ref = InterlockedDecrement( &This->ref );
|
||||
|
||||
TRACE( "(%p) releasing from %d\n", This, ref + 1 );
|
||||
TRACE( "(%p) ref %d\n", This, ref );
|
||||
|
||||
if (ref == 0)
|
||||
{
|
||||
|
@ -566,53 +583,39 @@ static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, RE
|
|||
if (!riid || !ppobj)
|
||||
return E_POINTER;
|
||||
|
||||
*ppobj = NULL;
|
||||
|
||||
#if DIRECTINPUT_VERSION == 0x0700
|
||||
if (IsEqualGUID( &IID_IUnknown, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInputA, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInput2A, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInput7A, riid ))
|
||||
{
|
||||
IsEqualGUID( &IID_IDirectInputA, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInput2A, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInput7A, riid ))
|
||||
*ppobj = &This->IDirectInput7A_iface;
|
||||
IUnknown_AddRef( (IUnknown*)*ppobj );
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID( &IID_IDirectInputW, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInput2W, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInput7W, riid ))
|
||||
{
|
||||
else if (IsEqualGUID( &IID_IDirectInputW, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInput2W, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInput7W, riid ))
|
||||
*ppobj = &This->IDirectInput7W_iface;
|
||||
IUnknown_AddRef( (IUnknown*)*ppobj );
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID( &IID_IDirectInput8A, riid ))
|
||||
{
|
||||
#else
|
||||
if (IsEqualGUID( &IID_IUnknown, riid ) ||
|
||||
IsEqualGUID( &IID_IDirectInput8A, riid ))
|
||||
*ppobj = &This->IDirectInput8A_iface;
|
||||
IUnknown_AddRef( (IUnknown*)*ppobj );
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
if (IsEqualGUID( &IID_IDirectInput8W, riid ))
|
||||
{
|
||||
else if (IsEqualGUID( &IID_IDirectInput8W, riid ))
|
||||
*ppobj = &This->IDirectInput8W_iface;
|
||||
IUnknown_AddRef( (IUnknown*)*ppobj );
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IsEqualGUID( &IID_IDirectInputJoyConfig8, riid ))
|
||||
{
|
||||
*ppobj = &This->IDirectInputJoyConfig8_iface;
|
||||
IUnknown_AddRef( (IUnknown*)*ppobj );
|
||||
|
||||
if(*ppobj)
|
||||
{
|
||||
IUnknown_AddRef( (IUnknown*)*ppobj );
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
FIXME( "Unsupported interface: %s\n", debugstr_guid(riid));
|
||||
*ppobj = NULL;
|
||||
WARN( "Unsupported interface: %s\n", debugstr_guid(riid));
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
@ -690,7 +693,7 @@ static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTA
|
|||
{
|
||||
IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
|
||||
|
||||
TRACE("(%p)->(%p, 0x%04x)\n", iface, hinst, version);
|
||||
TRACE("(%p)->(%p, 0x%04x)\n", This, hinst, version);
|
||||
|
||||
if (!hinst)
|
||||
return DIERR_INVALIDPARAM;
|
||||
|
@ -947,7 +950,7 @@ static HRESULT WINAPI IDirectInput8AImpl_Initialize(LPDIRECTINPUT8A iface, HINST
|
|||
{
|
||||
IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
|
||||
|
||||
TRACE("(%p)->(%p, 0x%04x)\n", iface, hinst, version);
|
||||
TRACE("(%p)->(%p, 0x%04x)\n", This, hinst, version);
|
||||
|
||||
if (!hinst)
|
||||
return DIERR_INVALIDPARAM;
|
||||
|
@ -1104,10 +1107,12 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
|
|||
|
||||
if (lpCallback(&didevis[i], lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP)
|
||||
{
|
||||
IDirectInputDevice_Release(lpdid);
|
||||
HeapFree(GetProcessHeap(), 0, didevis);
|
||||
HeapFree(GetProcessHeap(), 0, username_w);
|
||||
return DI_OK;
|
||||
}
|
||||
IDirectInputDevice_Release(lpdid);
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, didevis);
|
||||
|
@ -1130,9 +1135,11 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
|
|||
|
||||
if (lpCallback(&didevi, lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP)
|
||||
{
|
||||
IDirectInputDevice_Release(lpdid);
|
||||
HeapFree(GetProcessHeap(), 0, username_w);
|
||||
return DI_OK;
|
||||
}
|
||||
IDirectInputDevice_Release(lpdid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1260,9 +1267,34 @@ static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
|
|||
|
||||
/* Copy parameters */
|
||||
diCDParamsW.dwSize = sizeof(DICONFIGUREDEVICESPARAMSW);
|
||||
diCDParamsW.dwcUsers = lpdiCDParams->dwcUsers;
|
||||
diCDParamsW.dwcFormats = lpdiCDParams->dwcFormats;
|
||||
diCDParamsW.lprgFormats = &diafW;
|
||||
diCDParamsW.hwnd = lpdiCDParams->hwnd;
|
||||
diCDParamsW.lptszUserNames = NULL;
|
||||
|
||||
if (lpdiCDParams->lptszUserNames) {
|
||||
char *start = lpdiCDParams->lptszUserNames;
|
||||
WCHAR *to = NULL;
|
||||
int total_len = 0;
|
||||
for (i = 0; i < lpdiCDParams->dwcUsers; i++)
|
||||
{
|
||||
char *end = start + 1;
|
||||
int len;
|
||||
while (*(end++));
|
||||
len = MultiByteToWideChar(CP_ACP, 0, start, end - start, NULL, 0);
|
||||
total_len += len + 2; /* length of string and two null char */
|
||||
if (to)
|
||||
to = HeapReAlloc(GetProcessHeap(), 0, to, sizeof(WCHAR) * total_len);
|
||||
else
|
||||
to = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * total_len);
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, start, end - start, to + (total_len - len - 2), len);
|
||||
to[total_len] = 0;
|
||||
to[total_len - 1] = 0;
|
||||
}
|
||||
diCDParamsW.lptszUserNames = to;
|
||||
}
|
||||
|
||||
diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiCDParams->lprgFormats->dwNumActions);
|
||||
_copy_diactionformatAtoW(&diafW, lpdiCDParams->lprgFormats);
|
||||
|
@ -1290,6 +1322,8 @@ static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
|
|||
|
||||
HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
|
||||
|
||||
heap_free((void*) diCDParamsW.lptszUserNames);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -1777,7 +1811,7 @@ static DWORD WINAPI hook_thread_proc(void *param)
|
|||
DispatchMessageW(&msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
FreeLibraryAndExitThread(DINPUT_instance, 0);
|
||||
}
|
||||
|
||||
static DWORD hook_thread_id;
|
||||
|
@ -1794,15 +1828,16 @@ static CRITICAL_SECTION dinput_hook_crit = { &dinput_critsect_debug, -1, 0, 0, 0
|
|||
static BOOL check_hook_thread(void)
|
||||
{
|
||||
static HANDLE hook_thread;
|
||||
HMODULE module;
|
||||
|
||||
EnterCriticalSection(&dinput_hook_crit);
|
||||
|
||||
TRACE("IDirectInputs left: %d\n", list_count(&direct_input_list));
|
||||
if (!list_empty(&direct_input_list) && !hook_thread)
|
||||
{
|
||||
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR*)DINPUT_instance, &module);
|
||||
hook_thread_event = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
hook_thread = CreateThread(NULL, 0, hook_thread_proc, hook_thread_event, 0, &hook_thread_id);
|
||||
LeaveCriticalSection(&dinput_hook_crit);
|
||||
}
|
||||
else if (list_empty(&direct_input_list) && hook_thread)
|
||||
{
|
||||
|
@ -1817,16 +1852,11 @@ static BOOL check_hook_thread(void)
|
|||
|
||||
hook_thread_id = 0;
|
||||
PostThreadMessageW(tid, WM_USER+0x10, 0, 0);
|
||||
LeaveCriticalSection(&dinput_hook_crit);
|
||||
|
||||
/* wait for hook thread to exit */
|
||||
WaitForSingleObject(hook_thread, INFINITE);
|
||||
CloseHandle(hook_thread);
|
||||
hook_thread = NULL;
|
||||
}
|
||||
else
|
||||
LeaveCriticalSection(&dinput_hook_crit);
|
||||
|
||||
LeaveCriticalSection(&dinput_hook_crit);
|
||||
return hook_thread_id != 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ extern void _copy_diactionformatWtoA(LPDIACTIONFORMATA, LPDIACTIONFORMATW) DECLS
|
|||
extern HRESULT _configure_devices(IDirectInput8W *iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) DECLSPEC_HIDDEN;
|
||||
|
||||
extern WCHAR* get_mapping_path(const WCHAR *device, const WCHAR *username) DECLSPEC_HIDDEN;
|
||||
extern DWORD get_device_type(DWORD version, BOOL is_joystick) DECLSPEC_HIDDEN;
|
||||
|
||||
#define IS_DIPROP(x) (((ULONG_PTR)(x) >> 16) == 0)
|
||||
|
||||
|
|
|
@ -167,7 +167,9 @@ static ULONG WINAPI LinuxInputEffectImpl_AddRef(
|
|||
LPDIRECTINPUTEFFECT iface)
|
||||
{
|
||||
LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
|
||||
return InterlockedIncrement(&(This->ref));
|
||||
ULONG ref = InterlockedIncrement(&This->ref);
|
||||
TRACE( "(%p) ref %d\n", This, ref );
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI LinuxInputEffectImpl_Download(
|
||||
|
@ -759,6 +761,8 @@ static ULONG WINAPI LinuxInputEffectImpl_Release(LPDIRECTINPUTEFFECT iface)
|
|||
LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
|
||||
ULONG ref = InterlockedDecrement(&(This->ref));
|
||||
|
||||
TRACE( "(%p) ref %d\n", This, ref );
|
||||
|
||||
if (ref == 0)
|
||||
{
|
||||
LinuxInputEffectImpl_Stop(iface);
|
||||
|
|
|
@ -28,12 +28,40 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "device_private.h"
|
||||
#include "joystick_private.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
#include "winreg.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dinput);
|
||||
|
||||
#define VID_MICROSOFT 0x045e
|
||||
|
||||
static const WORD PID_XBOX_CONTROLLERS[] = {
|
||||
0x0202, /* Xbox Controller */
|
||||
0x0285, /* Xbox Controller S */
|
||||
0x0289, /* Xbox Controller S */
|
||||
0x028e, /* Xbox360 Controller */
|
||||
0x028f, /* Xbox360 Wireless Controller */
|
||||
0x02d1, /* Xbox One Controller */
|
||||
0x02dd, /* Xbox One Controller (Covert Forces/Firmware 2015) */
|
||||
0x02e0, /* Xbox One X Controller */
|
||||
0x02e3, /* Xbox One Elite Controller */
|
||||
0x02e6, /* Wireless XBox Controller Dongle */
|
||||
0x02ea, /* Xbox One S Controller */
|
||||
0x02fd, /* Xbox One S Controller (Firmware 2017) */
|
||||
0x0719, /* Xbox 360 Wireless Adapter */
|
||||
};
|
||||
|
||||
/* Windows uses this GUID for guidProduct on non-keyboard/mouse devices.
|
||||
* Data1 contains the device VID (low word) and PID (high word).
|
||||
* Data4 ends with the ASCII bytes "PIDVID".
|
||||
*/
|
||||
const GUID DInput_PIDVID_Product_GUID = { /* device_pidvid-0000-0000-0000-504944564944 */
|
||||
0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44}
|
||||
};
|
||||
|
||||
static inline JoystickGenericImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface), JoystickGenericImpl, base);
|
||||
|
@ -76,6 +104,16 @@ DWORD typeFromGUID(REFGUID guid)
|
|||
}
|
||||
}
|
||||
|
||||
DWORD get_device_type(DWORD version, BOOL is_joystick)
|
||||
{
|
||||
if (is_joystick)
|
||||
return version >= 0x0800 ? DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8) :
|
||||
DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
||||
|
||||
return version >= 0x0800 ? DI8DEVTYPE_GAMEPAD | (DI8DEVTYPEJOYSTICK_STANDARD << 8) :
|
||||
DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_GAMEPAD << 8);
|
||||
}
|
||||
|
||||
static void _dump_DIEFFECT_flags(DWORD dwFlags)
|
||||
{
|
||||
if (TRACE_ON(dinput)) {
|
||||
|
@ -271,6 +309,89 @@ BOOL device_disabled_registry(const char* name)
|
|||
return do_disable;
|
||||
}
|
||||
|
||||
BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (vid == VID_MICROSOFT)
|
||||
{
|
||||
for (i = 0; i < ARRAY_SIZE(PID_XBOX_CONTROLLERS); i++)
|
||||
if (pid == PID_XBOX_CONTROLLERS[i]) return TRUE;
|
||||
}
|
||||
|
||||
return (devcaps->dwAxes == 6 && devcaps->dwButtons >= 14);
|
||||
}
|
||||
|
||||
static void remap_init(JoystickGenericImpl *This, int obj, ObjProps *remap_props)
|
||||
{
|
||||
/* Configure as if nothing changed so the helper functions can only change
|
||||
* what they need, thus reducing code duplication. */
|
||||
remap_props->lDevMin = remap_props->lMin = This->props[obj].lMin;
|
||||
remap_props->lDevMax = remap_props->lMax = This->props[obj].lMax;
|
||||
|
||||
remap_props->lDeadZone = This->props[obj].lDeadZone;
|
||||
remap_props->lSaturation = This->props[obj].lSaturation;
|
||||
}
|
||||
|
||||
static void remap_apply(JoystickGenericImpl *This, int obj, ObjProps *remap_props)
|
||||
{
|
||||
/* Many games poll the joystick immediately after setting the range
|
||||
* for calibration purposes, so the old values need to be remapped
|
||||
* to the new range before it does so */
|
||||
switch (This->base.data_format.wine_df->rgodf[obj].dwOfs){
|
||||
case DIJOFS_X : This->js.lX = joystick_map_axis(remap_props, This->js.lX); break;
|
||||
case DIJOFS_Y : This->js.lY = joystick_map_axis(remap_props, This->js.lY); break;
|
||||
case DIJOFS_Z : This->js.lZ = joystick_map_axis(remap_props, This->js.lZ); break;
|
||||
case DIJOFS_RX : This->js.lRx = joystick_map_axis(remap_props, This->js.lRx); break;
|
||||
case DIJOFS_RY : This->js.lRy = joystick_map_axis(remap_props, This->js.lRy); break;
|
||||
case DIJOFS_RZ : This->js.lRz = joystick_map_axis(remap_props, This->js.lRz); break;
|
||||
case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(remap_props, This->js.rglSlider[0]); break;
|
||||
case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(remap_props, This->js.rglSlider[1]); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void remap_range(JoystickGenericImpl *This, int obj, LPCDIPROPRANGE pr)
|
||||
{
|
||||
ObjProps remap_props;
|
||||
remap_init(This, obj, &remap_props);
|
||||
|
||||
remap_props.lMin = pr->lMin;
|
||||
remap_props.lMax = pr->lMax;
|
||||
|
||||
remap_apply(This, obj, &remap_props);
|
||||
|
||||
/* Store new values */
|
||||
This->props[obj].lMin = pr->lMin;
|
||||
This->props[obj].lMax = pr->lMax;
|
||||
}
|
||||
|
||||
static void remap_deadzone(JoystickGenericImpl *This, int obj, LPCDIPROPDWORD pd)
|
||||
{
|
||||
ObjProps remap_props;
|
||||
remap_init(This, obj, &remap_props);
|
||||
|
||||
remap_props.lDeadZone = pd->dwData;
|
||||
|
||||
remap_apply(This, obj, &remap_props);
|
||||
|
||||
/* Store new value */
|
||||
This->props[obj].lDeadZone = pd->dwData;
|
||||
}
|
||||
|
||||
static void remap_saturation(JoystickGenericImpl *This, int obj, LPCDIPROPDWORD pd)
|
||||
{
|
||||
ObjProps remap_props;
|
||||
remap_init(This, obj, &remap_props);
|
||||
|
||||
remap_props.lSaturation = pd->dwData;
|
||||
|
||||
remap_apply(This, obj, &remap_props);
|
||||
|
||||
/* Store new value */
|
||||
This->props[obj].lSaturation = pd->dwData;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* SetProperty : change input device properties
|
||||
*/
|
||||
|
@ -278,7 +399,6 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
|
|||
{
|
||||
JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
DWORD i;
|
||||
ObjProps remap_props;
|
||||
|
||||
TRACE("(%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
|
||||
|
||||
|
@ -295,69 +415,15 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
|
|||
case (DWORD_PTR)DIPROP_RANGE: {
|
||||
LPCDIPROPRANGE pr = (LPCDIPROPRANGE)ph;
|
||||
if (ph->dwHow == DIPH_DEVICE) {
|
||||
|
||||
/* Many games poll the joystick immediately after setting the range
|
||||
* for calibration purposes, so the old values need to be remapped
|
||||
* to the new range before it does so */
|
||||
|
||||
TRACE("proprange(%d,%d) all\n", pr->lMin, pr->lMax);
|
||||
for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++) {
|
||||
|
||||
remap_props.lDevMin = This->props[i].lMin;
|
||||
remap_props.lDevMax = This->props[i].lMax;
|
||||
|
||||
remap_props.lDeadZone = This->props[i].lDeadZone;
|
||||
remap_props.lSaturation = This->props[i].lSaturation;
|
||||
|
||||
remap_props.lMin = pr->lMin;
|
||||
remap_props.lMax = pr->lMax;
|
||||
|
||||
switch (This->base.data_format.wine_df->rgodf[i].dwOfs) {
|
||||
case DIJOFS_X : This->js.lX = joystick_map_axis(&remap_props, This->js.lX); break;
|
||||
case DIJOFS_Y : This->js.lY = joystick_map_axis(&remap_props, This->js.lY); break;
|
||||
case DIJOFS_Z : This->js.lZ = joystick_map_axis(&remap_props, This->js.lZ); break;
|
||||
case DIJOFS_RX : This->js.lRx = joystick_map_axis(&remap_props, This->js.lRx); break;
|
||||
case DIJOFS_RY : This->js.lRy = joystick_map_axis(&remap_props, This->js.lRy); break;
|
||||
case DIJOFS_RZ : This->js.lRz = joystick_map_axis(&remap_props, This->js.lRz); break;
|
||||
case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(&remap_props, This->js.rglSlider[0]); break;
|
||||
case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(&remap_props, This->js.rglSlider[1]); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
This->props[i].lMin = pr->lMin;
|
||||
This->props[i].lMax = pr->lMax;
|
||||
}
|
||||
for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++)
|
||||
remap_range(This, i, pr);
|
||||
} else {
|
||||
int obj = find_property(&This->base.data_format, ph);
|
||||
|
||||
TRACE("proprange(%d,%d) obj=%d\n", pr->lMin, pr->lMax, obj);
|
||||
if (obj >= 0) {
|
||||
|
||||
remap_props.lDevMin = This->props[obj].lMin;
|
||||
remap_props.lDevMax = This->props[obj].lMax;
|
||||
|
||||
remap_props.lDeadZone = This->props[obj].lDeadZone;
|
||||
remap_props.lSaturation = This->props[obj].lSaturation;
|
||||
|
||||
remap_props.lMin = pr->lMin;
|
||||
remap_props.lMax = pr->lMax;
|
||||
|
||||
switch (This->base.data_format.wine_df->rgodf[obj].dwOfs) {
|
||||
case DIJOFS_X : This->js.lX = joystick_map_axis(&remap_props, This->js.lX); break;
|
||||
case DIJOFS_Y : This->js.lY = joystick_map_axis(&remap_props, This->js.lY); break;
|
||||
case DIJOFS_Z : This->js.lZ = joystick_map_axis(&remap_props, This->js.lZ); break;
|
||||
case DIJOFS_RX : This->js.lRx = joystick_map_axis(&remap_props, This->js.lRx); break;
|
||||
case DIJOFS_RY : This->js.lRy = joystick_map_axis(&remap_props, This->js.lRy); break;
|
||||
case DIJOFS_RZ : This->js.lRz = joystick_map_axis(&remap_props, This->js.lRz); break;
|
||||
case DIJOFS_SLIDER(0): This->js.rglSlider[0] = joystick_map_axis(&remap_props, This->js.rglSlider[0]); break;
|
||||
case DIJOFS_SLIDER(1): This->js.rglSlider[1] = joystick_map_axis(&remap_props, This->js.rglSlider[1]); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
This->props[obj].lMin = pr->lMin;
|
||||
This->props[obj].lMax = pr->lMax;
|
||||
return DI_OK;
|
||||
}
|
||||
if (obj >= 0)
|
||||
remap_range(This, obj, pr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -366,15 +432,13 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
|
|||
if (ph->dwHow == DIPH_DEVICE) {
|
||||
TRACE("deadzone(%d) all\n", pd->dwData);
|
||||
for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++)
|
||||
This->props[i].lDeadZone = pd->dwData;
|
||||
remap_deadzone(This, i, pd);
|
||||
} else {
|
||||
int obj = find_property(&This->base.data_format, ph);
|
||||
|
||||
TRACE("deadzone(%d) obj=%d\n", pd->dwData, obj);
|
||||
if (obj >= 0) {
|
||||
This->props[obj].lDeadZone = pd->dwData;
|
||||
return DI_OK;
|
||||
}
|
||||
if (obj >= 0)
|
||||
remap_deadzone(This, obj, pd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -383,18 +447,21 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
|
|||
if (ph->dwHow == DIPH_DEVICE) {
|
||||
TRACE("saturation(%d) all\n", pd->dwData);
|
||||
for (i = 0; i < This->base.data_format.wine_df->dwNumObjs; i++)
|
||||
This->props[i].lSaturation = pd->dwData;
|
||||
remap_saturation(This, i, pd);
|
||||
} else {
|
||||
int obj = find_property(&This->base.data_format, ph);
|
||||
|
||||
TRACE("saturation(%d) obj=%d\n", pd->dwData, obj);
|
||||
if (obj >= 0) {
|
||||
This->props[obj].lSaturation = pd->dwData;
|
||||
return DI_OK;
|
||||
}
|
||||
if (obj >= 0)
|
||||
remap_saturation(This, obj, pd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (DWORD_PTR)DIPROP_CALIBRATIONMODE: {
|
||||
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
|
||||
FIXME("DIPROP_CALIBRATIONMODE(%d)\n", pd->dwData);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return IDirectInputDevice2WImpl_SetProperty(iface, rguid, ph);
|
||||
}
|
||||
|
@ -461,7 +528,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface,
|
|||
JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
int size;
|
||||
|
||||
TRACE("%p->(%p)\n",iface,lpDIDevCaps);
|
||||
TRACE("%p->(%p)\n",This,lpDIDevCaps);
|
||||
|
||||
if (lpDIDevCaps == NULL) {
|
||||
WARN("invalid pointer\n");
|
||||
|
@ -544,7 +611,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
|
|||
{
|
||||
JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
||||
TRACE("(%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph);
|
||||
TRACE("(%p,%s,%p)\n", This, debugstr_guid(rguid), pdiph);
|
||||
|
||||
if (TRACE_ON(dinput))
|
||||
_dump_DIPROPHEADER(pdiph);
|
||||
|
@ -627,7 +694,7 @@ HRESULT WINAPI JoystickAGenericImpl_GetDeviceInfo(
|
|||
DIPROPDWORD pd;
|
||||
DWORD index = 0;
|
||||
|
||||
TRACE("(%p,%p)\n", iface, pdidi);
|
||||
TRACE("(%p,%p)\n", This, pdidi);
|
||||
|
||||
if (pdidi == NULL) {
|
||||
WARN("invalid pointer\n");
|
||||
|
@ -654,7 +721,7 @@ HRESULT WINAPI JoystickAGenericImpl_GetDeviceInfo(
|
|||
/* we only support traditional joysticks for now */
|
||||
pdidi->dwDevType = This->devcaps.dwDevType;
|
||||
snprintf(pdidi->tszInstanceName, MAX_PATH, "Joystick %d", index);
|
||||
strcpy(pdidi->tszProductName, This->name);
|
||||
lstrcpynA(pdidi->tszProductName, This->name, MAX_PATH);
|
||||
if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3A)) {
|
||||
pdidi->guidFFDriver = GUID_NULL;
|
||||
pdidi->wUsagePage = 0;
|
||||
|
@ -771,8 +838,31 @@ HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
|
|||
JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
unsigned int i, j;
|
||||
BOOL has_actions = FALSE;
|
||||
WCHAR *username;
|
||||
DWORD size;
|
||||
BOOL load_success = FALSE;
|
||||
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
|
||||
/* Unless asked the contrary by these flags, try to load a previous mapping */
|
||||
if (!(dwFlags & DIDBAM_HWDEFAULTS))
|
||||
{
|
||||
if (!lpszUserName)
|
||||
GetUserNameW(NULL, &size);
|
||||
else
|
||||
size = lstrlenW(lpszUserName) + 1;
|
||||
|
||||
username = heap_alloc(size * sizeof(WCHAR));
|
||||
if (!lpszUserName)
|
||||
GetUserNameW(username, &size);
|
||||
else
|
||||
lstrcpynW(username, lpszUserName, size);
|
||||
|
||||
load_success = load_mapping_settings(&This->base, lpdiaf, username);
|
||||
heap_free(username);
|
||||
}
|
||||
|
||||
if (load_success) return DI_OK;
|
||||
|
||||
for (i=0; i < lpdiaf->dwNumActions; i++)
|
||||
{
|
||||
|
@ -850,7 +940,7 @@ HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
|
|||
{
|
||||
JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
|
||||
return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, This->base.data_format.wine_df);
|
||||
}
|
||||
|
@ -878,6 +968,8 @@ HRESULT WINAPI JoystickAGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
|
|||
|
||||
hr = JoystickWGenericImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
|
||||
|
||||
lpdiaf->dwCRC = diafW.dwCRC;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
|
||||
HeapFree(GetProcessHeap(), 0, lpszUserNameW);
|
||||
|
||||
|
@ -950,6 +1042,7 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
|
|||
int tokens = 0;
|
||||
int axis = 0;
|
||||
int pov = 0;
|
||||
int button;
|
||||
|
||||
get_app_key(&hkey, &appkey);
|
||||
|
||||
|
@ -961,6 +1054,34 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
|
|||
TRACE("setting default deadzone to: \"%s\" %d\n", buffer, This->deadzone);
|
||||
}
|
||||
|
||||
for (button = 0; button < MAX_MAP_BUTTONS; button++)
|
||||
This->button_map[button] = button;
|
||||
|
||||
if (!get_config_key(hkey, appkey, "ButtonMap", buffer, sizeof(buffer)))
|
||||
{
|
||||
static const char *delim = ",";
|
||||
int button = 0;
|
||||
char *token;
|
||||
|
||||
TRACE("ButtonMap = \"%s\"\n", buffer);
|
||||
for (token = strtok(buffer, delim);
|
||||
token != NULL && button < MAX_MAP_BUTTONS;
|
||||
token = strtok(NULL, delim), button++)
|
||||
{
|
||||
char *s;
|
||||
int value = strtol(token, &s, 10);
|
||||
if (value < 0 || *s != '\0')
|
||||
{
|
||||
ERR("invalid button number: \"%s\"", token);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("mapping physical button %d to DInput button %d", value, button);
|
||||
This->button_map[value] = button;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
This->axis_map = HeapAlloc(GetProcessHeap(), 0, This->device_axis_count * sizeof(int));
|
||||
if (!This->axis_map) return DIERR_OUTOFMEMORY;
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "devguid.h"
|
||||
#include "dinput.h"
|
||||
|
||||
#include "dinput_private.h"
|
||||
|
@ -84,6 +85,8 @@ struct JoyDev
|
|||
int *dev_axes_map;
|
||||
|
||||
WORD vendor_id, product_id, bus_type;
|
||||
|
||||
BOOL is_joystick;
|
||||
};
|
||||
|
||||
typedef struct JoystickImpl JoystickImpl;
|
||||
|
@ -123,19 +126,6 @@ static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903
|
|||
{0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
|
||||
};
|
||||
|
||||
/*
|
||||
* Construct the GUID in the same way of Windows doing this.
|
||||
* Data1 is concatenation of productid and vendorid.
|
||||
* Data2 and Data3 are NULL.
|
||||
* Data4 seems to be a constant.
|
||||
*/
|
||||
static const GUID DInput_Wine_Joystick_Constant_Part_GUID = {
|
||||
0x000000000,
|
||||
0x0000,
|
||||
0x0000,
|
||||
{0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44}
|
||||
};
|
||||
|
||||
#define MAX_JOYSTICKS 64
|
||||
static INT joystick_devices_count = -1;
|
||||
static struct JoyDev *joystick_devices;
|
||||
|
@ -177,6 +167,8 @@ static INT find_joystick_devices(void)
|
|||
int fd;
|
||||
struct JoyDev joydev, *new_joydevs;
|
||||
BYTE axes_map[ABS_MAX + 1];
|
||||
SHORT btn_map[KEY_MAX - BTN_MISC + 1];
|
||||
BOOL is_stylus = FALSE;
|
||||
|
||||
snprintf(joydev.device, sizeof(joydev.device), "%s%d", JOYDEV_NEW, i);
|
||||
if ((fd = open(joydev.device, O_RDONLY)) == -1)
|
||||
|
@ -220,6 +212,52 @@ static INT find_joystick_devices(void)
|
|||
joydev.button_count = 2;
|
||||
#endif
|
||||
|
||||
joydev.is_joystick = FALSE;
|
||||
if (ioctl(fd, JSIOCGBTNMAP, btn_map) < 0)
|
||||
{
|
||||
WARN("ioctl(%s,JSIOCGBTNMAP) failed: %s\n", joydev.device, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
INT j;
|
||||
/* in lieu of properly reporting HID usage, detect presence of
|
||||
* "joystick buttons" and report those devices as joysticks instead of
|
||||
* gamepads */
|
||||
for (j = 0; !joydev.is_joystick && j < joydev.button_count; j++)
|
||||
{
|
||||
switch (btn_map[j])
|
||||
{
|
||||
case BTN_TRIGGER:
|
||||
case BTN_THUMB:
|
||||
case BTN_THUMB2:
|
||||
case BTN_TOP:
|
||||
case BTN_TOP2:
|
||||
case BTN_PINKIE:
|
||||
case BTN_BASE:
|
||||
case BTN_BASE2:
|
||||
case BTN_BASE3:
|
||||
case BTN_BASE4:
|
||||
case BTN_BASE5:
|
||||
case BTN_BASE6:
|
||||
case BTN_DEAD:
|
||||
joydev.is_joystick = TRUE;
|
||||
break;
|
||||
case BTN_STYLUS:
|
||||
is_stylus = TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(is_stylus)
|
||||
{
|
||||
TRACE("Stylus detected. Skipping\n");
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ioctl(fd, JSIOCGAXMAP, axes_map) < 0)
|
||||
{
|
||||
WARN("ioctl(%s,JSIOCGAXMAP) failed: %s\n", joydev.device, strerror(errno));
|
||||
|
@ -239,6 +277,14 @@ static INT find_joystick_devices(void)
|
|||
joydev.dev_axes_map[j] = j;
|
||||
found_axes++;
|
||||
}
|
||||
else if (axes_map[j] <= 10)
|
||||
{
|
||||
/* Axes 8 through 10 are Wheel, Gas and Brake,
|
||||
* remap to 0, 1 and 2
|
||||
*/
|
||||
joydev.dev_axes_map[j] = axes_map[j] - 8;
|
||||
found_axes++;
|
||||
}
|
||||
else if (axes_map[j] == 16 ||
|
||||
axes_map[j] == 17)
|
||||
{
|
||||
|
@ -279,7 +325,7 @@ static INT find_joystick_devices(void)
|
|||
else
|
||||
{
|
||||
/* Concatenate product_id with vendor_id to mimic Windows behaviour */
|
||||
joydev.guid_product = DInput_Wine_Joystick_Constant_Part_GUID;
|
||||
joydev.guid_product = DInput_PIDVID_Product_GUID;
|
||||
joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id);
|
||||
}
|
||||
|
||||
|
@ -314,11 +360,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
|
|||
lpddi->guidInstance = DInput_Wine_Joystick_GUID;
|
||||
lpddi->guidInstance.Data3 = id;
|
||||
lpddi->guidProduct = joystick_devices[id].guid_product;
|
||||
/* we only support traditional joysticks for now */
|
||||
if (version >= 0x0800)
|
||||
lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
||||
else
|
||||
lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
||||
lpddi->dwDevType = get_device_type(version, joystick_devices[id].is_joystick);
|
||||
|
||||
/* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */
|
||||
if (joystick_devices[id].bus_type == BUS_USB &&
|
||||
|
@ -326,7 +368,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
|
|||
{
|
||||
lpddi->dwDevType |= DIDEVTYPE_HID;
|
||||
lpddi->wUsagePage = 0x01; /* Desktop */
|
||||
if (lpddi->dwDevType == DI8DEVTYPE_JOYSTICK || lpddi->dwDevType == DIDEVTYPE_JOYSTICK)
|
||||
if (joystick_devices[id].is_joystick)
|
||||
lpddi->wUsage = 0x04; /* Joystick */
|
||||
else
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
|
@ -372,7 +414,7 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
}
|
||||
|
||||
if ((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
|
||||
/* check whether we have a joystick */
|
||||
if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1)
|
||||
|
@ -401,7 +443,7 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
}
|
||||
|
||||
if ((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
|
||||
/* check whether we have a joystick */
|
||||
if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1)
|
||||
|
@ -673,7 +715,7 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface
|
|||
{
|
||||
JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
||||
TRACE("(this=%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph);
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
|
||||
_dump_DIPROPHEADER(pdiph);
|
||||
|
||||
if (!IS_DIPROP(rguid)) return DI_OK;
|
||||
|
@ -699,6 +741,29 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface
|
|||
break;
|
||||
}
|
||||
|
||||
case (DWORD_PTR) DIPROP_GUIDANDPATH:
|
||||
{
|
||||
static const WCHAR formatW[] = {'\\','\\','?','\\','h','i','d','#','v','i','d','_','%','0','4','x','&',
|
||||
'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0};
|
||||
static const WCHAR miW[] = {'m','i',0};
|
||||
static const WCHAR igW[] = {'i','g',0};
|
||||
|
||||
BOOL is_gamepad;
|
||||
LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
|
||||
WORD vid = This->joydev->vendor_id;
|
||||
WORD pid = This->joydev->product_id;
|
||||
|
||||
if (!pid || !vid)
|
||||
return DIERR_UNSUPPORTED;
|
||||
|
||||
is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid);
|
||||
pd->guidClass = GUID_DEVCLASS_HIDCLASS;
|
||||
sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid));
|
||||
|
||||
TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
|
||||
}
|
||||
|
@ -807,10 +872,13 @@ static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
|
|||
jse.type,jse.number,jse.value);
|
||||
if (jse.type & JS_EVENT_BUTTON)
|
||||
{
|
||||
int button;
|
||||
if (jse.number >= This->generic.devcaps.dwButtons) return;
|
||||
|
||||
inst_id = DIDFT_MAKEINSTANCE(jse.number) | DIDFT_PSHBUTTON;
|
||||
This->generic.js.rgbButtons[jse.number] = value = jse.value ? 0x80 : 0x00;
|
||||
button = This->generic.button_map[jse.number];
|
||||
|
||||
inst_id = DIDFT_MAKEINSTANCE(button) | DIDFT_PSHBUTTON;
|
||||
This->generic.js.rgbButtons[button] = value = jse.value ? 0x80 : 0x00;
|
||||
}
|
||||
else if (jse.type & JS_EVENT_AXIS)
|
||||
{
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "winreg.h"
|
||||
#include "devguid.h"
|
||||
#include "dinput.h"
|
||||
|
||||
#include "dinput_private.h"
|
||||
|
@ -83,6 +84,13 @@ struct wine_input_absinfo {
|
|||
LONG flat;
|
||||
};
|
||||
|
||||
enum wine_joystick_linuxinput_fd_state {
|
||||
WINE_FD_STATE_CLOSED = 0, /* No device has been opened yet */
|
||||
WINE_FD_STATE_OK, /* File descriptor is open and ready for reading */
|
||||
WINE_FD_STATE_DISCONNECTED, /* Read error occurred; might be able to reopen later */
|
||||
WINE_FD_STATE_INVALID, /* Device is no longer available at original pathname */
|
||||
};
|
||||
|
||||
/* implemented in effect_linuxinput.c */
|
||||
HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_list_entry, LPDIRECTINPUTEFFECT* peff);
|
||||
HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info);
|
||||
|
@ -100,7 +108,7 @@ struct JoyDev {
|
|||
GUID guid;
|
||||
GUID guid_product;
|
||||
|
||||
BOOL has_ff;
|
||||
BOOL has_ff, is_joystick;
|
||||
int num_effects;
|
||||
|
||||
/* data returned by EVIOCGBIT for caps, EV_ABS, EV_KEY, and EV_FF */
|
||||
|
@ -122,6 +130,7 @@ struct JoystickImpl
|
|||
|
||||
/* joystick private */
|
||||
int joyfd;
|
||||
enum wine_joystick_linuxinput_fd_state joyfd_state;
|
||||
|
||||
int dev_axes_to_di[ABS_MAX];
|
||||
POINTL povs[4];
|
||||
|
@ -164,19 +173,6 @@ static const GUID DInput_Wine_Joystick_Base_GUID = { /* 9e573eda-7734-11d2-8d4a-
|
|||
{0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7}
|
||||
};
|
||||
|
||||
/*
|
||||
* Construct the GUID in the same way of Windows doing this.
|
||||
* Data1 is concatenation of productid and vendorid.
|
||||
* Data2 and Data3 are NULL.
|
||||
* Data4 seems to be a constant.
|
||||
*/
|
||||
static const GUID DInput_Wine_Joystick_Constant_Part_GUID = {
|
||||
0x000000000,
|
||||
0x0000,
|
||||
0x0000,
|
||||
{0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44}
|
||||
};
|
||||
|
||||
#define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
|
||||
|
||||
#define MAX_JOYDEV 64
|
||||
|
@ -211,10 +207,7 @@ static void find_joydevs(void)
|
|||
}
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
WARN("Failed to open \"%s\": %d %s\n", buf, errno, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ioctl(fd, EVIOCGBIT(0, sizeof(joydev.evbits)), joydev.evbits) == -1)
|
||||
{
|
||||
|
@ -237,15 +230,41 @@ static void find_joydevs(void)
|
|||
|
||||
/* A true joystick has at least axis X and Y, and at least 1
|
||||
* button. copied from linux/drivers/input/joydev.c */
|
||||
if (!test_bit(joydev.absbits, ABS_X) || !test_bit(joydev.absbits, ABS_Y) ||
|
||||
if (((!test_bit(joydev.absbits, ABS_X) || !test_bit(joydev.absbits, ABS_Y)) &&
|
||||
!test_bit(joydev.absbits, ABS_WHEEL) &&
|
||||
!test_bit(joydev.absbits, ABS_GAS) &&
|
||||
!test_bit(joydev.absbits, ABS_BRAKE)) ||
|
||||
!(test_bit(joydev.keybits, BTN_TRIGGER) ||
|
||||
test_bit(joydev.keybits, BTN_A) ||
|
||||
test_bit(joydev.keybits, BTN_1)))
|
||||
test_bit(joydev.keybits, BTN_1) ||
|
||||
test_bit(joydev.keybits, BTN_BASE) ||
|
||||
test_bit(joydev.keybits, BTN_GEAR_UP) ||
|
||||
test_bit(joydev.keybits, BTN_GEAR_DOWN)))
|
||||
{
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* in lieu of properly reporting HID usage, detect presence of
|
||||
* "joystick buttons" and report those devices as joysticks instead of
|
||||
* gamepads */
|
||||
joydev.is_joystick =
|
||||
test_bit(joydev.keybits, BTN_TRIGGER) ||
|
||||
test_bit(joydev.keybits, BTN_THUMB) ||
|
||||
test_bit(joydev.keybits, BTN_THUMB2) ||
|
||||
test_bit(joydev.keybits, BTN_TOP) ||
|
||||
test_bit(joydev.keybits, BTN_TOP2) ||
|
||||
test_bit(joydev.keybits, BTN_PINKIE) ||
|
||||
test_bit(joydev.keybits, BTN_BASE) ||
|
||||
test_bit(joydev.keybits, BTN_BASE2) ||
|
||||
test_bit(joydev.keybits, BTN_BASE3) ||
|
||||
test_bit(joydev.keybits, BTN_BASE4) ||
|
||||
test_bit(joydev.keybits, BTN_BASE5) ||
|
||||
test_bit(joydev.keybits, BTN_BASE6) ||
|
||||
test_bit(joydev.keybits, BTN_GEAR_UP) ||
|
||||
test_bit(joydev.keybits, BTN_GEAR_DOWN) ||
|
||||
test_bit(joydev.keybits, BTN_DEAD);
|
||||
|
||||
if (!(joydev.device = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + 1)))
|
||||
{
|
||||
close(fd);
|
||||
|
@ -320,7 +339,7 @@ static void find_joydevs(void)
|
|||
joydev.bus_type = device_id.bustype;
|
||||
|
||||
/* Concatenate product_id with vendor_id to mimic Windows behaviour */
|
||||
joydev.guid_product = DInput_Wine_Joystick_Constant_Part_GUID;
|
||||
joydev.guid_product = DInput_PIDVID_Product_GUID;
|
||||
joydev.guid_product.Data1 = MAKELONG(joydev.vendor_id, joydev.product_id);
|
||||
}
|
||||
|
||||
|
@ -353,11 +372,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
|
|||
lpddi->guidInstance = joydevs[id].guid;
|
||||
lpddi->guidProduct = joydevs[id].guid_product;
|
||||
lpddi->guidFFDriver = GUID_NULL;
|
||||
|
||||
if (version >= 0x0800)
|
||||
lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
||||
else
|
||||
lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
||||
lpddi->dwDevType = get_device_type(version, joydevs[id].is_joystick);
|
||||
|
||||
/* Assume the joystick as HID if it is attached to USB bus and has a valid VID/PID */
|
||||
if (joydevs[id].bus_type == BUS_USB &&
|
||||
|
@ -365,7 +380,7 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
|
|||
{
|
||||
lpddi->dwDevType |= DIDEVTYPE_HID;
|
||||
lpddi->wUsagePage = 0x01; /* Desktop */
|
||||
if (lpddi->dwDevType == DI8DEVTYPE_JOYSTICK || lpddi->dwDevType == DIDEVTYPE_JOYSTICK)
|
||||
if (joydevs[id].is_joystick)
|
||||
lpddi->wUsage = 0x04; /* Joystick */
|
||||
else
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
|
@ -391,8 +406,8 @@ static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD ver
|
|||
lpddi->guidInstance = lpddiW.guidInstance;
|
||||
lpddi->guidProduct = lpddiW.guidProduct;
|
||||
lpddi->dwDevType = lpddiW.dwDevType;
|
||||
strcpy(lpddi->tszInstanceName, joydevs[id].name);
|
||||
strcpy(lpddi->tszProductName, joydevs[id].name);
|
||||
lstrcpynA(lpddi->tszInstanceName, joydevs[id].name, MAX_PATH);
|
||||
lstrcpynA(lpddi->tszProductName, joydevs[id].name, MAX_PATH);
|
||||
lpddi->guidFFDriver = lpddiW.guidFFDriver;
|
||||
lpddi->wUsagePage = lpddiW.wUsagePage;
|
||||
lpddi->wUsage = lpddiW.wUsage;
|
||||
|
@ -407,7 +422,7 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
}
|
||||
|
||||
if (!((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))))
|
||||
return S_FALSE;
|
||||
|
||||
|
@ -432,7 +447,7 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
}
|
||||
|
||||
if (!((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))))
|
||||
return S_FALSE;
|
||||
|
||||
|
@ -466,6 +481,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
|
|||
newDevice->generic.base.dinput = dinput;
|
||||
newDevice->generic.joy_polldev = joy_polldev;
|
||||
newDevice->joyfd = -1;
|
||||
newDevice->joyfd_state = WINE_FD_STATE_CLOSED;
|
||||
newDevice->joydev = &joydevs[index];
|
||||
newDevice->generic.name = newDevice->joydev->name;
|
||||
list_init(&newDevice->ff_effects);
|
||||
|
@ -483,14 +499,18 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
|
|||
/* Count number of available axes - supported Axis & POVs */
|
||||
for (i = 0; i < ABS_MAX; i++)
|
||||
{
|
||||
if (i < WINE_JOYSTICK_MAX_AXES &&
|
||||
if (idx < WINE_JOYSTICK_MAX_AXES &&
|
||||
i < ABS_HAT0X &&
|
||||
test_bit(newDevice->joydev->absbits, i))
|
||||
{
|
||||
newDevice->generic.device_axis_count++;
|
||||
newDevice->dev_axes_to_di[i] = idx;
|
||||
newDevice->generic.props[idx].lDevMin = newDevice->joydev->axes[i].minimum;
|
||||
newDevice->generic.props[idx].lDevMax = newDevice->joydev->axes[i].maximum;
|
||||
default_axis_map[idx] = i;
|
||||
if (i >= 8 && i <= 10) /* If it's a wheel axis... */
|
||||
default_axis_map[idx] = i - 8; /* ... remap to X/Y/Z */
|
||||
else
|
||||
default_axis_map[idx] = i;
|
||||
idx++;
|
||||
}
|
||||
else
|
||||
|
@ -669,6 +689,44 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF
|
|||
return DIERR_DEVICENOTREG;
|
||||
}
|
||||
|
||||
static int joydev_open_evdev(JoystickImpl *This)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if ((fd = open(This->joydev->device, O_RDWR)) == -1)
|
||||
{
|
||||
if ((fd = open(This->joydev->device, O_RDONLY)) == -1)
|
||||
{
|
||||
/* Couldn't open the device at all */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Couldn't open in r/w but opened in read-only. */
|
||||
WARN("Could not open %s in read-write mode. Force feedback will be disabled.\n", This->joydev->device);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct input_event event;
|
||||
|
||||
event.type = EV_FF;
|
||||
event.code = FF_GAIN;
|
||||
event.value = This->ff_gain;
|
||||
if (write(fd, &event, sizeof(event)) == -1)
|
||||
ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno));
|
||||
if (!This->ff_autocenter)
|
||||
{
|
||||
/* Disable autocenter. */
|
||||
event.code = FF_AUTOCENTER;
|
||||
event.value = 0;
|
||||
if (write(fd, &event, sizeof(event)) == -1)
|
||||
ERR("Failed disabling autocenter: %d %s\n", errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
const struct dinput_device joystick_linuxinput_device = {
|
||||
"Wine Linux-input joystick driver",
|
||||
|
@ -693,40 +751,14 @@ static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
|
|||
return res;
|
||||
}
|
||||
|
||||
if ((This->joyfd = open(This->joydev->device, O_RDWR)) == -1)
|
||||
if ((This->joyfd = joydev_open_evdev(This)) == -1)
|
||||
{
|
||||
if ((This->joyfd = open(This->joydev->device, O_RDONLY)) == -1)
|
||||
{
|
||||
/* Couldn't open the device at all */
|
||||
ERR("Failed to open device %s: %d %s\n", This->joydev->device, errno, strerror(errno));
|
||||
IDirectInputDevice2WImpl_Unacquire(iface);
|
||||
return DIERR_NOTFOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Couldn't open in r/w but opened in read-only. */
|
||||
WARN("Could not open %s in read-write mode. Force feedback will be disabled.\n", This->joydev->device);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct input_event event;
|
||||
|
||||
event.type = EV_FF;
|
||||
event.code = FF_GAIN;
|
||||
event.value = This->ff_gain;
|
||||
if (write(This->joyfd, &event, sizeof(event)) == -1)
|
||||
ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno));
|
||||
if (!This->ff_autocenter)
|
||||
{
|
||||
/* Disable autocenter. */
|
||||
event.code = FF_AUTOCENTER;
|
||||
event.value = 0;
|
||||
if (write(This->joyfd, &event, sizeof(event)) == -1)
|
||||
ERR("Failed disabling autocenter: %d %s\n", errno, strerror(errno));
|
||||
}
|
||||
ERR("Failed to open device %s: %d %s\n", This->joydev->device, errno, strerror(errno));
|
||||
IDirectInputDevice2WImpl_Unacquire(iface);
|
||||
return DIERR_NOTFOUND;
|
||||
}
|
||||
|
||||
This->joyfd_state = WINE_FD_STATE_OK;
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
|
@ -764,6 +796,7 @@ static HRESULT WINAPI JoystickWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
|
|||
|
||||
close(This->joyfd);
|
||||
This->joyfd = -1;
|
||||
This->joyfd_state = WINE_FD_STATE_CLOSED;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
@ -808,23 +841,79 @@ static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
|
|||
struct input_event ie;
|
||||
JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
|
||||
|
||||
if (This->joyfd==-1)
|
||||
return;
|
||||
if (This->joyfd == -1)
|
||||
{
|
||||
int fd;
|
||||
char namebuf[MAX_PATH + 8]; /* 8 == strlen(EVDEVDRIVER) */
|
||||
|
||||
if (This->joyfd_state != WINE_FD_STATE_DISCONNECTED)
|
||||
return;
|
||||
/* Try to reconnect to the device. */
|
||||
fd = joydev_open_evdev(This);
|
||||
if (fd == -1)
|
||||
return;
|
||||
namebuf[sizeof(namebuf) - strlen(EVDEVDRIVER) - 1] = 0;
|
||||
if (ioctl(fd, EVIOCGNAME(sizeof(namebuf) - strlen(EVDEVDRIVER) - 1), namebuf) == -1)
|
||||
{
|
||||
/* Couldn't get the name; assume it's a different device. */
|
||||
ERR("EVIOCGNAME(%s) failed: %d %s", This->joydev->device, errno, strerror(errno));
|
||||
This->joyfd_state = WINE_FD_STATE_INVALID;
|
||||
return;
|
||||
}
|
||||
strcat(namebuf, EVDEVDRIVER); /* Guaranteed to be safe. */
|
||||
if (strcmp(namebuf, This->joydev->name) != 0)
|
||||
{
|
||||
ERR("Device %s changed from \"%s\" to \"%s\"! Can't reconnect.\n", This->joydev->device, This->joydev->name, namebuf);
|
||||
This->joyfd_state = WINE_FD_STATE_INVALID;
|
||||
return;
|
||||
}
|
||||
if (InterlockedCompareExchange(&This->joyfd, fd, -1) == -1)
|
||||
{
|
||||
This->joyfd_state = WINE_FD_STATE_OK;
|
||||
TRACE("Reconnected to \"%s\" on %s", This->joydev->name, This->joydev->device);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Somebody beat us to it! Throw away our fd and use theirs. */
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
LONG value = 0;
|
||||
int inst_id = -1;
|
||||
int result;
|
||||
|
||||
plfd.fd = This->joyfd;
|
||||
plfd.events = POLLIN;
|
||||
|
||||
if (poll(&plfd,1,0) != 1)
|
||||
return;
|
||||
result = poll(&plfd,1,0);
|
||||
if (result != 1)
|
||||
{
|
||||
if (result == -1)
|
||||
{
|
||||
ERR("poll failed: %d %s\n", errno, strerror(errno));
|
||||
close(This->joyfd);
|
||||
This->joyfd = -1;
|
||||
This->joyfd_state = WINE_FD_STATE_DISCONNECTED;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* we have one event, so we can read */
|
||||
if (sizeof(ie)!=read(This->joyfd,&ie,sizeof(ie)))
|
||||
return;
|
||||
result = read(This->joyfd,&ie,sizeof(ie));
|
||||
if (result != sizeof(ie))
|
||||
{
|
||||
if (result == -1)
|
||||
{
|
||||
ERR("read failed: %d %s\n", errno, strerror(errno));
|
||||
close(This->joyfd);
|
||||
This->joyfd = -1;
|
||||
This->joyfd_state = WINE_FD_STATE_DISCONNECTED;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE("input_event: type %d, code %d, value %d\n",ie.type,ie.code,ie.value);
|
||||
switch (ie.type) {
|
||||
|
@ -836,6 +925,8 @@ static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
|
|||
if (btn & 0x80)
|
||||
{
|
||||
btn &= 0x7F;
|
||||
btn = This->generic.button_map[btn];
|
||||
|
||||
inst_id = DIDFT_MAKEINSTANCE(btn) | DIDFT_PSHBUTTON;
|
||||
This->generic.js.rgbButtons[btn] = value = ie.value ? 0x80 : 0x00;
|
||||
}
|
||||
|
@ -923,11 +1014,6 @@ static HRESULT WINAPI JoystickWImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
|
|||
|
||||
if (IS_DIPROP(rguid)) {
|
||||
switch (LOWORD(rguid)) {
|
||||
case (DWORD_PTR)DIPROP_CALIBRATIONMODE: {
|
||||
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
|
||||
FIXME("DIPROP_CALIBRATIONMODE(%d)\n", pd->dwData);
|
||||
break;
|
||||
}
|
||||
case (DWORD_PTR)DIPROP_AUTOCENTER: {
|
||||
LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
|
||||
|
||||
|
@ -973,7 +1059,7 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
|
|||
{
|
||||
JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
||||
TRACE("(this=%p,%s,%p)\n", iface, debugstr_guid(rguid), pdiph);
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
|
||||
_dump_DIPROPHEADER(pdiph);
|
||||
|
||||
if (!IS_DIPROP(rguid)) return DI_OK;
|
||||
|
@ -1016,6 +1102,29 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
|
|||
break;
|
||||
}
|
||||
|
||||
case (DWORD_PTR) DIPROP_GUIDANDPATH:
|
||||
{
|
||||
static const WCHAR formatW[] = {'\\','\\','?','\\','h','i','d','#','v','i','d','_','%','0','4','x','&',
|
||||
'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0};
|
||||
static const WCHAR miW[] = {'m','i',0};
|
||||
static const WCHAR igW[] = {'i','g',0};
|
||||
|
||||
BOOL is_gamepad;
|
||||
LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
|
||||
WORD vid = This->joydev->vendor_id;
|
||||
WORD pid = This->joydev->product_id;
|
||||
|
||||
if (!pid || !vid)
|
||||
return DIERR_UNSUPPORTED;
|
||||
|
||||
is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid);
|
||||
pd->guidClass = GUID_DEVCLASS_HIDCLASS;
|
||||
sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid));
|
||||
|
||||
TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "winreg.h"
|
||||
#include "devguid.h"
|
||||
#include "dinput.h"
|
||||
|
||||
#include "dinput_private.h"
|
||||
|
@ -124,6 +125,11 @@ static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W
|
|||
JoystickGenericImpl, base), JoystickImpl, generic);
|
||||
}
|
||||
|
||||
static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
|
||||
{
|
||||
return &This->generic.base.IDirectInputDevice8W_iface;
|
||||
}
|
||||
|
||||
typedef struct _EffectImpl {
|
||||
IDirectInputEffect IDirectInputEffect_iface;
|
||||
LONG ref;
|
||||
|
@ -801,7 +807,11 @@ static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
|
|||
TRACE("kIOHIDElementTypeInput_Button\n");
|
||||
if(button_idx < 128)
|
||||
{
|
||||
IOHIDDeviceGetValue(hid_device, element, &valueRef);
|
||||
valueRef = NULL;
|
||||
if (IOHIDDeviceGetValue(hid_device, element, &valueRef) != kIOReturnSuccess)
|
||||
return;
|
||||
if (valueRef == NULL)
|
||||
return;
|
||||
val = IOHIDValueGetIntegerValue(valueRef);
|
||||
newVal = val ? 0x80 : 0x0;
|
||||
oldVal = device->generic.js.rgbButtons[button_idx];
|
||||
|
@ -809,6 +819,8 @@ static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
|
|||
TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef), val, oldVal, newVal);
|
||||
if (oldVal != newVal)
|
||||
{
|
||||
button_idx = device->generic.button_map[button_idx];
|
||||
|
||||
inst_id = DIDFT_MAKEINSTANCE(button_idx) | DIDFT_PSHBUTTON;
|
||||
queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
|
||||
}
|
||||
|
@ -823,7 +835,11 @@ static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
|
|||
case kHIDUsage_GD_Hatswitch:
|
||||
{
|
||||
TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Hatswitch\n");
|
||||
IOHIDDeviceGetValue(hid_device, element, &valueRef);
|
||||
valueRef = NULL;
|
||||
if (IOHIDDeviceGetValue(hid_device, element, &valueRef) != kIOReturnSuccess)
|
||||
return;
|
||||
if (valueRef == NULL)
|
||||
return;
|
||||
val = IOHIDValueGetIntegerValue(valueRef);
|
||||
oldVal = device->generic.js.rgdwPOV[pov_idx];
|
||||
if (val >= 8)
|
||||
|
@ -850,7 +866,11 @@ static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
|
|||
{
|
||||
int wine_obj = -1;
|
||||
|
||||
IOHIDDeviceGetValue(hid_device, element, &valueRef);
|
||||
valueRef = NULL;
|
||||
if (IOHIDDeviceGetValue(hid_device, element, &valueRef) != kIOReturnSuccess)
|
||||
return;
|
||||
if (valueRef == NULL)
|
||||
return;
|
||||
val = IOHIDValueGetIntegerValue(valueRef);
|
||||
newVal = joystick_map_axis(&device->generic.props[idx], val);
|
||||
switch (usage)
|
||||
|
@ -945,6 +965,7 @@ static DWORD make_vid_pid(IOHIDDeviceRef device)
|
|||
static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
|
||||
{
|
||||
IOHIDDeviceRef device;
|
||||
BOOL is_joystick;
|
||||
|
||||
TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType, dwFlags, version, id);
|
||||
|
||||
|
@ -953,7 +974,7 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
device = get_device_ref(id);
|
||||
|
||||
if ((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800)))
|
||||
{
|
||||
if (dwFlags & DIEDFL_FORCEFEEDBACK) {
|
||||
|
@ -962,16 +983,19 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
if(get_ff(device, NULL) != S_OK)
|
||||
return S_FALSE;
|
||||
}
|
||||
is_joystick = get_device_property_long(device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick;
|
||||
/* Return joystick */
|
||||
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
|
||||
lpddi->guidInstance.Data3 = id;
|
||||
lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID;
|
||||
lpddi->guidProduct = DInput_PIDVID_Product_GUID;
|
||||
lpddi->guidProduct.Data1 = make_vid_pid(device);
|
||||
/* we only support traditional joysticks for now */
|
||||
if (version >= 0x0800)
|
||||
lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
||||
lpddi->dwDevType = get_device_type(version, is_joystick);
|
||||
lpddi->dwDevType |= DIDEVTYPE_HID;
|
||||
lpddi->wUsagePage = 0x01; /* Desktop */
|
||||
if (is_joystick)
|
||||
lpddi->wUsage = 0x04; /* Joystick */
|
||||
else
|
||||
lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
sprintf(lpddi->tszInstanceName, "Joystick %d", id);
|
||||
|
||||
/* get the device name */
|
||||
|
@ -989,6 +1013,7 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
char name[MAX_PATH];
|
||||
char friendly[32];
|
||||
IOHIDDeviceRef device;
|
||||
BOOL is_joystick;
|
||||
|
||||
TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType, dwFlags, version, id);
|
||||
|
||||
|
@ -997,7 +1022,7 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
device = get_device_ref(id);
|
||||
|
||||
if ((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version > 0x0300 && version < 0x0800)) ||
|
||||
((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
|
||||
|
||||
if (dwFlags & DIEDFL_FORCEFEEDBACK) {
|
||||
|
@ -1006,18 +1031,22 @@ static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
|
|||
if(get_ff(device, NULL) != S_OK)
|
||||
return S_FALSE;
|
||||
}
|
||||
is_joystick = get_device_property_long(device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick;
|
||||
/* Return joystick */
|
||||
lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
|
||||
lpddi->guidInstance.Data3 = id;
|
||||
lpddi->guidProduct = DInput_Wine_OsX_Joystick_GUID;
|
||||
lpddi->guidProduct = DInput_PIDVID_Product_GUID;
|
||||
lpddi->guidProduct.Data1 = make_vid_pid(device);
|
||||
/* we only support traditional joysticks for now */
|
||||
if (version >= 0x0800)
|
||||
lpddi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
|
||||
lpddi->dwDevType = get_device_type(version, is_joystick);
|
||||
lpddi->dwDevType |= DIDEVTYPE_HID;
|
||||
lpddi->wUsagePage = 0x01; /* Desktop */
|
||||
if (is_joystick)
|
||||
lpddi->wUsage = 0x04; /* Joystick */
|
||||
else
|
||||
lpddi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
|
||||
lpddi->wUsage = 0x05; /* Game Pad */
|
||||
sprintf(friendly, "Joystick %d", id);
|
||||
MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH);
|
||||
|
||||
/* get the device name */
|
||||
get_osx_device_name(id, name, MAX_PATH);
|
||||
|
||||
|
@ -1082,7 +1111,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
|
|||
|
||||
newDevice->generic.guidInstance = DInput_Wine_OsX_Joystick_GUID;
|
||||
newDevice->generic.guidInstance.Data3 = index;
|
||||
newDevice->generic.guidProduct = DInput_Wine_OsX_Joystick_GUID;
|
||||
newDevice->generic.guidProduct = DInput_PIDVID_Product_GUID;
|
||||
newDevice->generic.guidProduct.Data1 = make_vid_pid(device);
|
||||
newDevice->generic.joy_polldev = poll_osx_device_state;
|
||||
|
||||
|
@ -1327,6 +1356,53 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF
|
|||
return DIERR_DEVICENOTREG;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
|
||||
{
|
||||
JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
|
||||
_dump_DIPROPHEADER(pdiph);
|
||||
|
||||
if (!IS_DIPROP(rguid)) return DI_OK;
|
||||
|
||||
switch (LOWORD(rguid)) {
|
||||
case (DWORD_PTR) DIPROP_GUIDANDPATH:
|
||||
{
|
||||
static const WCHAR formatW[] = {'\\','\\','?','\\','h','i','d','#','v','i','d','_','%','0','4','x','&',
|
||||
'p','i','d','_','%','0','4','x','&','%','s','_','%','i',0};
|
||||
static const WCHAR miW[] = {'m','i',0};
|
||||
static const WCHAR igW[] = {'i','g',0};
|
||||
|
||||
BOOL is_gamepad;
|
||||
IOHIDDeviceRef device = get_device_ref(This->id);
|
||||
LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
|
||||
WORD vid = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey));
|
||||
WORD pid = get_device_property_long(device, CFSTR(kIOHIDProductIDKey));
|
||||
|
||||
if (!pid || !vid)
|
||||
return DIERR_UNSUPPORTED;
|
||||
|
||||
is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid);
|
||||
pd->guidClass = GUID_DEVCLASS_HIDCLASS;
|
||||
sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, This->id);
|
||||
|
||||
TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
|
||||
}
|
||||
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
|
||||
{
|
||||
JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
|
||||
return JoystickWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
|
||||
}
|
||||
|
||||
static HRESULT osx_set_autocenter(JoystickImpl *This,
|
||||
const DIPROPDWORD *header)
|
||||
{
|
||||
|
@ -1418,7 +1494,7 @@ static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface,
|
|||
EffectImpl *effect;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("%p %s %p %p %p\n", iface, debugstr_guid(type), params, out, outer);
|
||||
TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_guid(type), params, out, outer);
|
||||
dump_DIEFFECT(params, type, 0);
|
||||
|
||||
if(!This->ff){
|
||||
|
@ -1459,7 +1535,7 @@ static HRESULT WINAPI JoystickAImpl_CreateEffect(IDirectInputDevice8A *iface,
|
|||
{
|
||||
JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
|
||||
|
||||
TRACE("%p %s %p %p %p\n", iface, debugstr_guid(type), params, out, outer);
|
||||
TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_guid(type), params, out, outer);
|
||||
|
||||
return JoystickWImpl_CreateEffect(&This->generic.base.IDirectInputDevice8W_iface,
|
||||
type, params, out, outer);
|
||||
|
@ -1509,7 +1585,7 @@ static const IDirectInputDevice8AVtbl JoystickAvt =
|
|||
IDirectInputDevice2AImpl_Release,
|
||||
JoystickAGenericImpl_GetCapabilities,
|
||||
IDirectInputDevice2AImpl_EnumObjects,
|
||||
JoystickAGenericImpl_GetProperty,
|
||||
JoystickAImpl_GetProperty,
|
||||
JoystickAImpl_SetProperty,
|
||||
IDirectInputDevice2AImpl_Acquire,
|
||||
IDirectInputDevice2AImpl_Unacquire,
|
||||
|
@ -1545,7 +1621,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
|
|||
IDirectInputDevice2WImpl_Release,
|
||||
JoystickWGenericImpl_GetCapabilities,
|
||||
IDirectInputDevice2WImpl_EnumObjects,
|
||||
JoystickWGenericImpl_GetProperty,
|
||||
JoystickWImpl_GetProperty,
|
||||
JoystickWImpl_SetProperty,
|
||||
IDirectInputDevice2WImpl_Acquire,
|
||||
IDirectInputDevice2WImpl_Unacquire,
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
#define MAX_PROPS 164
|
||||
struct JoystickGenericImpl;
|
||||
|
||||
/* Number of buttons for which to allow remapping */
|
||||
#define MAX_MAP_BUTTONS 32
|
||||
|
||||
typedef void joy_polldev_handler(LPDIRECTINPUTDEVICE8A iface);
|
||||
|
||||
typedef struct JoystickGenericImpl
|
||||
|
@ -47,6 +50,7 @@ typedef struct JoystickGenericImpl
|
|||
char *name;
|
||||
int device_axis_count; /* Total number of axes in the device */
|
||||
int *axis_map; /* User axes remapping */
|
||||
int button_map[MAX_MAP_BUTTONS]; /* User button remapping */
|
||||
LONG deadzone; /* Default dead-zone */
|
||||
|
||||
joy_polldev_handler *joy_polldev;
|
||||
|
@ -96,5 +100,6 @@ HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LP
|
|||
|
||||
DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN;
|
||||
void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags) DECLSPEC_HIDDEN;
|
||||
BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif /* __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H */
|
||||
|
|
|
@ -215,6 +215,9 @@ static HRESULT keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVI
|
|||
if (id != 0)
|
||||
return E_FAIL;
|
||||
|
||||
if (dwFlags & DIEDFL_FORCEFEEDBACK)
|
||||
return S_FALSE;
|
||||
|
||||
if ((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) {
|
||||
|
@ -233,6 +236,9 @@ static HRESULT keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVI
|
|||
if (id != 0)
|
||||
return E_FAIL;
|
||||
|
||||
if (dwFlags & DIEDFL_FORCEFEEDBACK)
|
||||
return S_FALSE;
|
||||
|
||||
if ((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) {
|
||||
|
@ -520,11 +526,6 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo(
|
|||
SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(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->base.dinput->dwVersion, This->subtype);
|
||||
|
||||
return DI_OK;
|
||||
|
@ -553,7 +554,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,
|
|||
{
|
||||
SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
|
||||
TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph);
|
||||
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
|
||||
_dump_DIPROPHEADER(pdiph);
|
||||
|
||||
if (!IS_DIPROP(rguid)) return DI_OK;
|
||||
|
@ -619,7 +620,8 @@ static HRESULT WINAPI SysKeyboardWImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W ifac
|
|||
LPCWSTR lpszUserName,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
|
||||
return _build_action_map(iface, lpdiaf, lpszUserName, dwFlags, DIKEYBOARD_MASK, &c_dfDIKeyboard);
|
||||
}
|
||||
|
@ -659,7 +661,8 @@ static HRESULT WINAPI SysKeyboardWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
|
|||
LPCWSTR lpszUserName,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
|
||||
return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, &c_dfDIKeyboard);
|
||||
}
|
||||
|
@ -687,6 +690,8 @@ static HRESULT WINAPI SysKeyboardAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
|
|||
|
||||
hr = SysKeyboardWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
|
||||
|
||||
lpdiaf->dwCRC = diafW.dwCRC;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
|
||||
HeapFree(GetProcessHeap(), 0, lpszUserNameW);
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wingdi.h"
|
||||
#include "wine/winternl.h"
|
||||
#include "winuser.h"
|
||||
#include "winerror.h"
|
||||
#include "winreg.h"
|
||||
|
@ -157,6 +158,9 @@ static HRESULT mousedev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI
|
|||
if (id != 0)
|
||||
return E_FAIL;
|
||||
|
||||
if (dwFlags & DIEDFL_FORCEFEEDBACK)
|
||||
return S_FALSE;
|
||||
|
||||
if ((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) {
|
||||
|
@ -175,6 +179,9 @@ static HRESULT mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI
|
|||
if (id != 0)
|
||||
return E_FAIL;
|
||||
|
||||
if (dwFlags & DIEDFL_FORCEFEEDBACK)
|
||||
return S_FALSE;
|
||||
|
||||
if ((dwDevType == 0) ||
|
||||
((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) ||
|
||||
(((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) {
|
||||
|
@ -211,9 +218,9 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
|
|||
get_app_key(&hkey, &appkey);
|
||||
if (!get_config_key(hkey, appkey, "MouseWarpOverride", buffer, sizeof(buffer)))
|
||||
{
|
||||
if (!strcasecmp(buffer, "disable"))
|
||||
if (!_strnicmp(buffer, "disable", -1))
|
||||
newDevice->warp_override = WARP_DISABLE;
|
||||
else if (!strcasecmp(buffer, "force"))
|
||||
else if (!_strnicmp(buffer, "force", -1))
|
||||
newDevice->warp_override = WARP_FORCE_ON;
|
||||
}
|
||||
if (appkey) RegCloseKey(appkey);
|
||||
|
@ -723,6 +730,9 @@ static HRESULT WINAPI SysMouseWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
|
|||
else if (pdidoi->dwType & DIDFT_BUTTON)
|
||||
wsprintfW(pdidoi->tszName, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType) - 3);
|
||||
|
||||
if(pdidoi->dwType & DIDFT_AXIS)
|
||||
pdidoi->dwFlags |= DIDOI_ASPECTPOSITION;
|
||||
|
||||
_dump_OBJECTINSTANCEW(pdidoi);
|
||||
return res;
|
||||
}
|
||||
|
@ -758,11 +768,6 @@ static HRESULT WINAPI SysMouseAImpl_GetDeviceInfo(
|
|||
SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
|
||||
TRACE("(this=%p,%p)\n", This, pdidi);
|
||||
|
||||
if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
|
||||
WARN(" dinput3 not supported yet...\n");
|
||||
return DI_OK;
|
||||
}
|
||||
|
||||
fill_mouse_dideviceinstanceA(pdidi, This->base.dinput->dwVersion);
|
||||
|
||||
return DI_OK;
|
||||
|
@ -828,7 +833,8 @@ static HRESULT WINAPI SysMouseWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
|
|||
LPCWSTR lpszUserName,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
SysMouseImpl *This = impl_from_IDirectInputDevice8W(iface);
|
||||
FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
|
||||
|
||||
return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, &c_dfDIMouse2);
|
||||
}
|
||||
|
@ -856,6 +862,8 @@ static HRESULT WINAPI SysMouseAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
|
|||
|
||||
hr = SysMouseWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
|
||||
|
||||
lpdiaf->dwCRC = diafW.dwCRC;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
|
||||
HeapFree(GetProcessHeap(), 0, lpszUserNameW);
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
#ifndef __WINE_DINPUT_PRECOMP_H
|
||||
#define __WINE_DINPUT_PRECOMP_H
|
||||
|
||||
#include <wine/config.h>
|
||||
|
||||
#define WIN32_NO_STATUS
|
||||
#define _INC_WINDOWS
|
||||
#define COM_NO_WINDOWS_H
|
||||
|
|
|
@ -30,7 +30,7 @@ dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-4.0
|
|||
dll/directx/wine/d3dxof # Synced to WineStaging-3.17
|
||||
dll/directx/wine/ddraw # Synced to WineStaging-3.3
|
||||
dll/directx/wine/devenum # Synced to WineStaging-4.18
|
||||
dll/directx/wine/dinput # Synced to WineStaging-4.0
|
||||
dll/directx/wine/dinput # Synced to WineStaging-4.18
|
||||
dll/directx/wine/dinput8 # Synced to WineStaging-3.3
|
||||
dll/directx/wine/dmusic # Synced to WineStaging-4.0
|
||||
dll/directx/wine/dplay # Synced to WineStaging-3.3
|
||||
|
|
Loading…
Reference in a new issue