mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 09:00:11 +02:00
Gaze mode: the mouse's buttons work like Meta+J and Meta+K
The right button's press is held back like the left's: hold it, the pointer stops where you look, move onto the target, and the right click comes on the release (held still, it's a real right press). Right during the left's held-back press now starts a drag where the pointer is, as Meta+J then Meta+K does, in place of a right click there; letting go of either drops it. So once you've moved, the left alone only clicks, and the right starts a drag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
949f629338
commit
1f46616c75
4 files changed
+96
-31
No files matched your search
@@ -179,9 +179,13 @@
|
||||
// title bars, grab bars, and selections. Without gaze mode both still work from wherever the
|
||||
// pointer is.
|
||||
// In gaze mode the mouse's left button is a gaze precision button (POINTER_GAZE_MOUSE =
|
||||
// precision, the default), or clicks at once where the pointer is (direct). Pressing the right
|
||||
// button while the left one's press is held back clicks right there instead (correct with the
|
||||
// left, then right-click), and the left release does nothing.
|
||||
// precision, the default), or clicks at once where the pointer is (direct). With precision the
|
||||
// mouse's buttons work like the keyboard clicks: the right button's press is held back the same
|
||||
// way, and the right click comes on the release, where the pointer is by then (gaze_right).
|
||||
// Pressing the right button while the left one's press is held back presses the left button
|
||||
// where the pointer is now, and the mouse drags (gaze_left then gaze_right): letting go of
|
||||
// either drops it. So once you've moved the pointer, the left button alone only clicks; to drag
|
||||
// from there, press the right one. Held still for POINTER_GAZE_HOLD, either press is a real one.
|
||||
// POINTER_GAZE_MOUSE_MOVE: held (the default) or free. Held: while the gaze has the pointer,
|
||||
// moving the mouse does nothing; it moves the pointer only during a press (as a correction,
|
||||
// like a keyboard click's head). So a bumped or drifting mouse can't pull the pointer off what
|
||||
@@ -824,8 +828,11 @@ int main() {
|
||||
Clock::time_point movingSince[vr::k_unMaxTrackedDeviceCount] = {};
|
||||
// Tilt mode (see top of file).
|
||||
bool leftHeld = false, tilting = false, tiltStart = false, swallowedRight = false;
|
||||
// Right pressed during the left's held-back press: a right click there; the left's release is then nothing.
|
||||
bool chordRight = false;
|
||||
// The mouse's buttons in gaze mode (see the top): leftDown, rightDown as the relay last said;
|
||||
// aimRight, the held-back press is the right button's; chordDrag, a drag the right button
|
||||
// began during the left's held-back press (the first release drops it, the other's is nothing).
|
||||
bool leftDown = false, rightDown = false, aimRight = false, chordDrag = false;
|
||||
bool ignoreLeftUp = false, ignoreRightUp = false;
|
||||
double tiltYaw = 0, tiltPitch = 0;
|
||||
double dragDistance = 0, lastDistance = 1.5; // drag lock: distance from the anchor at the press
|
||||
bool onVrSettings = false; // the cursor is on the SteamVR Settings page (kept while dragging)
|
||||
@@ -978,26 +985,46 @@ int main() {
|
||||
};
|
||||
// The left button, from the relay's "btn trigger", with gaze mode's held-back press (see
|
||||
// the top).
|
||||
auto canAim = [&] {
|
||||
return gazeOn && gazeMousePrecision && gazeOwns && !aimHeld && !clickPress && !clickRelease &&
|
||||
hold.src == Src::None;
|
||||
};
|
||||
// Hold the press back: the pointer stops where the gaze put it.
|
||||
auto aimStart = [&](bool right) {
|
||||
gazeOwns = false;
|
||||
nudging = haveHead && Clock::now() - gz.at < std::chrono::milliseconds(200);
|
||||
nudgeRawHy = gz.rhy, nudgeRawHp = gz.rhp, nudgeHead = lastHead;
|
||||
nudgeAt = aimSince = Clock::now(), nudgeMoved = 0;
|
||||
aimHeld = true, aimRight = right;
|
||||
};
|
||||
// A drag the right button began (chordDrag): the first release drops it.
|
||||
auto chordDrop = [&](bool otherDown, bool &ignoreOtherUp) {
|
||||
chordDrag = false;
|
||||
if (leftHeld) releaseLeft();
|
||||
ignoreOtherUp = otherDown;
|
||||
if (debug) std::printf("mouse drag dropped\n");
|
||||
if (debug) std::fflush(stdout);
|
||||
};
|
||||
auto leftButton = [&](bool down) {
|
||||
leftDown = down;
|
||||
if (down) {
|
||||
if (gazeOn && gazeMousePrecision && gazeOwns && !aimHeld && !clickPress && !clickRelease &&
|
||||
hold.src == Src::None) {
|
||||
// Hold the press back: the pointer stops where the gaze put it.
|
||||
gazeOwns = false;
|
||||
nudging = haveHead && Clock::now() - gz.at < std::chrono::milliseconds(200);
|
||||
nudgeRawHy = gz.rhy, nudgeRawHp = gz.rhp, nudgeHead = lastHead;
|
||||
nudgeAt = aimSince = Clock::now(), nudgeMoved = 0;
|
||||
aimHeld = true;
|
||||
if (aimHeld && aimRight && !aimHand) {
|
||||
ignoreLeftUp = true; // the right's press is held back: the left does nothing
|
||||
return;
|
||||
}
|
||||
if (canAim()) {
|
||||
aimStart(false);
|
||||
return;
|
||||
}
|
||||
pressLeft();
|
||||
return;
|
||||
}
|
||||
if (chordRight) { // it was a right click (see the top)
|
||||
chordRight = false;
|
||||
if (ignoreLeftUp) {
|
||||
ignoreLeftUp = false;
|
||||
return;
|
||||
}
|
||||
if (aimHeld && !aimHand) {
|
||||
if (chordDrag) return chordDrop(rightDown, ignoreRightUp);
|
||||
if (aimHeld && !aimHand && !aimRight) {
|
||||
aimHeld = false;
|
||||
clickPress = true; // after this frame's pose, so it lands where the pointer was moved to
|
||||
gazeBack = nudgeMoved < 0.2;
|
||||
@@ -1005,6 +1032,46 @@ int main() {
|
||||
}
|
||||
if (leftHeld) releaseLeft();
|
||||
};
|
||||
// The right button (see the top); false: not taken here (a tilt, or passed on as it is).
|
||||
auto rightButton = [&](bool down) {
|
||||
rightDown = down;
|
||||
if (down) {
|
||||
if (aimHeld && !aimHand && !aimRight) {
|
||||
// During the left's held-back press: press the left where the pointer is now (the
|
||||
// correction is a lesson), and the mouse drags.
|
||||
aimHeld = false;
|
||||
chordDrag = gazeBack = true;
|
||||
pressLeft();
|
||||
if (debug) std::printf("mouse drag began (right during left)\n");
|
||||
if (debug) std::fflush(stdout);
|
||||
return true;
|
||||
}
|
||||
if (canAim() && !leftHeld) {
|
||||
aimStart(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (ignoreRightUp) {
|
||||
ignoreRightUp = false;
|
||||
return true;
|
||||
}
|
||||
if (chordDrag) {
|
||||
chordDrop(leftDown, ignoreLeftUp);
|
||||
return true;
|
||||
}
|
||||
if (aimHeld && !aimHand && aimRight) {
|
||||
aimHeld = aimRight = false;
|
||||
pressRight = clickPress = true; // the right click, where the pointer was moved to
|
||||
gazeBack = nudgeMoved < 0.2;
|
||||
return true;
|
||||
}
|
||||
if (leftHeld && heldButton == "b") { // its press, held still into a real one
|
||||
releaseLeft();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// POINTER_GAZE_MOUSE_MOVE=held (see the top): the gaze is fresh and nothing is pressed, so a
|
||||
// mouse move doesn't move the pointer.
|
||||
auto mouseMoveHeld = [&] {
|
||||
@@ -1364,13 +1431,9 @@ int main() {
|
||||
} else if (std::strncmp(buf, "btn trigger 0", 13) == 0) {
|
||||
leftButton(false);
|
||||
continue;
|
||||
} else if (std::strncmp(buf, "btn b 1", 7) == 0 && aimHeld && !aimHand) {
|
||||
// Right during the left's held-back press: a right click where the pointer is now,
|
||||
// the correction a lesson as with the left (see the top).
|
||||
aimHeld = false;
|
||||
pressRight = clickPress = true;
|
||||
gazeBack = nudgeMoved < 0.2;
|
||||
chordRight = swallowedRight = true; // both releases are nothing
|
||||
} else if (std::strncmp(buf, "btn b 1", 7) == 0 && rightButton(true)) {
|
||||
continue;
|
||||
} else if (std::strncmp(buf, "btn b 0", 7) == 0 && rightButton(false)) {
|
||||
continue;
|
||||
} else if (std::strncmp(buf, "btn b 1", 7) == 0 && leftHeld) {
|
||||
tilting = tiltStart = swallowedRight = true; // right press while dragging: tilt, no right-click
|
||||
@@ -2122,10 +2185,12 @@ int main() {
|
||||
|
||||
// A held-back press (see the top): held still long enough, it's a real press (a drag);
|
||||
// released, it's a click where the pointer is now (this frame's pose has gone out).
|
||||
if (!active) aimHeld = clickPress = aimHand = confirmLesson = false; // released meanwhile: nothing to click
|
||||
if (!active) aimHeld = aimRight = clickPress = aimHand = confirmLesson = false; // released meanwhile: nothing to click
|
||||
if (aimHeld && !aimHand && nudgeMoved < 0.2 && tnow - aimSince >= std::chrono::duration<double>(gazeHold)) {
|
||||
aimHeld = false;
|
||||
gazeBack = true;
|
||||
pressRight = aimRight; // the right button's: a real right press (see the top)
|
||||
aimRight = false;
|
||||
pressLeft();
|
||||
}
|
||||
// A keyboard click held still for POINTER_GAZE_HOLD: a real press, then the head drags
|
||||
|
||||
Reference in new issue
Block a user