Resolve directional pad directions in TrackpadInput

Phase 2 of the v1.20 trackpad work. Nothing dispatches these yet — the
directions are resolved and handed out, and Phase 3 wires them to the
virtual pad and to SendInput.

TrackpadMouse is renamed TrackpadInput. The name stopped being true once
the class resolves d-pad directions as well as driving the mouse; the
registry value L"TrackpadMouse" keeps its name, being the retired toggle
this has nothing to do with.

Directions come from the click rather than from touch, so a resting thumb
presses nothing, and the pad is split by where the click lands: inside
kPadRingRadius the press is the pad's click binding, outside it is the
direction under the thumb. The zone is decided once on the rising edge
and never revisited — sliding from ring to centre mid-press would
otherwise release a direction and fire the click, which is one physical
press meaning two things and the collision the split exists to stop.
Within a ring press the direction does keep following the thumb, so a
roll from up to right registers as both in turn.

Eight-way presses two directions on a diagonal; four-way rounds to the
nearer cardinal. A sector is held until the thumb clears its boundary by
8 degrees, because directions are edge-dispatched and a thumb parked on a
boundary would otherwise emit a stream of key down/up pairs rather than
merely flickering.

TrackpadDirectionProbe drives all of this through synthesized state
reports and checks 50 cases: sector bearings including the wrap through
0/360, both diagonal modes, the ring boundary either side, the zone
latching in both directions, release clearing state, hysteresis both
holding and letting go, every other mode resolving nothing, and a short
report being ignored. Feeding whole reports rather than calling the
resolver also covers the byte offsets, which is where a left-pad reader
ends up reading right-pad coordinates.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dylan DeverillandClaude Opus 5 committed 2026-09-06 21:26:09 -07:00
1 parent 234eb308b1
commit 93ff4a0f52
7 files changed
+709 -222

No files matched your search

+7 -5
View File
@@ -3,7 +3,7 @@
#include "InputInjection.h"
#include "ViGEmBusInfo.h"
#include "VirtualController.h"
#include "TrackpadMouse.h"
#include "TrackpadInput.h"
#include "KeyInput.h"
#include "TouchKeyboard.h"
#include "steam/SteamController.h"
@@ -35,8 +35,8 @@ struct ControllerManager::Slot {
std::unique_ptr<SteamController> sc;
std::unique_ptr<VirtualController> vc;
// One per physical pad — they are configured independently.
TrackpadMouse leftPad;
TrackpadMouse rightPad;
TrackpadInput leftPad;
TrackpadInput rightPad;
std::thread readThread;
std::atomic<bool> readRunning{false};
bool gameModeActive = false;
@@ -377,6 +377,8 @@ void ControllerManager::ApplyPadSettings(Slot& slot) {
slot.rightPad.SetMode(m_profile.rightPad.mode);
slot.leftPad.SetScrollDirection(m_profile.leftPad.scrollDir);
slot.rightPad.SetScrollDirection(m_profile.rightPad.scrollDir);
slot.leftPad.SetDiagonals(m_profile.leftPad.diagonals);
slot.rightPad.SetDiagonals(m_profile.rightPad.diagonals);
// The virtual controller reads pad modes straight off the profile it is
// handed every frame, so there is nothing to push to it here.
}
@@ -404,7 +406,7 @@ void ControllerManager::SetProfile(const ControllerProfile& profile) {
// Live update: the ReadLoop reads m_profile on every frame, so paddle and
// pad-click changes take effect on the very next report. Movement modes
// live inside the per-slot TrackpadMouse objects, so those are pushed.
// live inside the per-slot TrackpadInput objects, so those are pushed.
for (auto& slot : m_slots)
ApplyPadSettings(*slot);
}
@@ -1175,7 +1177,7 @@ void ControllerManager::ReadLoop(Slot* slot) {
// Edge-detected so each press sends exactly one down and each release
// exactly one up.
//
// Pad clicks ride this same path rather than living in TrackpadMouse,
// Pad clicks ride this same path rather than living in TrackpadInput,
// which is what makes a pad's click independent of its movement mode —
// the click used to be hardcoded to a left button and only fired while
// that pad was driving the mouse.