wired up key commands

This commit is contained in:
TheXamlGuy
2024-01-06 16:39:30 +00:00
parent a77c356389
commit 71881ad877
31 changed files with 282 additions and 82 deletions
@@ -3,8 +3,8 @@ using Microsoft.Extensions.DependencyInjection;
namespace Hyperbar.Widget.Contextual;
public class ContextualWidgetBuilder :
IWidgetBuilder
public class ContextualWidgetProvider :
IWidgetProvider
{
public void Create(IServiceCollection services) => services
.AddConfiguration<ContextualWidgetConfiguration>()
@@ -2,7 +2,6 @@
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>Hyperbar.Windows.Controls</RootNamespace>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<UseWinUI>true</UseWinUI>
<UseRidGraph>true</UseRidGraph>
@@ -1,5 +0,0 @@
namespace Hyperbar.Windows.Primary;
public interface IPrimaryCommand
{
}
@@ -0,0 +1,5 @@
namespace Hyperbar.Windows.Primary;
public interface IPrimaryCommandConfiguration
{
}
@@ -1,7 +1,7 @@
namespace Hyperbar.Windows.Primary;
public class KeyAcceleratorCommand :
IPrimaryCommand
public class KeyAcceleratorCommandConfiguration :
IPrimaryCommandConfiguration
{
public string? Icon { get; set; }
@@ -1,6 +1,6 @@
namespace Hyperbar.Windows.Primary;
public class PrimaryWidgetConfiguration :
List<IPrimaryCommand>
List<IPrimaryCommandConfiguration>
{
}
@@ -3,8 +3,8 @@ using Microsoft.Extensions.DependencyInjection;
namespace Hyperbar.Windows.Primary;
public class PrimaryWidgetBuilder :
IWidgetBuilder
public class PrimaryWidgetProvider :
IWidgetProvider
{
public void Create(IServiceCollection services) => services.AddConfiguration<PrimaryWidgetConfiguration>()
.AddWidgetTemplate<PrimaryWidgetViewModel>();
@@ -4,15 +4,13 @@ public class PrimaryWidgetViewModel :
WidgetViewModelBase
{
public PrimaryWidgetViewModel(ITemplateFactory templateFactory,
IServiceFactory serviceFactory) : base(templateFactory, serviceFactory)
IServiceFactory serviceFactory,
IMediator mediator) : base(templateFactory, serviceFactory)
{
;
Add<WidgetButtonViewModel>("Start", new Action(() => mediator.Send(new KeyAcceleratorCommand(VirtualKey.LeftWindows))));
Add<WidgetButtonViewModel>("test 1", new Action(() =>
{
}));
Add<WidgetButtonViewModel>("test 2", new Action(() => { }));
Add<WidgetButtonViewModel>("test 4", new Action(() => { }));
Add<WidgetButtonViewModel>("test 5", new Action(() => { }));
//Add<WidgetButtonViewModel>("test 2", new Action(() => { }));
//Add<WidgetButtonViewModel>("test 4", new Action(() => { }));
//Add<WidgetButtonViewModel>("test 5", new Action(() => { }));
}
}
@@ -2,7 +2,6 @@
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>Hyperbar.Desktop.Win32</RootNamespace>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<UseWinUI>true</UseWinUI>
<UseRidGraph>true</UseRidGraph>
@@ -0,0 +1,7 @@
namespace Hyperbar.Windows.Win32
{
public interface IVirtualKeyboard
{
void Send(int key, params int[] modifierKeys);
}
}
@@ -1,34 +1,35 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
using Windows.System;
using Windows.Win32;
using Windows.Win32.UI.KeyboardAndMouseInput;
namespace Hyperbar.Windows.Win32;
public class KeyInterop
public class VirtualKeyboard :
IVirtualKeyboard
{
private static readonly VirtualKey[] extendedKeys = [
VirtualKey.Menu,
VirtualKey.LeftMenu,
VirtualKey.NumberKeyLock,
VirtualKey.Insert,
VirtualKey.Delete,
VirtualKey.Home,
VirtualKey.End,
VirtualKey.Up,
VirtualKey.Down,
VirtualKey.Left,
VirtualKey.Right,
VirtualKey.Application,
VirtualKey.RightWindows,
VirtualKey.LeftWindows];
private readonly int[] extendedKeys = [
165, // RightMenu
164, // LeftMenu
144, // NumberKeyLock
45, // Insert
46, // Delete
36, // Home
35, // End
36, // Up,
40, // Down,
37, // Left
39, // Right,
93, // Application,
92, // RightWindows
91 // LeftWindows
];
public static void Send(VirtualKey key,
params VirtualKey[] modifierKeys)
public void Send(int key,
params int[] modifierKeys)
{
foreach (VirtualKey modiferKey in modifierKeys)
foreach (int modiferKey in modifierKeys)
{
Press(modiferKey);
}
@@ -36,17 +37,17 @@ public class KeyInterop
Press(key);
Release(key);
foreach (VirtualKey modifierKey in modifierKeys.Reverse())
foreach (int modifierKey in modifierKeys.Reverse())
{
Release(modifierKey);
}
}
private static void Press(VirtualKey key) => Send(key, true);
private void Press(int key) => Send(key, true);
private static void Release(VirtualKey key) => Send(key, false);
private void Release(int key) => Send(key, false);
private static unsafe void Send(VirtualKey key,
private unsafe void Send(int key,
bool pressed)
{
INPUT input = new()
@@ -69,7 +70,7 @@ public class KeyInterop
flags |= KEYBD_EVENT_FLAGS.KEYEVENTF_KEYUP;
}
if (extendedKeys.Contains(key))
if (extendedKeys.Contains((int)key))
{
flags |= KEYBD_EVENT_FLAGS.KEYEVENTF_EXTENDEDKEY;
}
+2 -2
View File
@@ -40,8 +40,8 @@ public partial class App :
services.AddTransient<DesktopFlyout>();
services.AddContentTemplate<CommandViewModel, CommandView>();
services.AddWidget<ContextualWidgetBuilder>();
services.AddWidget<PrimaryWidgetBuilder>();
services.AddWidgetProvider<ContextualWidgetProvider>();
services.AddWidgetProvider<PrimaryWidgetProvider>();
services.AddTransient(provider =>
{
@@ -0,0 +1,13 @@
using Hyperbar.Windows.Win32;
namespace Hyperbar.Windows;
public class KeyAcceleratorCommandHandler(IVirtualKeyboard virtualKeyboard) :
ICommandHandler<KeyAcceleratorCommand>
{
public ValueTask<Unit> Handle(KeyAcceleratorCommand command,
CancellationToken cancellationToken)
{ virtualKeyboard.Send((int)command.Key);
return default;
}
}
-1
View File
@@ -3,7 +3,6 @@
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RootNamespace>Hyperbar.Windows</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Platforms>x86;x64;ARM64</Platforms>
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
@@ -1,4 +1,5 @@
using Hyperbar.Extensions;
using Hyperbar.Windows.Win32;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@@ -6,17 +7,21 @@ namespace Hyperbar.Windows
{
public static class IServiceCollectionExtensions
{
public static IServiceCollection AddWidget<TCommandBuilder>(this IServiceCollection services)
where TCommandBuilder :
IWidgetBuilder, new()
public static IServiceCollection AddWidgetProvider<TWidgetProvider>(this IServiceCollection services)
where TWidgetProvider :
IWidgetProvider, new()
{
TCommandBuilder builder = new();
TWidgetProvider builder = new();
IHost? host = new HostBuilder()
.ConfigureServices(isolatedServices =>
{
isolatedServices.AddSingleton<IServiceFactory>(provider =>
new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!)));
isolatedServices.AddSingleton<IVirtualKeyboard, VirtualKeyboard>();
isolatedServices.AddSingleton<IMediator, Mediator>();
isolatedServices.AddHandler<KeyAcceleratorCommandHandler>();
isolatedServices.AddTransient<IWidgetView, WidgetView>();
isolatedServices.AddContentTemplate<WidgetButtonViewModel, WidgetButtonView>();
@@ -1,11 +0,0 @@
namespace Hyperbar.Windows;
public class KeyAcceleratorCommandHandler :
ICommandHandler<KeyAcceleratorCommand>
{
public ValueTask<Unit> Handle(KeyAcceleratorCommand command,
CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
@@ -0,0 +1,5 @@
namespace Hyperbar;
public record KeyAcceleratorCommand(VirtualKey Key,
VirtualKey[]? Modifiers = null) :
ICommand;
+175
View File
@@ -0,0 +1,175 @@
namespace Hyperbar;
public enum VirtualKey
{
None = 0,
LeftButton = 1,
RightButton = 2,
Cancel = 3,
MiddleButton = 4,
XButton1 = 5,
XButton2 = 6,
Back = 8,
Tab = 9,
Clear = 12,
Enter = 13,
Shift = 16,
Control = 17,
Menu = 18,
Pause = 19,
CapitalLock = 20,
Kana = 21,
Hangul = 21,
Junja = 23,
Final = 24,
Hanja = 25,
Kanji = 25,
Escape = 27,
Convert = 28,
NonConvert = 29,
Accept = 30,
ModeChange = 31,
Space = 32,
PageUp = 33,
PageDown = 34,
End = 35,
Home = 36,
Left = 37,
Up = 38,
Right = 39,
Down = 40,
Select = 41,
Print = 42,
Execute = 43,
Snapshot = 44,
Insert = 45,
Delete = 46,
Help = 47,
Number0 = 48,
Number1 = 49,
Number2 = 50,
Number3 = 51,
Number4 = 52,
Number5 = 53,
Number6 = 54,
Number7 = 55,
Number8 = 56,
Number9 = 57,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LeftWindows = 91,
RightWindows = 92,
Application = 93,
Sleep = 95,
NumberPad0 = 96,
NumberPad1 = 97,
NumberPad2 = 98,
NumberPad3 = 99,
NumberPad4 = 100,
NumberPad5 = 101,
NumberPad6 = 102,
NumberPad7 = 103,
NumberPad8 = 104,
NumberPad9 = 105,
Multiply = 106,
Add = 107,
Separator = 108,
Subtract = 109,
Decimal = 110,
Divide = 111,
F1 = 112,
F2 = 113,
F3 = 114,
F4 = 115,
F5 = 116,
F6 = 117,
F7 = 118,
F8 = 119,
F9 = 120,
F10 = 121,
F11 = 122,
F12 = 123,
F13 = 124,
F14 = 125,
F15 = 126,
F16 = 127,
F17 = 128,
F18 = 129,
F19 = 130,
F20 = 131,
F21 = 132,
F22 = 133,
F23 = 134,
F24 = 135,
NavigationView = 136,
NavigationMenu = 137,
NavigationUp = 138,
NavigationDown = 139,
NavigationLeft = 140,
NavigationRight = 141,
NavigationAccept = 142,
NavigationCancel = 143,
NumberKeyLock = 144,
Scroll = 145,
LeftShift = 160,
RightShift = 161,
LeftControl = 162,
RightControl = 163,
LeftMenu = 164,
RightMenu = 165,
GoBack = 166,
GoForward = 167,
Refresh = 168,
Stop = 169,
Search = 170,
Favorites = 171,
GoHome = 172,
GamepadA = 195,
GamepadB = 196,
GamepadX = 197,
GamepadY = 198,
GamepadRightShoulder = 199,
GamepadLeftShoulder = 200,
GamepadLeftTrigger = 201,
GamepadRightTrigger = 202,
GamepadDPadUp = 203,
GamepadDPadDown = 204,
GamepadDPadLeft = 205,
GamepadDPadRight = 206,
GamepadMenu = 207,
GamepadView = 208,
GamepadLeftThumbstickButton = 209,
GamepadRightThumbstickButton = 210,
GamepadLeftThumbstickUp = 211,
GamepadLeftThumbstickDown = 212,
GamepadLeftThumbstickRight = 213,
GamepadLeftThumbstickLeft = 214,
GamepadRightThumbstickUp = 215,
GamepadRightThumbstickDown = 216,
GamepadRightThumbstickRight = 217,
GamepadRightThumbstickLeft = 218
}
@@ -16,6 +16,7 @@ public class CommandClassHandlerWrapper<TRequest, TResponse>
{
MessageHandlerDelegate<TRequest, TResponse> handlerCopy = handler;
IPipelineBehavior<TRequest, TResponse> pipelineCopy = pipeline;
handler = (TRequest message, CancellationToken cancellationToken) =>
pipelineCopy.Handle(message, handlerCopy, cancellationToken);
}
+7 -5
View File
@@ -2,21 +2,23 @@
public interface IMediator
{
ValueTask Publish<TNotification>(TNotification notification,
ValueTask PublishAsync<TNotification>(TNotification notification,
CancellationToken cancellationToken = default)
where TNotification :
INotification;
ValueTask<TResponse> Send<TResponse>(IRequest<TResponse> request,
void Send<TResponse>(ICommand<TResponse> command);
ValueTask<TResponse> SendAsync<TResponse>(IRequest<TResponse> request,
CancellationToken cancellationToken = default);
ValueTask<TResponse> Send<TResponse>(ICommand<TResponse> command,
ValueTask<TResponse> SendAsync<TResponse>(ICommand<TResponse> command,
CancellationToken cancellationToken = default);
ValueTask<TResponse> Send<TResponse>(IQuery<TResponse> query,
ValueTask<TResponse> SendAsync<TResponse>(IQuery<TResponse> query,
CancellationToken cancellationToken = default);
ValueTask<object?> Send(object message, CancellationToken
ValueTask<object?> SendAsync(object message, CancellationToken
cancellationToken = default);
void Subscribe(object subscriber);
@@ -1,5 +0,0 @@
namespace Hyperbar;
public record KeyAcceleratorCommand(string Key,
string[]? Modifiers = null) :
ICommand;
+16 -5
View File
@@ -8,7 +8,7 @@ public class Mediator(IServiceProvider provider) :
{
private readonly ConditionalWeakTable<Type, dynamic> handlers = [];
public ValueTask Publish<TNotification>(TNotification notification,
public ValueTask PublishAsync<TNotification>(TNotification notification,
CancellationToken cancellationToken = default)
where TNotification :
INotification
@@ -36,7 +36,7 @@ public class Mediator(IServiceProvider provider) :
return default;
}
public ValueTask<TResponse> Send<TResponse>(IRequest<TResponse> request,
public ValueTask<TResponse> SendAsync<TResponse>(IRequest<TResponse> request,
CancellationToken cancellationToken = default)
{
dynamic? handler = provider.GetService(typeof(RequestClassHandlerWrapper<,>)
@@ -50,7 +50,7 @@ public class Mediator(IServiceProvider provider) :
return default;
}
public ValueTask<TResponse> Send<TResponse>(ICommand<TResponse> command,
public ValueTask<TResponse> SendAsync<TResponse>(ICommand<TResponse> command,
CancellationToken cancellationToken = default)
{
dynamic? handler = provider.GetService(typeof(CommandClassHandlerWrapper<,>)
@@ -64,7 +64,18 @@ public class Mediator(IServiceProvider provider) :
return default;
}
public ValueTask<TResponse> Send<TResponse>(IQuery<TResponse> query,
public void Send<TResponse>(ICommand<TResponse> command)
{
dynamic? handler = provider.GetService(typeof(CommandClassHandlerWrapper<,>)
.MakeGenericType(command.GetType(), typeof(TResponse)));
if (handler is not null)
{
_ = handler.Handle((dynamic)command, default(CancellationToken));
}
}
public ValueTask<TResponse> SendAsync<TResponse>(IQuery<TResponse> query,
CancellationToken cancellationToken = default)
{
dynamic? handler = provider.GetService(typeof(QueryClassHandlerWrapper<,>)
@@ -78,7 +89,7 @@ public class Mediator(IServiceProvider provider) :
return default;
}
public ValueTask<object?> Send(object message,
public ValueTask<object?> SendAsync(object message,
CancellationToken cancellationToken = default)
{
if (message.GetType().GetInterface(typeof(IRequest<>).Name) is { } requestType)
@@ -16,6 +16,7 @@ public class QueryClassHandlerWrapper<TRequest, TResponse>
{
MessageHandlerDelegate<TRequest, TResponse> handlerCopy = handler;
IPipelineBehavior<TRequest, TResponse> pipelineCopy = pipeline;
handler = (TRequest message, CancellationToken cancellationToken) =>
pipelineCopy.Handle(message, handlerCopy, cancellationToken);
}
@@ -2,7 +2,7 @@
namespace Hyperbar;
public interface IWidgetBuilder
public interface IWidgetProvider
{
void Create(IServiceCollection services);
}