aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx
diff options
context:
space:
mode:
authormageven <62494521+mageven@users.noreply.github.com>2020-08-24 02:24:11 +0530
committerGitHub <noreply@github.com>2020-08-23 22:54:11 +0200
commit27179d02180396750cc2ea08ac1e2cc5a91a8763 (patch)
treed9fb3e03f4553b0aad2c9dec7e74e38f864e199c /Ryujinx
parent01ff648bdf46b85409d1a834987a69150de7adb9 (diff)
Improve multi-controller support in HID and Controller Applet (#1453)
* Initial commit Enable proper LED patterns Toggle Hotkeys only on focus Ignore Handheld on Docked mode Remove PrimaryController Validate NpadIdType Rewrite NpadDevices to process config in update loop Cleanup * Notify in log periodically when no matched controllers * Remove duplicate StructArrayHelpers in favor of Common.Memory Fix struct padding CS0169 warns in Touchscreen * Remove GTK markup from Controller Applet Use IList instead of List Explicit list capacity in 1ms loop Fix formatting * Restrict ControllerWindow to show valid controller types Add selected player name to ControllerWindow title * ControllerWindow: Fix controller type initial value NpadDevices: Simplify default battery charge * Address AcK's comments Use explicit types and fix formatting * Remove HashSet for SupportedPlayers Fixes potential exceptions due to race * Fix ControllerSupportArg struct packing Also comes with two revisions of struct for 4/8 players max.
Diffstat (limited to 'Ryujinx')
-rw-r--r--Ryujinx/Ui/ControllerWindow.cs47
-rw-r--r--Ryujinx/Ui/ControllerWindow.glade7
-rw-r--r--Ryujinx/Ui/GLRenderer.cs25
-rw-r--r--Ryujinx/Ui/GtkHostUiHandler.cs56
-rw-r--r--Ryujinx/Ui/MainWindow.cs8
5 files changed, 111 insertions, 32 deletions
diff --git a/Ryujinx/Ui/ControllerWindow.cs b/Ryujinx/Ui/ControllerWindow.cs
index 35c3859f..9518ba98 100644
--- a/Ryujinx/Ui/ControllerWindow.cs
+++ b/Ryujinx/Ui/ControllerWindow.cs
@@ -5,6 +5,7 @@ using Ryujinx.Common.Utilities;
using Ryujinx.Configuration;
using Ryujinx.HLE.FileSystem;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.Json;
@@ -91,6 +92,23 @@ namespace Ryujinx.Ui
_virtualFileSystem = virtualFileSystem;
_inputConfig = ConfigurationState.Instance.Hid.InputConfig.Value.Find(inputConfig => inputConfig.PlayerIndex == _playerIndex);
+ Title = $"Ryujinx - Controller Settings - {_playerIndex}";
+
+ if (_playerIndex == PlayerIndex.Handheld)
+ {
+ _controllerType.Append(ControllerType.Handheld.ToString(), "Handheld");
+ _controllerType.Sensitive = false;
+ }
+ else
+ {
+ _controllerType.Append(ControllerType.ProController.ToString(), "Pro Controller");
+ _controllerType.Append(ControllerType.JoyconPair.ToString(), "Joycon Pair");
+ _controllerType.Append(ControllerType.JoyconLeft.ToString(), "Joycon Left");
+ _controllerType.Append(ControllerType.JoyconRight.ToString(), "Joycon Right");
+ }
+
+ _controllerType.Active = 0; // Set initial value to first in list.
+
//Bind Events
_lStickX.Clicked += Button_Pressed;
_lStickY.Clicked += Button_Pressed;
@@ -278,7 +296,12 @@ namespace Ryujinx.Ui
switch (config)
{
case KeyboardConfig keyboardConfig:
- _controllerType.SetActiveId(keyboardConfig.ControllerType.ToString());
+ if (!_controllerType.SetActiveId(keyboardConfig.ControllerType.ToString()))
+ {
+ _controllerType.SetActiveId(_playerIndex == PlayerIndex.Handheld
+ ? ControllerType.Handheld.ToString()
+ : ControllerType.ProController.ToString());
+ }
_lStickUp.Label = keyboardConfig.LeftJoycon.StickUp.ToString();
_lStickDown.Label = keyboardConfig.LeftJoycon.StickDown.ToString();
@@ -310,7 +333,12 @@ namespace Ryujinx.Ui
_rSr.Label = keyboardConfig.RightJoycon.ButtonSr.ToString();
break;
case ControllerConfig controllerConfig:
- _controllerType.SetActiveId(controllerConfig.ControllerType.ToString());
+ if (!_controllerType.SetActiveId(controllerConfig.ControllerType.ToString()))
+ {
+ _controllerType.SetActiveId(_playerIndex == PlayerIndex.Handheld
+ ? ControllerType.Handheld.ToString()
+ : ControllerType.ProController.ToString());
+ }
_lStickX.Label = controllerConfig.LeftJoycon.StickX.ToString();
_invertLStickX.Active = controllerConfig.LeftJoycon.InvertStickX;
@@ -894,24 +922,31 @@ namespace Ryujinx.Ui
{
InputConfig inputConfig = GetValues();
+ var newConfig = new List<InputConfig>();
+ newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
+
if (_inputConfig == null && inputConfig != null)
{
- ConfigurationState.Instance.Hid.InputConfig.Value.Add(inputConfig);
+ newConfig.Add(inputConfig);
}
else
{
if (_inputDevice.ActiveId == "disabled")
{
- ConfigurationState.Instance.Hid.InputConfig.Value.Remove(_inputConfig);
+ newConfig.Remove(_inputConfig);
}
else if (inputConfig != null)
{
- int index = ConfigurationState.Instance.Hid.InputConfig.Value.IndexOf(_inputConfig);
+ int index = newConfig.IndexOf(_inputConfig);
- ConfigurationState.Instance.Hid.InputConfig.Value[index] = inputConfig;
+ newConfig[index] = inputConfig;
}
}
+ // Atomically replace and signal input change.
+ // NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event.
+ ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
+
MainWindow.SaveConfig();
Dispose();
diff --git a/Ryujinx/Ui/ControllerWindow.glade b/Ryujinx/Ui/ControllerWindow.glade
index 2b780f13..c0532d90 100644
--- a/Ryujinx/Ui/ControllerWindow.glade
+++ b/Ryujinx/Ui/ControllerWindow.glade
@@ -138,13 +138,6 @@
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">The controller's type</property>
<property name="active">0</property>
- <items>
- <item id="Handheld" translatable="yes">Handheld</item>
- <item id="ProController" translatable="yes">Pro Controller</item>
- <item id="JoyconPair" translatable="yes">Paired Joycons</item>
- <item id="JoyconLeft" translatable="yes">Left Joycon</item>
- <item id="JoyconRight" translatable="yes">Right Joycon</item>
- </items>
<signal name="changed" handler="Controller_Changed" swapped="no"/>
</object>
<packing>
diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs
index 867401ad..203df72a 100644
--- a/Ryujinx/Ui/GLRenderer.cs
+++ b/Ryujinx/Ui/GLRenderer.cs
@@ -405,9 +405,9 @@ namespace Ryujinx.Ui
});
}
- List<GamepadInput> gamepadInputs = new List<GamepadInput>();
+ List<GamepadInput> gamepadInputs = new List<GamepadInput>(NpadDevices.MaxControllers);
- foreach (InputConfig inputConfig in ConfigurationState.Instance.Hid.InputConfig.Value.ToArray())
+ foreach (InputConfig inputConfig in ConfigurationState.Instance.Hid.InputConfig.Value)
{
ControllerKeys currentButton = 0;
JoystickPosition leftJoystick = new JoystickPosition();
@@ -497,18 +497,21 @@ namespace Ryujinx.Ui
});
}
- _device.Hid.Npads.SetGamepadsInput(gamepadInputs.ToArray());
+ _device.Hid.Npads.Update(gamepadInputs);
- // Hotkeys
- HotkeyButtons currentHotkeyButtons = KeyboardController.GetHotkeyButtons(OpenTK.Input.Keyboard.GetState());
-
- if (currentHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync) &&
- !_prevHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync))
+ if(IsFocused)
{
- _device.EnableDeviceVsync = !_device.EnableDeviceVsync;
- }
+ // Hotkeys
+ HotkeyButtons currentHotkeyButtons = KeyboardController.GetHotkeyButtons(OpenTK.Input.Keyboard.GetState());
+
+ if (currentHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync) &&
+ !_prevHotkeyButtons.HasFlag(HotkeyButtons.ToggleVSync))
+ {
+ _device.EnableDeviceVsync = !_device.EnableDeviceVsync;
+ }
- _prevHotkeyButtons = currentHotkeyButtons;
+ _prevHotkeyButtons = currentHotkeyButtons;
+ }
//Touchscreen
bool hasTouch = false;
diff --git a/Ryujinx/Ui/GtkHostUiHandler.cs b/Ryujinx/Ui/GtkHostUiHandler.cs
index 989fe14d..90830056 100644
--- a/Ryujinx/Ui/GtkHostUiHandler.cs
+++ b/Ryujinx/Ui/GtkHostUiHandler.cs
@@ -16,6 +16,62 @@ namespace Ryujinx.Ui
_parent = parent;
}
+ public bool DisplayMessageDialog(ControllerAppletUiArgs args)
+ {
+ string playerCount = args.PlayerCountMin == args.PlayerCountMax
+ ? $"exactly {args.PlayerCountMin}"
+ : $"{args.PlayerCountMin}-{args.PlayerCountMax}";
+
+ string message =
+ $"Application requests <b>{playerCount}</b> player(s) with:\n\n"
+ + $"<tt><b>TYPES:</b> {args.SupportedStyles}</tt>\n\n"
+ + $"<tt><b>PLAYERS:</b> {string.Join(", ", args.SupportedPlayers)}</tt>\n\n"
+ + (args.IsDocked ? "Docked mode set. <tt>Handheld</tt> is also invalid.\n\n" : "")
+ + "<i>Please reconfigure Input now and then press OK.</i>";
+
+ return DisplayMessageDialog("Controller Applet", message);
+ }
+
+ public bool DisplayMessageDialog(string title, string message)
+ {
+ ManualResetEvent dialogCloseEvent = new ManualResetEvent(false);
+ bool okPressed = false;
+
+ Application.Invoke(delegate
+ {
+ MessageDialog msgDialog = null;
+ try
+ {
+ msgDialog = new MessageDialog(_parent, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, null)
+ {
+ Title = title,
+ Text = message,
+ UseMarkup = true
+ };
+
+ msgDialog.SetDefaultSize(400, 0);
+
+ msgDialog.Response += (object o, ResponseArgs args) =>
+ {
+ if (args.ResponseId == ResponseType.Ok) okPressed = true;
+ dialogCloseEvent.Set();
+ msgDialog?.Dispose();
+ };
+
+ msgDialog.Show();
+ }
+ catch (Exception e)
+ {
+ Logger.Error?.Print(LogClass.Application, $"Error displaying Message Dialog: {e}");
+ dialogCloseEvent.Set();
+ }
+ });
+
+ dialogCloseEvent.WaitOne();
+
+ return okPressed;
+ }
+
public bool DisplayInputDialog(SoftwareKeyboardUiArgs args, out string userText)
{
ManualResetEvent dialogCloseEvent = new ManualResetEvent(false);
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index f077e9bd..d2b303e4 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -507,14 +507,6 @@ namespace Ryujinx.Ui
_windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1);
}
- device.Hid.Npads.AddControllers(ConfigurationState.Instance.Hid.InputConfig.Value.Select(inputConfig =>
- new HLE.HOS.Services.Hid.ControllerConfig
- {
- Player = (PlayerIndex)inputConfig.PlayerIndex,
- Type = (ControllerType)inputConfig.ControllerType
- }
- ).ToArray());
-
_glWidget = new GlRenderer(_emulationContext, ConfigurationState.Instance.Logger.GraphicsDebugLevel);
Application.Invoke(delegate