mirror of
https://github.com/ayufan/steam-deck-tools.git
synced 2026-04-05 06:15:26 +00:00
Add SteamController implementation
This adds a Steam Shortcuts, Desktop Mode, and X360 Emulation - Supports all Steam Shortcuts (including on-screen keyboard, and brightness) - Supports Desktop mode (with a scroll on left pad and left stick), and trackpoint (on right stick) - Supports X360 mode: hold Options for 1s to switch between Desktop and X360 - Holding Steam button enables Desktop like controls and stops passing all inputs to X360
This commit is contained in:
parent
203338b669
commit
ecbd0407c0
41 changed files with 2486 additions and 34 deletions
91
SteamController/Profiles/Context.cs
Normal file
91
SteamController/Profiles/Context.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
using static CommonHelpers.Log;
|
||||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public class Context : IDisposable
|
||||
{
|
||||
public const double JoystickToMouseSensitivity = 1200;
|
||||
public const double PadToMouseSensitivity = 200;
|
||||
public const double ThumbToWhellSensitivity = 2;
|
||||
|
||||
public Devices.SteamController Steam { get; private set; }
|
||||
public Devices.Xbox360Controller X360 { get; private set; }
|
||||
public Devices.KeyboardController Keyboard { get; private set; }
|
||||
public Devices.MouseController Mouse { get; private set; }
|
||||
|
||||
public List<Profile> Profiles { get; } = new List<Profile>();
|
||||
|
||||
public bool RequestDesktopMode { get; set; } = true;
|
||||
|
||||
public bool DesktopMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return RequestDesktopMode || !X360.Valid || !Mouse.Valid;
|
||||
}
|
||||
}
|
||||
|
||||
public Context()
|
||||
{
|
||||
Steam = new Devices.SteamController();
|
||||
X360 = new Devices.Xbox360Controller();
|
||||
Keyboard = new Devices.KeyboardController();
|
||||
Mouse = new Devices.MouseController();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
using (Steam) { }
|
||||
using (X360) { }
|
||||
using (Keyboard) { }
|
||||
using (Mouse) { }
|
||||
}
|
||||
|
||||
public bool Update()
|
||||
{
|
||||
Steam.BeforeUpdate();
|
||||
X360.BeforeUpdate();
|
||||
Keyboard.BeforeUpdate();
|
||||
Mouse.BeforeUpdate();
|
||||
|
||||
try
|
||||
{
|
||||
bool skip = false;
|
||||
|
||||
foreach (Profile profile in Profiles)
|
||||
{
|
||||
if (!profile.RunAlways && skip)
|
||||
{
|
||||
profile.Skipped(this);
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var status = profile.Run(this);
|
||||
if (status == Profile.Status.Stop)
|
||||
skip = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TraceLine("Profile: Exception: {0}", e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
TraceLine("Controller: Exception: {0}", e);
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Steam.Update();
|
||||
X360.Update();
|
||||
Keyboard.Update();
|
||||
Mouse.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
SteamController/Profiles/DebugProfile.cs
Normal file
64
SteamController/Profiles/DebugProfile.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
using static CommonHelpers.Log;
|
||||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public sealed class DebugProfile : Profile
|
||||
{
|
||||
public DebugProfile()
|
||||
{
|
||||
RunAlways = true;
|
||||
}
|
||||
|
||||
List<string> lastItems = new List<string>();
|
||||
|
||||
public override Status Run(Context c)
|
||||
{
|
||||
var items = new List<string>();
|
||||
|
||||
if (c.DesktopMode)
|
||||
items.Add("[DESKTOP]");
|
||||
else
|
||||
items.Add("[CONTROLLER]");
|
||||
|
||||
if (c.Steam.LizardButtons)
|
||||
items.Add("[LB]");
|
||||
if (c.Steam.LizardMouse)
|
||||
items.Add("[LM]");
|
||||
if (c.X360.Connected)
|
||||
items.Add("[X360]");
|
||||
else if (c.X360.Valid)
|
||||
items.Add("[no-X360]");
|
||||
|
||||
foreach (var button in c.Steam.AllButtons)
|
||||
{
|
||||
if (button is null || !button.LastValue)
|
||||
continue;
|
||||
|
||||
String text = button.Name;
|
||||
if (button.Consumed is not null)
|
||||
text += String.Format("[{0}]", button.Consumed);
|
||||
if (button.Value)
|
||||
text += "[P]";
|
||||
|
||||
items.Add(text);
|
||||
}
|
||||
|
||||
foreach (var key in c.Keyboard.DownKeys)
|
||||
{
|
||||
items.Add(String.Format("Key{0}", key));
|
||||
}
|
||||
|
||||
foreach (var mouse in c.Mouse.DownButtons)
|
||||
{
|
||||
items.Add(String.Format("Mouse{0}", mouse));
|
||||
}
|
||||
|
||||
if (!items.SequenceEqual(lastItems))
|
||||
{
|
||||
TraceLine("DEBUG: {0}", String.Join(" ", items));
|
||||
lastItems = items;
|
||||
}
|
||||
return Status.Continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
112
SteamController/Profiles/DesktopProfile.cs
Normal file
112
SteamController/Profiles/DesktopProfile.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
using PowerControl.Helpers;
|
||||
using WindowsInput;
|
||||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public sealed class DesktopProfile : Profile
|
||||
{
|
||||
public const bool LizardButtons = false;
|
||||
public const bool LizardMouse = true;
|
||||
|
||||
public const String Consumed = "DesktopProfileOwner";
|
||||
|
||||
public DesktopProfile()
|
||||
{
|
||||
}
|
||||
|
||||
public override Status Run(Context c)
|
||||
{
|
||||
if (!c.DesktopMode)
|
||||
{
|
||||
return Status.Continue;
|
||||
}
|
||||
|
||||
if (!c.Mouse.Valid)
|
||||
{
|
||||
// Failed to acquire secure context
|
||||
// Enable emergency Lizard
|
||||
c.Steam.LizardButtons = true;
|
||||
c.Steam.LizardMouse = true;
|
||||
return Status.Continue;
|
||||
}
|
||||
|
||||
c.Steam.LizardButtons = LizardButtons;
|
||||
c.Steam.LizardMouse = LizardMouse;
|
||||
|
||||
EmulateLizardButtons(c);
|
||||
EmulateLizardMouse(c);
|
||||
|
||||
if (c.Steam.LPadX)
|
||||
{
|
||||
c.Mouse.HorizontalScroll(c.Steam.LPadX.Scaled(Context.ThumbToWhellSensitivity, Devices.SteamController.SteamAxis.ScaledMode.Delta));
|
||||
}
|
||||
if (c.Steam.LPadY)
|
||||
{
|
||||
c.Mouse.VerticalScroll(c.Steam.LPadY.Scaled(Context.ThumbToWhellSensitivity, Devices.SteamController.SteamAxis.ScaledMode.Delta));
|
||||
}
|
||||
|
||||
if (c.Steam.BtnVirtualLeftThumbUp.HoldRepeat(Consumed))
|
||||
{
|
||||
c.Mouse.VerticalScroll(Context.ThumbToWhellSensitivity);
|
||||
}
|
||||
else if (c.Steam.BtnVirtualLeftThumbDown.HoldRepeat(Consumed))
|
||||
{
|
||||
c.Mouse.VerticalScroll(-Context.ThumbToWhellSensitivity);
|
||||
}
|
||||
else if (c.Steam.BtnVirtualLeftThumbLeft.HoldRepeat(Consumed))
|
||||
{
|
||||
c.Mouse.HorizontalScroll(-Context.ThumbToWhellSensitivity);
|
||||
}
|
||||
else if (c.Steam.BtnVirtualLeftThumbRight.HoldRepeat(Consumed))
|
||||
{
|
||||
c.Mouse.HorizontalScroll(Context.ThumbToWhellSensitivity);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnRStickTouch && (c.Steam.RightThumbX || c.Steam.RightThumbY))
|
||||
{
|
||||
c.Mouse.MoveBy(
|
||||
c.Steam.RightThumbX.Scaled(Context.JoystickToMouseSensitivity, Devices.SteamController.SteamAxis.ScaledMode.AbsoluteTime),
|
||||
-c.Steam.RightThumbY.Scaled(Context.JoystickToMouseSensitivity, Devices.SteamController.SteamAxis.ScaledMode.AbsoluteTime)
|
||||
);
|
||||
}
|
||||
|
||||
return Status.Continue;
|
||||
}
|
||||
|
||||
private void EmulateLizardButtons(Context c)
|
||||
{
|
||||
c.Mouse[Devices.MouseController.Button.Right] = c.Steam.BtnL2 || c.Steam.BtnLPadPress;
|
||||
c.Mouse[Devices.MouseController.Button.Left] = c.Steam.BtnR2 || c.Steam.BtnRPadPress;
|
||||
|
||||
#if true
|
||||
if (c.Steam.BtnA.Pressed())
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.RETURN);
|
||||
if (c.Steam.BtnDpadLeft.HoldRepeat(Consumed))
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.LEFT);
|
||||
if (c.Steam.BtnDpadRight.HoldRepeat(Consumed))
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.RIGHT);
|
||||
if (c.Steam.BtnDpadUp.HoldRepeat(Consumed))
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.UP);
|
||||
if (c.Steam.BtnDpadDown.HoldRepeat(Consumed))
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.DOWN);
|
||||
#else
|
||||
c.Keyboard[VirtualKeyCode.RETURN] = c.Steam.BtnA;
|
||||
c.Keyboard[VirtualKeyCode.LEFT] = c.Steam.BtnDpadLeft;
|
||||
c.Keyboard[VirtualKeyCode.RIGHT] = c.Steam.BtnDpadRight;
|
||||
c.Keyboard[VirtualKeyCode.UP] = c.Steam.BtnDpadUp;
|
||||
c.Keyboard[VirtualKeyCode.DOWN] = c.Steam.BtnDpadDown;
|
||||
#endif
|
||||
}
|
||||
|
||||
private void EmulateLizardMouse(Context c)
|
||||
{
|
||||
if (c.Steam.RPadX || c.Steam.RPadY)
|
||||
{
|
||||
c.Mouse.MoveBy(
|
||||
c.Steam.RPadX.Scaled(Context.PadToMouseSensitivity, Devices.SteamController.SteamAxis.ScaledMode.Delta),
|
||||
-c.Steam.RPadY.Scaled(Context.PadToMouseSensitivity, Devices.SteamController.SteamAxis.ScaledMode.Delta)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
SteamController/Profiles/Profile.cs
Normal file
19
SteamController/Profiles/Profile.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
namespace SteamController.Profiles
|
||||
{
|
||||
public abstract class Profile
|
||||
{
|
||||
public enum Status
|
||||
{
|
||||
Continue,
|
||||
Stop
|
||||
}
|
||||
|
||||
public bool RunAlways { get; set; }
|
||||
|
||||
public abstract Status Run(Context context);
|
||||
|
||||
public virtual void Skipped(Context context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
166
SteamController/Profiles/SteamShortcutsProfile.cs
Normal file
166
SteamController/Profiles/SteamShortcutsProfile.cs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
using System.Diagnostics;
|
||||
using ExternalHelpers;
|
||||
using PowerControl.Helpers;
|
||||
using WindowsInput;
|
||||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public sealed class SteamShortcutsProfile : Profile
|
||||
{
|
||||
public const bool LizardButtons = true;
|
||||
public const bool LizardMouse = false;
|
||||
|
||||
public const String Consumed = "SteamShortcutsProfile";
|
||||
public readonly TimeSpan HoldForShorcuts = TimeSpan.FromMilliseconds(200);
|
||||
public readonly TimeSpan HoldForKill = TimeSpan.FromSeconds(3);
|
||||
public readonly TimeSpan HoldForClose = TimeSpan.FromSeconds(1);
|
||||
public readonly TimeSpan HoldToSwitchDesktop = TimeSpan.FromSeconds(1);
|
||||
|
||||
public SteamShortcutsProfile()
|
||||
{
|
||||
RunAlways = true;
|
||||
}
|
||||
|
||||
public override Status Run(Context c)
|
||||
{
|
||||
// Steam + 3 dots simulate CTRL+ALT+DELETE
|
||||
if (c.Steam.BtnSteam.Hold(HoldForShorcuts, Consumed) && c.Steam.BtnQuickAccess.HoldOnce(HoldForShorcuts, Consumed))
|
||||
{
|
||||
c.Keyboard.KeyPress(new VirtualKeyCode[] { VirtualKeyCode.LCONTROL, VirtualKeyCode.LMENU }, VirtualKeyCode.DELETE);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnSteam.Hold(HoldForShorcuts, Consumed))
|
||||
{
|
||||
c.Steam.LizardButtons = LizardButtons;
|
||||
c.Steam.LizardMouse = LizardMouse;
|
||||
SteamShortcuts(c);
|
||||
AdditionalShortcuts(c);
|
||||
return Status.Stop;
|
||||
}
|
||||
|
||||
if (c.Steam.BtnOptions.HoldOnce(HoldToSwitchDesktop, Consumed))
|
||||
{
|
||||
c.RequestDesktopMode = !c.RequestDesktopMode;
|
||||
}
|
||||
|
||||
if (c.Steam.BtnQuickAccess.Hold(HoldForShorcuts, Consumed))
|
||||
{
|
||||
// nothing there, just consume
|
||||
return Status.Stop;
|
||||
}
|
||||
|
||||
return Status.Continue;
|
||||
}
|
||||
|
||||
private void SteamShortcuts(Context c)
|
||||
{
|
||||
c.Steam.LizardButtons = false;
|
||||
c.Steam.LizardMouse = true;
|
||||
|
||||
if (c.Steam.BtnA.Pressed())
|
||||
{
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.RETURN);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnB.HoldOnce(HoldForKill, Consumed))
|
||||
{
|
||||
// kill application
|
||||
}
|
||||
else if (c.Steam.BtnB.HoldOnce(HoldForClose, Consumed))
|
||||
{
|
||||
// close application
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.LMENU, VirtualKeyCode.F4);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnX.Pressed())
|
||||
{
|
||||
OnScreenKeyboard.Toggle();
|
||||
}
|
||||
|
||||
if (c.Steam.BtnL1.Pressed())
|
||||
{
|
||||
if (Process.GetProcessesByName("Magnify").Any())
|
||||
{
|
||||
// close magnifier
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.LWIN, VirtualKeyCode.ESCAPE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// enable magnifier
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.LWIN, VirtualKeyCode.OEM_PLUS);
|
||||
}
|
||||
}
|
||||
|
||||
if (c.Steam.BtnR1.Pressed())
|
||||
{
|
||||
// take screenshot
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.LWIN, VirtualKeyCode.SNAPSHOT);
|
||||
}
|
||||
|
||||
c.Mouse[Devices.MouseController.Button.Right] = c.Steam.BtnL2 || c.Steam.BtnLPadPress;
|
||||
c.Mouse[Devices.MouseController.Button.Left] = c.Steam.BtnR2 || c.Steam.BtnRPadPress;
|
||||
|
||||
if (c.Steam.BtnRStickTouch && (c.Steam.RightThumbX || c.Steam.RightThumbY))
|
||||
{
|
||||
c.Mouse.MoveBy(
|
||||
c.Steam.RightThumbX.Scaled(Context.JoystickToMouseSensitivity, Devices.SteamController.SteamAxis.ScaledMode.AbsoluteTime),
|
||||
-c.Steam.RightThumbY.Scaled(Context.JoystickToMouseSensitivity, Devices.SteamController.SteamAxis.ScaledMode.AbsoluteTime)
|
||||
);
|
||||
}
|
||||
|
||||
if (!c.Steam.LizardMouse)
|
||||
{
|
||||
EmulateLizardMouse(c);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnVirtualLeftThumbUp.HoldRepeat(Consumed))
|
||||
{
|
||||
WindowsSettingsBrightnessController.Increase(5);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnVirtualLeftThumbDown.HoldRepeat(Consumed))
|
||||
{
|
||||
WindowsSettingsBrightnessController.Increase(-5);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnDpadRight.Pressed())
|
||||
{
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.RETURN);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnDpadDown.Pressed())
|
||||
{
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.TAB);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnDpadLeft.Pressed())
|
||||
{
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.ESCAPE);
|
||||
}
|
||||
}
|
||||
|
||||
private void AdditionalShortcuts(Context c)
|
||||
{
|
||||
if (c.Steam.BtnMenu.Pressed())
|
||||
{
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.LWIN, VirtualKeyCode.TAB);
|
||||
}
|
||||
|
||||
if (c.Steam.BtnOptions.Pressed())
|
||||
{
|
||||
c.Keyboard.KeyPress(VirtualKeyCode.F11);
|
||||
}
|
||||
}
|
||||
|
||||
private void EmulateLizardMouse(Context c)
|
||||
{
|
||||
if (c.Steam.RPadX || c.Steam.RPadY)
|
||||
{
|
||||
c.Mouse.MoveBy(
|
||||
c.Steam.RPadX.Scaled(Context.PadToMouseSensitivity, Devices.SteamController.SteamAxis.ScaledMode.Delta),
|
||||
-c.Steam.RPadY.Scaled(Context.PadToMouseSensitivity, Devices.SteamController.SteamAxis.ScaledMode.Delta)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
SteamController/Profiles/X360Profile.cs
Normal file
66
SteamController/Profiles/X360Profile.cs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
using Nefarius.ViGEm.Client.Targets.Xbox360;
|
||||
|
||||
namespace SteamController.Profiles
|
||||
{
|
||||
public sealed class X360Profile : Profile
|
||||
{
|
||||
public override void Skipped(Context context)
|
||||
{
|
||||
if (!context.DesktopMode)
|
||||
{
|
||||
context.X360.Connected = true;
|
||||
ControlButtons(context);
|
||||
}
|
||||
}
|
||||
|
||||
public override Status Run(Context context)
|
||||
{
|
||||
if (context.DesktopMode)
|
||||
{
|
||||
context.X360.Connected = false;
|
||||
return Status.Continue;
|
||||
}
|
||||
|
||||
context.Steam.LizardButtons = false;
|
||||
context.Steam.LizardMouse = true;
|
||||
context.X360.Connected = true;
|
||||
|
||||
// DPad
|
||||
context.X360[Xbox360Button.Up] = context.Steam.BtnDpadUp;
|
||||
context.X360[Xbox360Button.Down] = context.Steam.BtnDpadDown;
|
||||
context.X360[Xbox360Button.Left] = context.Steam.BtnDpadLeft;
|
||||
context.X360[Xbox360Button.Right] = context.Steam.BtnDpadRight;
|
||||
|
||||
// Buttons
|
||||
context.X360[Xbox360Button.A] = context.Steam.BtnA;
|
||||
context.X360[Xbox360Button.B] = context.Steam.BtnB;
|
||||
context.X360[Xbox360Button.X] = context.Steam.BtnX;
|
||||
context.X360[Xbox360Button.Y] = context.Steam.BtnY;
|
||||
|
||||
// Sticks
|
||||
context.X360[Xbox360Axis.LeftThumbX] = context.Steam.LeftThumbX;
|
||||
context.X360[Xbox360Axis.LeftThumbY] = context.Steam.LeftThumbY;
|
||||
context.X360[Xbox360Axis.RightThumbX] = context.Steam.RightThumbX;
|
||||
context.X360[Xbox360Axis.RightThumbY] = context.Steam.RightThumbY;
|
||||
context.X360[Xbox360Button.LeftThumb] = context.Steam.BtnLeftStickPress;
|
||||
context.X360[Xbox360Button.RightThumb] = context.Steam.BtnRightStickPress;
|
||||
|
||||
// Triggers
|
||||
context.X360[Xbox360Slider.LeftTrigger] = context.Steam.LeftTrigger;
|
||||
context.X360[Xbox360Slider.RightTrigger] = context.Steam.RightTrigger;
|
||||
context.X360[Xbox360Button.LeftShoulder] = context.Steam.BtnL1;
|
||||
context.X360[Xbox360Button.RightShoulder] = context.Steam.BtnR1;
|
||||
|
||||
ControlButtons(context);
|
||||
return Status.Continue;
|
||||
}
|
||||
|
||||
private void ControlButtons(Context context)
|
||||
{
|
||||
// Controls
|
||||
context.X360[Xbox360Button.Guide] = context.Steam.BtnSteam.Pressed();
|
||||
context.X360[Xbox360Button.Back] = context.Steam.BtnMenu;
|
||||
context.X360[Xbox360Button.Start] = context.Steam.BtnOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue