Click stability: only a hand controller's press starts it

The 3D mouse drives SteamVR's laser through the ft_pointer virtual
controller, so its events reach the screens the same way a controller's
do. The filter held every press, which turned the mouse's short drags
(selecting a character or two, nudging a slider) into clicks. Mark
button events from hand controllers and start the filter only on those.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DeeJanuzandClaude Opus 5.5 committed 2026-10-01 23:19:58 -06:00
1 parent ba6ccdfbd1
commit 540d8c425c
5 files changed
+17 -7

No files matched your search

+3 -2
View File
@@ -11,7 +11,8 @@ struct ft_controller_click {
unsigned long suppressed, clicks, drags;
};
// Hold the desktop position at press time until movement exceeds a logical-pixel
// radius. No timer, delayed button-down, or change to native mouse input.
// radius. No timer or delayed button-down. Only a hand controller's press starts
// it: the 3D mouse drives a laser too, and its short drags must stay drags.
static inline bool ft_controller_click_filter(struct ft_controller_click *c,
struct ft_event *e, double scale) {
if (e->type == FT_BUTTON && e->button >= BTN_LEFT && e->button < BTN_LEFT+8) {
@@ -19,7 +20,7 @@ static inline bool ft_controller_click_filter(struct ft_controller_click *c,
if (e->pressed) c->buttons |= bit; else c->buttons &= ~bit;
}
if (e->type == FT_BUTTON && e->pressed) {
if (e->button == BTN_LEFT && !c->held && c->threshold > 0) {
if (e->button == BTN_LEFT && e->controller && !c->held && c->threshold > 0) {
c->held = true; c->dragging = false; c->screen = e->screen;
c->x = e->x; c->y = e->y; c->radius = c->threshold * scale;
} else if (e->button != BTN_LEFT) {
+6 -1
View File
@@ -1,7 +1,7 @@
#include <assert.h>
#include "../controller-click.h"
static struct ft_event event(enum ft_event_type t, bool down, double x, double y) {
return (struct ft_event){.type=t,.screen=0,.button=BTN_LEFT,.pressed=down,.x=x,.y=y};
return (struct ft_event){.type=t,.screen=0,.button=BTN_LEFT,.pressed=down,.controller=true,.x=x,.y=y};
}
int main(void) {
struct ft_controller_click c={.threshold=8};
@@ -34,4 +34,9 @@ int main(void) {
e=event(FT_BUTTON,true,100,100);ft_controller_click_filter(&c,&e,1);
e=event(FT_BUTTON,true,100,100);e.button=BTN_RIGHT;ft_controller_click_filter(&c,&e,1);
assert(!c.held);
// The 3D mouse's laser: a short drag stays a drag, and the release stays where it was.
e=event(FT_BUTTON,true,100,100);e.controller=false;assert(ft_controller_click_filter(&c,&e,1) && !c.held);
e=event(FT_MOTION,false,104,100);assert(ft_controller_click_filter(&c,&e,1));
e=event(FT_BUTTON,false,106,100);e.controller=false;
assert(ft_controller_click_filter(&c,&e,1) && e.x==106 && c.clicks==2 && c.suppressed==1);
}
+1
View File
@@ -1741,6 +1741,7 @@ void ft_vr_poll(void (*handle)(const struct ft_event *, void *), void *data) {
e.type = FT_BUTTON;
e.button = LinuxButton(ev.data.mouse.button);
e.pressed = ev.eventType == vr::VREvent_MouseButtonDown;
e.controller = IsHandController(ev.trackedDeviceIndex);
at();
if (!e.pressed && s.titleCarry) e.x = s.carryX, e.y = s.carryY, s.titleCarry = false;
if (e.pressed) {
+1
View File
@@ -25,6 +25,7 @@ struct ft_event {
double x, y; // FT_MOTION: buffer pixels from the top left
uint32_t button; // FT_BUTTON: linux BTN_*
bool pressed;
bool controller; // FT_BUTTON: from a hand controller's laser (not the 3D mouse's)
double dx, dy; // FT_SCROLL: notches (positive dy: scroll down)
uint32_t key; // FT_KEY: linux KEY_* from our keyboard (pressed: down or up)
};