[PATCH v7 2/7] Cygwin: pty: Add workaround for handling of backspace when pcon enabled

Takashi Yano takashi.yano@nifty.ne.jp
Fri Mar 27 13:36:35 GMT 2026


On Wed, 25 Mar 2026 22:04:08 +0900
Takashi Yano wrote:
> 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 the issue
> that replaces Ctrl-H with backspace (0x7f), which will be translated
> into Ctrl-H in pseudo console.
> 
> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
> Reviewed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> ---
>  winsup/cygwin/fhandler/console.cc | 12 ++++++-
>  winsup/cygwin/fhandler/pty.cc     | 57 ++++++++++++++++++++++++++-----
>  2 files changed, 60 insertions(+), 9 deletions(-)
> 
> diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
> index 2f59f8f24..9678775d1 100644
> --- a/winsup/cygwin/fhandler/console.cc
> +++ b/winsup/cygwin/fhandler/console.cc
> @@ -318,6 +318,16 @@ inrec_eq (const INPUT_RECORD *a, const INPUT_RECORD *b, DWORD n)
>  	     written event. Therefore they are ignored. */
>  	  const KEY_EVENT_RECORD *ak = &a[i].Event.KeyEvent;
>  	  const KEY_EVENT_RECORD *bk = &b[i].Event.KeyEvent;
> +	  WCHAR c1 = ak->uChar.UnicodeChar;
> +	  WCHAR c2 = bk->uChar.UnicodeChar;
> +	  if (inside_pcon)
> +	    {
> +	      /* Workaround for pseudo console in Windows 11 */
> +	      if (c1 == 8) /* Ctrl-H */
> +		c1 = 127; /* Backspace */
> +	      if (c2 == 8) /* Ctrl-H */
> +		c2 = 127; /* Backspace */
> +	    }
>  	  /* Fixup repeat count */
>  	  WORD r1 = ak->wRepeatCount;
>  	  WORD r2 = bk->wRepeatCount;
> @@ -326,7 +336,7 @@ inrec_eq (const INPUT_RECORD *a, const INPUT_RECORD *b, DWORD n)
>  	  if (r2 == 0)
>  	    r2 = 1;
>  	  if (ak->bKeyDown != bk->bKeyDown
> -	      || ak->uChar.UnicodeChar != bk->uChar.UnicodeChar
> +	      || c1 != c2
>  	      || r1 != r2)
>  	    return false;
>  	}
> diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
> index 371e67103..72a8ba140 100644
> --- a/winsup/cygwin/fhandler/pty.cc
> +++ b/winsup/cygwin/fhandler/pty.cc
> @@ -2266,28 +2266,65 @@ fhandler_pty_master::write (const void *ptr, size_t len)
>      { /* Reaches here when non-cygwin app is foreground and pseudo console
>  	 is activated. */
>        tmp_pathbuf tp;
> -      char *buf = (char *) ptr;
> +      char *buf = tp.c_get ();
>        size_t nlen = len;
>        if (get_ttyp ()->term_code_page != CP_UTF8)
>  	{
>  	  static mbstate_t mbp;
> -	  buf = tp.c_get ();
>  	  nlen = NT_MAX_PATH;
>  	  convert_mb_str (CP_UTF8, buf, &nlen,
>  			  get_ttyp ()->term_code_page, (const char *) ptr, len,
>  			  &mbp);
>  	}
> +      else
> +	memcpy (buf, ptr, nlen);
> +
> +      /* Retrieve console mode */
> +      HANDLE h_pcon_in = get_ttyp ()->h_pcon_in;
> +      DWORD cons_mode;
> +      if (!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);
> +	  DWORD resume_pid =
> +	    attach_console_temporarily (get_ttyp()->nat_pipe_owner_pid);
> +	  GetConsoleMode (h_pcon_in, &cons_mode);
> +	  resume_from_temporarily_attach (resume_pid);
> +	  CloseHandle (h_pcon_in);
> +	}
> +      else
> +	GetConsoleMode (h_pcon_in, &cons_mode);
>  
> -      for (size_t i = 0; i < nlen; i++)
> +      for (size_t i = 0, j = 0; i < nlen; i++)

This patch should fixed as follows:

-      for (size_t i = 0; i < nlen; i++)
+      len = nlen
+      for (size_t i = 0, j = 0; i < len; i++)

Sorry.

-- 
Takashi Yano <takashi.yano@nifty.ne.jp>


More information about the Cygwin-patches mailing list