Skip to content

Commit

Permalink
SteamController: Improve detection of Steam processes
Browse files Browse the repository at this point in the history
  • Loading branch information
ayufan committed Jan 21, 2023
1 parent caf6672 commit 9792dfd
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 62 deletions.
1 change: 1 addition & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

## 0.6.x

- SteamController: Improve detection of Steam processes (especially latest controller UI changes)
- SteamController: Add configuration wizard for the first time or when configuration was lost
- PowerControl: Show current time
- PowerControl: Consider the foreground process to be holding profile configuration as long as it is running
Expand Down
58 changes: 0 additions & 58 deletions SteamController/Helpers/SteamConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,52 +51,6 @@ public static bool? IsRunningGame
}
}

public static bool IsGamePadUI
{
get
{
var steamWindow = FindWindow("SDL_app", "SP");
// Support Steam client released around 2023-01-20, version: 1674182294
if (steamWindow == IntPtr.Zero)
steamWindow = FindWindow("SDL_app", "Steam Big Picture Mode");
if (steamWindow == IntPtr.Zero)
return false;

return GetForegroundWindow() == steamWindow;
}
}

public static bool IsPossibleGamePadUI
{
get
{
IntPtr hWnd = GetForegroundWindow();
if (hWnd == IntPtr.Zero)
return false;

StringBuilder className = new StringBuilder(256);
if (GetClassName(hWnd, className, className.Capacity) == 0)
return false;
if (className.ToString() != "SDL_app")
return false;

StringBuilder windowText = new StringBuilder(256);
if (GetWindowText(hWnd, windowText, windowText.Capacity) == 0)
return false;

bool valid = false;

// Support old Steam Clients
valid = valid || windowText.ToString().StartsWith("SP");

// Support Steam client released around 2023-01-20, version: 1674182294
// TODO: It appears that controller is not consumed when outside of big picture mode
// valid = valid || windowText.ToString().StartsWith("Controller Layout");

return valid && ForegroundProcess.Find(hWnd)?.ProcessName == "steamwebhelper";
}
}

public static String? SteamExe
{
get { return GetValue2<string>(SteamKey, SteamExeValue); }
Expand Down Expand Up @@ -446,17 +400,5 @@ public static bool UpdateControllerBlacklist(ushort vendorId, ushort productId,
return null;
}
}

[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);
}
}
83 changes: 79 additions & 4 deletions SteamController/Managers/SteamManager.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using SteamController.Helpers;

namespace SteamController.Managers
{
public sealed class SteamManager : Manager
{
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
new Classifier() { Type = "gamepadui_2023_01_20", ClassName = "SDL_app", WindowText = "Steam Big Picture Mode", ProcessName = "steamwebhelper" },
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" },
};

public const int DebounceStates = 1;

private string? lastState;
Expand Down Expand Up @@ -73,11 +86,73 @@ public override void Tick(Context context)
return "bigpicture";
if (SteamConfiguration.IsRunningGame.GetValueOrDefault(false))
return "game";
if (SteamConfiguration.IsGamePadUI)
return "gamepadui";
if (SteamConfiguration.IsPossibleGamePadUI)
return "possiblegamepadui";
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;
}

return null;
}

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; }
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;
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);
}
}

0 comments on commit 9792dfd

Please sign in to comment.