Add Direct Mouse Support (#2374)

* and direct mouse support

* and direct mouse support

* hide cursor if mouse enabled

* add config

* update docs

* sorted usings
This commit is contained in:
emmauss 2021-06-24 00:09:08 +00:00 committed by GitHub
parent a10b2c5ff2
commit 77aab9aca3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 200 additions and 32 deletions

View File

@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
{ {
public MouseDevice(Switch device, bool active) : base(device, active) { } public MouseDevice(Switch device, bool active) : base(device, active) { }
public void Update(int mouseX, int mouseY, uint buttons = 0, int scrollX = 0, int scrollY = 0) public void Update(int mouseX, int mouseY, uint buttons = 0, int scrollX = 0, int scrollY = 0, bool connected = false)
{ {
ref RingLifo<MouseState> lifo = ref _device.Hid.SharedMemory.Mouse; ref RingLifo<MouseState> lifo = ref _device.Hid.SharedMemory.Mouse;
@ -27,6 +27,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
newState.DeltaY = mouseY - previousEntry.DeltaY; newState.DeltaY = mouseY - previousEntry.DeltaY;
newState.WheelDeltaX = scrollX; newState.WheelDeltaX = scrollX;
newState.WheelDeltaY = scrollY; newState.WheelDeltaY = scrollY;
newState.Attributes = connected ? MouseAttribute.IsConnected : MouseAttribute.None;
} }
lifo.Write(ref newState); lifo.Write(ref newState);

View File

@ -23,7 +23,7 @@ namespace Ryujinx.Input.HLE
public NpadManager CreateNpadManager() public NpadManager CreateNpadManager()
{ {
return new NpadManager(KeyboardDriver, GamepadDriver); return new NpadManager(KeyboardDriver, GamepadDriver, MouseDriver);
} }
public TouchScreenManager CreateTouchScreenManager() public TouchScreenManager CreateTouchScreenManager()

View File

@ -1,4 +1,4 @@
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.HLE.HOS.Services.Hid; using Ryujinx.HLE.HOS.Services.Hid;
@ -6,7 +6,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client; using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client;
using Switch = Ryujinx.HLE.Switch; using Switch = Ryujinx.HLE.Switch;
@ -26,22 +25,23 @@ namespace Ryujinx.Input.HLE
private readonly IGamepadDriver _keyboardDriver; private readonly IGamepadDriver _keyboardDriver;
private readonly IGamepadDriver _gamepadDriver; private readonly IGamepadDriver _gamepadDriver;
private readonly IGamepadDriver _mouseDriver;
private bool _isDisposed; private bool _isDisposed;
private List<InputConfig> _inputConfig; private List<InputConfig> _inputConfig;
private bool _enableKeyboard; private bool _enableKeyboard;
private bool _enableMouse;
private Switch _device; private Switch _device;
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver) public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver)
{ {
_controllers = new NpadController[MaxControllers]; _controllers = new NpadController[MaxControllers];
_cemuHookClient = new CemuHookClient(this); _cemuHookClient = new CemuHookClient(this);
_keyboardDriver = keyboardDriver; _keyboardDriver = keyboardDriver;
_gamepadDriver = gamepadDriver; _gamepadDriver = gamepadDriver;
_mouseDriver = mouseDriver;
_inputConfig = new List<InputConfig>(); _inputConfig = new List<InputConfig>();
_enableKeyboard = false;
_gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; _gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
_gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected; _gamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
@ -58,13 +58,13 @@ namespace Ryujinx.Input.HLE
private void HandleOnGamepadDisconnected(string obj) private void HandleOnGamepadDisconnected(string obj)
{ {
// Force input reload // Force input reload
ReloadConfiguration(_inputConfig, _enableKeyboard); ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
} }
private void HandleOnGamepadConnected(string id) private void HandleOnGamepadConnected(string id)
{ {
// Force input reload // Force input reload
ReloadConfiguration(_inputConfig, _enableKeyboard); ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -93,7 +93,7 @@ namespace Ryujinx.Input.HLE
} }
} }
public void ReloadConfiguration(List<InputConfig> inputConfig, bool enableKeyboard) public void ReloadConfiguration(List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse)
{ {
lock (_lock) lock (_lock)
{ {
@ -121,6 +121,7 @@ namespace Ryujinx.Input.HLE
_inputConfig = inputConfig; _inputConfig = inputConfig;
_enableKeyboard = enableKeyboard; _enableKeyboard = enableKeyboard;
_enableMouse = enableMouse;
_device.Hid.RefreshInputConfig(inputConfig); _device.Hid.RefreshInputConfig(inputConfig);
} }
@ -142,15 +143,15 @@ namespace Ryujinx.Input.HLE
} }
} }
public void Initialize(Switch device, List<InputConfig> inputConfig, bool enableKeyboard) public void Initialize(Switch device, List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse)
{ {
_device = device; _device = device;
_device.Configuration.RefreshInputConfig = RefreshInputConfigForHLE; _device.Configuration.RefreshInputConfig = RefreshInputConfigForHLE;
ReloadConfiguration(inputConfig, enableKeyboard); ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
} }
public void Update() public void Update(float aspectRatio = 0)
{ {
lock (_lock) lock (_lock)
{ {
@ -206,6 +207,48 @@ namespace Ryujinx.Input.HLE
_device.Hid.Keyboard.Update(hleKeyboardInput.Value); _device.Hid.Keyboard.Update(hleKeyboardInput.Value);
} }
if (_enableMouse)
{
var mouse = _mouseDriver.GetGamepad("0") as IMouse;
var mouseInput = IMouse.GetMouseStateSnapshot(mouse);
uint buttons = 0;
if (mouseInput.IsPressed(MouseButton.Button1))
{
buttons |= 1 << 0;
}
if (mouseInput.IsPressed(MouseButton.Button2))
{
buttons |= 1 << 1;
}
if (mouseInput.IsPressed(MouseButton.Button3))
{
buttons |= 1 << 2;
}
if (mouseInput.IsPressed(MouseButton.Button4))
{
buttons |= 1 << 3;
}
if (mouseInput.IsPressed(MouseButton.Button5))
{
buttons |= 1 << 4;
}
var position = IMouse.GetScreenPosition(mouseInput.Position, mouse.ClientSize, aspectRatio);
_device.Hid.Mouse.Update((int)position.X, (int)position.Y, buttons, (int)mouseInput.Scroll.X, (int)mouseInput.Scroll.Y, true);
}
else
{
_device.Hid.Mouse.Update(0, 0);
}
_device.TamperMachine.UpdateInput(hleInputStates); _device.TamperMachine.UpdateInput(hleInputStates);
} }
} }

View File

@ -29,7 +29,7 @@ namespace Ryujinx.Input.HLE
if (_wasClicking && !isClicking) if (_wasClicking && !isClicking)
{ {
MouseStateSnapshot snapshot = IMouse.GetMouseStateSnapshot(_mouse); MouseStateSnapshot snapshot = IMouse.GetMouseStateSnapshot(_mouse);
var touchPosition = IMouse.GetTouchPosition(snapshot.Position, _mouse.ClientSize, aspectRatio); var touchPosition = IMouse.GetScreenPosition(snapshot.Position, _mouse.ClientSize, aspectRatio);
TouchPoint currentPoint = new TouchPoint TouchPoint currentPoint = new TouchPoint
{ {
@ -58,7 +58,7 @@ namespace Ryujinx.Input.HLE
if (aspectRatio > 0) if (aspectRatio > 0)
{ {
MouseStateSnapshot snapshot = IMouse.GetMouseStateSnapshot(_mouse); MouseStateSnapshot snapshot = IMouse.GetMouseStateSnapshot(_mouse);
var touchPosition = IMouse.GetTouchPosition(snapshot.Position, _mouse.ClientSize, aspectRatio); var touchPosition = IMouse.GetScreenPosition(snapshot.Position, _mouse.ClientSize, aspectRatio);
TouchAttribute attribute = TouchAttribute.None; TouchAttribute attribute = TouchAttribute.None;

View File

@ -23,6 +23,11 @@ namespace Ryujinx.Input
/// </summary> /// </summary>
Vector2 GetPosition(); Vector2 GetPosition();
/// <summary>
/// Get the mouse scroll delta.
/// </summary>
Vector2 GetScroll();
/// <summary> /// <summary>
/// Get the client size. /// Get the client size.
/// </summary> /// </summary>
@ -40,22 +45,21 @@ namespace Ryujinx.Input
/// <returns>A snaphost of the state of the mouse.</returns> /// <returns>A snaphost of the state of the mouse.</returns>
public static MouseStateSnapshot GetMouseStateSnapshot(IMouse mouse) public static MouseStateSnapshot GetMouseStateSnapshot(IMouse mouse)
{ {
var position = mouse.GetPosition();
bool[] buttons = new bool[(int)MouseButton.Count]; bool[] buttons = new bool[(int)MouseButton.Count];
mouse.Buttons.CopyTo(buttons, 0); mouse.Buttons.CopyTo(buttons, 0);
return new MouseStateSnapshot(buttons, position); return new MouseStateSnapshot(buttons, mouse.GetPosition(), mouse.GetScroll());
} }
/// <summary> /// <summary>
/// Get the touch position of a mouse position relative to the app's view /// Get the position of a mouse on screen relative to the app's view
/// </summary> /// </summary>
/// <param name="mousePosition">The position of the mouse in the client</param> /// <param name="mousePosition">The position of the mouse in the client</param>
/// <param name="clientSize">The size of the client</param> /// <param name="clientSize">The size of the client</param>
/// <param name="aspectRatio">The aspect ratio of the view</param> /// <param name="aspectRatio">The aspect ratio of the view</param>
/// <returns>A snaphost of the state of the mouse.</returns> /// <returns>A snaphost of the state of the mouse.</returns>
public static Vector2 GetTouchPosition(Vector2 mousePosition, Size clientSize, float aspectRatio) public static Vector2 GetScreenPosition(Vector2 mousePosition, Size clientSize, float aspectRatio)
{ {
float mouseX = mousePosition.X; float mouseX = mousePosition.X;
float mouseY = mousePosition.Y; float mouseY = mousePosition.Y;

View File

@ -10,17 +10,28 @@ namespace Ryujinx.Input
{ {
private bool[] _buttonState; private bool[] _buttonState;
/// <summary>
/// The position of the mouse cursor
/// </summary>
public Vector2 Position { get; } public Vector2 Position { get; }
/// <summary>
/// The scroll delta of the mouse
/// </summary>
public Vector2 Scroll { get; }
/// <summary> /// <summary>
/// Create a new <see cref="MouseStateSnapshot"/>. /// Create a new <see cref="MouseStateSnapshot"/>.
/// </summary> /// </summary>
/// <param name="buttonState">The keys state</param> /// <param name="buttonState">The button state</param>
public MouseStateSnapshot(bool[] buttonState, Vector2 position) /// <param name="position">The position of the cursor</param>
/// <param name="scroll">The scroll delta</param>
public MouseStateSnapshot(bool[] buttonState, Vector2 position, Vector2 scroll)
{ {
_buttonState = buttonState; _buttonState = buttonState;
Position = position; Position = position;
Scroll = scroll;
} }
/// <summary> /// <summary>

View File

@ -1,5 +1,5 @@
{ {
"version": 24, "version": 27,
"enable_file_log": true, "enable_file_log": true,
"res_scale": 1, "res_scale": 1,
"res_scale_custom": 1, "res_scale_custom": 1,
@ -55,6 +55,7 @@
"custom_theme_path": "", "custom_theme_path": "",
"start_fullscreen": false, "start_fullscreen": false,
"enable_keyboard": false, "enable_keyboard": false,
"enable_mouse": false,
"hotkeys": { "hotkeys": {
"toggle_vsync": "Tab" "toggle_vsync": "Tab"
}, },

View File

@ -14,7 +14,7 @@ namespace Ryujinx.Configuration
/// <summary> /// <summary>
/// The current version of the file format /// The current version of the file format
/// </summary> /// </summary>
public const int CurrentVersion = 26; public const int CurrentVersion = 27;
public int Version { get; set; } public int Version { get; set; }
@ -224,6 +224,11 @@ namespace Ryujinx.Configuration
/// </summary> /// </summary>
public bool EnableKeyboard { get; set; } public bool EnableKeyboard { get; set; }
/// <summary>
/// Enable or disable mouse support (Independent from controllers binding)
/// </summary>
public bool EnableMouse { get; set; }
/// <summary> /// <summary>
/// Hotkey Keyboard Bindings /// Hotkey Keyboard Bindings
/// </summary> /// </summary>

View File

@ -269,6 +269,11 @@ namespace Ryujinx.Configuration
/// </summary> /// </summary>
public ReactiveObject<bool> EnableKeyboard { get; private set; } public ReactiveObject<bool> EnableKeyboard { get; private set; }
/// <summary>
/// Enable or disable mouse support (Independent from controllers binding)
/// </summary>
public ReactiveObject<bool> EnableMouse { get; private set; }
/// <summary> /// <summary>
/// Hotkey Keyboard Bindings /// Hotkey Keyboard Bindings
/// </summary> /// </summary>
@ -284,6 +289,7 @@ namespace Ryujinx.Configuration
public HidSection() public HidSection()
{ {
EnableKeyboard = new ReactiveObject<bool>(); EnableKeyboard = new ReactiveObject<bool>();
EnableMouse = new ReactiveObject<bool>();
Hotkeys = new ReactiveObject<KeyboardHotkeys>(); Hotkeys = new ReactiveObject<KeyboardHotkeys>();
InputConfig = new ReactiveObject<List<InputConfig>>(); InputConfig = new ReactiveObject<List<InputConfig>>();
} }
@ -471,6 +477,7 @@ namespace Ryujinx.Configuration
CustomThemePath = Ui.CustomThemePath, CustomThemePath = Ui.CustomThemePath,
StartFullscreen = Ui.StartFullscreen, StartFullscreen = Ui.StartFullscreen,
EnableKeyboard = Hid.EnableKeyboard, EnableKeyboard = Hid.EnableKeyboard,
EnableMouse = Hid.EnableMouse,
Hotkeys = Hid.Hotkeys, Hotkeys = Hid.Hotkeys,
KeyboardConfig = new List<object>(), KeyboardConfig = new List<object>(),
ControllerConfig = new List<object>(), ControllerConfig = new List<object>(),
@ -532,6 +539,7 @@ namespace Ryujinx.Configuration
Ui.CustomThemePath.Value = ""; Ui.CustomThemePath.Value = "";
Ui.StartFullscreen.Value = false; Ui.StartFullscreen.Value = false;
Hid.EnableKeyboard.Value = false; Hid.EnableKeyboard.Value = false;
Hid.EnableMouse.Value = false;
Hid.Hotkeys.Value = new KeyboardHotkeys Hid.Hotkeys.Value = new KeyboardHotkeys
{ {
ToggleVsync = Key.Tab ToggleVsync = Key.Tab
@ -828,6 +836,15 @@ namespace Ryujinx.Configuration
configurationFileUpdated = true; configurationFileUpdated = true;
} }
if (configurationFileFormat.Version < 27)
{
Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 27.");
configurationFileFormat.EnableMouse = false;
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScale.Value = configurationFileFormat.ResScale;
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
@ -878,6 +895,7 @@ namespace Ryujinx.Configuration
Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath; Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath;
Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen; Ui.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard; Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
Hid.EnableMouse.Value = configurationFileFormat.EnableMouse;
Hid.Hotkeys.Value = configurationFileFormat.Hotkeys; Hid.Hotkeys.Value = configurationFileFormat.Hotkeys;
Hid.InputConfig.Value = configurationFileFormat.InputConfig; Hid.InputConfig.Value = configurationFileFormat.InputConfig;

View File

@ -31,6 +31,11 @@ namespace Ryujinx.Input.GTK3
return _driver.CurrentPosition; return _driver.CurrentPosition;
} }
public Vector2 GetScroll()
{
return _driver.Scroll;
}
public GamepadStateSnapshot GetMappedStateSnapshot() public GamepadStateSnapshot GetMappedStateSnapshot()
{ {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@ -14,6 +14,7 @@ namespace Ryujinx.Input.GTK3
public bool[] PressedButtons { get; } public bool[] PressedButtons { get; }
public Vector2 CurrentPosition { get; private set; } public Vector2 CurrentPosition { get; private set; }
public Vector2 Scroll{ get; private set; }
public GTK3MouseDriver(Widget parent) public GTK3MouseDriver(Widget parent)
{ {
@ -22,10 +23,18 @@ namespace Ryujinx.Input.GTK3
_widget.MotionNotifyEvent += Parent_MotionNotifyEvent; _widget.MotionNotifyEvent += Parent_MotionNotifyEvent;
_widget.ButtonPressEvent += Parent_ButtonPressEvent; _widget.ButtonPressEvent += Parent_ButtonPressEvent;
_widget.ButtonReleaseEvent += Parent_ButtonReleaseEvent; _widget.ButtonReleaseEvent += Parent_ButtonReleaseEvent;
_widget.ScrollEvent += Parent_ScrollEvent;
PressedButtons = new bool[(int)MouseButton.Count]; PressedButtons = new bool[(int)MouseButton.Count];
} }
[GLib.ConnectBefore]
private void Parent_ScrollEvent(object o, ScrollEventArgs args)
{
Scroll = new Vector2((float)args.Event.X, (float)args.Event.Y);
}
[GLib.ConnectBefore] [GLib.ConnectBefore]
private void Parent_ButtonReleaseEvent(object o, ButtonReleaseEventArgs args) private void Parent_ButtonReleaseEvent(object o, ButtonReleaseEventArgs args)
{ {

View File

@ -63,6 +63,7 @@ namespace Ryujinx.Ui
private int _windowHeight; private int _windowHeight;
private int _windowWidth; private int _windowWidth;
private bool _isMouseInClient;
public RendererWidgetBase(InputManager inputManager, GraphicsDebugLevel glLogLevel) public RendererWidgetBase(InputManager inputManager, GraphicsDebugLevel glLogLevel)
{ {
@ -87,6 +88,9 @@ namespace Ryujinx.Ui
AddEvents((int)(EventMask.ButtonPressMask AddEvents((int)(EventMask.ButtonPressMask
| EventMask.ButtonReleaseMask | EventMask.ButtonReleaseMask
| EventMask.PointerMotionMask | EventMask.PointerMotionMask
| EventMask.ScrollMask
| EventMask.EnterNotifyMask
| EventMask.LeaveNotifyMask
| EventMask.KeyPressMask | EventMask.KeyPressMask
| EventMask.KeyReleaseMask)); | EventMask.KeyReleaseMask));
@ -125,6 +129,8 @@ namespace Ryujinx.Ui
{ {
ConfigurationState.Instance.HideCursorOnIdle.Event -= HideCursorStateChanged; ConfigurationState.Instance.HideCursorOnIdle.Event -= HideCursorStateChanged;
Window.Cursor = null;
NpadManager.Dispose(); NpadManager.Dispose();
Dispose(); Dispose();
} }
@ -136,9 +142,34 @@ namespace Ryujinx.Ui
_lastCursorMoveTime = Stopwatch.GetTimestamp(); _lastCursorMoveTime = Stopwatch.GetTimestamp();
} }
if(ConfigurationState.Instance.Hid.EnableMouse)
{
Window.Cursor = _invisibleCursor;
}
_isMouseInClient = true;
return false; return false;
} }
protected override bool OnEnterNotifyEvent(EventCrossing evnt)
{
Window.Cursor = ConfigurationState.Instance.Hid.EnableMouse ? _invisibleCursor : null;
_isMouseInClient = true;
return base.OnEnterNotifyEvent(evnt);
}
protected override bool OnLeaveNotifyEvent(EventCrossing evnt)
{
Window.Cursor = null;
_isMouseInClient = false;
return base.OnLeaveNotifyEvent(evnt);
}
protected override void OnGetPreferredHeight(out int minimumHeight, out int naturalHeight) protected override void OnGetPreferredHeight(out int minimumHeight, out int naturalHeight)
{ {
Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window); Gdk.Monitor monitor = Display.GetMonitorAtWindow(Window);
@ -241,11 +272,16 @@ namespace Ryujinx.Ui
_toggleDockedMode = toggleDockedMode; _toggleDockedMode = toggleDockedMode;
if (_hideCursorOnIdle) if (_hideCursorOnIdle && !ConfigurationState.Instance.Hid.EnableMouse)
{ {
long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime; long cursorMoveDelta = Stopwatch.GetTimestamp() - _lastCursorMoveTime;
Window.Cursor = (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency) ? _invisibleCursor : null; Window.Cursor = (cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency) ? _invisibleCursor : null;
} }
if(ConfigurationState.Instance.Hid.EnableMouse && _isMouseInClient)
{
Window.Cursor = _invisibleCursor;
}
} }
public void Initialize(Switch device) public void Initialize(Switch device)
@ -254,7 +290,7 @@ namespace Ryujinx.Ui
Renderer = Device.Gpu.Renderer; Renderer = Device.Gpu.Renderer;
Renderer?.Window.SetSize(_windowWidth, _windowHeight); Renderer?.Window.SetSize(_windowWidth, _windowHeight);
NpadManager.Initialize(device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard); NpadManager.Initialize(device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
TouchScreenManager.Initialize(device); TouchScreenManager.Initialize(device);
} }
@ -442,7 +478,7 @@ namespace Ryujinx.Ui
}); });
} }
NpadManager.Update(); NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
if ((Toplevel as MainWindow).IsFocused) if ((Toplevel as MainWindow).IsFocused)
{ {
@ -461,7 +497,7 @@ namespace Ryujinx.Ui
bool hasTouch = false; bool hasTouch = false;
// Get screen touch position // Get screen touch position
if ((Toplevel as MainWindow).IsFocused) if ((Toplevel as MainWindow).IsFocused && !ConfigurationState.Instance.Hid.EnableMouse)
{ {
hasTouch = TouchScreenManager.Update(true, (_inputManager.MouseDriver as GTK3MouseDriver).IsButtonPressed(MouseButton.Button1), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat()); hasTouch = TouchScreenManager.Update(true, (_inputManager.MouseDriver as GTK3MouseDriver).IsButtonPressed(MouseButton.Button1), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
} }

View File

@ -1150,7 +1150,7 @@ namespace Ryujinx.Ui.Windows
if (_mainWindow.RendererWidget != null) if (_mainWindow.RendererWidget != null)
{ {
_mainWindow.RendererWidget.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard); _mainWindow.RendererWidget.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
} }
// Atomically replace and signal input change. // Atomically replace and signal input change.

View File

@ -56,6 +56,7 @@ namespace Ryujinx.Ui.Windows
[GUI] CheckButton _expandRamToggle; [GUI] CheckButton _expandRamToggle;
[GUI] CheckButton _ignoreToggle; [GUI] CheckButton _ignoreToggle;
[GUI] CheckButton _directKeyboardAccess; [GUI] CheckButton _directKeyboardAccess;
[GUI] CheckButton _directMouseAccess;
[GUI] ComboBoxText _systemLanguageSelect; [GUI] ComboBoxText _systemLanguageSelect;
[GUI] ComboBoxText _systemRegionSelect; [GUI] ComboBoxText _systemRegionSelect;
[GUI] Entry _systemTimeZoneEntry; [GUI] Entry _systemTimeZoneEntry;
@ -245,6 +246,11 @@ namespace Ryujinx.Ui.Windows
_directKeyboardAccess.Click(); _directKeyboardAccess.Click();
} }
if (ConfigurationState.Instance.Hid.EnableMouse)
{
_directMouseAccess.Click();
}
if (ConfigurationState.Instance.Ui.EnableCustomTheme) if (ConfigurationState.Instance.Ui.EnableCustomTheme)
{ {
_custThemeToggle.Click(); _custThemeToggle.Click();
@ -461,6 +467,7 @@ namespace Ryujinx.Ui.Windows
ConfigurationState.Instance.System.ExpandRam.Value = _expandRamToggle.Active; ConfigurationState.Instance.System.ExpandRam.Value = _expandRamToggle.Active;
ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active; ConfigurationState.Instance.System.IgnoreMissingServices.Value = _ignoreToggle.Active;
ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active; ConfigurationState.Instance.Hid.EnableKeyboard.Value = _directKeyboardAccess.Active;
ConfigurationState.Instance.Hid.EnableMouse.Value = _directMouseAccess.Active;
ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active; ConfigurationState.Instance.Ui.EnableCustomTheme.Value = _custThemeToggle.Active;
ConfigurationState.Instance.System.Language.Value = Enum.Parse<Language>(_systemLanguageSelect.ActiveId); ConfigurationState.Instance.System.Language.Value = Enum.Parse<Language>(_systemLanguageSelect.ActiveId);
ConfigurationState.Instance.System.Region.Value = Enum.Parse<Configuration.System.Region>(_systemRegionSelect.ActiveId); ConfigurationState.Instance.System.Region.Value = Enum.Parse<Configuration.System.Region>(_systemRegionSelect.ActiveId);

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.1 --> <!-- Generated with glade 3.38.2 -->
<interface> <interface>
<requires lib="gtk+" version="3.20"/> <requires lib="gtk+" version="3.20"/>
<object class="GtkAdjustment" id="_fsLogSpinAdjustment"> <object class="GtkAdjustment" id="_fsLogSpinAdjustment">
@ -520,6 +520,22 @@
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkCheckButton" id="_directMouseAccess">
<property name="label" translatable="yes">Direct Mouse Access</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="tooltip-text" translatable="yes">Enable or disable "direct keyboard access (HID) support" (Provides games access to your keyboard as a text entry device)</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">10</property>
<property name="position">2</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>

View File

@ -22,6 +22,7 @@
"enable_fs_integrity_checks", "enable_fs_integrity_checks",
"fs_global_access_log_mode", "fs_global_access_log_mode",
"enable_keyboard", "enable_keyboard",
"enable_mouse",
"keyboard_config", "keyboard_config",
"controller_config" "controller_config"
], ],
@ -1438,6 +1439,17 @@
false false
] ]
}, },
"enable_mouse": {
"$id": "#/properties/enable_mouse",
"type": "boolean",
"title": "(HID) Mouse Enable",
"description": "Enable or disable direct mouse access (HID) support (Provides games access to your mouse as a pointing device)",
"default": false,
"examples": [
true,
false
]
},
"hotkeys": { "hotkeys": {
"$id": "#/properties/hotkeys", "$id": "#/properties/hotkeys",
"type": "object", "type": "object",