[PATCH 2/6] Cygwin: pty: Add workaround for handling of backspace when pcon enabled
Takashi Yano
takashi.yano@nifty.ne.jp
Tue Mar 17 12:23:06 GMT 2026
In Windows 11, pseudo console has a weird behaviour that the Ctrl-H
is translated into Ctrl-Backspace (not Backspace). Similary, Backspace
(0x7f) is translated into Ctrl-H. Due to this behaviour, inrec_eq()
in cons_master_thread() fails to compare backspace/Ctrl-H events in
the input record sequence. This patch is a workaround for that issue
which pushes the Ctrl-H or Backspace as a ConsoleInput event instead
of sending char code to pseudo console.
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Reviewed-by:
---
winsup/cygwin/fhandler/pty.cc | 64 +++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
index 371e67103..bde88ab0e 100644
--- a/winsup/cygwin/fhandler/pty.cc
+++ b/winsup/cygwin/fhandler/pty.cc
@@ -2290,9 +2290,73 @@ fhandler_pty_master::write (const void *ptr, size_t len)
}
}
+ /* In Windows 11, pseudo console has a weird behaviour that
+ Ctrl-H is translated into Ctrl-Backspace (not Backspace).
+ Similary, backspace (0x7f) is translated into Ctrl-H. The
+ following code is a workaround for that issue. */
+ char *bs_pos1 = (char *) memchr (buf, '\010' /* ^H */, nlen);
+ char *bs_pos2 = (char *) memchr (buf, '\177' /* BS */, nlen);
+ HANDLE h_pcon_in = get_ttyp ()->h_pcon_in;
+ DWORD resume_pid = 0;
+ if ((bs_pos1 || bs_pos2)
+ && !nat_pipe_owner_self (get_ttyp ()->nat_pipe_owner_pid))
+ {
+ HANDLE pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
+ get_ttyp ()->nat_pipe_owner_pid);
+ DuplicateHandle (pcon_owner, h_pcon_in,
+ GetCurrentProcess (), &h_pcon_in,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+ CloseHandle(pcon_owner);
+ resume_pid =
+ attach_console_temporarily (get_ttyp()->nat_pipe_owner_pid);
+ }
+
DWORD n;
+ while (bs_pos1)
+ {
+ if (bs_pos1 - buf > 0)
+ WriteFile (to_slave_nat, buf, bs_pos1 - buf, &n, NULL);
+ INPUT_RECORD r;
+ r.EventType = KEY_EVENT;
+ r.Event.KeyEvent.bKeyDown = 1;
+ r.Event.KeyEvent.wRepeatCount = 0;
+ r.Event.KeyEvent.wVirtualKeyCode = 0;
+ r.Event.KeyEvent.wVirtualScanCode = 0;
+ r.Event.KeyEvent.uChar.AsciiChar = '\010'; /* ^H */
+ r.Event.KeyEvent.dwControlKeyState = LEFT_CTRL_PRESSED;
+ WriteConsoleInput(h_pcon_in, &r, 1, &n);
+ r.Event.KeyEvent.bKeyDown = 0;
+ WriteConsoleInput(h_pcon_in, &r, 1, &n);
+ nlen -= bs_pos1 - buf + 1;
+ buf = bs_pos1 + 1;
+ bs_pos1 = (char *) memchr (buf, '\010' /* ^H */, nlen);
+ }
+ while (bs_pos2)
+ {
+ if (bs_pos2 - buf > 0)
+ WriteFile (to_slave_nat, buf, bs_pos2 - buf, &n, NULL);
+ INPUT_RECORD r;
+ r.EventType = KEY_EVENT;
+ r.Event.KeyEvent.bKeyDown = 1;
+ r.Event.KeyEvent.wRepeatCount = 0;
+ r.Event.KeyEvent.wVirtualKeyCode = 0;
+ r.Event.KeyEvent.wVirtualScanCode = 0;
+ r.Event.KeyEvent.uChar.AsciiChar = '\177'; /* BS */
+ r.Event.KeyEvent.dwControlKeyState = 0;
+ WriteConsoleInput(h_pcon_in, &r, 1, &n);
+ r.Event.KeyEvent.bKeyDown = 0;
+ WriteConsoleInput(h_pcon_in, &r, 1, &n);
+ nlen -= bs_pos2 - buf + 1;
+ buf = bs_pos2 + 1;
+ bs_pos2 = (char *) memchr (buf, '\177' /* BS */, nlen);
+ }
if (nlen)
WriteFile (to_slave_nat, buf, nlen, &n, NULL);
+
+ if (resume_pid)
+ resume_from_temporarily_attach (resume_pid);
+ if (h_pcon_in)
+ CloseHandle(h_pcon_in);
ReleaseMutex (input_mutex);
return orig_len;
--
2.51.0
More information about the Cygwin-patches
mailing list