From d0d5af28bd64ce74bf67f314db54f9d3e2fff73d Mon Sep 17 00:00:00 2001 From: bryan Date: Thu, 27 Aug 2026 14:20:38 +0200 Subject: Copy with WM_COPY only; do not inject Ctrl+C. SendInput of Ctrl+C typed a stray c or sent SIGINT into Alacritty and Zed. Those apps ignore WM_COPY, so they are left alone. --- README | 14 ++++++------- config.def.h | 10 ---------- selc.c | 65 ++++-------------------------------------------------------- 3 files changed, 10 insertions(+), 79 deletions(-) diff --git a/README b/README index e9a2379..e2725e3 100644 --- a/README +++ b/README @@ -39,8 +39,10 @@ selection, then: 1. ignore non-client hits (caption, scrollbars, resize) 2. ignore password Edit controls 3. WM_COPY to the focused child (SendMessageTimeout) - 4. if the clipboard sequence did not change, inject Ctrl+C - except into console classes listed in config.h + +No keys are injected. Apps that do not handle WM_COPY (most +GPU terminals and editors) are left alone; they will not see +Ctrl+C or a stray 'c'. Logon autostart is HKCU\...\Run\selc, so it starts with the interactive session. That is the right time; a clipboard helper @@ -49,12 +51,8 @@ cannot run in session 0. Remarks -Injected Ctrl+C is skipped for ConsoleWindowClass, Windows -Terminal, and mintty so a false gesture cannot interrupt a -job. Those hosts often already copy on select. - UIPI: an unelevated selc cannot copy from an elevated window. Run it at the same integrity level as the programs you use. -Edit config.h (copied from config.def.h) for thresholds and -the no-Ctrl+C class list. Recompile. +Edit config.h (copied from config.def.h) for thresholds. +Recompile. diff --git a/config.def.h b/config.def.h index 357bcba..14d2fc1 100644 --- a/config.def.h +++ b/config.def.h @@ -10,13 +10,3 @@ enum { KEYSEL = 1, /* copy on shift+arrows/home/end/pgup/pgdn */ CTRLA = 0 /* copy after Ctrl+A; 0: Explorer would copy files */ }; - -/* - * Root window classes that must not receive injected Ctrl+C. - * WM_COPY is still tried. Console hosts treat Ctrl+C as interrupt. - */ -static const char *nocctrlc[] = { - "ConsoleWindowClass", - "CASCADIA_HOSTING_WINDOW_CLASS", - "mintty", -}; diff --git a/selc.c b/selc.c index 1b8eb86..b32bf74 100644 --- a/selc.c +++ b/selc.c @@ -42,9 +42,7 @@ static void attachio(int force); static int samewin(HWND a, HWND b); static int isclient(HWND hw, POINT pt); static int ispass(HWND hw); -static int skipctrlc(HWND hw); static int goodsel(const struct Sel *s); -static void sendctrlc(void); static void docopy(void); static void request(int kbd); static LRESULT CALLBACK mouseproc(int code, WPARAM wp, LPARAM lp); @@ -131,24 +129,6 @@ ispass(HWND hw) return (style & ES_PASSWORD) != 0; } -static int -skipctrlc(HWND hw) -{ - char cls[64]; - HWND root; - int i; - - root = GetAncestor(hw, GA_ROOT); - if (!root) - root = hw; - if (!GetClassNameA(root, cls, (int)sizeof(cls))) - return 0; - for (i = 0; i < (int)LEN(nocctrlc); i++) - if (strcmp(cls, nocctrlc[i]) == 0) - return 1; - return 0; -} - static int goodsel(const struct Sel *s) { @@ -163,36 +143,6 @@ goodsel(const struct Sel *s) return 1; } -static void -sendctrlc(void) -{ - INPUT in[4]; - int n, ctrl; - - ctrl = (GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0; - memset(in, 0, sizeof(in)); - n = 0; - if (!ctrl) { - in[n].type = INPUT_KEYBOARD; - in[n].ki.wVk = VK_CONTROL; - n++; - } - in[n].type = INPUT_KEYBOARD; - in[n].ki.wVk = 'C'; - n++; - in[n].type = INPUT_KEYBOARD; - in[n].ki.wVk = 'C'; - in[n].ki.dwFlags = KEYEVENTF_KEYUP; - n++; - if (!ctrl) { - in[n].type = INPUT_KEYBOARD; - in[n].ki.wVk = VK_CONTROL; - in[n].ki.dwFlags = KEYEVENTF_KEYUP; - n++; - } - SendInput((UINT)n, in, sizeof(INPUT)); -} - static void docopy(void) { @@ -219,19 +169,12 @@ docopy(void) seq = GetClipboardSequenceNumber(); SendMessageTimeoutA(foc, WM_COPY, 0, 0, SMTO_ABORTIFHUNG | SMTO_NORMAL, COPYTO, &dummy); - if (GetClipboardSequenceNumber() != seq) { - if (verbose) + if (verbose) { + if (GetClipboardSequenceNumber() != seq) fprintf(stderr, "selc: WM_COPY\n"); - goto done; - } - if (skipctrlc(foc) || skipctrlc(fg)) { - if (verbose) - fprintf(stderr, "selc: skip Ctrl+C\n"); - goto done; + else + fprintf(stderr, "selc: no copy\n"); } - sendctrlc(); - if (verbose) - fprintf(stderr, "selc: Ctrl+C\n"); done: if (attached) AttachThreadInput(mine, tid, FALSE); -- cgit v1.2.3