Skip to content

Commit

Permalink
Merge pull request #18702 from ramezgerges/wasm_modifier_key_tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund authored Nov 20, 2024
2 parents 7135b26 + acd661b commit 44d7617
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/SamplesApp/UITests.Shared/UITests.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -4266,6 +4266,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Input\Keyboard\Keyboard_Modifiers.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Input\Keyboard\Keyboard_iOS_Theme.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down Expand Up @@ -8203,6 +8207,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Input\Keyboard\Keyboard_Events.xaml.cs">
<DependentUpon>Keyboard_Events.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Input\Keyboard\Keyboard_Modifiers.xaml.cs">
<DependentUpon>Keyboard_Modifiers.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Input\Keyboard\Keyboard_iOS_Theme.xaml.cs">
<DependentUpon>Keyboard_iOS_Theme.xaml</DependentUpon>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Page
x:Class="UITests.Windows_UI_Xaml_Input.Keyboard.Keyboard_Modifiers"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UITests.Windows_UI_Xaml_Input.Keyboard"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<StackPanel>
<TextBlock>
<Run Text="Repro steps (only Uno targets, not WinUI):" />
<LineBreak />
<Run Text="1. You should see 'Modifiers pressed: None' below." />
<LineBreak />
<Run Text="2. Press the Shift key. You should see the modifier status below change to reflect that shift is pressed" />
<LineBreak />
<Run Text="3. Release the Shift key. You should see tha modifier status below go back to 'Modifiers pressed: None'" />
</TextBlock>
<TextBlock x:Name="statusTb" Text="Modifiers pressed: None" />
</StackPanel>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using System.Linq;
using Windows.System;
using Windows.UI.Core;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Uno.UI.Samples.Controls;

namespace UITests.Windows_UI_Xaml_Input.Keyboard
{
[Sample("Keyboard", IsManualTest = true)]
public sealed partial class Keyboard_Modifiers : Page
{
#if HAS_UNO
private DispatcherTimer _timer;
#endif

public Keyboard_Modifiers()
{
this.InitializeComponent();
#if HAS_UNO
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(100);
_timer.Tick += (_, _) =>
{
var mods = PlatformHelpers.GetKeyboardModifiers();
var modString = "";
if (mods.HasFlag(VirtualKeyModifiers.Shift))
{
modString += " Shift";
}
if (mods.HasFlag(VirtualKeyModifiers.Control))
{
modString += " Ctrl";
}
if (mods.HasFlag(VirtualKeyModifiers.Windows))
{
modString += " Win";
}
if (mods.HasFlag(VirtualKeyModifiers.Menu))
{
modString += " Menu";
}

if (string.IsNullOrEmpty(modString))
{
modString = "None";
}
statusTb.Text = $"Modifiers pressed: {modString}";
};

Loaded += (_, _) => _timer.Start();
Unloaded += (_, _) => _timer.Stop();
#endif
}
}
}
17 changes: 17 additions & 0 deletions src/Uno.UI/ts/WindowManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ namespace Uno.UI {
private static dispatchSuspendingMethod: any;
private static getDependencyPropertyValueMethod: any;
private static setDependencyPropertyValueMethod: any;
private static keyTrackingMethod: any;

private constructor(private containerElementId: string, private loadingElementId: string) {
this.initDom();
Expand Down Expand Up @@ -1437,6 +1438,7 @@ namespace Uno.UI {
WindowManager.dispatchEventMethod = exports.Microsoft.UI.Xaml.UIElement.DispatchEvent;
WindowManager.focusInMethod = exports.Microsoft.UI.Xaml.Input.FocusManager.ReceiveFocusNative;
WindowManager.dispatchSuspendingMethod = exports.Microsoft.UI.Xaml.Application.DispatchSuspending;
WindowManager.keyTrackingMethod = (<any>globalThis).DotnetExports.Uno.Uno.UI.Core.KeyboardStateTracker.UpdateKeyStateNative;
} else {
throw `Unable to find dotnet exports`;
}
Expand All @@ -1451,6 +1453,13 @@ namespace Uno.UI {
document.body.addEventListener("focusin", this.onfocusin);
document.body.appendChild(this.containerElement);

// On WASM, if no one subscribes to key<Down|Up>, not only will the event not fire on any UIElement,
// but the browser won't even notify us that a key was pressed/released, and this breaks KeyboardStateTracker
// key tracking, which depends on RaiseEvent being called even if no one is subscribing. Instead, we
// subscribe on the body and make sure to call KeyboardStateTracker ourselves here.
document.body.addEventListener("keydown", this.onBodyKeyDown);
document.body.addEventListener("keyup", this.onBodyKeyUp);

window.addEventListener("resize", x => WindowManager.resize());
window.addEventListener("contextmenu", x => {
if (!(x.target instanceof HTMLInputElement) ||
Expand Down Expand Up @@ -1593,6 +1602,14 @@ namespace Uno.UI {
public moveWindow(x: number, y: number) {
window.moveTo(x, y);
}

private onBodyKeyDown(event: KeyboardEvent) {
WindowManager.keyTrackingMethod(event.key, true);
}

private onBodyKeyUp(event: KeyboardEvent) {
WindowManager.keyTrackingMethod(event.key, false);
}
}

if (typeof define === "function") {
Expand Down
20 changes: 19 additions & 1 deletion src/Uno.UWP/UI/Core/Internal/KeyboardStateTracker.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.JavaScript;
using Windows.System;
using Windows.UI.Core;

Expand All @@ -13,7 +14,7 @@ namespace Uno.UI.Core;
/// In UWP/WinUI, every key has a locked state (not only Caps Lock, etc.). The sequence of states is as follows:
/// (None) -> (Down) -> (None) -> (Down + Locked) -> (None + Locked) -> (Down) -> (None) -> etc.
/// </remarks>
internal static class KeyboardStateTracker
internal static partial class KeyboardStateTracker
{
private static readonly Dictionary<VirtualKey, CoreVirtualKeyStates> _keyStates = new Dictionary<VirtualKey, CoreVirtualKeyStates>();

Expand Down Expand Up @@ -106,4 +107,21 @@ internal static void Reset()
_keyStates.Clear();
}
}

#if __WASM__
#pragma warning disable IDE0051 // Remove unused private members
[JSExport]
private static void UpdateKeyStateNative(string key, bool down)
#pragma warning restore IDE0051 // Remove unused private members
{
if (down)
{
OnKeyDown(VirtualKeyHelper.FromKey(key));
}
else
{
OnKeyUp(VirtualKeyHelper.FromKey(key));
}
}
#endif
}

0 comments on commit 44d7617

Please sign in to comment.