mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-30 14:39:42 +08:00
[GUI] Add native Vulkan host surface support and more (#337)
* [GUI] Add native Vulkan host surface support and more * reuse * [GUI] set width session menu
This commit is contained in:
@@ -69,11 +69,118 @@ public sealed class PosixHostInput : IHostInput
|
||||
{
|
||||
// GLFW only delivers key events to the focused window, so a
|
||||
// delivering keyboard implies focus.
|
||||
return _source?.HasKeyboardFocus ?? false;
|
||||
return _source?.HasKeyboardFocus ?? IsEmbeddedX11WindowFocused();
|
||||
}
|
||||
|
||||
public bool IsKeyDown(int virtualKey)
|
||||
{
|
||||
return _source?.IsKeyDown(virtualKey) ?? false;
|
||||
var source = _source;
|
||||
if (source is not null)
|
||||
{
|
||||
return source.IsKeyDown(virtualKey);
|
||||
}
|
||||
|
||||
return IsEmbeddedX11WindowFocused() && IsEmbeddedX11KeyDown(virtualKey);
|
||||
}
|
||||
|
||||
private static bool IsEmbeddedX11WindowFocused()
|
||||
{
|
||||
if (!OperatingSystem.IsLinux())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var display = HostSessionControl.EmbeddedHostDisplay;
|
||||
var window = HostSessionControl.EmbeddedHostWindow;
|
||||
if (display == 0 || window == 0 || XGetInputFocus(display, out var focusedWindow, out _) == 0 || focusedWindow == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetTopLevelWindow(display, focusedWindow) == GetTopLevelWindow(display, window);
|
||||
}
|
||||
|
||||
private static bool IsEmbeddedX11KeyDown(int virtualKey)
|
||||
{
|
||||
var display = HostSessionControl.EmbeddedHostDisplay;
|
||||
var keysym = ToX11Keysym(virtualKey);
|
||||
if (display == 0 || keysym == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var keycode = XKeysymToKeycode(display, keysym);
|
||||
if (keycode == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var keymap = new byte[32];
|
||||
XQueryKeymap(display, keymap);
|
||||
return (keymap[keycode >> 3] & (1 << (keycode & 7))) != 0;
|
||||
}
|
||||
|
||||
private static nint GetTopLevelWindow(nint display, nint window)
|
||||
{
|
||||
var current = window;
|
||||
for (var depth = 0; depth < 16; depth++)
|
||||
{
|
||||
if (XQueryTree(display, current, out var root, out var parent, out var children, out _) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (children != 0)
|
||||
{
|
||||
XFree(children);
|
||||
}
|
||||
|
||||
if (parent == 0 || parent == root)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
current = parent;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static nuint ToX11Keysym(int virtualKey)
|
||||
{
|
||||
return virtualKey switch
|
||||
{
|
||||
0x08 => 0xFF08, // Backspace
|
||||
0x09 => 0xFF09, // Tab
|
||||
0x0D => 0xFF0D, // Return
|
||||
0x1B => 0xFF1B, // Escape
|
||||
0x25 => 0xFF51, // Left
|
||||
0x26 => 0xFF52, // Up
|
||||
0x27 => 0xFF53, // Right
|
||||
0x28 => 0xFF54, // Down
|
||||
>= 0x41 and <= 0x5A => (nuint)virtualKey,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("libX11.so.6")]
|
||||
private static extern int XGetInputFocus(nint display, out nint focus, out int revertTo);
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("libX11.so.6")]
|
||||
private static extern int XQueryKeymap(nint display, [System.Runtime.InteropServices.Out] byte[] keysReturn);
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("libX11.so.6")]
|
||||
private static extern byte XKeysymToKeycode(nint display, nuint keysym);
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("libX11.so.6")]
|
||||
private static extern int XQueryTree(
|
||||
nint display,
|
||||
nint window,
|
||||
out nint root,
|
||||
out nint parent,
|
||||
out nint children,
|
||||
out uint childCount);
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("libX11.so.6")]
|
||||
private static extern int XFree(nint data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user