diff --git a/docs/controller-click-stability.md b/docs/controller-click-stability.md index 8523955..5539ced 100644 --- a/docs/controller-click-stability.md +++ b/docs/controller-click-stability.md @@ -6,10 +6,12 @@ zone delivers the click at the original position, even if the hand moved during release. Moving outside the zone begins a normal drag immediately; returning to the zone does not turn it back into a click. There is no hold-duration timer. -This filters overlay pointer content events on desktop monitors only. Native mouse -input, SteamVR UI, separate screen grab bars and floating-app title-bar carrying -are unaffected. Multi-button gestures keep their existing behavior. A motion -onto another desktop monitor starts a drag; cross-monitor motion is not stabilized. +This filters overlay pointer content events on desktop monitors only, and only +presses from hand controllers start it. The 3D mouse (whose laser comes from the +`ft_pointer` virtual controller), SteamVR UI, separate screen grab bars and +floating-app title-bar carrying are unaffected. Multi-button gestures keep their +existing behavior. A motion onto another desktop monitor starts a drag; +cross-monitor motion is not stabilized. CLI (runtime preferences, reset to 8 on desktop restart): diff --git a/screens/controller-click.h b/screens/controller-click.h index 077f355..ec5cfe6 100644 --- a/screens/controller-click.h +++ b/screens/controller-click.h @@ -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) { diff --git a/screens/tests/controller-click-test.c b/screens/tests/controller-click-test.c index a807fe4..1f368bd 100644 --- a/screens/tests/controller-click-test.c +++ b/screens/tests/controller-click-test.c @@ -1,7 +1,7 @@ #include #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); } diff --git a/screens/vr.cpp b/screens/vr.cpp index 53ddc5f..90624fa 100644 --- a/screens/vr.cpp +++ b/screens/vr.cpp @@ -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) { diff --git a/screens/vr.h b/screens/vr.h index eb7abf8..6189327 100644 --- a/screens/vr.h +++ b/screens/vr.h @@ -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) };