Part of selection-hook — A Node.js native module for monitoring text selections across applications.
See also: Guide · Windows Platform Details · Linux Platform Details
- Constructor
- Methods
- Lifecycle —
start(),stop(),isRunning(),cleanup() - Selection —
getCurrentSelection(),setSelectionPassiveMode() - Mouse Tracking —
enableMouseMoveEvent(),disableMouseMoveEvent() - Clipboard —
enableClipboard(),disableClipboard(),setClipboardMode(),writeToClipboard(),readFromClipboard() - Filtering —
setGlobalFilterMode(),setFineTunedList() - Platform-Specific —
macIsProcessTrusted(),macRequestProcessTrust(),linuxGetEnvInfo()
- Lifecycle —
- Events —
text-selection,mouse-move,mouse-up,mouse-down,mouse-wheel,key-down,key-up,status,error - Types —
SelectionConfig,TextSelectionData,MouseEventData,MouseWheelEventData,KeyboardEventData,LinuxEnvInfo,Point - Constants —
INVALID_COORDINATE,SelectionMethod,PositionLevel,FilterMode,FineTunedListType,DisplayProtocol,CompositorType - TypeScript Support
const hook = new SelectionHook();Creates a new SelectionHook instance and initializes the native module. The native instance is created immediately in the constructor, so query methods (e.g., linuxGetEnvInfo(), macIsProcessTrusted()) and configuration methods (e.g., enableClipboard(), setGlobalFilterMode()) can be called before start().
All configuration and query methods can be called before
start()unless otherwise noted.
Start monitoring text selections.
Configuration methods can be called before start() to pre-configure the hook. If start() is called with a config object, only config values that differ from defaults will be applied — values equal to defaults are skipped (pre-start settings for those fields are preserved).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
config |
SelectionConfig |
No | — | Configuration options. See SelectionConfig for all available fields and defaults. |
Returns: boolean — true if started successfully.
hook.start({
debug: true,
enableClipboard: false,
globalFilterMode: SelectionHook.FilterMode.EXCLUDE_LIST,
globalFilterList: ["WindowsTerminal.exe", "cmd.exe"],
});See SelectionHook.FilterMode for filter mode details.
Linux:
enableClipboard,clipboardMode, andclipboardFilterListhave no effect on Linux (clipboard fallback is not implemented). On Wayland,globalFilterMode/globalFilterListare ineffective becauseprogramNameis always empty. See Linux platform details for full details.
macOS: macOS requires accessibility permissions for the selection-hook to function properly. Ensure the user has enabled accessibility permissions before calling
start().
- Node: use
selection-hook'smacIsProcessTrusted()andmacRequestProcessTrust()to check and request permissions.- Electron: use Electron's
systemPreferences.isTrustedAccessibilityClient()to check permissions.
Stop monitoring text selections.
Returns: boolean — true if stopped successfully.
Check if selection-hook is currently running.
Returns: boolean — true if monitoring is active.
Release resources and stop monitoring. Should be called before the application exits.
Get the current text selection if any exists.
Returns: TextSelectionData | null — Current selection data, or null if no selection exists or if the hook is not running.
Set passive mode for selection. In passive mode, text-selection events will not be emitted — selections are only retrieved via getCurrentSelection().
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
passive |
boolean |
Yes | — | true to enable passive mode, false to disable. |
Returns: boolean — true if set successfully.
// Enable passive mode — retrieve selections on demand
hook.setSelectionPassiveMode(true);
// Later, when triggered by a shortcut or key hold:
const selection = hook.getCurrentSelection();
if (selection) {
console.log("Selected text:", selection.text);
}Enable mouse move events. This causes high CPU usage due to frequent event firing. Disabled by default.
Returns: boolean — true if enabled successfully.
Disable mouse move events. This is the default state.
Returns: boolean — true if disabled successfully.
Linux: Linux uses PRIMARY selection instead of clipboard fallback.
enableClipboard(),disableClipboard(), andsetClipboardMode()have no effect.writeToClipboard()returnsfalseandreadFromClipboard()returnsnull. Host applications should use their own clipboard API (e.g., Electron clipboard).
Enable clipboard fallback for text selection. Enabled by default.
On Windows, applications outside INCLUDE_CLIPBOARD_DELAY_READ use restore-first fallback: it backs up all formats it can copy and attempts to restore them after retrieval, including restoring an originally empty clipboard to empty. Unsupported or unreadable formats are skipped without refusing retrieval, but cannot be restored.
Once the fallback inserts any copy-shortcut input, including a partial insertion, it always attempts to restore the original clipboard and still returns text already read. A user's Ctrl+C after injection can therefore be overwritten by restoration. This is the deliberate cost of restore-first behavior.
The only preservation exception requires a physical Ctrl+C, Ctrl+X, Ctrl+Insert, or Shift+Delete keydown that occurs during the clipboard transaction (after the fallback starts; keys pressed earlier, for example while accessibility APIs are still being tried, do not count) and before any injection, with zero copy-shortcut inputs inserted in the transaction, followed by a confirmed clipboard sequence change. Extra modifiers and injected shortcuts do not qualify. The candidate sequence must be newer than both the sequence at keydown and the sequence after clearing and closing the clipboard, accounting for sequence wraparound, and remain stable when the clipboard is opened, read, and the transaction completes. Changes caused by our own locked read do not invalidate a confirmed user copy. Without stable evidence, restoration remains the default. Ordinary keys, mouse input, and context-menu copy do not qualify; content copied through a context menu may therefore be overwritten.
Recognizing one of these physical shortcuts immediately prevents further copy injections in that transaction, even before the sequence changes. Explicit getCurrentSelection() calls continue polling within the original budget and return the user's text when it arrives, including while Ctrl+C remains held.
Automatic retrieval checks whether Ctrl is held at three keyboard-interruption checkpoints: before the Ctrl+Insert stage starts, before the Ctrl+C stage starts, and before reading in the Ctrl+C stage. If Ctrl is held at a reached checkpoint, retrieval aborts, emits no text-selection event, and attempts to restore the original clipboard. If Ctrl is not held at the reached checkpoints, a physical copy/cut during the transaction and before any injection follows the same rule as an explicit call: it stops further injection, continues polling within the original budget, returns the user's text, and preserves the confirmed write. This includes Shift+Delete and Ctrl+C whose Ctrl has already been released. Any actual copy-shortcut injection still requires restoration as described above.
Restoration is best effort. Each clipboard open in this path has at most five attempts with 5 ms between failed attempts. A failed format does not prevent attempts to restore the remaining saved formats, and restoration failure does not discard text already read. stop() or teardown still attempts restoration unless a user copy was already confirmed. Persistent Windows API failures can prevent full restoration. Applications configured in INCLUDE_CLIPBOARD_DELAY_READ retain the legacy behavior unchanged; these restore-first changes do not apply. See Windows clipboard fallback for details.
Returns: boolean — true if enabled successfully.
Disable clipboard fallback for text selection. Clipboard is enabled by default.
Returns: boolean — true if disabled successfully.
Configure how clipboard fallback works with different programs. See SelectionHook.FilterMode constants for details.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
mode |
FilterMode |
Yes | — | Clipboard filter mode. |
programList |
string[] |
No | [] |
Program names to include or exclude. |
Returns: boolean — true if set successfully.
// Only use clipboard fallback for specific apps that need it
hook.setClipboardMode(SelectionHook.FilterMode.INCLUDE_LIST, [
"acrobat.exe", "wps.exe"
]);
// Prevent clipboard fallback in apps where Ctrl+C has special behavior
hook.setClipboardMode(SelectionHook.FilterMode.EXCLUDE_LIST, [
"code.exe", "devenv.exe"
]);See Windows Platform Details — Clipboard Fallback for details on when and why to configure this.
Write text to the system clipboard. Useful for implementing custom copy functions.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
text |
string |
Yes | — | Text to write to clipboard. |
Returns: boolean — true if written successfully.
Read text from the system clipboard.
Returns: string | null — Clipboard text content, or null if clipboard is empty or contains non-text data.
Configure which applications should trigger text selection events. You can include or exclude specific applications from selection monitoring. See SelectionHook.FilterMode constants for details.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
mode |
FilterMode |
Yes | — | Global filter mode. |
programList |
string[] |
No | [] |
Program names to include or exclude. |
Returns: boolean — true if set successfully.
// Only monitor selections in specific programs
hook.setGlobalFilterMode(SelectionHook.FilterMode.INCLUDE_LIST, [
"chrome.exe", "firefox.exe", "code.exe"
]);
// Monitor all programs except terminals
hook.setGlobalFilterMode(SelectionHook.FilterMode.EXCLUDE_LIST, [
"WindowsTerminal.exe", "cmd.exe", "powershell.exe"
]);Linux: On Wayland,
programNameis always empty so program-based filtering will not work.
Configure fine-tuned lists for specific application behaviors. This allows you to customize how the selection hook behaves with certain applications that may have unique characteristics.
For example, you can add acrobat.exe to those lists to enable text selected in Acrobat.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
listType |
FineTunedListType |
Yes | — | Fine-tuned list type. |
programList |
string[] |
No | [] |
Program names for the fine-tuned list. |
Returns: boolean — true if set successfully.
// Skip cursor detection for apps with custom cursors
hook.setFineTunedList(
SelectionHook.FineTunedListType.EXCLUDE_CLIPBOARD_CURSOR_DETECT,
["acrobat.exe", "cajviewer.exe"]
);
// Add clipboard read delay for apps that modify clipboard multiple times
hook.setFineTunedList(
SelectionHook.FineTunedListType.INCLUDE_CLIPBOARD_DELAY_READ,
["acrobat.exe"]
);Platform: Windows only. See Windows Platform Details — App Compatibility for when and why to use these lists.
Check if the process is trusted for accessibility. If the process is not trusted, selection-hook will still run, but it won't respond to any events. Make sure to guide the user through the authorization process before calling start().
Returns: boolean — true if the process is trusted for accessibility.
Platform: macOS only.
Try to request accessibility permissions. This MAY show a dialog to the user if permissions are not granted.
Returns: boolean — The current permission status, not the request result.
Platform: macOS only.
Get Linux environment information. Returns an object with display protocol, compositor type, input device access status, and root status. All values are detected once at construction time and cached. Returns null on non-Linux platforms.
Returns: LinuxEnvInfo | null — Linux environment info, or null on non-Linux platforms.
See LinuxEnvInfo for the full structure, and SelectionHook.CompositorType for compositor constants.
const info = hook.linuxGetEnvInfo();
// info = {
// displayProtocol: 2, // SelectionHook.DisplayProtocol.WAYLAND
// compositorType: 1, // SelectionHook.CompositorType.KWIN
// hasInputDeviceAccess: true, // user can access input devices
// isRoot: false
// }Platform: Linux only.
Emitted when text is selected in any application. See TextSelectionData for the data structure.
hook.on("text-selection", (data) => {
// data contains selection information
});Mouse events. See MouseEventData for the data structure.
hook.on("mouse-up", (data) => {
// data contains mouse coordinates and button info
});Mouse wheel events. See MouseWheelEventData for the data structure.
hook.on("mouse-wheel", (data) => {
// data contains wheel direction info
});Keyboard events. See KeyboardEventData for the data structure.
hook.on("key-down", (data) => {
// data contains key code and modifier info
});Hook status changes.
hook.on("status", (status) => {
// status is a string, e.g. "started", "stopped"
});Error events. General errors are only emitted when debug is set to true in start(). Fatal errors (e.g., hook startup/shutdown failures) are always emitted regardless of the debug setting.
hook.on("error", (error) => {
// error is an Error object
});Coordinate note: All coordinates are returned as screen coordinates — the raw values from each platform's display system. To convert to logical coordinates (DIP) for UI positioning:
- Windows: Use
screen.screenToDipPoint(point)in Electron.- macOS: No conversion needed — screen coordinates are already logical on macOS. Note:
screen.screenToDipPoint()is not available on macOS.- Linux: Use
screen.screenToDipPoint(point)in Electron — works uniformly for both X11 and Wayland sessions. Coordinates may be-99999when unavailable on Wayland. See Coordinate Systems and HiDPI Scaling for details.
Represents a 2D coordinate point.
{ x: number; y: number }Configuration options for start(). All fields are optional. Can also be set individually via configuration methods before or after start().
| Property | Type | Default | Description |
|---|---|---|---|
debug |
boolean |
false |
Enable debug logging. |
enableMouseMoveEvent |
boolean |
false |
Enable mouse move tracking. Can be set at runtime. |
enableClipboard |
boolean |
true |
Enable clipboard fallback. Can be set at runtime. |
selectionPassiveMode |
boolean |
false |
Enable passive mode. Can be set at runtime. |
clipboardMode |
FilterMode |
DEFAULT |
Clipboard filter mode. Can be set at runtime. |
clipboardFilterList |
string[] |
[] |
Program list for clipboard mode. Can be set at runtime. |
globalFilterMode |
FilterMode |
DEFAULT |
Global filter mode. Can be set at runtime. |
globalFilterList |
string[] |
[] |
Program list for global filter mode. Can be set at runtime. |
See SelectionHook.FilterMode for filter mode details.
Represents text selection information including content, source application, and coordinates.
| Property | Type | Description |
|---|---|---|
text |
string |
The selected text content. |
programName |
string |
Name of the application where selection occurred. Always empty on Linux Wayland. |
startTop |
Point |
First paragraph's top-left coordinates (px). |
startBottom |
Point |
First paragraph's bottom-left coordinates (px). |
endTop |
Point |
Last paragraph's top-right coordinates (px). |
endBottom |
Point |
Last paragraph's bottom-right coordinates (px). |
mousePosStart |
Point |
Mouse position when selection started (px). |
mousePosEnd |
Point |
Mouse position when selection ended (px). |
method |
SelectionMethod |
Indicates which method was used to detect the text selection. |
posLevel |
PositionLevel |
Indicates which positional data is provided. |
isFullscreen |
boolean |
Whether the window is in fullscreen mode. macOS only. |
Linux:
startTop/startBottom/endTop/endBottomare always-99999(INVALID_COORDINATE) because selection bounding rectangles are not available. On Wayland,mousePosStart/mousePosEndmay also be-99999when the coordinate source (libevdev) cannot provide actual screen positions — see Linux platform details for the compositor-dependent fallback chain.
See PositionLevel for how posLevel determines which coordinate fields are meaningful.
Contains mouse click/movement information in screen coordinates.
| Property | Type | Description |
|---|---|---|
x |
number |
Horizontal pointer position (px). |
y |
number |
Vertical pointer position (px). |
button |
number |
Same as WebAPIs' MouseEvent.button. 0=Left, 1=Middle, 2=Right, 3=Back, 4=Forward, -1=None, 99=Unknown. |
Linux Wayland:
x/ymay beINVALID_COORDINATE(-99999). See Coordinate note.
If button != -1 during a mouse-move event, it indicates dragging.
Describes mouse wheel scrolling events.
| Property | Type | Description |
|---|---|---|
x |
number |
Horizontal pointer position (px). |
y |
number |
Vertical pointer position (px). |
button |
number |
0=Vertical, 1=Horizontal scroll. |
flag |
number |
1=Up/Right, -1=Down/Left. |
Linux Wayland:
x/ymay beINVALID_COORDINATE(-99999). See Coordinate note.
Represents keyboard key presses/releases.
| Property | Type | Description |
|---|---|---|
uniKey |
string |
Unified key name, refer to MDN KeyboardEvent.key, converted from vkCode. |
vkCode |
number |
Virtual key code. Definitions and values vary by platform (see below). |
sys |
boolean |
Whether modifier keys (Ctrl/Alt/Win(Super)/⌘/⌥/Fn) are pressed simultaneously. |
scanCode |
number? |
Hardware scan code. Windows only. |
flags |
number |
Additional state flags. On Linux: modifier bitmask (0x01=Shift, 0x02=Ctrl, 0x04=Alt, 0x08=Meta). |
Platform-specific vkCode values:
- Windows:
VK_*values ofvkCode - macOS:
kVK_*values ofkCGKeyboardEventKeycode - Linux:
KEY_*values from<linux/input-event-codes.h>
Returned by linuxGetEnvInfo(). Contains cached Linux environment information detected at construction time.
| Property | Type | Description |
|---|---|---|
displayProtocol |
number |
Display protocol (SelectionHook.DisplayProtocol). |
compositorType |
number |
Compositor type (SelectionHook.CompositorType). |
hasInputDeviceAccess |
boolean |
Whether the user can access input devices (needed for Wayland libevdev input monitoring). Checks input group, ACLs, capabilities, and actual device access. Always true on X11. |
isRoot |
boolean |
Whether the process is running as root. |
Platform: Linux only.
Sentinel value (-99999) indicating that a coordinate is unavailable or unreliable. On Linux Wayland, mouse event coordinates and selection position coordinates may be set to this value when the input source (libevdev) cannot provide actual screen positions. Check coordinate fields against this value before using them for UI positioning.
if (data.mousePosEnd.x !== SelectionHook.INVALID_COORDINATE) {
// Position is reliable, use it
}Indicates which method was used to detect the text selection.
| Constant | Value | Platform | Description |
|---|---|---|---|
NONE |
0 |
— | No selection detected. |
UIA |
1 |
Windows | UI Automation. |
FOCUSCTL |
2 |
Windows | Deprecated — no longer emitted. Retained for backward compatibility with historical data. |
ACCESSIBLE |
3 |
Windows | Accessibility interface. |
AXAPI |
11 |
macOS | Accessibility API. |
ATSPI |
21 |
Linux | Assistive Technology Service Provider Interface. Reserved — not currently used. |
PRIMARY |
22 |
Linux | Primary Selection. |
CLIPBOARD |
99 |
Windows, macOS | Clipboard fallback. Not used on Linux. |
Indicates which positional data is provided.
| Constant | Value | Description |
|---|---|---|
NONE |
0 |
No position information. |
MOUSE_SINGLE |
1 |
Only mousePosStart and mousePosEnd are provided, and they are equal. |
MOUSE_DUAL |
2 |
mousePosStart and mousePosEnd are provided with different positions (drag selection). On Linux Wayland, achievable when the compositor provides accurate cursor positions at both mouse-down and mouse-up. |
SEL_FULL |
3 |
All mouse positions and paragraph coordinates (startTop/startBottom/endTop/endBottom) are provided. Not available on Linux. |
SEL_DETAILED |
4 |
Detailed selection coordinates. Reserved for future use. |
| Constant | Value | Description |
|---|---|---|
DEFAULT |
0 |
No filtering — all programs pass through. |
INCLUDE_LIST |
1 |
Only the programs in the list will pass the filter. |
EXCLUDE_LIST |
2 |
Only the programs NOT in the list will pass the filter. |
Defines types for fine-tuned application behavior lists.
| Constant | Value | Description |
|---|---|---|
EXCLUDE_CLIPBOARD_CURSOR_DETECT |
0 |
Exclude cursor detection for clipboard operations. Useful for applications with custom cursors (e.g., Adobe Acrobat) where cursor shape detection may not work reliably. |
INCLUDE_CLIPBOARD_DELAY_READ |
1 |
Add a clipboard read delay for applications that write multiple times in quick succession (e.g., Adobe Acrobat). Listed applications retain the legacy clipboard path unchanged; the restore-first changes described under enableClipboard() do not apply. |
Platform: Windows only.
Defines the display protocol types used on Linux systems.
| Constant | Value | Description |
|---|---|---|
UNKNOWN |
0 |
No protocol detected or not applicable. |
X11 |
1 |
X11 windowing system protocol. |
WAYLAND |
2 |
Wayland display server protocol. |
Platform: Linux only.
Identifies the compositor. Values represent the compositor, not the desktop environment (DE). DE-bundled compositors are detected via XDG_CURRENT_DESKTOP (each DE uses exactly one compositor); standalone compositors are detected via their own environment variables.
| Constant | Compositor | Desktop Environment | Detected via |
|---|---|---|---|
UNKNOWN |
— | — | — |
KWIN |
KWin (kwin_wayland) |
KDE Plasma | XDG_CURRENT_DESKTOP contains "KDE" |
MUTTER |
mutter (gnome-shell) |
GNOME | XDG_CURRENT_DESKTOP contains "GNOME" |
HYPRLAND |
Hyprland | (standalone) | HYPRLAND_INSTANCE_SIGNATURE env var |
SWAY |
sway | (standalone) | SWAYSOCK env var |
WLROOTS |
various (labwc, river, ...) | (standalone) | XDG_CURRENT_DESKTOP contains "wlroots" |
COSMIC_COMP |
cosmic-comp | COSMIC (System76) | XDG_CURRENT_DESKTOP contains "COSMIC" |
Platform: Linux only. See Wayland Compositor Compatibility for cursor position accuracy and selection monitoring details per compositor.
This module includes TypeScript definitions. Since selection-hook is a native Node-API module, it uses CommonJS exports. Use import for types and require for the runtime value:
import {
SelectionHookConstructor,
SelectionHookInstance,
SelectionConfig,
TextSelectionData,
MouseEventData,
MouseWheelEventData,
KeyboardEventData,
LinuxEnvInfo,
Point,
} from "selection-hook";
// use `SelectionHookConstructor` for SelectionHook Class
const SelectionHook: SelectionHookConstructor = require("selection-hook");
// use `SelectionHookInstance` for SelectionHook instance
const hook: SelectionHookInstance = new SelectionHook();See index.d.ts for details.