diff --git a/README.md b/README.md index 895bf53..da7b175 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ When **Steamless Mode** is active, the app disables the controller's built-in ke - System tray icon shows connection and mode status - **Steamless Mode** — disables lizard mode and exposes controller as Xbox 360 gamepad - **Trackpad Mouse** — use the right (or left) trackpad as a mouse cursor -- **Back Buttons for Clicking** — map R4/R5 (or L4/L5) to left/right mouse click +- **Back Buttons for Clicking** — the upper paddles (L4/R4) left-click by default; rebind any paddle to a gamepad button, right click, or Off - **Use Left Trackpad Instead** — mirror all trackpad/back-button functionality to the left side for left-handed users - **Start with Windows** — launch automatically at login - Settings persist across restarts diff --git a/src/app/BackButtonConfig.h b/src/app/BackButtonConfig.h index 7459a79..b3f9297 100644 --- a/src/app/BackButtonConfig.h +++ b/src/app/BackButtonConfig.h @@ -12,7 +12,7 @@ enum class BackButtonAction : uint8_t { LB, RB, LT, RT, // Row 3 — d-pad DPadUp, DPadDown, DPadLeft, DPadRight, - // Row 4 — stick clicks, menu buttons, mouse buttons, and "none" (natural behavior) + // Row 4 — stick clicks, menu buttons, mouse buttons, and "none" (paddle does nothing) LeftMouseButton, RightMouseButton, None, Menu, View, @@ -21,10 +21,11 @@ enum class BackButtonAction : uint8_t { }; struct BackButtonConfig { - // Default: each back paddle uses its natural behavior (mouse click when that mode is on). - BackButtonAction l4 = BackButtonAction::None; + // Default: the upper paddles left-click the mouse (this used to be the + // "Back Buttons as Mouse Click" tray toggle), the lower paddles are unbound. + BackButtonAction l4 = BackButtonAction::LeftMouseButton; BackButtonAction l5 = BackButtonAction::None; - BackButtonAction r4 = BackButtonAction::None; + BackButtonAction r4 = BackButtonAction::LeftMouseButton; BackButtonAction r5 = BackButtonAction::None; }; diff --git a/src/app/ControllerManager.cpp b/src/app/ControllerManager.cpp index 057d8a1..3ea6516 100644 --- a/src/app/ControllerManager.cpp +++ b/src/app/ControllerManager.cpp @@ -34,6 +34,11 @@ struct ControllerManager::Slot { // thread for that timeout on every one of those attempts. std::chrono::steady_clock::time_point lastSilentAt{}; + // Mouse buttons currently held down by a back paddle, so leaving game mode + // mid-press releases them instead of stranding the button down. + bool paddleMouseLeftDown = false; + bool paddleMouseRightDown = false; + // Haptic edge-detection state for touch (movement ticks). bool hapticWasRightTouching = false; bool hapticWasLeftTouching = false; @@ -197,6 +202,7 @@ ControllerManager::~ControllerManager() { if (slot->gameModeActive) { StopReadLoop(*slot); slot->trackpad.Reset(); + ReleasePaddleMouseButtons(*slot); slot->vc.reset(); slot->gameModeActive = false; } @@ -276,10 +282,17 @@ void ControllerManager::SetBackButtonConfig(const BackButtonConfig& cfg) { // change takes effect on the very next report. } -void ControllerManager::SetBackButtonsEnabled(bool enabled) { - m_backButtonsEnabled = enabled; - for (auto& slot : m_slots) - slot->trackpad.SetBackButtonsEnabled(enabled); +void ControllerManager::ReleasePaddleMouseButtons(Slot& slot) { + auto send = [](DWORD flags) { + INPUT inp{}; + inp.type = INPUT_MOUSE; + inp.mi.dwFlags = flags; + SendInput(1, &inp, sizeof(INPUT)); + }; + if (slot.paddleMouseLeftDown) send(MOUSEEVENTF_LEFTUP); + if (slot.paddleMouseRightDown) send(MOUSEEVENTF_RIGHTUP); + slot.paddleMouseLeftDown = false; + slot.paddleMouseRightDown = false; } void ControllerManager::SetControllerPlatform(ControllerPlatform platform) { @@ -443,9 +456,9 @@ ControllerManager::EnableGameModeSlot(Slot& slot, bool& vigemMissingOut, EventLog::Write("GAMEMODE: enabled %ls", slot.path.c_str()); slot.gameModeActive = true; slot.trackpad.Reset(); + ReleasePaddleMouseButtons(slot); slot.trackpad.SetTrackpadEnabled(m_trackpadMouseEnabled); slot.trackpad.SetUseLeftTrackpad(m_useLeftTrackpad); - slot.trackpad.SetBackButtonsEnabled(m_backButtonsEnabled); StartReadLoop(slot); return GameModeOutcome::Enabled; } @@ -457,6 +470,7 @@ void ControllerManager::DisableGameModeSlot(Slot& slot) { if (slot.sc->IsOpen()) slot.sc->SetRumble(0, 0); slot.trackpad.Reset(); + ReleasePaddleMouseButtons(slot); slot.vc.reset(); slot.sc->EnableLizardMode(); // Reopen shared so Steam can obtain write access — game mode is no longer active. @@ -563,7 +577,7 @@ void ControllerManager::ReadLoop(Slot* slot) { if (!SteamController::IsStateReportId(buf[0])) continue; - if (slot->vc) slot->vc->Update(buf, n, m_backConfig, m_backButtonsEnabled); + if (slot->vc) slot->vc->Update(buf, n, m_backConfig); slot->trackpad.Update(buf, n); // Trackpad haptics. @@ -764,8 +778,7 @@ void ControllerManager::ReadLoop(Slot* slot) { // Fire mouse button events for back paddles mapped to LeftMouseButton/RightMouseButton. // Uses edge detection so we only send DOWN on press and UP on release. - // Skipped when backButtonsEnabled — TrackpadMouse already handles L4/R4 in that mode. - if (!m_backButtonsEnabled && hasPrev) { + if (hasPrev) { struct PaddleEdge { bool cur; bool prev; BackButtonAction action; }; const PaddleEdge edges[] = { { n>4 && (buf[4]&SteamController::BTN_L4)!=0, (prevBuf[4]&SteamController::BTN_L4)!=0, m_backConfig.l4 }, @@ -776,8 +789,13 @@ void ControllerManager::ReadLoop(Slot* slot) { for (const auto& e : edges) { if (e.cur == e.prev) continue; DWORD flag = 0; - if (e.action == BackButtonAction::LeftMouseButton) flag = e.cur ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; - else if (e.action == BackButtonAction::RightMouseButton) flag = e.cur ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; + if (e.action == BackButtonAction::LeftMouseButton) { + flag = e.cur ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; + slot->paddleMouseLeftDown = e.cur; + } else if (e.action == BackButtonAction::RightMouseButton) { + flag = e.cur ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; + slot->paddleMouseRightDown = e.cur; + } if (flag) { INPUT inp{}; inp.type = INPUT_MOUSE; inp.mi.dwFlags = flag; SendInput(1, &inp, sizeof(INPUT)); } } } diff --git a/src/app/ControllerManager.h b/src/app/ControllerManager.h index b953b9f..3fe2666 100644 --- a/src/app/ControllerManager.h +++ b/src/app/ControllerManager.h @@ -57,14 +57,12 @@ public: void SetTrackpadMouseEnabled(bool enabled); void SetUseLeftTrackpad(bool enabled); void SetBackButtonConfig(const BackButtonConfig& cfg); - void SetBackButtonsEnabled(bool enabled); void SetControllerPlatform(ControllerPlatform platform); bool IsConnected() const { return !m_slots.empty(); } bool IsGameModeActive() const; bool IsTrackpadMouseEnabled() const { return m_trackpadMouseEnabled; } bool IsUseLeftTrackpad() const { return m_useLeftTrackpad; } - bool IsBackButtonsEnabled() const { return m_backButtonsEnabled; } ControllerPlatform GetControllerPlatform() const { return m_controllerPlatform; } const BackButtonConfig& GetBackButtonConfig() const { return m_backConfig; } @@ -81,6 +79,7 @@ private: GameModeOutcome EnableGameModeSlot(Slot& slot, bool& vigemMissingOut, uint32_t stateWaitMs); void DisableGameModeSlot(Slot& slot); + void ReleasePaddleMouseButtons(Slot& slot); void StartReadLoop(Slot& slot); void StopReadLoop(Slot& slot); void ReadLoop(Slot* slot); @@ -91,7 +90,6 @@ private: std::vector> m_slots; bool m_trackpadMouseEnabled = false; bool m_useLeftTrackpad = false; - bool m_backButtonsEnabled = false; bool m_steamPresent = false; ControllerPlatform m_controllerPlatform = ControllerPlatform::Xbox; BackButtonConfig m_backConfig; diff --git a/src/app/RemapWindow.cpp b/src/app/RemapWindow.cpp index 6c49332..5d18b53 100644 --- a/src/app/RemapWindow.cpp +++ b/src/app/RemapWindow.cpp @@ -104,7 +104,7 @@ button{font-family:'Barlow',system-ui,sans-serif;cursor:pointer;border:none;back

Back Button Mapping

-

Click Rebind on a button, then press any gamepad button on your controller. The new binding shows up here instantly.

+

Click Rebind on a button, then press any gamepad button on your controller. The new binding shows up here instantly. Pick Off to stop a paddle doing anything at all.

LEFT GRIP
@@ -127,11 +127,12 @@ button{font-family:'Barlow',system-ui,sans-serif;cursor:pointer;border:none;back