mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-03-30 11:16:56 +00:00
[Linux] Implemented INativeWindow keyboard/mouse events
The mouse cursor is now confined to the display bounds.
This commit is contained in:
parent
e61b39a1a1
commit
3881992bf7
|
@ -28,6 +28,7 @@
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
|
|
||||||
namespace OpenTK.Platform.Linux
|
namespace OpenTK.Platform.Linux
|
||||||
|
@ -359,10 +360,9 @@ namespace OpenTK.Platform.Linux
|
||||||
return MouseButton.Button8;
|
return MouseButton.Button8;
|
||||||
case EvdevButton.BTN8:
|
case EvdevButton.BTN8:
|
||||||
return MouseButton.Button9;
|
return MouseButton.Button9;
|
||||||
case EvdevButton.BTN9:
|
|
||||||
return MouseButton.LastButton;
|
|
||||||
default:
|
default:
|
||||||
return MouseButton.LastButton;
|
Debug.Print("[Input] Unknown EvdevButton {0}", button);
|
||||||
|
return MouseButton.Left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,9 +258,8 @@ namespace OpenTK.Platform.Linux
|
||||||
public Fixed24 DeltaY { get { return GetDY(@event); } }
|
public Fixed24 DeltaY { get { return GetDY(@event); } }
|
||||||
public Fixed24 X { get { return GetAbsX(@event); } }
|
public Fixed24 X { get { return GetAbsX(@event); } }
|
||||||
public Fixed24 Y { get { return GetAbsY(@event); } }
|
public Fixed24 Y { get { return GetAbsY(@event); } }
|
||||||
// Are the following useful?
|
public Fixed24 TransformedX(int width) { return GetAbsXTransformed(@event, width); }
|
||||||
//public Fixed24 TransformedX(int width) { return GetAbsXTransformed(@event, width); }
|
public Fixed24 TransformedY(int height) { return GetAbsYTransformed(@event, height); }
|
||||||
//public Fixed24 TransformedY(int height) { return GetAbsXTransformed(@event, height); }
|
|
||||||
|
|
||||||
[DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_time", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_time", CallingConvention = CallingConvention.Cdecl)]
|
||||||
static extern uint GetTime(IntPtr @event);
|
static extern uint GetTime(IntPtr @event);
|
||||||
|
|
|
@ -28,7 +28,9 @@
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using OpenTK.Input;
|
using OpenTK.Input;
|
||||||
|
@ -108,6 +110,9 @@ namespace OpenTK.Platform.Linux
|
||||||
DeviceCollection<KeyboardDevice> Keyboards = new DeviceCollection<KeyboardDevice>();
|
DeviceCollection<KeyboardDevice> Keyboards = new DeviceCollection<KeyboardDevice>();
|
||||||
DeviceCollection<MouseDevice> Mice = new DeviceCollection<MouseDevice>();
|
DeviceCollection<MouseDevice> Mice = new DeviceCollection<MouseDevice>();
|
||||||
|
|
||||||
|
// Todo: do we need to maintain the geometry of each display separately?
|
||||||
|
Rectangle bounds;
|
||||||
|
|
||||||
// Global mouse cursor state
|
// Global mouse cursor state
|
||||||
Vector2 CursorPosition = Vector2.Zero;
|
Vector2 CursorPosition = Vector2.Zero;
|
||||||
// Global mouse cursor offset (used for emulating SetPosition)
|
// Global mouse cursor offset (used for emulating SetPosition)
|
||||||
|
@ -210,6 +215,12 @@ namespace OpenTK.Platform.Linux
|
||||||
ret < 0 && !(error == ErrorNumber.Again || error == ErrorNumber.Interrupted) ||
|
ret < 0 && !(error == ErrorNumber.Again || error == ErrorNumber.Interrupted) ||
|
||||||
(poll_fd.revents & (PollFlags.Hup | PollFlags.Error | PollFlags.Invalid)) != 0;
|
(poll_fd.revents & (PollFlags.Hup | PollFlags.Error | PollFlags.Invalid)) != 0;
|
||||||
|
|
||||||
|
// We need to query the desktop bounds in order to position the mouse cursor correctly.
|
||||||
|
// This value will be used for the current bunch of input events. If a monitor changes
|
||||||
|
// resolution in the meantime, we might be slightly off in our calculations - this error
|
||||||
|
// will be corrected when the next bunch of input events arrives.
|
||||||
|
UpdateDisplayBounds();
|
||||||
|
|
||||||
if (ret > 0 && (poll_fd.revents & (PollFlags.In | PollFlags.Pri)) != 0)
|
if (ret > 0 && (poll_fd.revents & (PollFlags.In | PollFlags.Pri)) != 0)
|
||||||
{
|
{
|
||||||
ProcessEvents(input_context);
|
ProcessEvents(input_context);
|
||||||
|
@ -225,6 +236,19 @@ namespace OpenTK.Platform.Linux
|
||||||
Debug.Print("[Input] Exited input loop.", poll_fd.fd, poll_fd.events);
|
Debug.Print("[Input] Exited input loop.", poll_fd.fd, poll_fd.events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpdateDisplayBounds()
|
||||||
|
{
|
||||||
|
bounds = Rectangle.Empty;
|
||||||
|
for (DisplayIndex i = DisplayIndex.First; i < DisplayIndex.Sixth; i++)
|
||||||
|
{
|
||||||
|
DisplayDevice display = DisplayDevice.GetDisplay(i);
|
||||||
|
if (display != null)
|
||||||
|
{
|
||||||
|
bounds = Rectangle.Union(bounds, display.Bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Setup()
|
void Setup()
|
||||||
{
|
{
|
||||||
// Todo: add static path fallback when udev is not installed.
|
// Todo: add static path fallback when udev is not installed.
|
||||||
|
@ -425,16 +449,22 @@ namespace OpenTK.Platform.Linux
|
||||||
{
|
{
|
||||||
mouse.State.Position += delta;
|
mouse.State.Position += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CursorPosition = new Vector2(
|
||||||
|
MathHelper.Clamp(CursorPosition.X + delta.X, bounds.Left, bounds.Right),
|
||||||
|
MathHelper.Clamp(CursorPosition.Y + delta.Y, bounds.Top, bounds.Bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandlePointerMotionAbsolute(MouseDevice mouse, PointerEvent e)
|
void HandlePointerMotionAbsolute(MouseDevice mouse, PointerEvent e)
|
||||||
{
|
{
|
||||||
Vector2 position = new Vector2(e.X, e.Y);
|
|
||||||
if (mouse != null)
|
if (mouse != null)
|
||||||
{
|
{
|
||||||
mouse.State.Position = position;
|
mouse.State.Position = new Vector2(e.X, e.Y);
|
||||||
}
|
}
|
||||||
CursorPosition = position; // update global cursor position
|
|
||||||
|
CursorPosition = new Vector2(
|
||||||
|
e.TransformedX(bounds.Width),
|
||||||
|
e.TransformedY(bounds.Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int GetId(IntPtr device)
|
static int GetId(IntPtr device)
|
||||||
|
|
|
@ -32,6 +32,7 @@ using System.Diagnostics;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
|
using OpenTK.Input;
|
||||||
using OpenTK.Platform.Egl;
|
using OpenTK.Platform.Egl;
|
||||||
|
|
||||||
namespace OpenTK.Platform.Linux
|
namespace OpenTK.Platform.Linux
|
||||||
|
@ -43,9 +44,13 @@ namespace OpenTK.Platform.Linux
|
||||||
LinuxWindowInfo window;
|
LinuxWindowInfo window;
|
||||||
string title;
|
string title;
|
||||||
Icon icon;
|
Icon icon;
|
||||||
bool exists;
|
|
||||||
Rectangle bounds;
|
Rectangle bounds;
|
||||||
Size client_size;
|
Size client_size;
|
||||||
|
bool exists;
|
||||||
|
bool is_focused;
|
||||||
|
|
||||||
|
KeyboardState previous_keyboard;
|
||||||
|
MouseState previous_mouse;
|
||||||
|
|
||||||
public LinuxNativeWindow(IntPtr display, IntPtr gbm, int fd,
|
public LinuxNativeWindow(IntPtr display, IntPtr gbm, int fd,
|
||||||
int x, int y, int width, int height, string title,
|
int x, int y, int width, int height, string title,
|
||||||
|
@ -147,10 +152,83 @@ namespace OpenTK.Platform.Linux
|
||||||
return SurfaceFormat.RGBA8888;
|
return SurfaceFormat.RGBA8888;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyboardState ProcessKeyboard(KeyboardState keyboard)
|
||||||
|
{
|
||||||
|
for (Key i = 0; i < Key.LastKey; i++)
|
||||||
|
{
|
||||||
|
if (keyboard[i])
|
||||||
|
{
|
||||||
|
OnKeyDown(i, previous_keyboard[i]);
|
||||||
|
// Todo: implement libxkb-common binding for text input
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!keyboard[i] && previous_keyboard[i])
|
||||||
|
{
|
||||||
|
OnKeyUp(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keyboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseState ProcessMouse(MouseState mouse)
|
||||||
|
{
|
||||||
|
for (MouseButton i = 0; i < MouseButton.LastButton; i++)
|
||||||
|
{
|
||||||
|
if (mouse[i] && !previous_mouse[i])
|
||||||
|
{
|
||||||
|
OnMouseDown(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mouse[i] && previous_mouse[i])
|
||||||
|
{
|
||||||
|
OnMouseUp(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouse.Position != previous_mouse.Position)
|
||||||
|
{
|
||||||
|
OnMouseMove(mouse.X, mouse.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouse.Scroll != previous_mouse.Scroll)
|
||||||
|
{
|
||||||
|
OnMouseWheel(mouse.Scroll.X, mouse.Scroll.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: focus follows mouse. Literally.
|
||||||
|
bool cursor_in = Bounds.Contains(new Point(mouse.X, mouse.Y));
|
||||||
|
if (!cursor_in && Focused)
|
||||||
|
{
|
||||||
|
OnMouseLeave(EventArgs.Empty);
|
||||||
|
SetFocus(false);
|
||||||
|
}
|
||||||
|
else if (cursor_in && !Focused)
|
||||||
|
{
|
||||||
|
OnMouseEnter(EventArgs.Empty);
|
||||||
|
SetFocus(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetFocus(bool focus)
|
||||||
|
{
|
||||||
|
if (is_focused != focus)
|
||||||
|
{
|
||||||
|
is_focused = focus;
|
||||||
|
OnFocusedChanged(EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#region INativeWindow Members
|
#region INativeWindow Members
|
||||||
|
|
||||||
public override void ProcessEvents()
|
public override void ProcessEvents()
|
||||||
{
|
{
|
||||||
|
// Note: there is no event-based keyboard/mouse input available.
|
||||||
|
// We will fake that by polling OpenTK.Input.
|
||||||
|
previous_keyboard = ProcessKeyboard(Keyboard.GetState());
|
||||||
|
previous_mouse = ProcessMouse(Mouse.GetCursorState());
|
||||||
|
|
||||||
base.ProcessEvents();
|
base.ProcessEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +294,7 @@ namespace OpenTK.Platform.Linux
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return true;
|
return is_focused;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue