mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 07:00:14 +02:00
Pointer: sleep on the command socket while the pointer is off
The main loop slept a fixed 8 ms, about 116 wakeups a second, whether the pointer was awake or not, and every second it looked up every overlay's handle and read a string property from all 64 device slots to find its own device. With the pointer off and hand gestures off, the loop now waits in poll() on its command socket for up to 250 ms, or 20 ms while mapped Frame controller buttons are being read (SteamVR input has no event to wait for). A mouse command ends the wait at once. The headset's activity level, the game check, and the "vrgame" and "gazeawake" repeats keep going at that pace. The 50 ms visibility poll and the 1 s handle lookups run only while the pointer is awake, and waking forces both. The device index is looked for only while it's unknown, and again after SteamVR activates or deactivates a device. The HMD pose history is kept only with hand gestures on, its one user. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
19032f8963
commit
0680297efa
3 files changed
+41
-11
No files matched your search
@@ -36,6 +36,13 @@
|
||||
// pointer is off the helper also stops listing overlays with vrcmd, whose connection every
|
||||
// second kept SteamVR from going to standby.
|
||||
//
|
||||
// Idle: while the pointer is off (and hand gestures are off), the main loop waits for a command
|
||||
// on its socket for up to 250 ms instead of running every 8 ms, or 20 ms while it reads mapped
|
||||
// Frame controller buttons (vrbuttons.h), which have no event to wait for. What has to go on
|
||||
// meanwhile still does: the headset's activity level, the game check and the relay's "vrgame"
|
||||
// and "gazeawake" repeats, and a mouse command wakes it at once. The overlay lookups (the 50 ms
|
||||
// visibility poll, the once-a-second handles) wait for the pointer to wake, and run right then.
|
||||
//
|
||||
// Last used wins: when a real controller moves (picked up), the pointer is released
|
||||
// (driver "hide", which also drops its hand role hint), so the controller gets
|
||||
// its role and laser back. The next mouse input reconnects and claims the laser again.
|
||||
@@ -329,6 +336,7 @@ extern "C" {
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -859,6 +867,8 @@ int main() {
|
||||
std::map<std::string, bool> sceneGraph; // no texture: plane test instead of ComputeOverlayIntersection
|
||||
std::map<std::string, bool> visible; // refreshed every 50 ms
|
||||
auto lastVisible = std::chrono::steady_clock::now();
|
||||
auto lastSlow = std::chrono::steady_clock::now() - std::chrono::seconds(10);
|
||||
unsigned listGeneration = 0; // the overlay list the handles were looked up from
|
||||
// The plane of the last panel the cursor was on, and the last point on it (panel edges).
|
||||
Vec3 edgePoint, edgeNormal, edgeLast;
|
||||
std::string edgeKey;
|
||||
@@ -901,6 +911,8 @@ int main() {
|
||||
wokeAt = t;
|
||||
active = true;
|
||||
recenter = true;
|
||||
// Overlay handles and visibility weren't looked at while it was off (see "Idle" at the top).
|
||||
lastSlow = lastVisible = t - std::chrono::seconds(10);
|
||||
SendTo(out, "ft_pointer", "role " + role); // POINTER_ROLE, before it takes it
|
||||
SendTo(out, "ft_pointer", "show");
|
||||
claimPending = true; // take the laser without clicking, once SteamVR has bound the device
|
||||
@@ -1127,8 +1139,6 @@ int main() {
|
||||
return gazeOn && gazeMouseHeld && !inGame && !headsetOff && Clock::now() - gz.at < std::chrono::seconds(1) &&
|
||||
!aimHeld && !leftHeld && !tilting && hold.src == Src::None && !clickPress && !clickRelease;
|
||||
};
|
||||
auto lastSlow = std::chrono::steady_clock::now() - std::chrono::seconds(10);
|
||||
unsigned listGeneration = 0; // the overlay list the handles were looked up from
|
||||
|
||||
// --- Panel placement (see "Placement" at the top of the file) ---
|
||||
// Device pose, given in the standing universe, sent to the driver in raw space.
|
||||
@@ -1669,7 +1679,7 @@ int main() {
|
||||
}
|
||||
|
||||
// Hands (see the top): pinches and grips from ft-hands.
|
||||
{
|
||||
if (handsOn) {
|
||||
vr::TrackedDevicePose_t h0;
|
||||
sys->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0, &h0, 1);
|
||||
if (h0.bPoseIsValid) poses.Add(tnow, h0.mDeviceToAbsoluteTracking);
|
||||
@@ -1968,9 +1978,10 @@ int main() {
|
||||
}
|
||||
followAt = tnow;
|
||||
|
||||
// Slow work, once a second and when the overlay list is new: overlay handles, our device index.
|
||||
// Slow work, once a second and when the overlay list is new: overlay handles, our device
|
||||
// index. Only while the pointer is awake (see "Idle" at the top).
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (now - lastSlow > std::chrono::seconds(1) || overlays.Generation() != listGeneration) {
|
||||
if (active && (now - lastSlow > std::chrono::seconds(1) || overlays.Generation() != listGeneration)) {
|
||||
lastSlow = now;
|
||||
listGeneration = overlays.Generation();
|
||||
handles.clear();
|
||||
@@ -1992,16 +2003,16 @@ int main() {
|
||||
sceneGraph[key] = (tw == 0 || th == 0) && tt == vr::VROverlayTransform_Absolute &&
|
||||
key.rfind("frametop.", 0) != 0;
|
||||
}
|
||||
ours = vr::k_unTrackedDeviceIndexInvalid;
|
||||
for (vr::TrackedDeviceIndex_t i = 0; i < vr::k_unMaxTrackedDeviceCount; ++i) {
|
||||
// Our device keeps its index; it's looked for again when a device is activated or
|
||||
// deactivated (the events below).
|
||||
for (vr::TrackedDeviceIndex_t i = 0; ours == vr::k_unTrackedDeviceIndexInvalid && i < vr::k_unMaxTrackedDeviceCount; ++i) {
|
||||
char type[64] = "";
|
||||
sys->GetStringTrackedDeviceProperty(i, vr::Prop_ControllerType_String, type, sizeof type);
|
||||
if (std::strcmp(type, "ft_pointer") == 0) ours = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (now - lastVisible > std::chrono::milliseconds(50) || visible.size() != handles.size()) {
|
||||
if (active && (now - lastVisible > std::chrono::milliseconds(50) || visible.size() != handles.size())) {
|
||||
lastVisible = now;
|
||||
visible.clear();
|
||||
for (const auto &[key, h] : handles) visible[key] = overlay->IsOverlayVisible(h);
|
||||
@@ -2320,6 +2331,8 @@ int main() {
|
||||
if (ev.eventType == vr::VREvent_DashboardActivated || ev.eventType == vr::VREvent_DashboardDeactivated ||
|
||||
ev.eventType == vr::VREvent_DashboardOverlayCreated || ev.eventType == vr::VREvent_SceneApplicationChanged)
|
||||
overlays.Kick();
|
||||
if (ev.eventType == vr::VREvent_TrackedDeviceActivated || ev.eventType == vr::VREvent_TrackedDeviceDeactivated)
|
||||
ours = vr::k_unTrackedDeviceIndexInvalid;
|
||||
if (ev.eventType == vr::VREvent_Quit) {
|
||||
sys->AcknowledgeQuit_Exiting();
|
||||
|
||||
@@ -2328,6 +2341,15 @@ int main() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(8));
|
||||
// Idle (see the top): wait for a command instead. Not with anything still to finish (the
|
||||
// claim pulse, a click's release, a press).
|
||||
const bool idle = !active && !handsOn && !claimPending && !claimHeld && !clickRelease && !leftHeld &&
|
||||
hold.src == Src::None;
|
||||
if (idle) {
|
||||
pollfd p{in, POLLIN, 0};
|
||||
poll(&p, 1, controllerButtons.Watching(inGame) ? 20 : 250);
|
||||
} else {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(8));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user