Terminal.Gui
Terminal.Gui copied to clipboard
Shift+key denied by text field as "control character" on remote systems
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:
- Pull the Terminal.GUI
- Start the unmodified UICatalog project
- Put the cursor in any text input field
- Type Shift+a - nothing happens
- 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.
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
:
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#
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'
No A for me: (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:
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?
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:
-
cmd.exe
run via Win+R -> does not work, no A-
EDIT: FIXED BY
-usc
!!
-
EDIT: FIXED BY
- new fancy Windows Terminal with cmd.exe tab -> does work
- PowerShell 7 -> does work in Terminal tab, not standalone
- 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:
First screenshot without numlock:
Hex values:
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
:
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!
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.
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.
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.
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.
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.
@tznind Here is a screenshot at the position you asked for:
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:
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
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
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?
Well I believe there some way to handle that PACKET key so the right keystroke is filtered. I'm curious :-)