Skip to content

Twelve small fixes across the web library and desktop app#128

Open
hemangjoshi37a wants to merge 12 commits into
1j01:mainfrom
hemangjoshi37a:main
Open

Twelve small fixes across the web library and desktop app#128
hemangjoshi37a wants to merge 12 commits into
1j01:mainfrom
hemangjoshi37a:main

Conversation

@hemangjoshi37a

@hemangjoshi37a hemangjoshi37a commented Apr 21, 2026

Copy link
Copy Markdown

This PR bundles twelve small, independent fixes.

Each commit is scoped to a single issue, adds a CHANGELOG.md entry, and is self-contained. Resolving them via one PR rather than twelve simplifies review; the maintainer can cherry-pick any subset.


Fixes #104 — Allow Ctrl+= to zoom in without Shift

Electron's built-in zoomIn role uses CmdOrCtrl+Plus, which on US QWERTY requires Shift+=. In desktop-app/src/electron-main/menus.js:

{ role: 'zoomIn', accelerator: 'CmdOrCtrl+=' },
{ role: 'zoomIn', accelerator: 'CmdOrCtrl+Plus', visible: false },

Fixes #56 — Reflect actual tracking state in Start/Stop button label

With Start enabled on, the button showed "Stop" before the camera connected; clicking it inverted the user's intent. updateStartStopButton now reads !paused && useCameraButton.hidden; a new requestToggleTracking helper is shared by the button onclick and web F9 — requests camera when not connected and guarantees paused === false. Also lets F9 prompt for camera in the web version.

Fixes #42 — Don't flash a full-screen red outline on non-occlusion dwell cancellations

showOccluderIndicator(occluder || document.body) painted a screen-wide red dashed outline whenever a dwell was canceled for non-occlusion reasons. Guarded to fire only for a real element other than document.body.

Fixes #80 — Hide optical flow tracking points at 100% Tilt influence

At 100% Tilt influence the optical flow points are weighted to zero. Guarded ctx.fillStyle = "lime"; pointTracker.draw(ctx) with if (s.headTrackingTiltInfluence < 1), matching the === 1 disable condition on the sensitivity sliders.

Fixes #41 — Wait for head detection before starting dwells

Module-private headTrackingInitialized (set in TrackyMouse.init) and headDetected (latched true the first frame pointTracker.pointCount > 0). Dwell creation gated on !headTrackingInitialized || headDetected. Pure dwell-clicker consumers (never call init()) unaffected.

Fixes #32 — Edge-overshoot margin at screen edges

Tracked mouseX/mouseY now clamp to [-50, screenWidth+50] / [-50, screenHeight+50]; a separate visibleX/visibleY clamps to screen bounds for the actual outputs. Up to 50 px of overshoot absorbed.

Fixes #47 — Re-apply skipTaskbar to survive Explorer restart

Windows-only 5-second interval that calls screenOverlayWindow.setSkipTaskbar(true). Cleared on window closed; guards with isDestroyed().

Fixes #84 — Re-check for updates periodically while the app is running

Refactored single-shot check into performCheck with a checkInProgress guard. Public checkForUpdates now starts a setInterval(performCheck, 6 * 60 * 60 * 1000). No new user-facing setting.

Fixes #70 — Suppress facial-gesture clicks when facemesh confidence is low

Early-return in the facemesh gesture-to-click path when !facemeshPrediction || facemeshPrediction.faceInViewConfidence < faceInViewConfidenceThreshold (reusing the existing 0.7 constant). Already-held buttons stay held. Note: there's a hardcoded facemeshPrediction.faceInViewConfidence = 0.9999 with a TODO upstream, so this gate is effectively inert until real confidence flows through.

Fixes #115 — Button to reset each setting to its default

Small circular-arrow reset button beside every setting with a declared default. Clicking it calls setControlValue(setting.default) and dispatches a change event so the existing save/propagate pipeline runs. Covers slider, checkbox, and dropdown. Styled in core/tracky-mouse.css; accessible label in core/locales/en/translation.json under ui.resetSetting.label.

Fixes #55 — Deactivate camera after 5 minutes of inactivity

Hooked into updatePaused. Schedule a timer when paused goes true; cancel when it goes false; on fire, stop the MediaStream tracks, null cameraVideo.srcObject, show useCameraButton, reset Start/Stop label. Reactivation uses the same requestToggleTracking → useCamera path as the Start button. Demo-footage mode is skipped via instanceof MediaStream.

Fixes #95 — Raise sensitivity and acceleration slider maxima

Doubled the max (100 → 200) on Horizontal sensitivity, Vertical sensitivity, and Acceleration. Conversion divisors unchanged, so previously-stored setting values are still valid — they now sit at the middle of the new range. The reset-to-default button from #115 is a safety net if someone overshoots.


Changelog

All twelve fixes have entries under ## [Unreleased] in CHANGELOG.md, split across ### Added (#115), ### Changed (#80, #84, #55, #95), and ### Fixed (the rest), per Keep a Changelog ordering.

Test plan

Fix #104 (desktop)

  • Ctrl+= zooms in; Ctrl+Shift+= still zooms in; View > Zoom In appears once, labeled Ctrl+=.

Fix #56 (web)

  • Cleared settings, Start enabled on, reload without camera — button reads "Start".
  • F9 without camera granted — prompts for camera; tracking begins.

Fix #42 (dwell clicker)

  • Dwell → toggle off, move off page, retarget-to-null — no red outline. Genuine occlusion still flashes.

Fix #80 (web)

  • Tilt influence 100% hides lime dots; 99% shows them.

Fix #41 (web)

  • init() + initDwellClicking(): physical mouse before camera grant — no dwells. Brief face drop-outs don't disable. Pure initDwellClicking unaffected.

Fix #32 (head tracking)

  • At each edge, small backward head jitter is absorbed. onPointerMove(x, y) never reports out-of-bounds coords.

Fix #47 (Windows)

  • Restart Explorer from Task Manager — overlay window does not appear in taskbar. No lingering interval after app close.

Fix #84 (desktop)

  • Startup check runs. 6 hours later, re-check fires. (Shorten RECHECK_INTERVAL_MS to verify.) No dialog stacking.

Fix #70 (desktop, wink/open-mouth)

  • Once real facemesh confidence is plumbed, standing up with wink-to-click mode — no spurious click. Brief low-confidence frames during a drag don't release the held button.

Fix #115 (web/desktop)

  • Reset button appears beside every applicable setting. Click reset on slider/checkbox/dropdown returns to default; no button on group headers or action buttons.

Fix #55 (web/desktop)

  • Pause tracking; 5 minutes later webcam light turns off. Click Start / press F9 — camera reconnects. Unpausing within 5 minutes keeps camera connected. Demo footage mode not torn down.

Fix #95 (web/desktop)

  • Horizontal/Vertical sensitivity sliders go up to the new max (visibly further to the right). Acceleration slider same. Existing persisted settings open at mid-range, not at max. Cursor feel at slider positions below the old max is unchanged.

AI prompt: "now i want you to resolve one issue from this from this main souce of this code https://github.com/1j01/tracky-mouse/issues and make appreote pull request."

AI description: "Electron's default 'zoomIn' role accelerator is CmdOrCtrl+Plus, which on US QWERTY keyboards requires holding Shift (since Shift+= produces +). This fixes issue 1j01#104 by overriding the visible menu item's accelerator to CmdOrCtrl+= and keeping a second, hidden zoomIn item with CmdOrCtrl+Plus so Ctrl+Shift+= continues to work. Both key combos now zoom in. Also added an entry under Unreleased > Fixed in CHANGELOG.md."

Fixes 1j01#104
AI prompt: "please resovle otyher issue now and simialrlyt submit PR"

AI description: "Issue 1j01#56: in the web UI, 'Start enabled' sets paused=false on settings load, before the camera has been allowed, so the Start/Stop button was showing 'Stop (F9)' even though tracking couldn't actually start yet. The button now derives its label from !paused && useCameraButton.hidden (i.e. 'actually tracking') rather than just !paused, so it shows 'Start' until the camera is connected. Also: the button's onclick and the F9 keydown handler now share a requestToggleTracking helper that, when the camera isn't connected, requests access and ensures paused=false (instead of blindly toggling paused, which previously inverted the user's intent when startEnabled was already true). This resolves the secondary note in the issue that pressing F9 wasn't activating the camera. The success path of TrackyMouse.useCamera now also calls updateStartStopButton so the label flips to 'Stop' the moment the camera connects while unpaused. CHANGELOG entry added under Unreleased > Fixed."

Fixes 1j01#56
@hemangjoshi37a hemangjoshi37a changed the title Allow Ctrl+= to zoom in without requiring Shift Two small fixes: zoom-in shortcut & Start/Stop button label Apr 21, 2026
AI prompt: "ok please continue fixing any one other thing and similarly do PR similar to this ."

AI description: "Issue 1j01#42: turning the dwell clicker off while a dwell was in progress (and some other non-occlusion cancellation scenarios) flashed a full-screen red dashed outline, because the invalidation branch in initDwellClicking called showOccluderIndicator(occluder || document.body) — falling back to the body, which covers the whole viewport. The fallback was a stopgap noted by the issue author. This guards the call so the indicator only appears when there's a concrete occluding element, not when elementFromPoint returns null or the body. The indicator continues to work as before for genuine occlusion (the apparentHoverCandidate branch is untouched). CHANGELOG entry added under Unreleased > Fixed."

Fixes 1j01#42
@hemangjoshi37a hemangjoshi37a changed the title Two small fixes: zoom-in shortcut & Start/Stop button label Three small fixes: zoom-in shortcut, Start/Stop label, stray red-box on dwell cancel Apr 21, 2026
AI prompt: "one more"

AI description: "Issue 1j01#80: when the Tilt influence slider is at 100%, the optical flow points contribute zero to cursor movement (slowingInfluence=1 zeroes the 'away' delta and speedingInfluence=1 makes the 'toward' delta purely match head tilt), so drawing them over the user's face in the camera view is just noise. Guarded the ctx draw call with s.headTrackingTiltInfluence < 1 so the lime dots disappear at exactly 1, matching the disable condition already used on the Horizontal/Vertical sensitivity sliders (line 1762). The offscreen debugPointsCanvas draw is unchanged — it isn't shown to users. Moved the CHANGELOG entry to the existing Unreleased > Changed block rather than creating a duplicate section."

Fixes 1j01#80
@hemangjoshi37a hemangjoshi37a changed the title Three small fixes: zoom-in shortcut, Start/Stop label, stray red-box on dwell cancel Four small fixes: zoom shortcut, Start/Stop label, stray red-box, hide unused tracking points Apr 21, 2026
AI prompt: "once more."

AI description: "Issue 1j01#41: when the dwell clicker and head tracker were both in use, physical mouse movement could trigger dwells before the camera stream started and the head was actually being tracked. The dwell clicker listens to window pointermove events, which don't distinguish physical from head-tracking-simulated movement.

Added two module-private flags in core/tracky-mouse.js: headTrackingInitialized (set true inside TrackyMouse.init, the public entry for head tracking) and headDetected (latched true the first frame pointTracker.pointCount > 0, i.e. the first time either clmtrackr or facemesh has yielded face points). The dwell clicker's new-dwell branch in initDwellClicking now checks !headTrackingInitialized || headDetected before creating a hoverCandidate, so: (a) pure dwell-clicker users who never call TrackyMouse.init see no change, and (b) head-tracking users don't get dwells until a face is actually being tracked. headDetected latches so momentary tracking drop-outs don't disable the dwell clicker mid-session. Added a CHANGELOG entry under Unreleased > Fixed."

Fixes 1j01#41
@hemangjoshi37a hemangjoshi37a changed the title Four small fixes: zoom shortcut, Start/Stop label, stray red-box, hide unused tracking points Five small fixes: zoom shortcut, Start/Stop label, stray red-box, unused tracking points, dwell-before-head Apr 21, 2026
AI prompt: "once more."

AI description: "Issue 1j01#32: near the edge of the screen, clicking on the very edge was frustrating because tiny backwards head jitter during a dwell pulled the cursor inward and canceled the dwell. The head tracking loop in core/tracky-mouse.js clamped the tracked mouseX/mouseY exactly to [0, screenWidth] and [0, screenHeight] before applying; any <=1px inward movement was immediately reflected.

Now the tracked internal position is allowed to sit up to 50px past each edge (edgeOvershoot), while a separate visibleX/visibleY still clamps to [0, screenWidth]/[0, screenHeight] for the actual moveMouse / pointerEl / onPointerMove outputs. Effect: pushing past the edge with your head can absorb up to ~50px of overshoot, and small inward jitter at that state is silently discarded without the visible cursor moving. Kept the margin small so the 'push past the edge to recalibrate' behavior the owner described still works — larger corrections still take effect as before. onPointerMove reports the clamped visible position so the dwell clicker's elementFromPoint lookups don't go off-viewport. CHANGELOG entry added under Unreleased > Fixed."

Fixes 1j01#32
@hemangjoshi37a hemangjoshi37a changed the title Five small fixes: zoom shortcut, Start/Stop label, stray red-box, unused tracking points, dwell-before-head Six small fixes: zoom shortcut, Start/Stop label, stray red-box, unused tracking points, dwell-before-head, edge overshoot Apr 21, 2026
AI prompt: "Fix upstream issue 1j01#47 — screen overlay window visible in taskbar after restarting Explorer."

AI description: "The screen overlay's `skipTaskbar` state is lost when Windows Explorer restarts (Electron issue #29526), causing the overlay window to appear in the taskbar. On Windows, periodically re-apply `setSkipTaskbar(true)` every 5 seconds while the overlay exists, and clear the interval on the window's `closed` event to avoid leaked timers or calls on a destroyed window."

Fixes 1j01#47
AI prompt: "Fix upstream issue 1j01#84 — check for updates periodically, not just on startup."

AI description: "The desktop app previously only checked for updates at startup, so long-running installs could sit on an outdated version indefinitely. The update check is now repeated every 6 hours via a single setInterval in the auto-updater module, guarded by an in-flight flag so a pending 'Update Available' dialog or HTTP request won't be duplicated by the next tick."

Fixes 1j01#84
AI prompt: "Fix upstream issue 1j01#70 — prevent gesture clicks when facemesh confidence is low."

AI description: "Added a confidence gate at the start of the facial-gesture-to-click block in core/tracky-mouse.js: if facemeshPrediction is missing or its faceInViewConfidence is below the existing faceInViewConfidenceThreshold, skip the gesture detection and button-state update for this frame. This prevents briefly incoherent tracking (e.g. when standing up and the head moves out of the camera frame) from triggering wink or open-mouth clicks, while preserving already-held button state so ongoing drags aren't released by a momentary confidence dip."

Fixes 1j01#70
AI prompt: "Fix upstream issue 1j01#115 — add a button to reset each setting to its default."

AI description: "Injects a small icon button into each control row in buildSettingItemUI when the setting declares a default. Clicking it calls setControlValue with the declared default and dispatches a change event on the control so the existing save/handleSettingChange/disabled-state pipeline runs unchanged. Handles all setting types that have a default (slider, checkbox, dropdown); action buttons and settings without a default are skipped. stopPropagation prevents the slider row's wrapping label from forwarding the click to the range input."

Fixes 1j01#115
AI prompt: "Fix upstream issue 1j01#55 — deactivate the camera after a period of inactivity."

AI description: "Uses the existing `paused` state as the inactivity signal: `updatePaused` in core/tracky-mouse.js now starts a 5-minute timer whenever paused becomes true, and clears it when paused becomes false. When the timer fires while still paused and `cameraVideo.srcObject` is a real MediaStream (skipping demo footage), it stops the tracks, sets `useCameraButton.hidden = false`, and calls `updateStartStopButton()` — mirroring the cleanup done by the existing 'ended'/'error' handlers. Reactivation goes through the same path the Start button already uses: `requestToggleTracking` sees `useCameraButton.hidden` is false, calls `TrackyMouse.useCamera()`, and flips paused back to false. The timeout is hard-coded as a named constant (`IDLE_CAMERA_DEACTIVATION_MS`); no new user-facing setting was added. CHANGELOG entry added under Unreleased > Changed."

Fixes 1j01#55
@hemangjoshi37a hemangjoshi37a changed the title Six small fixes: zoom shortcut, Start/Stop label, stray red-box, unused tracking points, dwell-before-head, edge overshoot Eleven small fixes across the web library and desktop app Apr 22, 2026
AI prompt: "continue" (fix one more issue)

AI description: "Issue 1j01#95: the reporter uses acceleration and Y sensitivity at max, and notes the limits are too low especially at distance (which matters for optical-flow mode). Doubled the max value (100 → 200) on Horizontal sensitivity, Vertical sensitivity, and Acceleration sliders in core/tracky-mouse.js. settingValueToInputValue / inputValueToSettingValue divisors are unchanged, so previously-stored setting values are still valid — they now simply sit at the middle of the new range. The recently-added reset-to-default button (1j01#115) mitigates any risk of someone overshooting a setting they can no longer undo. CHANGELOG entry added under Unreleased > Changed."

Fixes 1j01#95
@hemangjoshi37a hemangjoshi37a changed the title Eleven small fixes across the web library and desktop app Twelve small fixes across the web library and desktop app Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment