1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 21:38:38 +00:00

Windows - Use user32 APIs to manage windows for input provider and Vulkan

This commit is contained in:
Robert 2023-04-27 10:50:13 +02:00
parent c50a572363
commit ebe7f68e9d
5 changed files with 69 additions and 69 deletions

View File

@ -1,18 +0,0 @@
using System.Linq;
using Artemis.UI.Exceptions;
using Avalonia.Platform;
namespace Artemis.UI.Windows.Extensions;
public static class IWindowImplExtensions
{
public static IPlatformHandle GetHandle(this IWindowImpl window)
{
// This is unfortunate
IPlatformHandle? handle = (IPlatformHandle?) window.GetType().GetProperties().FirstOrDefault(p => p.Name == "Handle")?.GetValue(window);
if (handle == null)
throw new ArtemisUIException("Could not get IWindowImpl internal platform handle, Avalonia API change?");
return handle;
}
}

View File

@ -4,10 +4,7 @@ using System.Runtime.InteropServices;
using System.Timers;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Windows.Extensions;
using Artemis.UI.Windows.Utilities;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
using Linearstar.Windows.RawInput;
using Linearstar.Windows.RawInput.Native;
using Serilog;
@ -19,7 +16,7 @@ public class WindowsInputProvider : InputProvider
private const int GWL_WNDPROC = -4;
private const int WM_INPUT = 0x00FF;
private readonly IWindowImpl _window;
private readonly nint _hWnd;
private readonly nint _hWndProcHook;
private readonly WndProc? _fnWndProcHook;
private readonly IInputService _inputService;
@ -32,7 +29,7 @@ public class WindowsInputProvider : InputProvider
private nint CustomWndProc(nint hWnd, uint msg, nint wParam, nint lParam)
{
OnWndProcCalled(hWnd, msg, wParam, lParam);
return CallWindowProc(_hWndProcHook, hWnd, msg, wParam, lParam);
return User32.CallWindowProc(_hWndProcHook, hWnd, msg, wParam, lParam);
}
public WindowsInputProvider(ILogger logger, IInputService inputService)
@ -44,16 +41,14 @@ public class WindowsInputProvider : InputProvider
_taskManagerTimer.Elapsed += TaskManagerTimerOnElapsed;
_taskManagerTimer.Start();
_window = PlatformManager.CreateWindow();
IPlatformHandle handle = _window.GetHandle();
_hWndProcHook = GetWindowLongPtr(handle.Handle, GWL_WNDPROC);
_hWnd = User32.CreateWindowEx(0, "STATIC", "", 0x80000000, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
_hWndProcHook = User32.GetWindowLongPtr(_hWnd, GWL_WNDPROC);
_fnWndProcHook = CustomWndProc;
nint newLong = Marshal.GetFunctionPointerForDelegate(_fnWndProcHook);
SetWindowLongPtr(handle.Handle, GWL_WNDPROC, newLong);
User32.SetWindowLongPtr(_hWnd, GWL_WNDPROC, newLong);
RawInputDevice.RegisterDevice(HidUsageAndPage.Keyboard, RawInputDeviceFlags.InputSink, handle.Handle);
RawInputDevice.RegisterDevice(HidUsageAndPage.Mouse, RawInputDeviceFlags.InputSink, handle.Handle);
RawInputDevice.RegisterDevice(HidUsageAndPage.Keyboard, RawInputDeviceFlags.InputSink, _hWnd);
RawInputDevice.RegisterDevice(HidUsageAndPage.Mouse, RawInputDeviceFlags.InputSink, _hWnd);
}
public static Guid Id { get; } = new("6737b204-ffb1-4cd9-8776-9fb851db303a");
@ -239,30 +234,10 @@ public class WindowsInputProvider : InputProvider
#region Native
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CallWindowProc(nint lpPrevWndFunc, IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Unicode)]
private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Unicode)]
private static extern IntPtr SetWindowLongPtr(nint hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetCursorPos(ref Win32Point pt);
[StructLayout(LayoutKind.Sequential)]
private struct Win32Point
{
public readonly int X;
public readonly int Y;
}
private static Win32Point GetCursorPosition()
{
Win32Point w32Mouse = new();
GetCursorPos(ref w32Mouse);
User32.GetCursorPos(ref w32Mouse);
return w32Mouse;
}

View File

@ -1,8 +1,5 @@
using System;
using System.Linq;
using Artemis.UI.Windows.Extensions;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
using SharpVk;
using SharpVk.Khronos;
@ -10,12 +7,16 @@ namespace Artemis.UI.Windows.SkiaSharp.Vulkan;
internal sealed class Win32VkContext : VkContext
{
private readonly nint _hWnd;
public Win32VkContext()
{
Window = PlatformManager.CreateWindow();
// Use WS_CHILD and WS_VISIBLE with WS_VISIBLE set to false
_hWnd = User32.CreateWindowEx(0, "STATIC", "", 0x80000000, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
Instance = Instance.Create(null, new[] {"VK_KHR_surface", "VK_KHR_win32_surface"});
PhysicalDevice = Instance.EnumeratePhysicalDevices().First();
Surface = Instance.CreateWin32Surface(Kernel32.CurrentModuleHandle, Window.GetHandle().Handle);
Surface = Instance.CreateWin32Surface(Kernel32.CurrentModuleHandle, _hWnd);
(GraphicsFamily, PresentFamily) = FindQueueFamilies();
@ -45,12 +46,10 @@ internal sealed class Win32VkContext : VkContext
};
}
public IWindowImpl Window { get; }
public override void Dispose()
{
base.Dispose();
Window.Dispose();
User32.DestroyWindow(_hWnd);
}
private IntPtr Proc(string name, IntPtr instanceHandle, IntPtr deviceHandle)

View File

@ -0,0 +1,51 @@
using System;
using System.Runtime.InteropServices;
namespace Artemis.UI.Windows;
static class User32
{
[DllImport("user32.dll")]
public static extern IntPtr CreateWindowEx(
uint dwExStyle,
string lpClassName,
string lpWindowName,
uint dwStyle,
int x,
int y,
int nWidth,
int nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lpParam);
[DllImport("user32.dll")]
public static extern bool DestroyWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr CallWindowProc(nint lpPrevWndFunc, IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", CharSet = CharSet.Unicode)]
public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Unicode)]
public static extern IntPtr SetWindowLongPtr(nint hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(ref Win32Point pt);
}
[StructLayout(LayoutKind.Sequential)]
public struct Win32Point
{
public readonly int X;
public readonly int Y;
}

View File

@ -1,5 +1,4 @@
using System;
using System.Runtime.InteropServices;
namespace Artemis.UI.Windows.Utilities;
@ -8,15 +7,9 @@ public static class WindowUtilities
public static int GetActiveProcessId()
{
// Get foreground window handle
IntPtr hWnd = GetForegroundWindow();
IntPtr hWnd = User32.GetForegroundWindow();
GetWindowThreadProcessId(hWnd, out uint processId);
User32.GetWindowThreadProcessId(hWnd, out uint processId);
return (int) processId;
}
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
}