Skip to content

Commit ea25ba7

Browse files
committed
Cygwin: console: Fix master thread for OpenConsole.exe
If the console is originating from a pseudo console, current master thread code does not work as expected if ENABLE_VIRTUAL_TERMINAL_INPUT flag is set, particularly when OpenConsole.exe is used. This is because the pseudo console does not preserve all the key event as is. All bKeyDown == 0 events will be omitted from the input record written by WriteConsoleInput() and events regarding pressing shift/control/alt keys will be dropped as well. This patch adds strip_inrec() function to remove all the key events of bKeyDown == 0 or UnicodeChar == 0 before comparing/writing input record. This function is called only when the console is originating from a pseudo console and ENABLE_VIRTUAL_TERMINAL_INPUT flag is set. Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp> Reviewed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
1 parent 10a3de5 commit ea25ba7

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

winsup/cygwin/fhandler/console.cc

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,23 @@ cons_master_thread (VOID *arg)
305305
return 0;
306306
}
307307

308+
static inline DWORD
309+
strip_inrec (INPUT_RECORD *r, DWORD n)
310+
{
311+
/* Pseudo console with OpenConsole.exe removes the events
312+
whose bKeyDown is 0 as well as ones whose charcode is 0. */
313+
DWORD j = 0;
314+
for (DWORD i = 0; i < n; i++)
315+
{
316+
if (r[i].EventType != KEY_EVENT)
317+
r[j++] = r[i];
318+
else if (r[i].Event.KeyEvent.bKeyDown
319+
&& r[i].Event.KeyEvent.uChar.UnicodeChar)
320+
r[j++] = r[i];
321+
}
322+
return j;
323+
}
324+
308325
/* Compare two INPUT_RECORD sequences */
309326
static inline bool
310327
inrec_eq (const INPUT_RECORD *a, const INPUT_RECORD *b, DWORD n)
@@ -417,6 +434,8 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
417434
while (con.owner == GetCurrentProcessId ())
418435
{
419436
DWORD total_read, n, i;
437+
DWORD mode;
438+
bool need_strip = false;
420439

421440
if (con.disable_master_thread)
422441
{
@@ -472,6 +491,23 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
472491
{
473492
case WAIT_OBJECT_0:
474493
acquire_attach_mutex (mutex_timeout);
494+
/* When ENABLE_VIRTUAL_TERMINAL_INPUT is set, the key events
495+
are not preserved as is. Particularly, when OpenConsole.exe
496+
is used, the following key events are simplified so much.
497+
Writing the events:
498+
press shift key -> press 'A' key ->
499+
lease 'A' key -> release shift key
500+
results in only one key event with:
501+
uChar.UnicodeChar = 0x41,
502+
wVirtualKeyCode = 0,
503+
wVirtualScanCode = 0,
504+
dwControlKeyState = 0,
505+
bKeyDown = 1
506+
Therefore, we need fixup the input record by calling
507+
strip_inrec() if the ENABLE_VIRTUAL_TERMINAL_INPUT flag is
508+
set, so that the input records are compared as expected. */
509+
GetConsoleMode (p->input_handle, &mode);
510+
need_strip = inside_pcon && (mode & ENABLE_VIRTUAL_TERMINAL_INPUT);
475511
total_read = 0;
476512
while (cygwait (p->input_handle, (DWORD) 0) == WAIT_OBJECT_0
477513
&& total_read < inrec_size)
@@ -483,6 +519,8 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
483519
total_read += len;
484520
}
485521
release_attach_mutex ();
522+
if (need_strip)
523+
total_read = strip_inrec (input_rec, total_read);
486524
break;
487525
case WAIT_TIMEOUT:
488526
con.num_processed = 0;
@@ -607,6 +645,8 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
607645
acquire_attach_mutex (mutex_timeout);
608646
PeekConsoleInputW (p->input_handle, input_tmp, inrec_size, &n);
609647
release_attach_mutex ();
648+
if (need_strip)
649+
n = strip_inrec (input_tmp, n);
610650
if (n < min (total_read, inrec_size))
611651
break; /* Someone has read input without acquiring
612652
input_mutex. ConEmu cygwin-connector? */
@@ -625,6 +665,8 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
625665
n += len;
626666
}
627667
release_attach_mutex ();
668+
if (need_strip)
669+
n = strip_inrec (input_tmp, n);
628670
bool fixed = false;
629671
for (DWORD ofs = n - total_read; ofs > 0; ofs--)
630672
{

0 commit comments

Comments
 (0)