v1.6.16: system-aligned mouse thresholds + UIA selection pre-gate - #6
Merged
Conversation
User report: long-press paste mode firing during slow window drag and scroll,
and the selection toolbar firing on double-click-to-open in Explorer / desktop
icons / other non-text contexts. The "no text was actually selected" cases were
slipping through because WM_COPY succeeds in many non-selection contexts (copies
the focused element's content / filename).
Layer A — system thresholds (MouseHook):
LongPressMoveCancelDistSq and MultiClickRadiusSq now resolve from
GetSystemMetrics(SM_CXDRAG) and (SM_CXDOUBLECLK) at process start. Same numbers
DragDetect uses internally; typically 16 (4 px). The old hardcoded 64 (8 px)
let a slow drag onset sit inside the cancel radius for the full long-press
timeout. Falls back to 4 px if a stripped runner returns 0.
Layer B+C — UIA selection pre-gate (TextCapture.ProbeSelectionViaUIA):
Runs before the clipboard pipeline. Three outcomes:
- HasText — TextPattern.GetSelection returns non-empty text → use it directly,
skip the WM_COPY → snapshot → clear → restore dance entirely.
- Suppress — Either TextPattern is present but the selection is degenerate, OR
focused element is DataItem/ListItem/TreeItem with
SelectionItemPattern (Explorer file row, desktop icon, list row).
No toolbar.
- Unknown — No TextPattern in the walk, no matching item type, or UIA threw.
Falls through to the existing WM_COPY → CopyViaUIA → Ctrl+Insert
pipeline. Preserves compatibility with Java Swing / legacy Edge /
shallow-UIA-tree apps that broke the previous gates.
Why this gate doesn't repeat the v1.6.5–1.6.12 over-suppression mistakes: it
only acts on definitive answers. The old gates treated "no TextPattern found"
as a stop signal (false negatives in browsers / Electron because focus lands
on parent panes). This one falls through in that case — the historical
problem apps still hit the clipboard path.
Tests: 2 new range checks for the system-metric-derived thresholds (can't pin
exact numbers since they depend on the runner's OS settings, but the bug we
fixed is excluded — values > 8 px slip past). 275 tests pass.
rokogan
added a commit
that referenced
this pull request
Jun 29, 2026
From an adversarial review of the v2.0.0 diff: - TextCapture: only restore the clipboard if its sequence number still equals the one right after our copy — if a third party wrote in the meantime, they own it now; don't clobber them. [review #1] - ResultPopup: broaden the online-lookup consent wording so it's accurate for custom "fetch" recipe actions (which send to their own host), not just the three built-in services. [review #6] - SelectionTracker: claim the Ctrl+C debounce slot before the 100ms await so a rapid second Ctrl+C is dropped instead of double-firing. [review #2] - MouseHook/KeyboardHook: null _hookThread in Uninstall so a later Install() isn't no-op'd by the non-null guard. [review #7] - SettingsManager: prune stale IDs from AppHiddenActions too, dropping now-empty per-app entries. [review #13] Release build clean; 289 tests pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two-layer fix for false-positive toolbar / paste mode triggers reported during slow window drag, scroll, and double-click-to-open in Explorer.
LongPressMoveCancelDistSqandMultiClickRadiusSqnow resolve fromGetSystemMetrics(SM_CXDRAG)/SM_CXDOUBLECLKat process start. Same thresholdDragDetectuses internally; typically 4 px. The old hardcoded 8 px let a slow drag onset sit inside the cancel radius for the full long-press timeout.TextCapture.ProbeSelectionViaUIA). Runs before the clipboard pipeline:HasText—TextPattern.GetSelectionreturns non-empty → use it directly, skip the clipboard dance entirely.Suppress— TextPattern present but selection is degenerate, or focused element isDataItem/ListItem/TreeItemwithSelectionItemPattern(Explorer file row, desktop icon, list row). No toolbar.Unknown— no TextPattern, no matching item type, or UIA threw → falls through to the existing WM_COPY → CopyViaUIA → Ctrl+Insert pipeline.Why this gate doesn't repeat past mistakes
Three UIA gates were tried and reverted across v1.6.5–v1.6.12 because they suppressed on "no TextPattern found" (false negatives in browsers / Electron, which focus parent panes). This one only suppresses on definitive answers (empty selection or item type). Anything ambiguous falls through to the unchanged clipboard fallback, so the historical problem apps still work.
What this kills
DataItem+SelectionItemPattern→ Layer C suppresses (was: WM_COPY copied filename → toolbar appeared).Fallback for misses
Settings → Excluded appsstill works app-by-app (the gate isn't excluded-app aware; the existingForegroundApp.IsExcludedcheck still runs upstream).Test plan
SnapActions.exepublishes locally (~170 MB self-contained)%APPDATA%\SnapActions\logs\YYYY-MM-DD.logforUIA pre-gate ...entries to verify which path fires per appFiles
SnapActions/Core/MouseHook.cs— Layer ASnapActions/Core/TextCapture.cs— Layer B+C (ProbeSelectionViaUIA + pre-gate call)SnapActions/Core/SelectionTracker.cs— comment-only, updated history noteSnapActions/SnapActions.csproj— version 1.6.15 → 1.6.16SnapActions.Tests/MouseHookGeometryTests.cs— threshold sanity tests