934b5a64e5
* Fix redundancies * Add back elses * Loading Screen fixes * Redesign User Profile Manager - Backported long selection bar in Grid/List view not working - Backported UserSelector is jank * Fix SelectionIndicator * Fix DataType * Fix SaveManager bug * Remove debug log * Load saves on UIThread * Reduce UI thread blocking * Fix locale keys * Use block namespaces * Fix close button width * Make UserProfile ordering consistent * Alphabetical order * Adjust layout, remove green circle for blue selector * Fix some inconsistencies * Fix no inital selected profile * Adjust appearance of edit button * Adjust SaveManager * Remove redundant warning dialog * Make firmware avatar selector clearer * View redesign again :hero_depressed: * Consistency adjustments * Adjust margins * Make `UserProfileImageSelector` consistent * Make `UserFirmwareAvatarSelector` consistent * Fix long grid view selector * Switch case * Remove long selection bar Handled in #4178 * Consistency * Started dialog titles * Fixes * Remaining titles * Update Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml Co-authored-by: Mary-nyan <thog@protonmail.com> * Fix build * Hide UserRecoverer if no LostProfiles are found * UserEditor Avatar Placeholder * Watermark + locale adjustment * Border radius * Remove unnecessary styles * Fix firmware avatar image order * Cleanup `ColorPickerButton` * Make `UserId` copy/paste able * Make `FirmwareAvatarSelector` 6 images wide * Make selection bar better * Unsaved changes dialogue * Fix indentation * Remove extra check * Address suggestions * Reorganise - Remove unused views - Rename views to match convention - Fix weird namespacing * Update Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml Co-authored-by: Ac_K <Acoustik666@gmail.com> * UserRecovererView empty placeholder * Update Ryujinx.Ava/UI/Views/User/UserSelectorView.axaml.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/Views/User/UserSaveManagerView.axaml.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/Views/User/UserRecovererView.axaml.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/Views/User/UserFirmwareAvatarSelectorView.axaml.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/ViewModels/UserFirmwareAvatarSelectorViewModel.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/Models/UserProfile.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Update Ryujinx.Ava/UI/Controls/NavigationDialogHost.axaml.cs Co-authored-by: Ac_K <Acoustik666@gmail.com> * Remove AddModel * Update Ryujinx.Ava/Assets/Locales/en_US.json Co-authored-by: Ac_K <Acoustik666@gmail.com> * Fix bug Co-authored-by: Mary-nyan <thog@protonmail.com> Co-authored-by: Ac_K <Acoustik666@gmail.com>
232 lines
No EOL
7.8 KiB
C#
232 lines
No EOL
7.8 KiB
C#
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;
|
|
}
|
|
|
|
public EmbeddedWindow()
|
|
{
|
|
var stateObserverable = this.GetObservable(BoundsProperty);
|
|
|
|
stateObserverable.Subscribe(StateChanged);
|
|
|
|
this.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 = LoadCursor(IntPtr.Zero, (IntPtr)Cursors.IDC_ARROW)
|
|
};
|
|
|
|
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);
|
|
}
|
|
}
|
|
} |