mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 10:00:11 +02:00
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>
47 lines
2.0 KiB
C
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
|