Releases: 0xfullex/selection-hook
Release list
v2.0.3
What's Fixed
Fixes a memory leak and several classes of incorrect selection detection. All of
them surface when the Node.js main thread is busy — which happens on every
garbage collection or heavy render.
- Memory leak when the event queue fills up (#19, #20) — event payloads were
never freed if the enqueue failed. - Long drags wrongly treated as selections — gesture timing was measured when
the event was processed, not when it happened. Two events 16 seconds apart
could be seen 0.02 ms apart, so the 15-second maximum drag time never applied. - Selections silently dropped — selecting text and then moving the pointer
away while the main thread was busy discarded the selection with no error. - Held mouse buttons reported as
None(Windows) — during a drag with a full
queue,mouse-movelost the button state. - Shift+Click missed when Shift was released before the queue drained
(Windows). - Stale gesture state after
stop()/start()— a restarted session could
pair a newmouse-upwith the previous session'smouse-down.
Root cause in every case: event state was rebuilt while processing the event
instead of captured when it occurred. Both platforms now carry a complete
snapshot in the event payload.
Compatibility
No API or configuration changes. Linux is unchanged in this release.
Full Changelog: v2.0.2...v2.0.3
v2.0.2
Bug Fixes
Selection Retrieval Fails When a tabindex Container Has Focus (#18, supersedes #14)
In Chromium-based browsers (Chrome, Edge, Electron), an element with a tabindex attribute (any value, including -1) receives accessibility focus when clicked, but the selection itself is managed by an ancestor (the UIA Document / AXWebArea). Previously only the focused element was queried, so retrieval failed on pages using tabindex containers (e.g. MUI tables with tabindex rows) and fell back to the clipboard — which on Windows is gated by cursor shape and control type, making text-selection events fire unreliably.
Windows:
- After the focused-element TextPattern and LegacyIAccessible attempts fail, walk up the UIA ancestor chain (up to 10 levels) and retry TextPattern
- Ancestors may only succeed via
GetSelection— the document-range fallbacks remain focused-element-only, so non-standard providers cannot return whole-document text as a false positive - Query
IsSelectionActivebefore fetching text in the document-range fallbacks, avoiding needless whole-document reads - Selections in
tabindexcontainers are now retrieved via UI Automation regardless of cursor shape, with selection coordinates, instead of relying on the gated clipboard fallback
macOS:
- Add an ancestor walk-up strategy so selections spanning multiple child nodes (e.g. across table rows with
tabindex) are retrieved via AXAPI instead of falling back to the clipboard
Linux is unaffected: the Primary Selection mechanism does not depend on the focused accessibility element.
Embedded Object Markers Polluting Extracted Text (Windows)
Chromium's UIA TextPattern returns embedded objects (inline images, icons) as U+FFFC object-replacement characters wrapped in line breaks (\n\uFFFC\n). With the new UIA retrieval path these markers would have surfaced in the extracted text. They are now stripped together with their adjacent line breaks, matching native copy behavior — inline icons no longer inject  characters or break sentences across lines. Line breaks not adjacent to a marker (real paragraph breaks) are preserved.
Documentation
- Document the UIA ancestor walk-up behavior in
WINDOWS.md(en / zh-CN)
Full Changelog: v2.0.1...v2.0.2
v2.0.1
Bug Fixes
Clipboard Backup/Restore: All Formats Support (#8)
Previously, clipboard backup/restore during selection detection only preserved plain text. All other formats (images, HTML, RTF, files, custom app formats) were permanently lost.
Windows:
- Enumerate and backup all clipboard formats via
EnumClipboardFormats - Skip synthesized formats (CF_TEXT, CF_BITMAP, etc.) to let Windows re-synthesize on restore
- Skip unsafe formats (CF_PRIVATEFIRST–CF_PRIVATELAST, CF_OWNERDISPLAY)
- Special handling for CF_ENHMETAFILE via
GetEnhMetaFileBits/SetEnhMetaFileBits
macOS:
- Backup all pasteboard items and type representations via
[item dataForType:] - Support multiple pasteboard items (e.g. multi-file copy in Finder)
- Use
NSPasteboardContentsCurrentHostOnlyto avoid triggering Universal Clipboard sync on restore
Clipboard Sequence Tracking Fix
- Windows: Update
clipboard_sequenceafter allRestoreClipboardcall sites to prevent false-positive selection reads on subsequent mouse events - macOS: Add
RestoreClipboardon timeout path (when Cmd+C response is not detected in time) to prevent clipboard data loss
Build Compatibility
- Replace non-ASCII characters (em-dashes, etc.) in C++ comments with ASCII equivalents to avoid MSVC C4819 warnings on non-Unicode code pages
Documentation
- Document UIPI limitation for elevated/administrator windows on Windows
- Document Electron same-process selection limitation (clipboard fallback +
--disable-renderer-accessibilitydeadlock risk)
v2.0.0
What's New
Linux Platform Support
- Full X11 support via XFixes PRIMARY selection monitoring with bidirectional trigger detection
- Wayland support via wlr-data-control protocol for PRIMARY selection monitoring
- Wayland compositor cursor position calibration (KDE KWin, GNOME Mutter, Hyprland) with XWayland coordinate normalization
- Data-control debounce fallback for Wayland environments without input access
linuxGetEnvInfo()API for querying display server, compositor, and session detailsINVALID_COORDINATE(-99999) sentinel for unavailable screen positions- Mouse drag suppression to avoid spurious selection change events
- Right-click early-exit guard for X11
Cross-Platform Improvements
- Whitespace-only selection filtering (unified
IsTrimmedEmptyacross all platforms) - Native instance creation moved to constructor — config/query methods now available before
start() - TypeScript
exportsfield and typecheck validation SelectionConfigtype definitions aligned with actual implementation
Bug Fixes
- Windows: Restored key-check polling loop in
GetTextViaClipboard; multiple critical fixes - macOS: Critical bug fixes from code review
- Linux: Fixed X11 primary selection detection failures; Wayland IPC coordinate normalization
Developer Experience
npm run formatcommand with clang-format enforcement across codebase- Comprehensive documentation: API reference, platform guides, usage guide
- Chinese (zh-CN) documentation translations
- Linux prebuild support in CI/CD pipeline
- Beta publishing support with npm dist-tag
Breaking Changes
- Linux platform added as a supported target (new native dependencies)
SelectionConfiginterface updated to match actual implementation- Event data structure aligned with documentation
v1.0.13
v1.0.12
What's Changed
- fix(windows): enhance double-click detection by checking window state before selection
- fix: ignore QUNS_BUSY in ShouldProcessGetSelection by @aooiuu in #10
New Contributors
Full Changelog: v1.0.11...v1.0.12
v1.0.11
- fix(macOS): add type safety for AXAPI calls to prevent crashes
Full Changelog: v1.0.10...v1.0.11
v1.0.10
- fix(macOS): improve validation for selected text range to handle empty strings and ensure valid extraction
Full Changelog: v1.0.9...v1.0.10
v1.0.9
- [Windows] refactor: remove FocusControl method
- [macOS] fix: validate and adjust selected text range to prevent crashes
Full Changelog: v1.0.8...v1.0.9
v1.0.8
- fix(macOS): shift+click cursor detection
- fix(Windows): use SetProcessDPIAware instead of SetProcessDpiAwareness when WIndows version is blow 8.1
- fix(Windows): enhance mouse cursor detection for clipboard mode
Full Changelog: v1.0.7...v1.0.8