Files
DeeJanuz--frametop/screens/controller-click.h
T
DeeJanuzandClaude Opus 5.5 540d8c425c 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>
2026-10-01 23:19:58 -06:00

47 lines
2.0 KiB
C

#ifndef FT_CONTROLLER_CLICK_H
#define FT_CONTROLLER_CLICK_H
#include <math.h>
#include <linux/input-event-codes.h>
#include "vr.h"
struct ft_controller_click {
bool held, dragging;
int screen;
uint32_t buttons;
double x, y, threshold, radius;
unsigned long suppressed, clicks, drags;
};
// Hold the desktop position at press time until movement exceeds a logical-pixel
// 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) {
uint32_t bit = 1u << (e->button-BTN_LEFT);
if (e->pressed) c->buttons |= bit; else c->buttons &= ~bit;
}
if (e->type == FT_BUTTON && e->pressed) {
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) {
c->held = false; // Multi-button gestures retain their usual semantics.
}
} else if (e->type == FT_MOTION && c->held && !c->dragging) {
if (e->screen == c->screen && hypot(e->x-c->x, e->y-c->y) <= c->radius) {
++c->suppressed;
return false;
}
c->dragging = true; ++c->drags;
} else if (e->type == FT_BUTTON && e->button == BTN_LEFT && !e->pressed && c->held) {
if (!c->dragging) {
e->screen = c->screen; e->x = c->x; e->y = c->y;
++c->clicks;
}
c->held = false; c->dragging = false;
} else if (e->type == FT_LEAVE && c->held) {
return false; // Preserve the implicit grab through tiny edge excursions.
}
return true;
}
#endif