From: Rémi Bernon rbernon@codeweavers.com
--- dlls/joy.cpl/joy.rc | 17 +- dlls/joy.cpl/main.c | 398 ++++++++++++---------------------------- dlls/joy.cpl/resource.h | 5 +- 3 files changed, 124 insertions(+), 296 deletions(-)
diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc index d1c179d2ef3..0d4c719166d 100644 --- a/dlls/joy.cpl/joy.rc +++ b/dlls/joy.cpl/joy.rc @@ -54,25 +54,16 @@ STYLE WS_CAPTION | WS_CHILD | WS_DISABLED CAPTION "Test Joystick" FONT 8, "Ms Shell Dlg" { - COMBOBOX IDC_TESTSELECTCOMBO, 5, 5, 200, 60, CBS_DROPDOWNLIST | CBS_HASSTRINGS + COMBOBOX IDC_TESTSELECTCOMBO, 15, 10, 291, 60, CBS_DROPDOWNLIST | CBS_HASSTRINGS GROUPBOX "Buttons", IDC_STATIC, 15, 100, 291, 70 GROUPBOX "", IDC_TESTGROUPXY, 15, 30, 60, 60 GROUPBOX "", IDC_TESTGROUPRXRY, 92, 30, 60, 60 GROUPBOX "", IDC_TESTGROUPZRZ, 169, 30, 60, 60 GROUPBOX "", IDC_TESTGROUPPOV, 246, 30, 60, 60 -} - -IDD_FORCEFEEDBACK DIALOG 0, 0, 320, 300 -STYLE WS_CAPTION | WS_CHILD | WS_DISABLED -CAPTION "Test Force Feedback" -FONT 8, "Ms Shell Dlg" -{ - COMBOBOX IDC_FFSELECTCOMBO, 5, 5, 200, 60, CBS_DROPDOWNLIST | CBS_HASSTRINGS - LTEXT "Available Effects", IDC_STATIC, 10, 30, 100, 10 - LISTBOX IDC_FFEFFECTLIST, 10, 40, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY + LTEXT "Force Feedback Effect", IDC_STATIC, 15, 180, 291, 10 + LISTBOX IDC_FFEFFECTLIST, 15, 190, 291, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY LTEXT "Press any button in the controller to activate the chosen effect. The effect direction can be changed with the controller axis.", - IDC_STATIC, 10, 110, 210, 25 - GROUPBOX "Direction", IDC_STATIC, 220, 30, 60, 60 + IDC_STATIC, 15, 260, 291, 25 }
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c index e48762d18f1..e5377a71aa9 100644 --- a/dlls/joy.cpl/main.c +++ b/dlls/joy.cpl/main.c @@ -59,16 +59,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(joycpl); #define TEST_AXIS_MIN -25 #define TEST_AXIS_MAX 25
-#define FF_AXIS_X 248 -#define FF_AXIS_Y 60 -#define FF_AXIS_SIZE_X 3 -#define FF_AXIS_SIZE_Y 3 - #define FF_PLAY_TIME 2*DI_SECONDS #define FF_PERIOD_TIME FF_PLAY_TIME/4
-#define NUM_PROPERTY_PAGES 3 - struct effect { struct list entry; @@ -86,7 +79,6 @@ struct Graphics HWND hwnd; HWND buttons[TEST_MAX_BUTTONS]; HWND axes[TEST_MAX_AXES]; - HWND ff_axis; };
struct JoystickData @@ -613,7 +605,6 @@ static void dump_joy_state(DIJOYSTATE* st) static DWORD WINAPI input_thread(void *param) { int axes_pos[TEST_MAX_AXES][2]; - DIJOYSTATE state; struct JoystickData *data = param;
/* Setup POV as clock positions @@ -629,63 +620,114 @@ static DWORD WINAPI input_thread(void *param) int pov_pos[9][2] = { {0, -ma}, {ma/2, -ma/2}, {ma, 0}, {ma/2, ma/2}, {0, ma}, {-ma/2, ma/2}, {-ma, 0}, {-ma/2, -ma/2}, {0, 0} };
- ZeroMemory(&state, sizeof(state)); - while (!data->stop) { IDirectInputDevice8W *device; + IDirectInputEffect *effect; + DIJOYSTATE state = {0}; unsigned int i, j;
- memset( &state, 0, sizeof(state) ); - if (WaitForSingleObject( device_state_event, TEST_POLL_TIME ) == WAIT_TIMEOUT) continue;
if ((device = get_selected_device())) { IDirectInputDevice8_GetDeviceState( device, sizeof(state), &state ); IDirectInputDevice8_Release( device ); - }
- dump_joy_state(&state); + dump_joy_state(&state);
- /* Indicate pressed buttons */ - for (i = 0; i < TEST_MAX_BUTTONS; i++) - SendMessageW(data->graphics.buttons[i], BM_SETSTATE, !!state.rgbButtons[i], 0); + /* Indicate pressed buttons */ + for (i = 0; i < TEST_MAX_BUTTONS; i++) + SendMessageW(data->graphics.buttons[i], BM_SETSTATE, !!state.rgbButtons[i], 0);
- /* Indicate axis positions, axes showing are hardcoded for now */ - axes_pos[0][0] = state.lX; - axes_pos[0][1] = state.lY; - axes_pos[1][0] = state.lRx; - axes_pos[1][1] = state.lRy; - axes_pos[2][0] = state.lZ; - axes_pos[2][1] = state.lRz; + /* Indicate axis positions, axes showing are hardcoded for now */ + axes_pos[0][0] = state.lX; + axes_pos[0][1] = state.lY; + axes_pos[1][0] = state.lRx; + axes_pos[1][1] = state.lRy; + axes_pos[2][0] = state.lZ; + axes_pos[2][1] = state.lRz;
- /* Set pov values */ - for (j = 0; j < ARRAY_SIZE(pov_val); j++) - { - if (state.rgdwPOV[0] == pov_val[j]) + /* Set pov values */ + for (j = 0; j < ARRAY_SIZE(pov_val); j++) { - axes_pos[3][0] = pov_pos[j][0]; - axes_pos[3][1] = pov_pos[j][1]; + if (state.rgdwPOV[0] == pov_val[j]) + { + axes_pos[3][0] = pov_pos[j][0]; + axes_pos[3][1] = pov_pos[j][1]; + } + } + + for (i = 0; i < TEST_MAX_AXES; i++) + { + RECT r; + + r.left = (TEST_AXIS_X + TEST_NEXT_AXIS_X*i + axes_pos[i][0]); + r.top = (TEST_AXIS_Y + axes_pos[i][1]); + r.bottom = r.right = 0; /* unused */ + MapDialogRect(data->graphics.hwnd, &r); + + SetWindowPos(data->graphics.axes[i], 0, r.left, r.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE); } }
- for (i = 0; i < TEST_MAX_AXES; i++) + if ((effect = get_selected_effect())) { - RECT r; - - r.left = (TEST_AXIS_X + TEST_NEXT_AXIS_X*i + axes_pos[i][0]); - r.top = (TEST_AXIS_Y + axes_pos[i][1]); - r.bottom = r.right = 0; /* unused */ - MapDialogRect(data->graphics.hwnd, &r); + DWORD flags = DIEP_AXES | DIEP_DIRECTION | DIEP_NORESTART; + LONG direction[3] = {0}; + DWORD axes[3] = {0}; + DIEFFECT params = + { + .dwSize = sizeof(DIEFFECT), + .dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS, + .rglDirection = direction, + .rgdwAxes = axes, + .cAxes = 3, + }; + + IDirectInputEffect_GetParameters( effect, ¶ms, flags ); + params.rgdwAxes[0] = state.lX; + params.rgdwAxes[1] = state.lY; + + for (i=0; i < TEST_MAX_BUTTONS; i++) + { + if (state.rgbButtons[i]) + { + IDirectInputEffect_SetParameters( effect, ¶ms, flags ); + IDirectInputEffect_Start( effect, 1, 0 ); + break; + } + }
- SetWindowPos(data->graphics.axes[i], 0, r.left, r.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + IDirectInputEffect_Release( effect ); } }
return 0; }
+static void initialize_effects_list( HWND hwnd, IDirectInputDevice8W *device ) +{ + struct effect *effect; + + clear_effects(); + + IDirectInputDevice8_EnumEffects( device, enum_effects, device, 0 ); + + SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_RESETCONTENT, 0, 0); + SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_ADDSTRING, 0, (LPARAM)L"None"); + + LIST_FOR_EACH_ENTRY( effect, &effects, struct effect, entry ) + { + DIEFFECTINFOW info = {.dwSize = sizeof(DIEFFECTINFOW)}; + GUID guid; + + if (FAILED(IDirectInputEffect_GetEffectGuid( effect->effect, &guid ))) continue; + if (FAILED(IDirectInputDevice8_GetEffectInfo( device, &info, &guid ))) continue; + SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_ADDSTRING, 0, (LPARAM)(info.tszName + 5)); + } +} + static void test_handle_joychange(HWND hwnd, struct JoystickData *data) { DIDEVCAPS caps = {.dwSize = sizeof(DIDEVCAPS)}; @@ -706,9 +748,36 @@ static void test_handle_joychange(HWND hwnd, struct JoystickData *data) if (FAILED(IDirectInputDevice8_GetCapabilities( device, &caps ))) return;
set_selected_device( device ); + initialize_effects_list( hwnd, device ); for (i = 0; i < TEST_MAX_BUTTONS; i++) ShowWindow( data->graphics.buttons[i], i < caps.dwButtons ); }
+static void ff_handle_effectchange( HWND hwnd ) +{ + IDirectInputDevice8W *device; + struct list *entry; + int sel; + + set_selected_effect( NULL ); + + sel = SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_GETCURSEL, 0, 0) - 1; + if (sel < 0) return; + + entry = list_head( &effects ); + while (sel-- && entry) entry = list_next( &effects, entry ); + if (!entry) return; + + set_selected_effect( LIST_ENTRY( entry, struct effect, entry )->effect ); + + if ((device = get_selected_device())) + { + IDirectInputDevice8_Unacquire( device ); + IDirectInputDevice8_SetCooperativeLevel( device, GetAncestor( hwnd, GA_ROOT ), DISCL_BACKGROUND | DISCL_EXCLUSIVE ); + IDirectInputDevice8_Acquire( device ); + IDirectInputDevice8_Release( device ); + } +} + /********************************************************************* * button_number_to_wchar [internal] * Transforms an integer in the interval [0,99] into a 2 character WCHAR string @@ -822,233 +891,6 @@ static INT_PTR CALLBACK test_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM { case MAKEWPARAM(IDC_TESTSELECTCOMBO, CBN_SELCHANGE): test_handle_joychange(hwnd, data); - break; - } - return TRUE; - - case WM_NOTIFY: - switch(((LPNMHDR)lparam)->code) - { - case PSN_SETACTIVE: - { - DWORD tid; - - refresh_test_joystick_list(hwnd, data); - - data->stop = FALSE; - - /* Set the first joystick as default */ - SendDlgItemMessageW(hwnd, IDC_TESTSELECTCOMBO, CB_SETCURSEL, 0, 0); - test_handle_joychange(hwnd, data); - - thread = CreateThread(NULL, 0, input_thread, (void*) data, 0, &tid); - } - break; - - case PSN_RESET: /* intentional fall-through */ - case PSN_KILLACTIVE: - /* Stop input thread */ - data->stop = TRUE; - MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, 0); - CloseHandle(thread); - break; - } - return TRUE; - } - return FALSE; -} - -/********************************************************************* - * Joystick force feedback testing functions - * - */ -static void draw_ff_axis(HWND hwnd, struct JoystickData *data) -{ - HINSTANCE hinst = (HINSTANCE) GetWindowLongPtrW(hwnd, GWLP_HINSTANCE); - RECT r; - - r.left = FF_AXIS_X; - r.top = FF_AXIS_Y; - r.right = r.left + FF_AXIS_SIZE_X; - r.bottom = r.top + FF_AXIS_SIZE_Y; - MapDialogRect(hwnd, &r); - - /* Draw direction axis */ - data->graphics.ff_axis = CreateWindowW(L"Button", NULL, WS_CHILD | WS_VISIBLE, - r.left, r.top, r.right - r.left, r.bottom - r.top, - hwnd, NULL, NULL, hinst); -} - -static void initialize_effects_list( HWND hwnd, IDirectInputDevice8W *device ) -{ - struct effect *effect; - - clear_effects(); - - IDirectInputDevice8_EnumEffects( device, enum_effects, device, 0 ); - - SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_RESETCONTENT, 0, 0); - - LIST_FOR_EACH_ENTRY( effect, &effects, struct effect, entry ) - { - DIEFFECTINFOW info = {.dwSize = sizeof(DIEFFECTINFOW)}; - GUID guid; - - if (FAILED(IDirectInputEffect_GetEffectGuid( effect->effect, &guid ))) continue; - if (FAILED(IDirectInputDevice8_GetEffectInfo( device, &info, &guid ))) continue; - SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_ADDSTRING, 0, (LPARAM)(info.tszName + 5)); - } -} - -static void ff_handle_joychange( HWND hwnd ) -{ - DIDEVCAPS caps = {.dwSize = sizeof(DIDEVCAPS)}; - IDirectInputDevice8W *device; - struct list *entry; - int i; - - i = SendDlgItemMessageW( hwnd, IDC_FFSELECTCOMBO, CB_GETCURSEL, 0, 0 ); - if (i < 0) return; - - entry = list_head( &devices ); - while (i-- && entry) entry = list_next( &devices, entry ); - if (!entry) return; - - device = LIST_ENTRY( entry, struct device, entry )->device; - if (FAILED(IDirectInputDevice8_GetCapabilities( device, &caps ))) return; - - set_selected_device( device ); - initialize_effects_list( hwnd, device ); -} - -static void ff_handle_effectchange( HWND hwnd ) -{ - IDirectInputDevice8W *device; - struct list *entry; - int sel; - - set_selected_effect( NULL ); - - sel = SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_GETCURSEL, 0, 0); - if (sel < 0) return; - - entry = list_head( &effects ); - while (sel-- && entry) entry = list_next( &effects, entry ); - if (!entry) return; - - set_selected_effect( LIST_ENTRY( entry, struct effect, entry )->effect ); - - if ((device = get_selected_device())) - { - IDirectInputDevice8_Unacquire( device ); - IDirectInputDevice8_SetCooperativeLevel( device, GetAncestor( hwnd, GA_ROOT ), DISCL_BACKGROUND | DISCL_EXCLUSIVE ); - IDirectInputDevice8_Acquire( device ); - IDirectInputDevice8_Release( device ); - } -} - -static DWORD WINAPI ff_input_thread(void *param) -{ - struct JoystickData *data = param; - DIJOYSTATE state; - - ZeroMemory(&state, sizeof(state)); - - while (!data->stop) - { - int i; - DWORD flags = DIEP_AXES | DIEP_DIRECTION | DIEP_NORESTART; - IDirectInputDevice8W *device; - IDirectInputEffect *effect; - LONG direction[3] = {0}; - DWORD axes[3] = {0}; - DIEFFECT params = - { - .dwSize = sizeof(DIEFFECT), - .dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS, - .rglDirection = direction, - .rgdwAxes = axes, - .cAxes = 3, - }; - RECT r; - - if (WaitForSingleObject( device_state_event, TEST_POLL_TIME ) == WAIT_TIMEOUT) continue; - - if ((device = get_selected_device())) - { - IDirectInputDevice8_GetDeviceState( device, sizeof(state), &state ); - IDirectInputDevice8_Release( device ); - } - - if (!(effect = get_selected_effect())) continue; - - IDirectInputEffect_GetParameters( effect, ¶ms, flags ); - params.rgdwAxes[0] = state.lX; - params.rgdwAxes[1] = state.lY; - - r.left = FF_AXIS_X + state.lX; - r.top = FF_AXIS_Y + state.lY; - r.right = r.bottom = 0; /* unused */ - MapDialogRect(data->graphics.hwnd, &r); - - SetWindowPos(data->graphics.ff_axis, 0, r.left, r.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE); - - for (i=0; i < TEST_MAX_BUTTONS; i++) - if (state.rgbButtons[i]) - { - IDirectInputEffect_SetParameters( effect, ¶ms, flags ); - IDirectInputEffect_Start( effect, 1, 0 ); - break; - } - - IDirectInputEffect_Release( effect ); - } - - return 0; -} - - -/********************************************************************* - * ff_dlgproc [internal] - * - */ -static void refresh_ff_joystick_list(HWND hwnd, struct JoystickData *data) -{ - struct device *entry; - - SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_RESETCONTENT, 0, 0); - - LIST_FOR_EACH_ENTRY( entry, &devices, struct device, entry ) - { - DIDEVICEINSTANCEW info = {.dwSize = sizeof(DIDEVICEINSTANCEW)}; - if (FAILED(IDirectInputDevice8_GetDeviceInfo( entry->device, &info ))) continue; - SendDlgItemMessageW( hwnd, IDC_FFSELECTCOMBO, CB_ADDSTRING, 0, (LPARAM)info.tszInstanceName ); - } -} - -static INT_PTR CALLBACK ff_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - static HANDLE thread; - static struct JoystickData *data; - TRACE("(%p, 0x%08x/%d, 0x%Ix)\n", hwnd, msg, msg, lparam); - - switch (msg) - { - case WM_INITDIALOG: - { - data = (struct JoystickData*) ((PROPSHEETPAGEW*)lparam)->lParam; - - refresh_ff_joystick_list(hwnd, data); - draw_ff_axis(hwnd, data); - - return TRUE; - } - - case WM_COMMAND: - switch(wparam) - { - case MAKEWPARAM(IDC_FFSELECTCOMBO, CBN_SELCHANGE): - ff_handle_joychange( hwnd );
SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_SETCURSEL, 0, 0); ff_handle_effectchange( hwnd ); @@ -1064,22 +906,27 @@ static INT_PTR CALLBACK ff_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp switch(((LPNMHDR)lparam)->code) { case PSN_SETACTIVE: - refresh_ff_joystick_list(hwnd, data); + { + DWORD tid; + + refresh_test_joystick_list(hwnd, data);
data->stop = FALSE; + /* Set the first joystick as default */ - SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_SETCURSEL, 0, 0); - ff_handle_joychange( hwnd ); + SendDlgItemMessageW(hwnd, IDC_TESTSELECTCOMBO, CB_SETCURSEL, 0, 0); + test_handle_joychange(hwnd, data);
SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_SETCURSEL, 0, 0); ff_handle_effectchange( hwnd );
- thread = CreateThread(NULL, 0, ff_input_thread, (void*) data, 0, NULL); + thread = CreateThread(NULL, 0, input_thread, (void*) data, 0, &tid); + } break;
case PSN_RESET: /* intentional fall-through */ case PSN_KILLACTIVE: - /* Stop ff thread */ + /* Stop input thread */ data->stop = TRUE; MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, 0); CloseHandle(thread); @@ -1113,8 +960,8 @@ static int CALLBACK propsheet_callback(HWND hwnd, UINT msg, LPARAM lparam) static void display_cpl_sheets(HWND parent, struct JoystickData *data) { INITCOMMONCONTROLSEX icex; - PROPSHEETPAGEW psp[NUM_PROPERTY_PAGES]; BOOL activated = FALSE; + PROPSHEETPAGEW psp[2]; PROPSHEETHEADERW psh; ULONG_PTR cookie; ACTCTXW actctx; @@ -1155,13 +1002,6 @@ static void display_cpl_sheets(HWND parent, struct JoystickData *data) psp[id].lParam = (INT_PTR) data; id++;
- psp[id].dwSize = sizeof (PROPSHEETPAGEW); - psp[id].hInstance = hcpl; - psp[id].u.pszTemplate = MAKEINTRESOURCEW(IDD_FORCEFEEDBACK); - psp[id].pfnDlgProc = ff_dlgproc; - psp[id].lParam = (INT_PTR) data; - id++; - /* Fill out the PROPSHEETHEADER */ psh.dwSize = sizeof (PROPSHEETHEADERW); psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_USECALLBACK; diff --git a/dlls/joy.cpl/resource.h b/dlls/joy.cpl/resource.h index 671e9ad8c77..c15f8dfbdeb 100644 --- a/dlls/joy.cpl/resource.h +++ b/dlls/joy.cpl/resource.h @@ -36,7 +36,6 @@
#define IDD_LIST 1000 #define IDD_TEST 1001 -#define IDD_FORCEFEEDBACK 1002
#define IDC_JOYSTICKLIST 2000 #define IDC_DISABLEDLIST 2001 @@ -51,9 +50,7 @@ #define IDC_TESTGROUPRXRY 2102 #define IDC_TESTGROUPZRZ 2103 #define IDC_TESTGROUPPOV 2104 - -#define IDC_FFSELECTCOMBO 2200 -#define IDC_FFEFFECTLIST 2201 +#define IDC_FFEFFECTLIST 2105
#define ICO_MAIN 100