Terminal.Gui icon indicating copy to clipboard operation
Terminal.Gui copied to clipboard

Shift+key denied by text field as "control character" on remote systems

Open heinrich-ulbricht opened this issue 1 year ago • 13 comments

Describe the bug I cannot type any character with Shift modifier - no uppercase chars, no colon, no nothing. This does not happen on all systems.

To Reproduce Steps to reproduce the behavior:

  1. Pull the Terminal.GUI
  2. Start the unmodified UICatalog project
  3. Put the cursor in any text input field
  4. Type Shift+a - nothing happens
  5. Type a - a is typed

Expected behavior I expect A to be typed when pressing Shift+a

Screenshots It seems like the key is discarded as "control character". So the InsertText (kb) is never reached.

image

This does not happen on all systems, but on the one I have the debugger running ^^ Either the check should ignore the Shift modifier, or in an earlier step a conversion of Shift+a to uppercase A fails. Not sure how it is supposed to work.

(Note: removing the numlock modifier makes no difference.)

Here is the corresponding KeyEventRecord: image

Desktop (please complete the following information):

  • OS: Windows 11, English UI language, German keyboard language, through RDP session
  • Version: relatively recent dev version: https://github.com/gui-cs/Terminal.Gui/commit/3866e65919ec67c1159162fb271f5f99fcf3a169

Additional context

Call stack:

>	Terminal.Gui.dll!Terminal.Gui.TextField.ProcessKey(Terminal.Gui.KeyEvent kb) Line 565	C#
 	Terminal.Gui.dll!Terminal.Gui.View.ProcessHotKey(Terminal.Gui.KeyEvent keyEvent) Line 1881	C#
 	Terminal.Gui.dll!Terminal.Gui.Application.ProcessKeyEvent(Terminal.Gui.KeyEvent ke) Line 431	C#
 	Terminal.Gui.dll!Terminal.Gui.WindowsDriver.ProcessInput(Terminal.Gui.WindowsConsole.InputRecord inputEvent) Line 859	C#
 	Terminal.Gui.dll!Terminal.Gui.WindowsDriver.PrepareToRun.AnonymousMethod__34_0(Terminal.Gui.WindowsConsole.InputRecord e) Line 759	C#
 	Terminal.Gui.dll!Terminal.Gui.WindowsMainLoop.Terminal.Gui.IMainLoopDriver.MainIteration() Line 1881	C#
 	Terminal.Gui.dll!Terminal.Gui.MainLoop.MainIteration() Line 295	C#
 	Terminal.Gui.dll!Terminal.Gui.Application.RunMainLoopIteration(ref Terminal.Gui.Application.RunState state, bool wait, ref bool firstIteration) Line 1014	C#
 	Terminal.Gui.dll!Terminal.Gui.Application.RunLoop(Terminal.Gui.Application.RunState state, bool wait) Line 996	C#
 	Terminal.Gui.dll!Terminal.Gui.Application.Run(Terminal.Gui.Toplevel view, System.Func<System.Exception, bool> errorHandler) Line 1172	C#
 	UICatalog.dll!UICatalog.Scenario.Run() Line 200	C#
 	UICatalog.dll!UICatalog.UICatalogApp.Main(string[] args) Line 111	C#

heinrich-ulbricht avatar Sep 13 '22 20:09 heinrich-ulbricht

Thanks for reporting this. Does disabling the numlock toggle on the keyboard have any effect?

If you run UICatalog and go to the 'Keys' Scenario. What appears when you hit Shift+A in the 'Key stroke log'

keys

tznind avatar Sep 13 '22 20:09 tznind

No A for me: image (Note: KeyUp: Enter is from key-navigating to the scenario.) Switching off NumLock does make no difference. Above was without, here is with NumLock on: image

heinrich-ulbricht avatar Sep 13 '22 20:09 heinrich-ulbricht

Very strange. Does it make any difference if you launch with -usc?

Also what does your $TERM environment variable say (echo $TERM)

Also just to rule it out, I take it scroll lock or function lock are also off?

Looking at that Key value in your first screen shot it definitely looks like there is another flag bit set:

00010000000000000000000001000001 Decimal to Binary: 268435521

Can you please reproduce the first screenshot without numlock and we can see what the value of KeyValue is in watch window?

tznind avatar Sep 13 '22 20:09 tznind

I toggled scroll lock and function lock to be sure, no difference. Something is up with the way the command line is started, or hosted or whatever. Did some more tests:

  1. cmd.exe run via Win+R -> does not work, no A
    • EDIT: FIXED BY -usc !!
  2. new fancy Windows Terminal with cmd.exe tab -> does work
  3. PowerShell 7 -> does work in Terminal tab, not standalone
  4. PowerShell 5.1 -> does work in Terminal tab, not standalone

Looking at the process explorer I see different processes created around the application depending on how it's started.

Regarding the flag I suppose this is Key.ShiftMask - if you mean the left-most 1: image

First screenshot without numlock: image

Hex values: image

And by the way: -usc fixes it for case 1! What is this? EDIT: I see, it switches from WindowsDriver to NetDriver.

EDIT: Screenshot for -usc: image

heinrich-ulbricht avatar Sep 13 '22 21:09 heinrich-ulbricht

Yes. -usc is Application.UseSystemConsole=true, it changes which ConsoleDriver implementation is used. Without usc it is CursesDriver or WindowsDriver (depending on OS). With usc it is NetDriver.

Definitely looks like kb.Key is getting the extra bit mask in one driver but not the other. I'll have a closer look tomorrow and see if I can get to the bottom of this or @BDisp might have some suggestions.

Thanks for sticking with this and sharing those screenshots its very helpful!

tznind avatar Sep 13 '22 21:09 tznind

I already test with all the related terminals and I didn't get the issue with the WindowsDriver. I can digit Shift+A and I get the A on the TextField. What I thinking it could might happens is some Germain layout keyboard conflict on Windows using the WindowsDriver. Another think is some racing condition which restarting the machine could fix something.

BDisp avatar Sep 13 '22 22:09 BDisp

Ok so I have a hacky workaround which is to strip the Shift bit from the Key variable in the global key delegate. Make sure you put it after Init (or scenario.Init (Application.Top, _baseColorScheme); in UICatalog):

Application.RootKeyEvent = (k) => {
        // strip shift mask from key code
	k.Key = (Key)(k.KeyValue & (uint)0x0fffffff);
	return false;
};

But I would still like to get to the bottom of this. The entry point for key handling is

public WindowsConsole.ConsoleKeyInfoEx ToConsoleKeyInfoEx (WindowsConsole.KeyEventRecord keyEvent)

If you could put a conditional break point in there (e.g. see below). We should be able to see if that extra bit is being fed in by windows or is being introduced by Terminal.Gui. Note that you may need to add the shift mask to that conditional expression if it isn't hit in your environment.

image

I think what is supposed to happen is that keyEvent.dwControlKeyState stores the modifiers while keyEvent.wVirtualKeyCode and keyEvent.UnicodeChar both store only the letter.

tznind avatar Sep 14 '22 06:09 tznind

Will do as soon as I'm back on my Linux machine! When I'm RDPing from Windows it apparently... works. So Windows 10 -> Windows 11 via on-board RDP client works. But Linux -> Windows 11 via Remmina RDP client doesn't.

Not sure what to make of that. Is Remmina doing shenanigans there? We'll see.

heinrich-ulbricht avatar Sep 14 '22 09:09 heinrich-ulbricht

In Windows Terminal I had to delete some shortcut keys to be able to manage with some Terminal.Gui views. One I remember was the Ctrl+Shift+D, but a simple Shift+A which is necessary for display the upper case A letter, should never be used by applications. Since you only having this issue from Linux to Windows may be the Remmina isn't send the correct bit for the Windows desktop.

BDisp avatar Sep 14 '22 10:09 BDisp

@tznind Here is a screenshot at the position you asked for: image

Call stack:

>	Terminal.Gui.dll!Terminal.Gui.WindowsDriver.ToConsoleKeyInfoEx(Terminal.Gui.WindowsConsole.KeyEventRecord keyEvent) Line 1222	C#
 	Terminal.Gui.dll!Terminal.Gui.WindowsDriver.ProcessInput(Terminal.Gui.WindowsConsole.InputRecord inputEvent) Line 789	C#
 	Terminal.Gui.dll!Terminal.Gui.WindowsDriver.PrepareToRun.AnonymousMethod__34_0(Terminal.Gui.WindowsConsole.InputRecord e) Line 759	C#
 	Terminal.Gui.dll!Terminal.Gui.WindowsMainLoop.Terminal.Gui.IMainLoopDriver.MainIteration() Line 1881	C#
 	Terminal.Gui.dll!Terminal.Gui.MainLoop.MainIteration() Line 295	C#
 	Terminal.Gui.dll!Terminal.Gui.Application.RunMainLoopIteration(ref Terminal.Gui.Application.RunState state, bool wait, ref bool firstIteration) Line 1014	C#
 	Terminal.Gui.dll!Terminal.Gui.Application.RunLoop(Terminal.Gui.Application.RunState state, bool wait) Line 996	C#
 	Terminal.Gui.dll!Terminal.Gui.Application.Run(Terminal.Gui.Toplevel view, System.Func<System.Exception, bool> errorHandler) Line 1172	C#
 	UICatalog.dll!UICatalog.Scenario.Run() Line 200	C#
 	UICatalog.dll!UICatalog.UICatalogApp.Main(string[] args) Line 111	C#

Screenshot of the app after continuing: image

And I'm stupid. With my last test I still had the -usc parameter version selected in Visual Studio, so the error might still be there with the Windows to Windows RDP connection. Will check again, when I'm back at the Windows machine... fyi @BDisp

heinrich-ulbricht avatar Sep 14 '22 17:09 heinrich-ulbricht

Thanks for the screenshot wVirtualKeyCode is 231 in the image. The ConsoleKey Enum value for that is 'Packet':

Packet | 231 | The PACKET key (used to pass Unicode characters with keystrokes).

https://docs.microsoft.com/en-us/dotnet/api/system.consolekey?view=net-6.0

Not sure if that means anything but tomorrow I can try hacking my codebase to force every keystroke to those values and then step through the debugger to see if its being misinterpreted.

VK_PACKET 0xE7 Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP

tznind avatar Sep 14 '22 19:09 tznind

Seems to be connected to remote connecting to systems. Did a Google. Here is somebody experiencing this as well with AnyDesk: https://stackoverflow.com/q/73076917 more: https://www.autohotkey.com/boards/viewtopic.php?p=411629&sid=9c697f02b387bb791ef865bd52b8bdf8#p411629 more: https://github.com/microsoft/terminal/issues/12977 Fix for Terminal and UTF-16: https://github.com/microsoft/terminal/pull/13667#issue-1327924427

The dates seem recent. Might be something new?

heinrich-ulbricht avatar Sep 14 '22 20:09 heinrich-ulbricht

Well I believe there some way to handle that PACKET key so the right keystroke is filtered. I'm curious :-)

BDisp avatar Sep 14 '22 21:09 BDisp