mirror of
https://github.com/Ryujinx/Opentk.git
synced 2024-12-23 19:35:29 +00:00
[X11] Improved CursorVisible = false behavior
We now use an XGrabPointer to confine the cursor to the window, instead of the XWarpPointer hack. Fixes issue #28 and #36.
This commit is contained in:
parent
7e3b99c636
commit
a30af547f9
|
@ -96,6 +96,8 @@ namespace OpenTK.Platform.X11
|
||||||
static readonly IntPtr _atom_add = (IntPtr)1;
|
static readonly IntPtr _atom_add = (IntPtr)1;
|
||||||
static readonly IntPtr _atom_toggle = (IntPtr)2;
|
static readonly IntPtr _atom_toggle = (IntPtr)2;
|
||||||
|
|
||||||
|
// Used by OpenTK to detect mouse warp events
|
||||||
|
|
||||||
Rectangle bounds, client_rectangle;
|
Rectangle bounds, client_rectangle;
|
||||||
int border_left, border_right, border_top, border_bottom;
|
int border_left, border_right, border_top, border_bottom;
|
||||||
Icon icon;
|
Icon icon;
|
||||||
|
@ -121,7 +123,6 @@ namespace OpenTK.Platform.X11
|
||||||
MouseCursor cursor = MouseCursor.Default;
|
MouseCursor cursor = MouseCursor.Default;
|
||||||
IntPtr cursorHandle;
|
IntPtr cursorHandle;
|
||||||
bool cursor_visible = true;
|
bool cursor_visible = true;
|
||||||
int mouse_rel_x, mouse_rel_y;
|
|
||||||
|
|
||||||
// Keyboard input
|
// Keyboard input
|
||||||
readonly byte[] ascii = new byte[16];
|
readonly byte[] ascii = new byte[16];
|
||||||
|
@ -129,8 +130,6 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
readonly IntPtr EmptyCursor;
|
readonly IntPtr EmptyCursor;
|
||||||
|
|
||||||
public static bool MouseWarpActive = false;
|
|
||||||
|
|
||||||
readonly bool xi2_supported;
|
readonly bool xi2_supported;
|
||||||
readonly int xi2_opcode;
|
readonly int xi2_opcode;
|
||||||
|
|
||||||
|
@ -905,49 +904,15 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
case XEventName.MotionNotify:
|
case XEventName.MotionNotify:
|
||||||
{
|
{
|
||||||
// Try to detect and ignore events from XWarpPointer, below.
|
|
||||||
// This heuristic will fail if the user actually moves the pointer
|
|
||||||
// to the dead center of the window. Fortunately, this situation
|
|
||||||
// is very very uncommon. Todo: Can this be remedied?
|
|
||||||
int x = e.MotionEvent.x;
|
int x = e.MotionEvent.x;
|
||||||
int y = e.MotionEvent.y;
|
int y = e.MotionEvent.y;
|
||||||
// TODO: Have offset as a stored field, only update it when the window moves
|
|
||||||
// The middle point cannot be the average of the Bounds.left/right/top/bottom,
|
|
||||||
// because these fields take into account window decoration (borders, etc),
|
|
||||||
// which we do not want to account for.
|
|
||||||
Point offset = this.PointToClient(Point.Empty);
|
|
||||||
int middle_x = Width/2-offset.X;
|
|
||||||
int middle_y = Height/2-offset.Y;
|
|
||||||
|
|
||||||
Point screen_xy = PointToScreen(new Point(x, y));
|
if (x != 0 || y != 0)
|
||||||
if (!CursorVisible && MouseWarpActive &&
|
|
||||||
screen_xy.X == middle_x && screen_xy.Y == middle_y)
|
|
||||||
{
|
|
||||||
MouseWarpActive = false;
|
|
||||||
mouse_rel_x = x;
|
|
||||||
mouse_rel_y = y;
|
|
||||||
}
|
|
||||||
else if (!CursorVisible)
|
|
||||||
{
|
|
||||||
OnMouseMove(
|
|
||||||
MathHelper.Clamp(MouseState.X + x - mouse_rel_x, 0, Width),
|
|
||||||
MathHelper.Clamp(MouseState.Y + y - mouse_rel_y, 0, Height));
|
|
||||||
mouse_rel_x = x;
|
|
||||||
mouse_rel_y = y;
|
|
||||||
|
|
||||||
// Warp cursor to center of window.
|
|
||||||
MouseWarpActive = true;
|
|
||||||
Mouse.SetPosition(middle_x, middle_y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
OnMouseMove(
|
OnMouseMove(
|
||||||
MathHelper.Clamp(x, 0, Width),
|
MathHelper.Clamp(x, 0, Width),
|
||||||
MathHelper.Clamp(y, 0, Height));
|
MathHelper.Clamp(y, 0, Height));
|
||||||
mouse_rel_x = x;
|
|
||||||
mouse_rel_y = y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -971,7 +936,6 @@ namespace OpenTK.Platform.X11
|
||||||
{
|
{
|
||||||
int dx, dy;
|
int dx, dy;
|
||||||
MouseButton button = X11KeyMap.TranslateButton(e.ButtonEvent.button, out dx, out dy);
|
MouseButton button = X11KeyMap.TranslateButton(e.ButtonEvent.button, out dx, out dy);
|
||||||
|
|
||||||
if (button != MouseButton.LastButton)
|
if (button != MouseButton.LastButton)
|
||||||
{
|
{
|
||||||
OnMouseUp(button);
|
OnMouseUp(button);
|
||||||
|
@ -985,6 +949,11 @@ namespace OpenTK.Platform.X11
|
||||||
has_focus = true;
|
has_focus = true;
|
||||||
if (has_focus != previous_focus)
|
if (has_focus != previous_focus)
|
||||||
OnFocusedChanged(EventArgs.Empty);
|
OnFocusedChanged(EventArgs.Empty);
|
||||||
|
|
||||||
|
if (Focused && !CursorVisible)
|
||||||
|
{
|
||||||
|
GrabMouse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1000,6 +969,12 @@ namespace OpenTK.Platform.X11
|
||||||
case XEventName.LeaveNotify:
|
case XEventName.LeaveNotify:
|
||||||
if (CursorVisible)
|
if (CursorVisible)
|
||||||
{
|
{
|
||||||
|
int x = MathHelper.Clamp(e.CrossingEvent.x, 0, Width);
|
||||||
|
int y = MathHelper.Clamp(e.CrossingEvent.y, 0, Height);
|
||||||
|
if (x != MouseState.X || y != MouseState.Y)
|
||||||
|
{
|
||||||
|
OnMouseMove(x, y);
|
||||||
|
}
|
||||||
OnMouseLeave(EventArgs.Empty);
|
OnMouseLeave(EventArgs.Empty);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1499,12 +1474,13 @@ namespace OpenTK.Platform.X11
|
||||||
{
|
{
|
||||||
using (new XLock(window.Display))
|
using (new XLock(window.Display))
|
||||||
{
|
{
|
||||||
|
UngrabMouse();
|
||||||
|
|
||||||
Point p = PointToScreen(new Point(MouseState.X, MouseState.Y));
|
Point p = PointToScreen(new Point(MouseState.X, MouseState.Y));
|
||||||
Mouse.SetPosition(p.X, p.Y);
|
Mouse.SetPosition(p.X, p.Y);
|
||||||
Functions.XFlush(window.Display);
|
|
||||||
|
|
||||||
// Note: if cursorHandle = IntPtr.Zero, this function
|
// Note: if cursorHandle = IntPtr.Zero, this restores the default cursor
|
||||||
// is equivalent to XUndefineCursor.
|
// (equivalent to calling XUndefineCursor)
|
||||||
Functions.XDefineCursor(window.Display, window.Handle, cursorHandle);
|
Functions.XDefineCursor(window.Display, window.Handle, cursorHandle);
|
||||||
cursor_visible = true;
|
cursor_visible = true;
|
||||||
}
|
}
|
||||||
|
@ -1513,13 +1489,30 @@ namespace OpenTK.Platform.X11
|
||||||
{
|
{
|
||||||
using (new XLock(window.Display))
|
using (new XLock(window.Display))
|
||||||
{
|
{
|
||||||
Functions.XDefineCursor(window.Display, window.Handle, EmptyCursor);
|
GrabMouse();
|
||||||
cursor_visible = false;
|
cursor_visible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GrabMouse()
|
||||||
|
{
|
||||||
|
Functions.XGrabPointer(window.Display, window.Handle, false,
|
||||||
|
EventMask.PointerMotionMask |
|
||||||
|
EventMask.ButtonMotionMask | EventMask.Button1MotionMask |
|
||||||
|
EventMask.Button2MotionMask | EventMask.Button3MotionMask |
|
||||||
|
EventMask.Button4MotionMask | EventMask.Button5MotionMask |
|
||||||
|
EventMask.ButtonPressMask | EventMask.ButtonReleaseMask,
|
||||||
|
GrabMode.GrabModeAsync, GrabMode.GrabModeAsync,
|
||||||
|
window.Handle, EmptyCursor, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UngrabMouse()
|
||||||
|
{
|
||||||
|
Functions.XUngrabPointer(window.Display, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
Loading…
Reference in a new issue