fix mouse input

This commit is contained in:
emmaus 2020-02-04 22:26:58 +00:00 committed by emmauss
commit 7047f01b26
7 changed files with 307 additions and 58 deletions

View file

@ -27,7 +27,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK.NetStandard" Version="1.0.4" />
<PackageReference Include="OpenTK.NetStandard" Version="1.0.5.12" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.6.0" />
</ItemGroup>

View file

@ -28,7 +28,8 @@
<ItemGroup>
<PackageReference Include="JsonPrettyPrinter" Version="1.0.1.1" />
<PackageReference Include="Utf8Json" Version="1.3.7" />
<PackageReference Include="Utf8Json" Version="1.3.7" /><PackageReference Include="OpenTK.NetStandard" Version="1.0.5.12" />
<PackageReference Include="SharpFontCore" Version="0.1.1" />
</ItemGroup>
</Project>

View file

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK.NetStandard" Version="1.0.4" />
<PackageReference Include="OpenTK.NetStandard" Version="1.0.5.12" />
</ItemGroup>
<ItemGroup>

View file

@ -74,7 +74,7 @@
<PackageReference Include="DiscordRichPresence" Version="1.0.147" />
<PackageReference Include="GtkSharp" Version="3.22.25.56" />
<PackageReference Include="GtkSharp.Dependencies" Version="1.1.0" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
<PackageReference Include="OpenTK.NetStandard" Version="1.0.5.10" />
<PackageReference Include="OpenTK.NetStandard" Version="1.0.5.12" />
</ItemGroup>
<ItemGroup>

View file

@ -7,18 +7,38 @@ using System.Text;
using OpenTK.Input;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Input;
using Ryujinx.Configuration;
using Ryujinx.Graphics.OpenGL;
using Ryujinx.HLE;
using Ryujinx.HLE.Input;
using Ryujinx.Profiler.UI;
using Ryujinx.Ui;
using System;
using System.Threading;
using Gdk;
namespace Ryujinx.Ui
{
public class GLRenderer : GLWidget
{
private const int TouchScreenWidth = 1280;
private const int TouchScreenHeight = 720;
private const int TargetFps = 60;
public ManualResetEvent waitEvent { get; set; }
public bool IsActive { get; set; }
public bool IsStopped { get; set; }
public bool IsFocussed { get; set; } = true;
private const int TargetFps = 60;
private double _mouseX;
private double _mouseY;
private bool _titleEvent;
private string _newTitle;
private readonly long _ticksPerFrame;
@ -30,6 +50,10 @@ namespace Ryujinx.Ui
private Renderer _renderer;
private HotkeyButtons _prevHotkeyButtons = 0;
private Input.NpadController _primaryController;
public GLRenderer(Switch device) :base (new GraphicsMode(), 3, 3, GraphicsContextFlags.ForwardCompatible)
{
waitEvent = new ManualResetEvent(false);
@ -44,6 +68,20 @@ namespace Ryujinx.Ui
_chrono = new System.Diagnostics.Stopwatch();
_ticksPerFrame = System.Diagnostics.Stopwatch.Frequency / TargetFps;
_primaryController = new Input.NpadController(ConfigurationState.Instance.Hid.JoystickControls);
AddEvents((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask));
}
private void Parent_FocusOutEvent(object o, Gtk.FocusOutEventArgs args)
{
IsFocussed = false;
}
private void Parent_FocusInEvent(object o, Gtk.FocusInEventArgs args)
{
IsFocussed = true;
}
private void GLRenderer_Destroyed(object sender, EventArgs e)
@ -55,7 +93,8 @@ namespace Ryujinx.Ui
private void GLRenderer_Initialized(object sender, EventArgs e)
{
Start();
GraphicsContext.MakeCurrent(null);
waitEvent.Set();
}
protected override bool OnConfigureEvent(EventConfigure evnt)
@ -69,20 +108,49 @@ namespace Ryujinx.Ui
public void Start()
{
_renderer.Initialize();
IsRenderHandler = true;
_chrono.Restart();
IsActive = true;
GLib.Idle.Add(Render, GLib.Priority.DefaultIdle);
Gtk.Window parent = this.Toplevel as Gtk.Window;
parent.FocusInEvent += Parent_FocusInEvent;
parent.FocusOutEvent += Parent_FocusOutEvent;
parent.Present();
Thread renderLoopThread = new Thread(Render);
renderLoopThread.Name = "GUI.RenderLoop";
renderLoopThread.Start();
MainLoop();
renderLoopThread.Join();
Exit();
}
protected override bool OnButtonPressEvent(EventButton evnt)
{
_mouseX = evnt.X;
_mouseY = evnt.Y;
return false;
}
public void Exit()
{
Gtk.Window parent = this.Toplevel as Gtk.Window;
parent.FocusInEvent -= Parent_FocusInEvent;
parent.FocusOutEvent -= Parent_FocusOutEvent;
_device.DisposeGpu();
IsStopped = true;
IsActive = false;
waitEvent.Set();
}
@ -97,18 +165,20 @@ namespace Ryujinx.Ui
_renderer = (Renderer)_device.Gpu.Renderer;
}
public bool Render()
public void Render()
{
if (!IsActive)
{
return true;
}
GraphicsContext.MakeCurrent(WindowInfo);
_renderer.Initialize();
while (IsActive)
{
if (IsStopped)
{
return false;
return;
}
GraphicsContext.MakeCurrent(WindowInfo);
GL.ClearColor(Color4.Black);
_ticks += _chrono.ElapsedTicks;
@ -135,10 +205,10 @@ namespace Ryujinx.Ui
string titleIdSection = string.IsNullOrWhiteSpace(_device.System.TitleIdText) ? string.Empty
: " | " + _device.System.TitleIdText.ToUpper();
string newTitle = $"Ryujinx{titleNameSection}{titleIdSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " +
_newTitle = $"Ryujinx{titleNameSection}{titleIdSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " +
$"Game Vsync: {(_device.EnableDeviceVsync ? "On" : "Off")}";
this.ParentWindow.Title = newTitle;
_titleEvent = true;
_device.System.SignalVsync();
@ -146,13 +216,184 @@ namespace Ryujinx.Ui
_ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame);
}
return true;
}
}
public void SwapBuffers()
{
OpenTK.Graphics.GraphicsContext.CurrentContext.SwapBuffers();
}
public void MainLoop()
{
while (IsActive)
{
if (_titleEvent)
{
_titleEvent = false;
Gtk.Application.Invoke(delegate
{
this.ParentWindow.Title = _newTitle;
});
}
UpdateFrame();
// Polling becomes expensive if it's not slept
Thread.Sleep(5);
}
}
private bool UpdateFrame()
{
if (!IsActive)
{
return true;
}
if (IsStopped)
{
return false;
}
HotkeyButtons currentHotkeyButtons = 0;
ControllerButtons currentButton = 0;
JoystickPosition leftJoystick;
JoystickPosition rightJoystick;
HLE.Input.Keyboard? hidKeyboard = null;
KeyboardState keyboard = OpenTK.Input.Keyboard.GetState();
MouseState mouse = OpenTK.Input.Mouse.GetCursorState();
int leftJoystickDx = 0;
int leftJoystickDy = 0;
int rightJoystickDx = 0;
int rightJoystickDy = 0;
// Keyboard Input
#if USE_PROFILING
// Profiler input, lets the profiler get access to the main windows keyboard state
_profileWindow.UpdateKeyInput(keyboard);
#endif
// Normal Input
currentHotkeyButtons = KeyboardControls.GetHotkeyButtons(ConfigurationState.Instance.Hid.KeyboardControls, keyboard);
currentButton = KeyboardControls.GetButtons(ConfigurationState.Instance.Hid.KeyboardControls, keyboard);
if (ConfigurationState.Instance.Hid.EnableKeyboard)
{
hidKeyboard = KeyboardControls.GetKeysDown(ConfigurationState.Instance.Hid.KeyboardControls, keyboard);
}
(leftJoystickDx, leftJoystickDy) = KeyboardControls.GetLeftStick(ConfigurationState.Instance.Hid.KeyboardControls, keyboard);
(rightJoystickDx, rightJoystickDy) = KeyboardControls.GetRightStick(ConfigurationState.Instance.Hid.KeyboardControls, keyboard);
if (!hidKeyboard.HasValue)
{
hidKeyboard = new HLE.Input.Keyboard
{
Modifier = 0,
Keys = new int[0x8]
};
}
currentButton |= _primaryController.GetButtons();
// Keyboard has priority stick-wise
if (leftJoystickDx == 0 && leftJoystickDy == 0)
{
(leftJoystickDx, leftJoystickDy) = _primaryController.GetLeftStick();
}
if (rightJoystickDx == 0 && rightJoystickDy == 0)
{
(rightJoystickDx, rightJoystickDy) = _primaryController.GetRightStick();
}
leftJoystick = new JoystickPosition
{
Dx = leftJoystickDx,
Dy = leftJoystickDy
};
rightJoystick = new JoystickPosition
{
Dx = rightJoystickDx,
Dy = rightJoystickDy
};
currentButton |= _device.Hid.UpdateStickButtons(leftJoystick, rightJoystick);
bool hasTouch = false;
// Get screen touch position from left mouse click
// OpenTK always captures mouse events, even if out of focus, so check if window is focused.
if (IsFocussed && mouse.LeftButton == ButtonState.Pressed)
{
int scrnWidth = AllocatedWidth;
int scrnHeight = AllocatedHeight;
if (AllocatedWidth > (AllocatedHeight * TouchScreenWidth) / TouchScreenHeight)
{
scrnWidth = (AllocatedHeight * TouchScreenWidth) / TouchScreenHeight;
}
else
{
scrnHeight = (AllocatedWidth * TouchScreenHeight) / TouchScreenWidth;
}
if (mouse.X >= 0 &&
mouse.Y >= 0 &&
mouse.X < scrnWidth &&
mouse.Y < scrnHeight)
{
int mX = ((int)_mouseX * TouchScreenWidth) / scrnWidth;
int mY = ((int)_mouseY * TouchScreenHeight) / scrnHeight;
TouchPoint currentPoint = new TouchPoint
{
X = mX,
Y = mY,
// Placeholder values till more data is acquired
DiameterX = 10,
DiameterY = 10,
Angle = 90
};
hasTouch = true;
_device.Hid.SetTouchPoints(currentPoint);
}
}
if (!hasTouch)
{
_device.Hid.SetTouchPoints();
}
if (ConfigurationState.Instance.Hid.EnableKeyboard && hidKeyboard.HasValue)
{
_device.Hid.WriteKeyboard(hidKeyboard.Value);
}
BaseController controller = _device.Hid.PrimaryController;
controller.SendInput(currentButton, leftJoystick, rightJoystick);
// Toggle vsync
if (currentHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync) &&
!_prevHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync))
{
_device.EnableDeviceVsync = !_device.EnableDeviceVsync;
}
_prevHotkeyButtons = currentHotkeyButtons;
return true;
}
}
}

View file

@ -51,6 +51,8 @@ namespace Ryujinx.Ui
private static int _graphicsContextCount;
private static bool _sharedContextInitialized;
public bool IsRenderHandler { get; set; } = false;
#endregion
#region Attributes
@ -140,7 +142,7 @@ namespace Ryujinx.Ui
{
try
{
_graphicsContext.MakeCurrent(_windowInfo);
GraphicsContext.MakeCurrent(WindowInfo);
}catch(Exception ex)
{
@ -148,13 +150,13 @@ namespace Ryujinx.Ui
OnShuttingDown();
if (GraphicsContext.ShareContexts && (Interlocked.Decrement(ref _graphicsContextCount) == 0))
if (OpenTK.Graphics.GraphicsContext.ShareContexts && (Interlocked.Decrement(ref _graphicsContextCount) == 0))
{
OnGraphicsContextShuttingDown();
_sharedContextInitialized = false;
}
_graphicsContext.Dispose();
GraphicsContext.Dispose();
}
}
@ -228,8 +230,8 @@ namespace Ryujinx.Ui
{
if (!_initialized)
Initialize();
else
_graphicsContext.MakeCurrent(_windowInfo);
else if(!IsRenderHandler)
GraphicsContext.MakeCurrent(WindowInfo);
return true;
}
@ -237,9 +239,9 @@ namespace Ryujinx.Ui
// Called on Resize
protected override bool OnConfigureEvent(Gdk.EventConfigure evnt)
{
if (_graphicsContext != null)
if (GraphicsContext != null)
{
_graphicsContext.Update(_windowInfo);
GraphicsContext.Update(WindowInfo);
}
return true;
@ -290,35 +292,35 @@ namespace Ryujinx.Ui
// IWindowInfo
if (OpenTK.Configuration.RunningOnWindows)
{
_windowInfo = InitializeWindows();
WindowInfo = InitializeWindows();
}
else if (OpenTK.Configuration.RunningOnMacOS)
{
_windowInfo = InitializeOSX();
WindowInfo = InitializeOSX();
}
else
{
_windowInfo = InitializeX(graphicsMode);
WindowInfo = InitializeX(graphicsMode);
}
// GraphicsContext
_graphicsContext = new GraphicsContext(graphicsMode, _windowInfo, GLVersionMajor, GLVersionMinor, GraphicsContextFlags);
_graphicsContext.MakeCurrent(_windowInfo);
GraphicsContext = new GraphicsContext(graphicsMode, WindowInfo, GLVersionMajor, GLVersionMinor, GraphicsContextFlags);
GraphicsContext.MakeCurrent(WindowInfo);
if (GraphicsContext.ShareContexts)
if (OpenTK.Graphics.GraphicsContext.ShareContexts)
{
Interlocked.Increment(ref _graphicsContextCount);
if (!_sharedContextInitialized)
{
_sharedContextInitialized = true;
((IGraphicsContextInternal)_graphicsContext).LoadAll();
((IGraphicsContextInternal)GraphicsContext).LoadAll();
OnGraphicsContextInitialized();
}
}
else
{
((IGraphicsContextInternal)_graphicsContext).LoadAll();
((IGraphicsContextInternal)GraphicsContext).LoadAll();
OnGraphicsContextInitialized();
}
@ -527,6 +529,9 @@ namespace Ryujinx.Ui
}
}
public IGraphicsContext GraphicsContext { get => _graphicsContext; set => _graphicsContext = value; }
public IWindowInfo WindowInfo { get => _windowInfo; set => _windowInfo = value; }
[DllImport(UnixLibX11Name, EntryPoint = "XGetVisualInfo")]
private static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, out int nitems);

View file

@ -401,6 +401,8 @@ namespace Ryujinx.Ui
_gLWigdet.waitEvent.WaitOne();
_gLWigdet.Start();
Application.Invoke(delegate
{
_viewBox.Remove(_gLWigdet);