Launcher: the trackpad pointer measures from where the stick rests, so it does not creep

This commit is contained in:
NorthDroplet committed 2026-10-08 08:04:48 +00:00
1 parent 7a34ead2d5
commit 93ff021d7e
3 files changed
+47 -6

No files matched your search

+20 -4
View File
@@ -5,6 +5,7 @@
#include <imgui.h>
#include <imgui_internal.h>
#include <cmath>
#include <iostream>
#include <map>
#include <optional>
@@ -432,13 +433,13 @@ int main() {
PadFeed stick;
PadFeed trackpad(true);
ImGui::GetIO().AddMousePosEvent(400, 300);
frame(trackpad, pad());
for (int i = 0; i < 20; ++i) frame(trackpad, pad()); // it settles first
for (int i = 0; i < 10; ++i) frame(trackpad, pad(0, 3300, 0)); // a slow swipe
frame(trackpad, pad());
check(ImGui::GetIO().MousePos.x > 405, "A slow swipe on the trackpad moves the pointer");
fresh();
ImGui::GetIO().AddMousePosEvent(400, 300);
frame(stick, pad());
for (int i = 0; i < 20; ++i) frame(stick, pad());
for (int i = 0; i < 10; ++i) frame(stick, pad(0, 3300, 0));
frame(stick, pad());
check(!stick.pointing() && ImGui::GetIO().MousePos.x == 400, "The same small tilt of a thumbstick does not");
@@ -446,7 +447,7 @@ int main() {
fresh();
PadFeed slowing(true);
ImGui::GetIO().AddMousePosEvent(100, 300);
frame(slowing, pad());
for (int i = 0; i < 20; ++i) frame(slowing, pad());
for (int i = 0; i < 5; ++i) frame(slowing, pad(0, 20000, 0)); // the swipe
const float swiped = ImGui::GetIO().MousePos.x;
float tilt = 20000;
@@ -459,6 +460,21 @@ int main() {
frame(slowing, pad(0, -900, -1200));
check(slowed > swiped + 60, "A swipe that slows down moves the pointer to its end");
check(ImGui::GetIO().MousePos.x == slowed, "The pointer stops when the thumb lifts");
fresh();
PadFeed drifting(true);
ImGui::GetIO().AddMousePosEvent(400, 300);
for (int i = 0; i < 60; ++i) frame(drifting, pad(0, -2600, -2600)); // resting off the middle
check(!drifting.pointing() && ImGui::GetIO().MousePos.x == 400 && ImGui::GetIO().MousePos.y == 300,
"A trackpad resting off the middle does not move the pointer");
for (int i = 0; i < 10; ++i) frame(drifting, pad(0, 9000, -2600));
check(drifting.pointing() && ImGui::GetIO().MousePos.x > 420 && std::abs(ImGui::GetIO().MousePos.y - 300) < 1,
"A swipe moves it from where the trackpad rests");
for (int i = 0; i < 60; ++i) frame(drifting, pad(0, -1000, 1500)); // lifted: resting somewhere new
const ImVec2 rested = ImGui::GetIO().MousePos;
for (int i = 0; i < 60; ++i) frame(drifting, pad(0, -1000, 1500));
check(ImGui::GetIO().MousePos.x == rested.x && ImGui::GetIO().MousePos.y == rested.y,
"After a touch it rests again without the pointer creeping");
}
// ------------------------------------------------ trackpad pointer
@@ -468,7 +484,7 @@ int main() {
auto& io = ImGui::GetIO();
io.AddMousePosEvent(400, 300);
feed.mouse_moved(ImVec2(400, 300));
frame(feed, pad());
for (int i = 0; i < 20; ++i) frame(feed, pad());
frame(feed, pad(0, 3000, 0));
check(!feed.pointing() && io.MousePos.x == 400, "A thumb resting near the middle does not move the pointer");
+23 -2
View File
@@ -41,6 +41,12 @@ constexpr PointerFeel stick_feel{0.2f, 1400.0f, true};
// tilt drops back to rest the moment the thumb lifts. Small swipes must move
// the pointer and a quick one must cross the window.
constexpr PointerFeel trackpad_feel{0.06f, 2600.0f, false};
// The right stick never rests quite at the middle, and Steam's trackpad rests
// a little off it too, somewhere new after each touch. A reading that holds
// this still, this near the middle, for this long is where it rests.
constexpr float rest_jitter = 0.01f;
constexpr float rest_limit = 0.12f;
constexpr float rest_seconds = 0.3f;
// A mouse move this close to the last one is the same place reported again.
constexpr float pointer_slack = 2.0f;
@@ -105,9 +111,24 @@ void PadFeed::update(ImGuiIO& io, const PadState& input, float scale) {
if (pressed & focus_bits) pointing_ = false;
const PointerFeel& feel = trackpad_ ? trackpad_feel : stick_feel;
const float x = axis(pad.right_x), y = -axis(pad.right_y); // screen Y grows downward
const float raw_x = axis(pad.right_x), raw_y = -axis(pad.right_y); // screen Y grows downward
if (std::abs(raw_x - last_x_) < rest_jitter && std::abs(raw_y - last_y_) < rest_jitter &&
std::sqrt(raw_x * raw_x + raw_y * raw_y) < rest_limit) {
steady_ += io.DeltaTime;
if (steady_ >= rest_seconds) {
rest_ = ImVec2(raw_x, raw_y);
rest_known_ = true;
}
} else {
steady_ = 0;
}
last_x_ = raw_x;
last_y_ = raw_y;
// Measured from where it rests, and not at all until that is known: a
// pointer creeping off on its own would take the screen from the focus.
const float x = raw_x - rest_.x, y = raw_y - rest_.y;
const float tilt = std::min(1.0f, std::sqrt(x * x + y * y));
const bool steering = tilt > feel.dead_zone;
const bool steering = rest_known_ && tilt > feel.dead_zone;
// The first R3 only shows the pointer: a stray click must not press
// whatever the mouse last rested on.
const bool click = pointing_ && (pressed & right_thumb);
+4
View File
@@ -54,6 +54,10 @@ private:
ImGuiKey back_key_{ImGuiKey_Escape};
bool pointing_{};
bool clicking_{}; // R3 holds the left button
ImVec2 rest_{}; // where the right stick rests
bool rest_known_{};
float steady_{}; // seconds the right stick held still
float last_x_{}, last_y_{};
ImVec2 pointer_{};
ImVec2 mouse_{-1, -1}; // where the last mouse move was
};