Add function to lock the mouse

Unused currently. Cursor.Clip code copied from feos. Hopefully works on Linux too
This commit is contained in:
CasualPokePlayer 2025-02-23 02:53:36 -08:00
parent 49297ca9b7
commit c5029cb2bb
2 changed files with 110 additions and 0 deletions

View File

@ -962,6 +962,15 @@ namespace BizHawk.Client.EmuHawk
SingleInstanceDispose();
}
if (OSTailoredCode.IsUnixHost)
{
if (_x11Display != IntPtr.Zero)
{
XlibImports.XCloseDisplay(_x11Display);
_x11Display = IntPtr.Zero;
}
}
base.Dispose(disposing);
}
@ -4807,5 +4816,50 @@ namespace BizHawk.Client.EmuHawk
RA?.Restart();
}
private IntPtr _x11Display;
public void LockMouse(bool wantLock)
{
if (wantLock)
{
var fbLocation = Point.Subtract(Bounds.Location, new(PointToClient(Location)));
fbLocation.Offset(_presentationPanel.Control.Location);
Cursor.Clip = new(fbLocation, _presentationPanel.Control.Size);
}
else
{
Cursor.Clip = Rectangle.Empty;
}
// Cursor.Clip is a no-op on Linux, so we need this too
if (OSTailoredCode.IsUnixHost)
{
if (_x11Display == IntPtr.Zero)
{
_x11Display = XlibImports.XOpenDisplay(null);
}
if (wantLock)
{
const XlibImports.EventMask eventMask = XlibImports.EventMask.ButtonPressMask | XlibImports.EventMask.ButtonMotionMask
| XlibImports.EventMask.ButtonReleaseMask | XlibImports.EventMask.PointerMotionMask
| XlibImports.EventMask.PointerMotionHintMask | XlibImports.EventMask.LeaveWindowMask;
var grabResult = XlibImports.XGrabPointer(_x11Display, Handle, false, eventMask,
XlibImports.GrabMode.Async, XlibImports.GrabMode.Async, Handle, IntPtr.Zero, XlibImports.CurrentTime);
if (grabResult == XlibImports.GrabResult.AlreadyGrabbed)
{
// try to grab again after releasing whatever current active grab
_ = XlibImports.XUngrabPointer(_x11Display, XlibImports.CurrentTime);
_ = XlibImports.XGrabPointer(_x11Display, Handle, false, eventMask,
XlibImports.GrabMode.Async, XlibImports.GrabMode.Async, Handle, IntPtr.Zero, XlibImports.CurrentTime);
}
}
else
{
_ = XlibImports.XUngrabPointer(_x11Display, XlibImports.CurrentTime);
}
}
}
}
}

View File

@ -138,6 +138,62 @@ namespace BizHawk.Common
[DllImport(XLIB)]
public static extern int XFreeEventData(IntPtr display, ref XGenericEventCookie cookie);
[Flags]
public enum EventMask : uint
{
NoEventMask = 0,
KeyPressMask = 1 << 0,
KeyReleaseMask = 1 << 1,
ButtonPressMask = 1 << 2,
ButtonReleaseMask = 1 << 3,
EnterWindowMask = 1 << 4,
LeaveWindowMask = 1 << 5,
PointerMotionMask = 1 << 6,
PointerMotionHintMask = 1 << 7,
Button1MotionMask = 1 << 8,
Button2MotionMask = 1 << 9,
Button3MotionMask = 1 << 10,
Button4MotionMask = 1 << 11,
Button5MotionMask = 1 << 12,
ButtonMotionMask = 1 << 13,
KeymapStateMask = 1 << 14,
ExposureMask = 1 << 15,
VisibilityChangeMask = 1 << 16,
StructureNotifyMask = 1 << 17,
ResizeRedirectMask = 1 << 18,
SubstructureNotifyMask = 1 << 19,
SubstructureRedirectMask= 1 << 20,
FocusChangeMask = 1 << 21,
PropertyChangeMask = 1 << 22,
ColormapChangeMask = 1 << 23,
OwnerGrabButtonMask = 1 << 24
}
public enum GrabMode : int
{
Sync = 0,
Async = 1,
}
// special Time
public const uint CurrentTime = 0;
public enum GrabResult : int
{
GrabSuccess = 0,
AlreadyGrabbed = 1,
GrabInvalidTime = 2,
GrabNotViewable = 3,
GrabFrozen = 4,
}
[DllImport(XLIB)]
public static extern GrabResult XGrabPointer(IntPtr display, IntPtr grab_window, [MarshalAs(UnmanagedType.Bool)] bool owner_events,
EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, IntPtr cursor, nuint time);
[DllImport(XLIB)]
public static extern int XUngrabPointer(IntPtr display, nuint time);
[DllImport(XLIB)]
public static extern unsafe int XQueryKeymap(IntPtr display, byte* keys_return);