2022-11-25 10:56:17 +01:00
|
|
|
using System.Diagnostics;
|
2023-01-21 22:01:17 +01:00
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Text;
|
2023-02-08 15:40:08 +01:00
|
|
|
using System.Text.RegularExpressions;
|
2022-11-25 10:56:17 +01:00
|
|
|
using SteamController.Helpers;
|
|
|
|
|
|
|
|
|
|
namespace SteamController.Managers
|
|
|
|
|
{
|
|
|
|
|
public sealed class SteamManager : Manager
|
|
|
|
|
{
|
2023-01-21 22:01:17 +01:00
|
|
|
private static readonly Classifier[] Classifiers = new Classifier[]
|
|
|
|
|
{
|
|
|
|
|
new Classifier() { Type = "gamepadui", ClassName = "SDL_app", WindowText = "SP", ProcessName = "steamwebhelper" },
|
|
|
|
|
new Classifier() { Type = "possiblegamepadui", ClassName = "SDL_app", WindowTextPrefix = "SP", ProcessName = "steamwebhelper" },
|
|
|
|
|
|
|
|
|
|
// Support Steam client released around 2023-01-20, version: 1674182294
|
2023-02-08 15:40:08 +01:00
|
|
|
new Classifier() { Type = "gamepadui_2023_01_20", ClassName = "SDL_app", ProcessName = "steamwebhelper" },
|
2023-01-21 22:01:17 +01:00
|
|
|
new Classifier() { Type = "controllerui_2023_01_20", ClassName = "CUIEngineWin32", ProcessName = "steam" },
|
|
|
|
|
// new Classifier() { Type = "possiblegamepadui_2023_01_20", ClassName = "SDL_app", WindowTextSuffix = "Controller Layout", ProcessName = "steamwebhelper" },
|
|
|
|
|
};
|
|
|
|
|
|
2022-12-04 21:14:08 +01:00
|
|
|
public const int DebounceStates = 1;
|
|
|
|
|
|
2022-12-04 20:43:57 +01:00
|
|
|
private string? lastState;
|
2022-12-04 21:14:08 +01:00
|
|
|
private int stateChanged;
|
2022-11-27 13:41:28 +01:00
|
|
|
|
2022-11-25 10:56:17 +01:00
|
|
|
public override void Tick(Context context)
|
|
|
|
|
{
|
2023-01-21 21:41:55 +01:00
|
|
|
if (Settings.Default.EnableSteamDetection != true)
|
2022-11-25 10:56:17 +01:00
|
|
|
{
|
2022-11-29 22:50:07 +01:00
|
|
|
context.State.SteamUsesSteamInput = false;
|
|
|
|
|
context.State.SteamUsesX360Controller = false;
|
2022-12-04 20:43:57 +01:00
|
|
|
lastState = null;
|
2022-12-04 21:14:08 +01:00
|
|
|
stateChanged = 0;
|
2022-11-25 10:56:17 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-04 20:43:57 +01:00
|
|
|
var usesController = UsesController();
|
2022-11-27 13:41:28 +01:00
|
|
|
if (lastState == usesController)
|
2022-12-04 21:14:08 +01:00
|
|
|
{
|
|
|
|
|
stateChanged = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (stateChanged < DebounceStates)
|
|
|
|
|
{
|
|
|
|
|
stateChanged++;
|
2022-11-27 13:41:28 +01:00
|
|
|
return;
|
2022-12-04 21:14:08 +01:00
|
|
|
}
|
2022-11-27 13:41:28 +01:00
|
|
|
|
2022-12-04 20:43:57 +01:00
|
|
|
if (usesController is not null)
|
2022-11-27 13:41:28 +01:00
|
|
|
{
|
2022-11-29 22:50:07 +01:00
|
|
|
context.State.SteamUsesSteamInput = Helpers.SteamConfiguration.IsControllerBlacklisted(
|
2022-11-27 13:41:28 +01:00
|
|
|
Devices.SteamController.VendorID,
|
|
|
|
|
Devices.SteamController.ProductID
|
|
|
|
|
) != true;
|
|
|
|
|
|
2022-11-29 22:50:07 +01:00
|
|
|
context.State.SteamUsesX360Controller = Helpers.SteamConfiguration.IsControllerBlacklisted(
|
2022-11-27 13:41:28 +01:00
|
|
|
Devices.Xbox360Controller.VendorID,
|
|
|
|
|
Devices.Xbox360Controller.ProductID
|
|
|
|
|
) != true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2022-11-29 22:50:07 +01:00
|
|
|
context.State.SteamUsesSteamInput = false;
|
|
|
|
|
context.State.SteamUsesX360Controller = false;
|
2022-11-27 13:41:28 +01:00
|
|
|
}
|
2022-11-25 10:56:17 +01:00
|
|
|
|
2022-11-27 13:41:28 +01:00
|
|
|
lastState = usesController;
|
2022-12-04 21:14:08 +01:00
|
|
|
stateChanged = 0;
|
2022-12-04 20:43:57 +01:00
|
|
|
|
|
|
|
|
#if DEBUG
|
|
|
|
|
CommonHelpers.Log.TraceLine(
|
|
|
|
|
"SteamManager: uses={0}, isRunning={1}, usesSteamInput={2}, usesX360={3}",
|
|
|
|
|
usesController,
|
|
|
|
|
SteamConfiguration.IsRunning,
|
|
|
|
|
context.State.SteamUsesSteamInput,
|
|
|
|
|
context.State.SteamUsesX360Controller
|
|
|
|
|
);
|
|
|
|
|
#endif
|
2022-11-25 10:56:17 +01:00
|
|
|
}
|
|
|
|
|
|
2022-12-04 20:43:57 +01:00
|
|
|
private string? UsesController()
|
2022-11-25 10:56:17 +01:00
|
|
|
{
|
2022-11-28 20:28:21 +01:00
|
|
|
if (!SteamConfiguration.IsRunning)
|
2022-11-25 10:56:17 +01:00
|
|
|
return null;
|
2022-12-04 20:43:57 +01:00
|
|
|
if (SteamConfiguration.IsBigPictureMode.GetValueOrDefault(false))
|
|
|
|
|
return "bigpicture";
|
|
|
|
|
if (SteamConfiguration.IsRunningGame.GetValueOrDefault(false))
|
|
|
|
|
return "game";
|
2023-01-21 22:01:17 +01:00
|
|
|
return ClassifyForegroundProcess();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private string? ClassifyForegroundProcess()
|
|
|
|
|
{
|
|
|
|
|
IntPtr hWnd = GetForegroundWindow();
|
|
|
|
|
if (hWnd == IntPtr.Zero)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
StringBuilder classNameBuilder = new StringBuilder(256);
|
|
|
|
|
if (GetClassName(hWnd, classNameBuilder, classNameBuilder.Capacity) == 0)
|
|
|
|
|
return null;
|
|
|
|
|
var className = classNameBuilder.ToString();
|
|
|
|
|
|
|
|
|
|
StringBuilder windowTextBuilder = new StringBuilder(256);
|
|
|
|
|
if (GetWindowText(hWnd, windowTextBuilder, windowTextBuilder.Capacity) == 0)
|
|
|
|
|
return null;
|
|
|
|
|
var windowText = windowTextBuilder.ToString();
|
|
|
|
|
|
|
|
|
|
var processName = ForegroundProcess.Find(hWnd)?.ProcessName;
|
|
|
|
|
if (processName is null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
foreach (var classifier in Classifiers)
|
|
|
|
|
{
|
|
|
|
|
if (classifier.Match(className, windowText, processName))
|
|
|
|
|
return classifier.Type;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-04 20:43:57 +01:00
|
|
|
return null;
|
2022-11-25 10:56:17 +01:00
|
|
|
}
|
2023-01-21 22:01:17 +01:00
|
|
|
|
|
|
|
|
private struct Classifier
|
|
|
|
|
{
|
|
|
|
|
public String Type { get; set; }
|
|
|
|
|
public String? ClassName { get; set; }
|
|
|
|
|
public String? WindowText { get; set; }
|
|
|
|
|
public String? WindowTextPrefix { get; set; }
|
|
|
|
|
public String? WindowTextSuffix { get; set; }
|
2023-02-08 15:40:08 +01:00
|
|
|
public Regex? WindowTextRegex { get; set; }
|
2023-01-21 22:01:17 +01:00
|
|
|
public String? ProcessName { get; set; }
|
|
|
|
|
|
|
|
|
|
public bool Match(string className, string windowText, string processName)
|
|
|
|
|
{
|
|
|
|
|
if (ClassName is not null && className != ClassName)
|
|
|
|
|
return false;
|
|
|
|
|
if (WindowText is not null && windowText != WindowText)
|
|
|
|
|
return false;
|
2023-02-08 15:40:08 +01:00
|
|
|
if (WindowTextRegex is not null && WindowTextRegex.IsMatch(windowText))
|
|
|
|
|
return false;
|
2023-01-21 22:01:17 +01:00
|
|
|
if (WindowTextPrefix is not null && !windowText.StartsWith(WindowTextPrefix))
|
|
|
|
|
return false;
|
|
|
|
|
if (WindowTextSuffix is not null && !windowText.EndsWith(WindowTextSuffix))
|
|
|
|
|
return false;
|
|
|
|
|
if (ProcessName is not null && !processName.EndsWith(ProcessName))
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[DllImport("user32.dll")]
|
|
|
|
|
private static extern IntPtr GetForegroundWindow();
|
|
|
|
|
|
|
|
|
|
[DllImport("user32.dll", SetLastError = true)]
|
|
|
|
|
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
|
|
|
|
|
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
|
|
|
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
|
|
|
|
|
|
|
|
|
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
|
|
|
|
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
|
2022-11-25 10:56:17 +01:00
|
|
|
}
|
|
|
|
|
}
|