diff --git a/plugins/LilyPad/Config.cpp b/plugins/LilyPad/Config.cpp index 2aa289c00e..d5ff4edfbe 100644 --- a/plugins/LilyPad/Config.cpp +++ b/plugins/LilyPad/Config.cpp @@ -1502,6 +1502,18 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l return 0; } +// Returns 0 if pad doesn't exist due to mtap settings, as a convenience. +int GetPadString(wchar_t *string, unsigned int port, unsigned int slot) { + if (!slot) { + wsprintfW(string, L"Pad %i", port+1); + } + else { + wsprintfW(string, L"Pad %i-%i", port+1, slot+1); + if (!config.multitap[port]) return 0; + } + return 1; +} + void UpdatePadPages() { HPROPSHEETPAGE pages[10]; int count = 0; @@ -1511,13 +1523,7 @@ void UpdatePadPages() { for (int slot=0; slot<4; slot++) { if (config.padConfigs[port][slot].type == DisabledPad) continue; wchar_t title[20]; - if (!slot) { - wsprintfW(title, L"Pad %i", port+1); - } - else { - if (!config.multitap[port]) continue; - wsprintfW(title, L"Pad %i-%i", port+1, slot+1); - } + if (!GetPadString(title, port, slot)) continue; PROPSHEETPAGE psp; ZeroMemory(&psp, sizeof(psp)); @@ -1570,16 +1576,11 @@ void UpdatePadList(HWND hWnd) { int slot; int port; int index = 0; - wchar_t *strings[] = {L"Disabled", L"Dualshock 2", L"Guitar"}; + wchar_t *padTypes[] = {L"Disabled", L"Dualshock 2", L"Guitar"}; for (port=0; port<2; port++) { for (slot = 0; slot<4; slot++) { - wchar_t text[100]; - if (!slot) - wsprintf(text, L"Pad %i", port+1); - else { - if (!config.multitap[port]) continue; - wsprintf(text, L"Pad %i-%i", port+1, slot+1); - } + wchar_t text[20]; + if (!GetPadString(text, port, slot)) continue; LVITEM item; item.iItem = index; item.iSubItem = 0; @@ -1594,7 +1595,7 @@ void UpdatePadList(HWND hWnd) { item.iSubItem = 1; if (2 < (unsigned int)config.padConfigs[port][slot].type) config.padConfigs[port][slot].type = Dualshock2Pad; - item.pszText = strings[config.padConfigs[port][slot].type]; + item.pszText = padTypes[config.padConfigs[port][slot].type]; ListView_SetItem(hWndList, &item); item.iSubItem = 2; @@ -1845,37 +1846,41 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L int index = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED); int port1, slot1, port2, slot2; if (!ListIndexToPortAndSlot(index, &port1, &slot1)) break; - //HMENU hMenu = CreateMenu(); HMENU hMenu = CreatePopupMenu(); if (!hMenu) break; + MENUITEMINFOW info; for (port2=1; port2>=0; port2--) { for (slot2 = 3; slot2>=0; slot2--) { - if (port2 == port1 && slot2 == slot1) continue; - wchar_t text[100]; - if (!slot2) - wsprintf(text, L"Swap with Pad %i", port2+1); - else { - if (!config.multitap[port2]) continue; - wsprintf(text, L"Swap with Pad %i-%i", port2+1, slot2+1); - } - MENUITEMINFOW info; - memset(&info, 0, sizeof(info)); + wchar_t text[40]; + wchar_t pad[20]; + if (!GetPadString(pad, port2, slot2)) continue; info.cbSize = sizeof(info); info.fMask = MIIM_STRING | MIIM_ID; - info.wID = 0x10000 + port2+2*slot2; info.dwTypeData = text; - info.cch = wcslen(text); - InsertMenuItemW(hMenu, 0, 1, &info); + if (port2 == port1 && slot2 == slot1) { + int index = GetMenuItemCount(hMenu); + wsprintfW(text, L"Clear %s Bindings", pad); + info.wID = -1; + InsertMenuItemW(hMenu, index, 1, &info); + info.fMask = MIIM_TYPE; + info.fType = MFT_SEPARATOR; + InsertMenuItemW(hMenu, index, 1, &info); + } + else { + info.wID = port2+2*slot2; + wsprintfW(text, L"Swap with %s", pad); + InsertMenuItemW(hMenu, 0, 1, &info); + } } } POINT pos; GetCursorPos(&pos); - int res = TrackPopupMenuEx(hMenu, TPM_NONOTIFY|TPM_RETURNCMD, pos.x, pos.y, hWndProp, 0); + short res = TrackPopupMenuEx(hMenu, TPM_NONOTIFY|TPM_RETURNCMD, pos.x, pos.y, hWndProp, 0); DestroyMenu(hMenu); + if (!res) break; if (res > 0) { - slot2 = res - 0x10000; - port2 = slot2&1; - slot2 >>= 1; + slot2 = res / 2; + port2 = res&1; PadConfig padCfgTemp = config.padConfigs[port1][slot1]; config.padConfigs[port1][slot1] = config.padConfigs[port2][slot2]; config.padConfigs[port2][slot2] = padCfgTemp; @@ -1884,10 +1889,20 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L dm->devices[i]->pads[port1][slot1] = dm->devices[i]->pads[port2][slot2]; dm->devices[i]->pads[port2][slot2] = bindings; } - UpdatePadPages(); - UpdatePadList(hWnd); - PropSheet_Changed(hWndProp, hWnd); } + else { + for (int i=0; inumDevices; i++) { + free(dm->devices[i]->pads[port1][slot1].bindings); + for (int j=0; jdevices[i]->pads[port1][slot1].numFFBindings; j++) { + free(dm->devices[i]->pads[port1][slot1].ffBindings[j].axes); + } + free(dm->devices[i]->pads[port1][slot1].ffBindings); + memset(&dm->devices[i]->pads[port1][slot1], 0, sizeof(dm->devices[i]->pads[port1][slot1])); + } + } + UpdatePadPages(); + UpdatePadList(hWnd); + PropSheet_Changed(hWndProp, hWnd); } } } @@ -1906,6 +1921,10 @@ int CALLBACK PropSheetProc(HWND hWnd, UINT msg, LPARAM lParam) { void CALLBACK PADconfigure() { // Can end up here without PadConfigure() being called first. LoadSettings(); + // Can also end up here after running emulator a bit, and possibly + // disabling some devices due to focus changes, or releasing mouse. + RefreshEnabledDevices(0); + memset(hWnds, 0, sizeof(hWnds)); PROPSHEETPAGE psp; diff --git a/plugins/LilyPad/LilyPad.cpp b/plugins/LilyPad/LilyPad.cpp index 635e8b3ab7..f4b3801f0b 100644 --- a/plugins/LilyPad/LilyPad.cpp +++ b/plugins/LilyPad/LilyPad.cpp @@ -909,6 +909,11 @@ u8 CALLBACK PADstartPoll(int port) { } } +inline int IsDualshock2(u8 port, u8 slot) { + return config.padConfigs[query.port][query.slot].type == Dualshock2Pad || + (config.padConfigs[query.port][query.slot].type == GuitarPad && config.GH2); +} + u8 CALLBACK PADpoll(u8 value) { DEBUG_IN(value); if (query.lastByte+1 >= query.numBytes) { @@ -1038,9 +1043,14 @@ u8 CALLBACK PADpoll(u8 value) { break; // QUERY_MODEL_AND_MODE case 0x45: - if (config.padConfigs[query.port][query.slot].type != GuitarPad || config.GH2) SET_FINAL_RESULT(queryModelDS2) - else SET_FINAL_RESULT(queryModelDS1); - query.response[5] = pad->mode != MODE_DIGITAL; + if (IsDualshock2(query.port, query.slot)) { + SET_FINAL_RESULT(queryModelDS2) + } + else { + SET_FINAL_RESULT(queryModelDS1); + } + // Not digital mode. + query.response[5] = (pad->mode & 0xF) != 1; break; // QUERY_ACT case 0x46: @@ -1062,7 +1072,12 @@ u8 CALLBACK PADpoll(u8 value) { break; // SET_DS2_NATIVE_MODE case 0x4F: - SET_RESULT(setNativeMode); + if (IsDualshock2(query.port, query.slot)) { + SET_RESULT(setNativeMode); + } + else { + SET_FINAL_RESULT(setNativeMode); + } break; default: query.numBytes = 0; @@ -1140,6 +1155,7 @@ u8 CALLBACK PADpoll(u8 value) { pad->vibrate[query.lastByte-2] = value; } break; + // SET_DS2_NATIVE_MODE case 0x4F: if (query.lastByte == 3 || query.lastByte == 4) { pad->umask[query.lastByte-3] = value; diff --git a/plugins/LilyPad/LilyPad.rc b/plugins/LilyPad/LilyPad.rc index 9fd6224740..8c3b7ada71 100644 --- a/plugins/LilyPad/LilyPad.rc +++ b/plugins/LilyPad/LilyPad.rc @@ -226,15 +226,15 @@ BEGIN GROUPBOX "Pads",IDC_STATIC,7,140,410,67 CONTROL "Port 1 Multitap",IDC_MULTITAP1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,152,63,10 CONTROL "Port 2 Multitap",IDC_MULTITAP2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,164,63,10 - CONTROL "",IDC_PAD_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_TABSTOP,81,152,183,48,WS_EX_CLIENTEDGE - COMBOBOX IDC_PAD_TYPE,270,153,140,41,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CONTROL "",IDC_PAD_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_TABSTOP,81,151,183,50,WS_EX_CLIENTEDGE + COMBOBOX IDC_PAD_TYPE,270,152,140,41,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP CONTROL "Use analog mode whenever possible",IDC_ANALOG_START1, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,270,170,132,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,270,169,132,10 GROUPBOX "Device Diagnostics",IDC_STATIC,7,211,201,99 CONTROL "",IDC_LIST,"SysListView32",LVS_LIST | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_VSCROLL | WS_TABSTOP,15,224,185,61,WS_EX_CLIENTEDGE PUSHBUTTON "Test Device",ID_TEST,86,289,57,15 PUSHBUTTON "Refresh",ID_REFRESH,152,289,48,15 - GROUPBOX "Miscellaneous",IDC_STATIC,216,211,201,35 + GROUPBOX "Miscellaneous",IDC_STATIC,216,211,201,34 CONTROL "Use GS thread (Recommended)",IDC_GS_THREAD_INPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,221,116,10 CONTROL "Disable screensaver",IDC_DISABLE_SCREENSAVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,232,80,10 CONTROL "Local volume control",IDC_VISTA_VOLUME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,221,77,10 diff --git a/plugins/LilyPad/RawInput.cpp b/plugins/LilyPad/RawInput.cpp index 32d299a09d..0fbde4513f 100644 --- a/plugins/LilyPad/RawInput.cpp +++ b/plugins/LilyPad/RawInput.cpp @@ -111,8 +111,6 @@ public: } }; -static POINT rawOrigCursorPos; - class RawInputMouse : public WindowsMouse { public: HANDLE hDevice; @@ -135,8 +133,7 @@ public: // EatWndProc fail. In all other cases, no unmatched initialization/cleanup // lines. if (!rawMouseActivatedCount++) { - GetCursorPos(&rawOrigCursorPos); - ShowCursor(0); + GetMouseCapture(hWnd); if (!rawKeyboardActivatedCount && !EatWndProc(hWnd, RawInputWndProc)) { Deactivate(); return 0; @@ -157,9 +154,8 @@ public: active = 0; rawMouseActivatedCount --; if (!rawMouseActivatedCount) { - ShowCursor(1); ReleaseRawMice(); - SetCursorPos(rawOrigCursorPos.x, rawOrigCursorPos.y); + ReleaseMouseCapture(); if (!rawKeyboardActivatedCount) { ReleaseExtraProc(RawInputWndProc); } @@ -225,6 +221,11 @@ ExtraWndProcResult RawInputWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l memset(dev->physicalControlState, 0, sizeof(int) * dev->numPhysicalControls); } } + else if (uMsg == WM_SIZE && rawMouseActivatedCount) { + // Doesn't really matter for raw mice, as I disable legacy stuff, but shouldn't hurt. + WindowsMouse::WindowResized(hWnd); + } + return CONTINUE_BLISSFULLY; } diff --git a/plugins/LilyPad/WindowsMessaging.cpp b/plugins/LilyPad/WindowsMessaging.cpp index dd36b70eb3..c85783e430 100644 --- a/plugins/LilyPad/WindowsMessaging.cpp +++ b/plugins/LilyPad/WindowsMessaging.cpp @@ -79,20 +79,10 @@ public: Deactivate(); return 0; } + GetMouseCapture(hWnd); - SetCapture(hWnd); - ShowCursor(0); - - GetCursorPos(&origCursorPos); active = 1; - RECT r; - GetWindowRect(hWnd, &r); - ClipCursor(&r); - center.x = (r.left + r.right)/2; - center.y = (r.top + r.bottom)/2; - SetCursorPos(center.x, center.y); - wmm = this; AllocState(); @@ -102,10 +92,7 @@ public: void Deactivate() { FreeState(); if (active) { - ClipCursor(0); - ReleaseCapture(); - ShowCursor(1); - SetCursorPos(origCursorPos.x, origCursorPos.y); + ReleaseMouseCapture(); if (!wmk) ReleaseExtraProc(WindowsMessagingWndProc); active = 0; @@ -179,6 +166,9 @@ ExtraWndProcResult WindowsMessagingWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, wmm->UpdateAxis(3, ((int)wParam>>16)/WHEEL_DELTA); return NO_WND_PROC; } + else if (uMsg == WM_SIZE && wmm->active) { + WindowsMouse::WindowResized(hWnd); + } // Taken care of elsewhere. When binding, killing focus means stop reading input. // When running PCSX2, I release all mouse and keyboard input elsewhere. /*else if (uMsg == WM_KILLFOCUS) { diff --git a/plugins/LilyPad/WindowsMouse.cpp b/plugins/LilyPad/WindowsMouse.cpp index 72a951f925..6d2e4db653 100644 --- a/plugins/LilyPad/WindowsMouse.cpp +++ b/plugins/LilyPad/WindowsMouse.cpp @@ -2,6 +2,9 @@ #include "VKey.h" #include "WindowsMouse.h" +POINT WindowsMouse::origCursorPos; +POINT WindowsMouse::center; + WindowsMouse::WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID, wchar_t *deviceID) : Device(api, MOUSE, displayName, instanceID, deviceID) { int i; @@ -41,4 +44,32 @@ void WindowsMouse::UpdateAxis(unsigned int axis, int delta) { physicalControlState[5+axis] += (delta<<(16 - 3*(axis < 2))); } +void WindowsMouse::WindowResized(HWND hWnd) { + RECT r; + GetWindowRect(hWnd, &r); + ClipCursor(&r); + center.x = (r.left + r.right)/2; + center.y = (r.top + r.bottom)/2; + SetCursorPos(center.x, center.y); +} +void WindowsMouse::GetMouseCapture(HWND hWnd) { + SetCapture(hWnd); + ShowCursor(0); + + GetCursorPos(&origCursorPos); + + RECT r; + GetWindowRect(hWnd, &r); + ClipCursor(&r); + center.x = (r.left + r.right)/2; + center.y = (r.top + r.bottom)/2; + SetCursorPos(center.x, center.y); +} + +void WindowsMouse::ReleaseMouseCapture() { + ClipCursor(0); + ReleaseCapture(); + ShowCursor(1); + SetCursorPos(origCursorPos.x, origCursorPos.y); +} diff --git a/plugins/LilyPad/WindowsMouse.h b/plugins/LilyPad/WindowsMouse.h index b3085c5bb9..5fa5772c4a 100644 --- a/plugins/LilyPad/WindowsMouse.h +++ b/plugins/LilyPad/WindowsMouse.h @@ -3,8 +3,16 @@ // Shared functionality for WM and RAW keyboards. class WindowsMouse : public Device { public: - POINT origCursorPos; - POINT center; + // Used by GetMouseCapture()/ReleaseMouseCapture() + // Static because can have multiple raw mice active at once, + // and only get/release capture once. + static POINT origCursorPos; + static POINT center; + + static void GetMouseCapture(HWND hWnd); + static void WindowResized(HWND hWnd); + static void ReleaseMouseCapture(); + // hWheel variable lets me display no horizontal wheel for raw input, just to make it clear // that it's not supported. WindowsMouse(DeviceAPI api, int hWheel, wchar_t *displayName, wchar_t *instanceID=0, wchar_t *deviceID=0);