| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- using Avalonia;
- using Avalonia.Controls;
- using Avalonia.Input;
- using Avalonia.Platform;
- using SPB.Graphics;
- using SPB.Platform;
- using SPB.Platform.GLX;
- using System;
- using System.Runtime.InteropServices;
- using System.Runtime.Versioning;
- using System.Threading.Tasks;
- using static Ryujinx.Ava.UI.Helpers.Win32NativeInterop;
- namespace Ryujinx.Ava.UI.Helpers
- {
- public class EmbeddedWindow : NativeControlHost
- {
- private WindowProc _wndProcDelegate;
- private string _className;
- protected GLXWindow X11Window { get; set; }
- protected IntPtr WindowHandle { get; set; }
- protected IntPtr X11Display { get; set; }
- protected IntPtr NsView { get; set; }
- protected IntPtr MetalLayer { get; set; }
- private UpdateBoundsCallbackDelegate _updateBoundsCallback;
- public event EventHandler<IntPtr> WindowCreated;
- public event EventHandler<Size> SizeChanged;
- protected virtual void OnWindowDestroyed() { }
- protected virtual void OnWindowDestroying()
- {
- WindowHandle = IntPtr.Zero;
- X11Display = IntPtr.Zero;
- NsView = IntPtr.Zero;
- MetalLayer = IntPtr.Zero;
- }
- public EmbeddedWindow()
- {
- var stateObserverable = this.GetObservable(BoundsProperty);
- stateObserverable.Subscribe(StateChanged);
- Initialized += NativeEmbeddedWindow_Initialized;
- }
- public virtual void OnWindowCreated() { }
- private void NativeEmbeddedWindow_Initialized(object sender, EventArgs e)
- {
- OnWindowCreated();
- Task.Run(() =>
- {
- WindowCreated?.Invoke(this, WindowHandle);
- });
- }
- private void StateChanged(Rect rect)
- {
- SizeChanged?.Invoke(this, rect.Size);
- _updateBoundsCallback?.Invoke(rect);
- }
- protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
- {
- if (OperatingSystem.IsLinux())
- {
- return CreateLinux(parent);
- }
- else if (OperatingSystem.IsWindows())
- {
- return CreateWin32(parent);
- }
- else if (OperatingSystem.IsMacOS())
- {
- return CreateMacOs(parent);
- }
- return base.CreateNativeControlCore(parent);
- }
- protected override void DestroyNativeControlCore(IPlatformHandle control)
- {
- OnWindowDestroying();
- if (OperatingSystem.IsLinux())
- {
- DestroyLinux();
- }
- else if (OperatingSystem.IsWindows())
- {
- DestroyWin32(control);
- }
- else if (OperatingSystem.IsMacOS())
- {
- DestroyMacOS();
- }
- else
- {
- base.DestroyNativeControlCore(control);
- }
- OnWindowDestroyed();
- }
- [SupportedOSPlatform("linux")]
- protected virtual IPlatformHandle CreateLinux(IPlatformHandle parent)
- {
- X11Window = PlatformHelper.CreateOpenGLWindow(FramebufferFormat.Default, 0, 0, 100, 100) as GLXWindow;
- WindowHandle = X11Window.WindowHandle.RawHandle;
- X11Display = X11Window.DisplayHandle.RawHandle;
- return new PlatformHandle(WindowHandle, "X11");
- }
- [SupportedOSPlatform("windows")]
- IPlatformHandle CreateWin32(IPlatformHandle parent)
- {
- _className = "NativeWindow-" + Guid.NewGuid();
- _wndProcDelegate = WndProc;
- var wndClassEx = new WNDCLASSEX
- {
- cbSize = Marshal.SizeOf<WNDCLASSEX>(),
- hInstance = GetModuleHandle(null),
- lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate),
- style = ClassStyles.CS_OWNDC,
- lpszClassName = Marshal.StringToHGlobalUni(_className),
- hCursor = CreateArrowCursor()
- };
- var atom = RegisterClassEx(ref wndClassEx);
- var handle = CreateWindowEx(
- 0,
- _className,
- "NativeWindow",
- WindowStyles.WS_CHILD,
- 0,
- 0,
- 640,
- 480,
- parent.Handle,
- IntPtr.Zero,
- IntPtr.Zero,
- IntPtr.Zero);
- WindowHandle = handle;
- Marshal.FreeHGlobal(wndClassEx.lpszClassName);
- return new PlatformHandle(WindowHandle, "HWND");
- }
- [SupportedOSPlatform("windows")]
- IntPtr WndProc(IntPtr hWnd, WindowsMessages msg, IntPtr wParam, IntPtr lParam)
- {
- var point = new Point((long)lParam & 0xFFFF, ((long)lParam >> 16) & 0xFFFF);
- var root = VisualRoot as Window;
- bool isLeft = false;
- switch (msg)
- {
- case WindowsMessages.LBUTTONDOWN:
- case WindowsMessages.RBUTTONDOWN:
- isLeft = msg == WindowsMessages.LBUTTONDOWN;
- this.RaiseEvent(new PointerPressedEventArgs(
- this,
- new Pointer(0, PointerType.Mouse, true),
- root,
- this.TranslatePoint(point, root).Value,
- (ulong)Environment.TickCount64,
- new PointerPointProperties(isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton, isLeft ? PointerUpdateKind.LeftButtonPressed : PointerUpdateKind.RightButtonPressed),
- KeyModifiers.None));
- break;
- case WindowsMessages.LBUTTONUP:
- case WindowsMessages.RBUTTONUP:
- isLeft = msg == WindowsMessages.LBUTTONUP;
- this.RaiseEvent(new PointerReleasedEventArgs(
- this,
- new Pointer(0, PointerType.Mouse, true),
- root,
- this.TranslatePoint(point, root).Value,
- (ulong)Environment.TickCount64,
- new PointerPointProperties(isLeft ? RawInputModifiers.LeftMouseButton : RawInputModifiers.RightMouseButton, isLeft ? PointerUpdateKind.LeftButtonReleased : PointerUpdateKind.RightButtonReleased),
- KeyModifiers.None,
- isLeft ? MouseButton.Left : MouseButton.Right));
- break;
- case WindowsMessages.MOUSEMOVE:
- this.RaiseEvent(new PointerEventArgs(
- PointerMovedEvent,
- this,
- new Pointer(0, PointerType.Mouse, true),
- root,
- this.TranslatePoint(point, root).Value,
- (ulong)Environment.TickCount64,
- new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.Other),
- KeyModifiers.None));
- break;
- }
- return DefWindowProc(hWnd, msg, wParam, lParam);
- }
- [SupportedOSPlatform("macos")]
- IPlatformHandle CreateMacOs(IPlatformHandle parent)
- {
- MetalLayer = MetalHelper.GetMetalLayer(out IntPtr nsView, out _updateBoundsCallback);
- NsView = nsView;
- return new PlatformHandle(nsView, "NSView");
- }
- void DestroyLinux()
- {
- X11Window?.Dispose();
- }
- [SupportedOSPlatform("windows")]
- void DestroyWin32(IPlatformHandle handle)
- {
- DestroyWindow(handle.Handle);
- UnregisterClass(_className, GetModuleHandle(null));
- }
- [SupportedOSPlatform("macos")]
- void DestroyMacOS()
- {
- MetalHelper.DestroyMetalLayer(NsView, MetalLayer);
- }
- }
- }
|