-
Notifications
You must be signed in to change notification settings - Fork 661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gathering keyboard input doesn't work (winui 3) #7330
Comments
KeyDown works for me, with CommunityToolkit.WinUI.UI.Controls.DataGrid |
@castorix Thanks for that! I just tested on a dummy app, and indeed, that works. I dug a bit deeper. The problem happens when the datagrid is part of a Here's the simplest example I came up with: Long story short:
The current behavior is beyond horrible. |
A classic way in Win32 is with Hooks
with declarations :
|
This is a big issue for us, we can't listen for key presses on specific controls because keyboard input can come at any time (regardless of what the app is doing) from keyboard wedge barcode scanners. I then notify the relevant areas of the app using MessagingCenter that a barcode has been scanned. Have I really got to dig into Win32 code? |
This is pretty hard core. And I still 99% think it won't work for me. Anyway, I will give it a try, thanks! |
You could add a test with Microsoft.UI.Xaml.Input.FocusManager.GetFocusedElement |
I got it going, thanks to Castorix and some digging around on Google. It needs some tidying up after being hacked together but seems to work ok.
|
For the specific case of the INS key, check wParam == (IntPtr)(int)Windows.System.VirtualKey.Insert. Then you could just send that event using MessagingCenter to your code that checks if the DataGrid is being edited. |
I think what you're seeing is that input events stop bubbling up the tree once they've been handled. If you click on a row in the DataGrid, that row gets keyboard focus, so KeyDown bubbles up from there. If the DataGrid sets KeyRoutedEventArgs.Handled to true, the Pivot's KeyDown event won't get raised. You can override this for input events using UIElement.AddHandler (passing true for |
@castorix Thanks, so the workaround works. I'm not happy I have to resort to this, but at least it works. |
I was in a similar boat, needing to capture characters entered on the keyboard. I preferred to use Sadly, I couldn't figure out a good clean solution, so I ended up reverting the app to UWP to use |
Listening to PreviewKeyDown works for me. KeyDown is indeed getting stopped from being bubbled up once handled. Maybe, this should be documented on KeyDown for apps which have need for a global "key handler" irrespective of any input element which has focus. |
Can't believe we are here because Microsoft forgot that a PC use a mouse and ... a keyboard. |
WinUI3 has no current mechanism to allow applications to process keyboard input prior to it being handled in the Xaml tree. Converting this to a feature proposal. |
Hey Microsoft! Please, Please allow us to use our beloved keyboard. (Typed this message on a Mac where Keyboards are supported) |
I will add that it used to work. No matter that the webview2 is 1x1 pixel and there are tons of GUI components around it. |
@applefanbois I am sorry, I missed the part about WebView2 in the initial postings on this issue. I was responding to the point:
This is not a point that I necessarily disagree with, but the fact remains that there is no provision for it currently in Xaml and its work would be on the level of a Feature to implement it. I am only surmising (since I wasn't here at the time), but I guess that that wasn't built into Xaml because it originated in UWP and there was a Core Window available that could provide that capability. However, when moving this from UWP to desktop, the new windowing infrastructure does not provide that and hence there is no easy way to do it in Xaml. Again, I don't disagree that it would be useful, but at this point it would be a feature request. We have had a number of discussions about achieving this capability, but there is no work currently planned to do so. As to the Webview issues (I am still not seeing it in the original posts, but can response to it). For the most part from my testing today, things are working as expected, although not necessarily as we want. If you have a webview in your scene and focus is anywhere other than the Webview, then keys event routing works as designed. The issue is that WebView, as I am sure you are aware, is an open source component and so we (Microsoft) do not have as much control over it as we did when we were using IE. WebView is currently really bad at cooperating with its host; It is mostly just a black box that Xaml pushes data (like urls) into and then it does its own thing. Hence, if the Webview has focus, the key input will go (as it should) to the Webview first. But the WebView doesn't tell Xaml whether or not it handled it. We have similar issues with scroll chaining and pointer events as well. Ideally, WebView would be able to tell its host whether it did anything with an input and whether the host should try to do something. Currently that doesn't happen, but we do have some people who have been looking at this. Now, if you are saying that WebView2 is eating keyboard input when it doesn't have the focus, that would definitely be a bug and if you provide a repro we can look at it. @jtorjo Thanks for the repro application. I am not familiar with the community toolkit, so it helped let me look at it. The behavior you speak about is probably more about the controls than it is input. When keyboard input comes in, we attempt to deliver it first to the element with keyboard focus and then each ancestor above it until someone tells us they handled it. So, when you first fire up you application keyboard focus is on the first pivot tab and any keyboard input would go first to the pivot control where your event handler fires. Since it does not mark the event as handle, we attempt to fire it on each ancestor as well (but they don't do anything with it). Once you select an item, you have move keyboard focus to that item. Keyboard input first goes to that item (which does nothing) then works its way up the tree where (because it is never marked as handled) it goes through both the DataGrid and the Pivot control event handlers. Tapping on the "Tab Two" (as you probably now have guessed) moves keyboard focus back to the pivot before it changes tabs. And so on. From input's perspective, this is how it is supposed to work. Is it unfortunate behavior (especially for this particular scenario), probably, but there are ways to work around it. I am not a controls person, but I suspect that you could listen for the selection changed event and force focus into the first item of the list whenever a tab changed. You could probably even listen to focus events and remember which element had focus when the tab was last active and set focus back into it. Or you could certainly request this feature be added to the Pivot control itself, but again, I am not a controls person so I don't know how that would fit into their plans or whether there would be a generic enough implementation that it would make sense to add it. |
@JJBrychell, very deep and detailed explanation. Thanks a lot!👍 |
Example of the BUG : Inside all my ScrollViewer, I do a "scroll.KeyDown += scroll_KeyDown; Everything is contained in a ScrollViewer + Canvas for hierarchy. the KeyDown event always works, but as soon as a Webview2 is present, even at 1x1 in the bottom right of the window, the KeyDown event will stop working. Even when the focus is not on the Webview2. |
@applefanbois I apologize, but I still cannot repro your issue: Given the following Xaml:
I see the expected (although agreed - not optimal) behavior. If focus in on the button, then the Scroll_KeyDown event gets called, but if focus is in WebView, it does not. |
@JJBrychell I don't know what is that, I do everything dynamically and programmatically. |
Sadly your amazing fix has caused other problems. When using a French Canadian keyboard, we can type é & ç as long as it is only 1 key press. Pressing the ^ key will produce ^^ everywhere. Not only the problem is in everything WinUI3, but also Webview2. So the final answer is : You cannot intercept keyboard events on a WinUI3 win32 app. Sadly Microsoft does not know that desktop computers use a device called Keyboard. |
@applefanbois I again apologize as I have no idea what "amazing fix" you are referring too. The only workaround I gave (with a caveat I am not a controls person) had to do with setting focus. Cleary, I am not understanding your issue and so will refrain from any additional suggestions until we have a repro that I/We can actually look at to understand what is going on. |
I was talking about the code that use "GetCharFromKey" Simple to reproduce, just set your keyboard to French-Canadian and try to type è, ï, ê ... anywhere. |
Those keys are called "dead keys" (ToUnicode(Ex) returns < 0) |
I don't need to intercept those keys. But the problem is that those dead keys will stop working normally in webview2 and in all WinUI3 input text. |
And you are using that code from "WinAPI.cs" and m_HookProcedure = new HookProc(HookProcedure); As soon as I call the SetWindowsHookEx I won't be able to type those characters in webview2 and text controls. When I press on a dead keys, it will do this ^^ |
Do you return, in the hook procedure : |
Well I copy the code back then from a little further down. I modified the code, but same problem. Are you using a French-Canadian setting for the keyboard? |
A "Français (France)" setting, but accents work normally...
|
My project is a winui3 + win32 with a lot of obscure stuff to support only one single instance and multiple windows. Maybe something is making my stuff behaving differently? |
Did you try the last test code above in a blank WinUI 3 project with 2 TextBoxes ? |
I have the exact same code. |
Describe the bug
I simply can't believe that this is an issue in 2022:
There's simply no reliable way to capture keyboard in winui -- I have no idea what to do.
I won't reiterate what Gavin Williams already said in #3986 -- we don't have a CoreWindow in WinUI 3, and I don't see any way to reliably capture keys.
Steps to reproduce the bug
I have a
DataGrid
and I want to capture keyboard input for it.Obviously, since I don't have access to
CoreWindow
, I tried to capture itsKeyDown
orPreviewKeyDown
Of course it doesn't work.
Then I tried to capture the parent's Keydown:
This doesn't work either. There's simply no way to capture this. How am I supposed to create a half decent app when I can't even handle an INS hotkey?
LATER EDIT: Turns out the issue with the datagrid not handling
KeyDown
happens when it's placed on a pivot.Expected behavior
KeyDown
, this should work reliably (see below, when Datagrid is on a Pivot)Screenshots
No response
NuGet package version
WinUI 3 - Windows App SDK 1.0.4
Windows app type
Device form factor
Desktop
Windows version
Windows 10 (21H1): Build 19043
Additional context
No response
The text was updated successfully, but these errors were encountered: