Skip to content
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

🚧 Testing input injector with 1.2.221109.1 WinAppSDK in CI #183

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
"isRoot": true,
"tools": {
"uno.check": {
"version": "1.3.1",
"version": "1.10.0",
"commands": [
"uno-check"
]
},
"xamlstyler.console": {
"version": "3.2008.4",
"version": "3.2206.4",
"commands": [
"xstyler"
]
Expand Down
32 changes: 16 additions & 16 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Needed until XAML Styler updates to .NET 6
- name: Install .NET Core 3.1 SDK
uses: actions/setup-dotnet@v1
- name: Install .NET 6 SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: '3.1.x'
dotnet-version: '6.0.x'

# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3

# Restore Tools from Manifest list in the Repository
- name: Restore dotnet tools
Expand All @@ -49,13 +49,13 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Install .NET 6 SDK
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.202'
dotnet-version: '6.0.x'

# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3

# Restore Tools from Manifest list in the Repository
- name: Restore dotnet tools
Expand Down Expand Up @@ -123,13 +123,13 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- name: Install .NET 6 SDK
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.202'
dotnet-version: '6.0.x'

# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3

# Restore Tools from Manifest list in the Repository
- name: Restore dotnet tools
Expand Down Expand Up @@ -200,13 +200,13 @@ jobs:

steps:
- name: Install .NET 6 SDK
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.202'
dotnet-version: '6.0.x'

# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Add msbuild to PATH
uses: microsoft/[email protected]
Expand Down Expand Up @@ -255,13 +255,13 @@ jobs:

steps:
- name: Install .NET 6 SDK
uses: actions/setup-dotnet@v1
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.201'
dotnet-version: '6.0.x'

# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Generate solution
shell: pwsh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.8" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.8" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.8" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.8" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
</ItemGroup>

<ItemGroup>
Expand Down
20 changes: 11 additions & 9 deletions common/CommunityToolkit.Labs.Tests.Shared/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Windows.UI.Xaml.Navigation;
#else
using Microsoft.UI.Dispatching;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
Expand All @@ -25,6 +26,7 @@
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
using System.Runtime.InteropServices;
#endif

namespace CommunityToolkit.Labs.Tests;
Expand All @@ -37,16 +39,16 @@ public sealed partial class App : Application
// MacOS and iOS don't know the correct type without a full namespace declaration, confusing it with NSWindow and UIWindow.
// Using static will not work.
#if WINAPPSDK
private static Microsoft.UI.Xaml.Window currentWindow = Microsoft.UI.Xaml.Window.Current;
public static Microsoft.UI.Xaml.Window CurrentWindow = Microsoft.UI.Xaml.Window.Current;
#else
private static Windows.UI.Xaml.Window currentWindow = Windows.UI.Xaml.Window.Current;
public static Windows.UI.Xaml.Window CurrentWindow = Windows.UI.Xaml.Window.Current;
#endif

// Holder for test content to abstract Window.Current.Content
public static FrameworkElement? ContentRoot
{
get => currentWindow.Content as FrameworkElement;
set => currentWindow.Content = value;
get => CurrentWindow.Content as FrameworkElement;
set => CurrentWindow.Content = value;
}

// Abstract CoreApplication.MainView.DispatcherQueue
Expand All @@ -57,7 +59,7 @@ public static DispatcherQueue DispatcherQueue
#if !WINAPPSDK
return CoreApplication.MainView.DispatcherQueue;
#else
return currentWindow.DispatcherQueue;
return CurrentWindow.DispatcherQueue;
#endif
}
}
Expand All @@ -79,23 +81,23 @@ public App()
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
#if WINAPPSDK
currentWindow = new Window();
CurrentWindow = new Window();
#endif

// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (currentWindow.Content is not Frame rootFrame)
if (CurrentWindow.Content is not Frame rootFrame)
{
// Create a Frame to act as the navigation context and navigate to the first page
currentWindow.Content = rootFrame = new Frame();
CurrentWindow.Content = rootFrame = new Frame();

rootFrame.NavigationFailed += OnNavigationFailed;
}

////Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();

// Ensure the current window is active
currentWindow.Activate();
CurrentWindow.Activate();

#if !WINAPPSDK
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.Run(e.Arguments);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@
<Compile Include="$(MSBuildThisFileDirectory)App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Input\InputHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Input\InputSimulator.Bounds.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Input\InputSimulator.Touch.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Log.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Input\InputSimulator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)VisualUITestBase.cs" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="$(MSBuildThisFileDirectory)NativeMethods.txt" />
</ItemGroup>
</Project>
30 changes: 30 additions & 0 deletions common/CommunityToolkit.Labs.Tests.Shared/Input/InputHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if WINAPPSDK
using MainWindow = Microsoft.UI.Xaml.Window;
#else
using MainWindow = Windows.UI.Xaml.Window;
#endif

namespace CommunityToolkit.Labs.Tests;

public static class InputHelpers
{
/// <summary>
/// Helper extension method to create a new <see cref="InputSimulator"/> chain for the current window.
/// </summary>
/// <param name="window"><see cref="Window"/> class for your application.</param>
/// <returns>A new <see cref="InputSimulator"/> instance for that window.</returns>
public static InputSimulator InjectInput(this MainWindow window)
{
return new InputSimulator(window);
}

public static Point CoordinatesToCenter(this UIElement parent, UIElement target)
{
var location = target.TransformToVisual(parent).TransformPoint(default(Point));
return new(location.X + target.ActualSize.X / 2, location.Y + target.ActualSize.Y / 2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if WINAPPSDK
using Windows.Win32;
using Windows.Win32.Foundation;
using Win32Rect = Windows.Win32.Foundation.RECT;
using Win32Point = System.Drawing.Point;
#endif

namespace CommunityToolkit.Labs.Tests;

//// This polyfill is needed as the WindowsAppSDK doesn't provide client based coordinates. See Issue: TODO: File bug currentWindow.Bounds should be the same between the two platforms. Should AppWindow also have Bounds?

public partial class InputSimulator
{
#if WINAPPSDK
private Rect Bounds
{
get
{
if (_currentWindowRef.TryGetTarget(out var currentWindow))
{
var hWnd = (HWND)WinRT.Interop.WindowNative.GetWindowHandle(currentWindow);

// Get client area position
Win32Point[] points = new Win32Point[1];
PInvoke.MapWindowPoints(hWnd, HWND.Null, points);

// TODO: Check LastError?

// And size
if (points.Length == 1 && PInvoke.GetClientRect(hWnd, out Win32Rect size))
{
return new Rect(points[0].X, points[0].Y, size.right - size.left, size.bottom - size.top);
}
}

return default;
}
}
#else
private Rect Bounds => _currentWindowRef.TryGetTarget(out Window window) ? window.Bounds : default;
#endif

private Point TranslatePointForWindow(Point point)
{
// TODO: Do we want a ToPoint extension in the Toolkit? (is there an existing enum we can use to specify which corner/point of the rect? e.g. topleft, center, middleright, etc...?

// Get the top left screen coordinates of the app window rect.
var bounds = Bounds; // Don't double-retrieve the calculated property, TODO: Just make some point helpers (or use ones in Toolkit)
Point appBoundsTopLeft = new Point(bounds.Left, bounds.Top);

// Create the point for input injection and calculate its screen location.
return new Point(
appBoundsTopLeft.X + point.X,
appBoundsTopLeft.Y + point.Y);

}
}
Loading