diff --git a/HandheldCompanion.iss b/HandheldCompanion.iss
index c89379e23..6b9984b50 100644
--- a/HandheldCompanion.iss
+++ b/HandheldCompanion.iss
@@ -26,7 +26,7 @@
#define InstallerVersion '0.2'
#define MyAppSetupName 'Handheld Companion'
#define MyBuildId 'HandheldCompanion'
-#define MyAppVersion '0.22.0.2'
+#define MyAppVersion '0.22.0.3'
#define MyAppPublisher 'BenjaminLSR'
#define MyAppCopyright 'Copyright @ BenjaminLSR'
#define MyAppURL 'https://github.com/Valkirie/HandheldCompanion'
diff --git a/HandheldCompanion/Commands/Functions/Windows/OnScreenKeyboardLegacyCommands.cs b/HandheldCompanion/Commands/Functions/Windows/OnScreenKeyboardLegacyCommands.cs
index a838284c0..649580864 100644
--- a/HandheldCompanion/Commands/Functions/Windows/OnScreenKeyboardLegacyCommands.cs
+++ b/HandheldCompanion/Commands/Functions/Windows/OnScreenKeyboardLegacyCommands.cs
@@ -40,7 +40,7 @@ public override void Execute(bool IsKeyDown, bool IsKeyUp, bool IsBackground)
{
// Start a new osk.exe process
Process OSK = Process.Start(new ProcessStartInfo("osk.exe") { UseShellExecute = true, WindowStyle = ProcessWindowStyle.Hidden });
- await Task.Delay(200);
+ await Task.Delay(200).ConfigureAwait(false); // Avoid blocking the synchronization context
// Find the OSK window.
IntPtr hwndOSK = FindWindow("OSKMainClass", null);
diff --git a/HandheldCompanion/Controllers/GordonController.cs b/HandheldCompanion/Controllers/GordonController.cs
index 1682afcf8..5f15a5a2b 100644
--- a/HandheldCompanion/Controllers/GordonController.cs
+++ b/HandheldCompanion/Controllers/GordonController.cs
@@ -221,16 +221,16 @@ public override void UpdateInputs(long ticks, float delta)
base.UpdateInputs(ticks, delta);
}
- private async Task OnControllerInputReceived(GordonControllerInputEventArgs input)
- {
- this.input = input;
- }
public override void Plug()
{
try
{
- Controller.OnControllerInputReceived = input => OnControllerInputReceived(input);
+ Controller.OnControllerInputReceived += input =>
+ {
+ this.input = input;
+ return Task.CompletedTask;
+ };
// open controller
Open();
diff --git a/HandheldCompanion/Controllers/IController.cs b/HandheldCompanion/Controllers/IController.cs
index 7726a2208..00246feb1 100644
--- a/HandheldCompanion/Controllers/IController.cs
+++ b/HandheldCompanion/Controllers/IController.cs
@@ -300,7 +300,7 @@ public virtual void Rumble(int delay = 125, byte LargeMotor = byte.MaxValue, byt
rumbleTask = Task.Run(async () =>
{
SetVibration(LargeMotor, SmallMotor);
- await Task.Delay(delay);
+ await Task.Delay(delay).ConfigureAwait(false); // Avoid blocking the synchronization context
SetVibration(0, 0);
});
}
@@ -365,7 +365,7 @@ public virtual void CyclePort()
Task.Run(async () =>
{
Details.Uninstall(false);
- await Task.Delay(3000);
+ await Task.Delay(3000).ConfigureAwait(false); // Avoid blocking the synchronization context
Devcon.Refresh();
});
break;
diff --git a/HandheldCompanion/Controllers/NeptuneController.cs b/HandheldCompanion/Controllers/NeptuneController.cs
index 749cf97d4..b7a2fb32d 100644
--- a/HandheldCompanion/Controllers/NeptuneController.cs
+++ b/HandheldCompanion/Controllers/NeptuneController.cs
@@ -260,16 +260,15 @@ private void Open()
Controller.RequestLizardMode(false);
// create handler
- Controller.OnControllerInputReceived += input => OnControllerInputReceived(input);
+ Controller.OnControllerInputReceived += input =>
+ {
+ this.input = input;
+ return Task.CompletedTask;
+ };
}
catch { }
}
- private async Task OnControllerInputReceived(NeptuneControllerInputEventArgs input)
- {
- this.input = input;
- }
-
private void Close()
{
try
@@ -394,7 +393,7 @@ private async void RumbleThreadLoop(object? obj)
if (GetHapticIntensity(FeedbackSmallMotor, MinIntensity, MaxIntensity, out var rightIntensity))
Controller.SetHaptic2(SCHapticMotor.Right, NCHapticStyle.Weak, rightIntensity);
- await Task.Delay(TimerManager.GetPeriod() * 2);
+ Thread.Sleep(TimerManager.GetPeriod() * 2);
}
}
diff --git a/HandheldCompanion/Controls/Hints/Hint_SteamInput.cs b/HandheldCompanion/Controls/Hints/Hint_SteamInput.cs
index 9c31284fa..9ee9fc285 100644
--- a/HandheldCompanion/Controls/Hints/Hint_SteamInput.cs
+++ b/HandheldCompanion/Controls/Hints/Hint_SteamInput.cs
@@ -51,7 +51,7 @@ protected override void HintActionButton_Click(object sender, RoutedEventArgs e)
// halt steam and wait
PlatformManager.Steam.StopProcess();
while (PlatformManager.Steam.IsRunning)
- await Task.Delay(1000);
+ await Task.Delay(1000).ConfigureAwait(false); // Avoid blocking the synchronization context;
// overwrite desktop layout
PlatformManager.Steam.SetUseSteamControllerConfigValue(0);
diff --git a/HandheldCompanion/Devices/ASUS/ROGAlly.cs b/HandheldCompanion/Devices/ASUS/ROGAlly.cs
index 544dff1d0..b9ba72fcf 100644
--- a/HandheldCompanion/Devices/ASUS/ROGAlly.cs
+++ b/HandheldCompanion/Devices/ASUS/ROGAlly.cs
@@ -504,10 +504,10 @@ private void HandleEvent(byte key)
case 56: // Armory crate: Click
case 166: // Command center: Click
{
- Task.Factory.StartNew(async () =>
+ Task.Run(async () =>
{
KeyPress(button);
- await Task.Delay(KeyPressDelay);
+ await Task.Delay(KeyPressDelay).ConfigureAwait(false); // Avoid blocking the synchronization context
KeyRelease(button);
});
}
diff --git a/HandheldCompanion/Devices/MSI/ClawA1M.cs b/HandheldCompanion/Devices/MSI/ClawA1M.cs
index 21175a797..98287290a 100644
--- a/HandheldCompanion/Devices/MSI/ClawA1M.cs
+++ b/HandheldCompanion/Devices/MSI/ClawA1M.cs
@@ -213,10 +213,10 @@ private void onWMIEvent(object sender, EventArrivedEventArgs e)
case WMIEventCode.LaunchMcxMainUI: // MSI Claw: Click
case WMIEventCode.LaunchMcxOSD: // Quick Settings: Click
{
- Task.Factory.StartNew(async () =>
+ Task.Run(async () =>
{
KeyPress(button);
- await Task.Delay(KeyPressDelay);
+ await Task.Delay(KeyPressDelay).ConfigureAwait(false); // Avoid blocking the synchronization context
KeyRelease(button);
});
}
diff --git a/HandheldCompanion/HandheldCompanion.csproj b/HandheldCompanion/HandheldCompanion.csproj
index 45ccedd6d..ddb7b6d18 100644
--- a/HandheldCompanion/HandheldCompanion.csproj
+++ b/HandheldCompanion/HandheldCompanion.csproj
@@ -12,11 +12,12 @@
HandheldCompanion.App
$(SolutionDir)bin\$(Configuration)
Resources\icon.ico
- 0.22.0.2
+ 0.22.0.3
app.manifest
AnyCPU;x64;x86
true
Always
+ true
diff --git a/HandheldCompanion/Inputs/AxisState.cs b/HandheldCompanion/Inputs/AxisState.cs
index 59bc4c904..0e4e9c51e 100644
--- a/HandheldCompanion/Inputs/AxisState.cs
+++ b/HandheldCompanion/Inputs/AxisState.cs
@@ -1,5 +1,6 @@
using Newtonsoft.Json;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
@@ -8,9 +9,9 @@ namespace HandheldCompanion.Inputs;
[Serializable]
public partial class AxisState : ICloneable
{
- public Dictionary State = new();
+ public ConcurrentDictionary State = new();
- public AxisState(Dictionary State)
+ public AxisState(ConcurrentDictionary State)
{
foreach (var state in State)
this[state.Key] = state.Value;
@@ -24,7 +25,7 @@ public AxisState()
public short this[AxisFlags axis]
{
- get => !State.ContainsKey(axis) ? (short)0 : State[axis];
+ get => State.TryGetValue(axis, out short value) ? value : (short)0;
set => State[axis] = value;
}
@@ -77,8 +78,8 @@ public override bool Equals(object obj)
return false;
}
- public static bool EqualsWithValues(Dictionary obj1,
- Dictionary obj2)
+ public static bool EqualsWithValues(ConcurrentDictionary obj1,
+ ConcurrentDictionary obj2)
{
if (obj1.Count != obj2.Count) return false;
{
diff --git a/HandheldCompanion/Inputs/ButtonState.cs b/HandheldCompanion/Inputs/ButtonState.cs
index 6372cb2f5..d840502ff 100644
--- a/HandheldCompanion/Inputs/ButtonState.cs
+++ b/HandheldCompanion/Inputs/ButtonState.cs
@@ -1,5 +1,6 @@
using Newtonsoft.Json;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
@@ -8,9 +9,9 @@ namespace HandheldCompanion.Inputs;
[Serializable]
public partial class ButtonState : ICloneable
{
- public Dictionary State = new();
+ public ConcurrentDictionary State = new();
- public ButtonState(Dictionary State)
+ public ButtonState(ConcurrentDictionary State)
{
foreach (var state in State)
this[state.Key] = state.Value;
@@ -24,7 +25,7 @@ public ButtonState()
public bool this[ButtonFlags button]
{
- get => State.ContainsKey(button) && State[button];
+ get => State.TryGetValue(button, out bool value) && value;
set => State[button] = value;
}
diff --git a/HandheldCompanion/Managers/ControllerManager.cs b/HandheldCompanion/Managers/ControllerManager.cs
index d6fe6c96f..56c585bad 100644
--- a/HandheldCompanion/Managers/ControllerManager.cs
+++ b/HandheldCompanion/Managers/ControllerManager.cs
@@ -413,7 +413,7 @@ private static async void HidDeviceArrived(PnPDetails details, Guid InterfaceGui
}
catch
{
- await Task.Delay(1000);
+ await Task.Delay(1000).ConfigureAwait(false); // Avoid blocking the synchronization context
}
}
@@ -600,7 +600,7 @@ private static async void HidDeviceArrived(PnPDetails details, Guid InterfaceGui
}
while (!controller.IsReady && controller.IsConnected())
- await Task.Delay(250);
+ await Task.Delay(250).ConfigureAwait(false); // Avoid blocking the synchronization context
// set (un)busy
controller.IsBusy = false;
@@ -640,7 +640,7 @@ private static async void HidDeviceRemoved(PnPDetails details, Guid IntefaceGuid
if (Controllers.TryGetValue(details.baseContainerDeviceInstanceId, out controller))
break;
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
}
if (controller is null)
@@ -693,7 +693,7 @@ private static void watchdogThreadLoop(object? obj)
foreach (XInputController xInputController in Controllers.Values.Where(c => c.Details is not null && c.Details.isXInput))
{
- byte UserIndex = DeviceManager.GetXInputIndexAsync(xInputController.Details.baseContainerDevicePath);
+ byte UserIndex = DeviceManager.GetXInputIndexAsync(xInputController.Details.baseContainerDevicePath, true);
// controller is not ready yet
if (UserIndex == byte.MaxValue)
@@ -882,7 +882,7 @@ private static async void XUsbDeviceArrived(PnPDetails details, Guid IntefaceGui
}
while (!controller.IsReady && controller.IsConnected())
- await Task.Delay(250);
+ await Task.Delay(250).ConfigureAwait(false); // Avoid blocking the synchronization context
// set (un)busy
controller.IsBusy = false;
@@ -932,7 +932,7 @@ private static async void XUsbDeviceRemoved(PnPDetails details, Guid IntefaceGui
if (Controllers.TryGetValue(details.baseContainerDeviceInstanceId, out controller))
break;
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
}
if (controller is null)
diff --git a/HandheldCompanion/Managers/DeviceManager.cs b/HandheldCompanion/Managers/DeviceManager.cs
index 5a09bbccc..0f2dd0830 100644
--- a/HandheldCompanion/Managers/DeviceManager.cs
+++ b/HandheldCompanion/Managers/DeviceManager.cs
@@ -501,7 +501,7 @@ private static void XUsbDevice_DeviceRemoved(DeviceEventArgs obj)
while (DateTime.Now < timeout && deviceEx is null)
{
deviceEx = FindDevice(InstanceId);
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
}
if (deviceEx is null)
@@ -533,7 +533,7 @@ private static void XUsbDevice_DeviceArrived(DeviceEventArgs obj)
while (DateTime.Now < timeout && deviceEx is null)
{
deviceEx = FindDevice(InstanceId);
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
}
if (deviceEx is not null && deviceEx.isGaming)
@@ -542,7 +542,7 @@ private static void XUsbDevice_DeviceArrived(DeviceEventArgs obj)
deviceEx.baseContainerDevicePath = obj.SymLink;
if (deviceEx.EnumeratorName.Equals("USB"))
- deviceEx.XInputUserIndex = GetXInputIndexAsync(obj.SymLink);
+ deviceEx.XInputUserIndex = GetXInputIndexAsync(obj.SymLink, false);
if (deviceEx.XInputUserIndex == byte.MaxValue)
deviceEx.XInputDeviceIdx = GetDeviceIndex(obj.SymLink);
@@ -576,7 +576,7 @@ private static void HidDevice_DeviceRemoved(DeviceEventArgs obj)
while (DateTime.Now < timeout && deviceEx is null)
{
deviceEx = FindDevice(InstanceId);
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
}
// skip if XInput
@@ -610,7 +610,7 @@ private static void HidDevice_DeviceArrived(DeviceEventArgs obj)
while (DateTime.Now < timeout && deviceEx is null)
{
deviceEx = GetDetails(obj.SymLink);
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
}
// skip if XInput
@@ -662,7 +662,7 @@ private static void UsbDevice_DeviceArrived(DeviceEventArgs obj)
}
}
- public static byte GetXInputIndexAsync(string SymLink)
+ public static byte GetXInputIndexAsync(string SymLink, bool UIthread)
{
byte ledState = 0;
@@ -684,7 +684,7 @@ public static byte GetXInputIndexAsync(string SymLink)
ledState = ledStateData[2];
}
- Task.Delay(1000);
+ Task.Delay(1000).ConfigureAwait(UIthread);
}
return XINPUT_LED_TO_PORT_MAP[ledState];
diff --git a/HandheldCompanion/Managers/DynamicLightingManager.cs b/HandheldCompanion/Managers/DynamicLightingManager.cs
index 07e248be6..8823b7e7a 100644
--- a/HandheldCompanion/Managers/DynamicLightingManager.cs
+++ b/HandheldCompanion/Managers/DynamicLightingManager.cs
@@ -143,7 +143,7 @@ private static async void InitializeDirect3DDevice()
if (ex.ResultCode == ResultCode.DeviceLost)
{
while (device is not null && device.TestCooperativeLevel() == ResultCode.DeviceLost)
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
// Recreate the device and resources
ReleaseDirect3DDevice();
diff --git a/HandheldCompanion/Managers/GPUManager.cs b/HandheldCompanion/Managers/GPUManager.cs
index ab4372e3b..9c6af5d39 100644
--- a/HandheldCompanion/Managers/GPUManager.cs
+++ b/HandheldCompanion/Managers/GPUManager.cs
@@ -185,7 +185,7 @@ private static void GPUDisconnect(GPU GPU)
private static void MultimediaManager_PrimaryScreenChanged(DesktopScreen screen)
{
AdapterInformation key = DisplayGPU.Keys.FirstOrDefault(GPU => GPU.Details.DeviceName == screen.screen.DeviceName);
- if (DisplayGPU.TryGetValue(key, out GPU gpu))
+ if (key is not null && DisplayGPU.TryGetValue(key, out GPU gpu))
{
LogManager.LogError("Retrieved DisplayAdapter: {0} for screen: {1}", gpu.ToString(), screen.screen.DeviceName);
diff --git a/HandheldCompanion/Managers/HotkeysManager.cs b/HandheldCompanion/Managers/HotkeysManager.cs
index 4443b660c..44c83db1a 100644
--- a/HandheldCompanion/Managers/HotkeysManager.cs
+++ b/HandheldCompanion/Managers/HotkeysManager.cs
@@ -46,8 +46,9 @@ public static async Task Start()
ProcessHotkey(fileName);
// get latest known version
+ // if last time HC version used old hotkey engine and user has no defined hotkeys
Version LastVersion = Version.Parse(SettingsManager.GetString("LastVersion"));
- if (LastVersion < Version.Parse(Settings.VersionHotkeyManager))
+ if (LastVersion < Version.Parse(Settings.VersionHotkeyManager) && hotkeys.Count == 0)
{
// create a few defaults hotkeys
if (!hotkeys.Values.Any(hotkey => hotkey.command is QuickToolsCommands quickToolsCommands))
@@ -152,6 +153,12 @@ private static void ProcessHotkey(string fileName)
// too old
throw new Exception("Hotkey is outdated.");
}
+ else if (version <= Version.Parse("0.22.0.2"))
+ {
+ outputraw = outputraw.Replace(
+ "\"System.Collections.Generic.Dictionary`2[[HandheldCompanion.Inputs.ButtonFlags, HandheldCompanion],[System.Boolean, System.Private.CoreLib]], System.Private.CoreLib\"",
+ "\"System.Collections.Concurrent.ConcurrentDictionary`2[[HandheldCompanion.Inputs.ButtonFlags, HandheldCompanion],[System.Boolean, System.Private.CoreLib]], System.Collections.Concurrent\"");
+ }
else if (version <= Version.Parse("0.21.8.0"))
{
outputraw = outputraw.Replace(
@@ -178,9 +185,16 @@ private static void ProcessHotkey(string fileName)
if (hotkey is null)
return;
- if (CheckAvailableButtonFlag(hotkey.ButtonFlags))
+ // check if button flags is already used
+ if (IsUsedButtonFlag(hotkey.ButtonFlags))
+ {
+ // update button flags
hotkey.ButtonFlags = GetAvailableButtonFlag();
+ // Delete the old file
+ File.Delete(fileName);
+ }
+
if (hotkey.ButtonFlags == ButtonFlags.None)
return;
@@ -281,16 +295,19 @@ private static void ProcessHotkey(string fileName)
var isPinned = (bool)dictionary["IsPinned"];
hotkey.IsPinned = isPinned;
- // Common ButtonFlags check
- if (CheckAvailableButtonFlag(hotkey.ButtonFlags))
+ // check if button flags is already used
+ if (IsUsedButtonFlag(hotkey.ButtonFlags))
+ {
+ // update button flags
hotkey.ButtonFlags = GetAvailableButtonFlag();
+ // Delete the old file
+ File.Delete(fileName);
+ }
+
if (hotkey.ButtonFlags == ButtonFlags.None)
return null;
- // Delete the old file
- File.Delete(fileName);
-
// Save new hotkey json
SerializeHotkey(hotkey);
@@ -301,7 +318,7 @@ private static void ProcessHotkey(string fileName)
return null;
}
- private static bool CheckAvailableButtonFlag(ButtonFlags buttonFlags)
+ private static bool IsUsedButtonFlag(ButtonFlags buttonFlags)
{
HashSet usedFlags = hotkeys.Values.Select(h => h.ButtonFlags).ToHashSet();
return usedFlags.Contains(buttonFlags);
diff --git a/HandheldCompanion/Managers/PerformanceManager.cs b/HandheldCompanion/Managers/PerformanceManager.cs
index d038e0735..ec1599564 100644
--- a/HandheldCompanion/Managers/PerformanceManager.cs
+++ b/HandheldCompanion/Managers/PerformanceManager.cs
@@ -664,7 +664,7 @@ private static async void tdpWatchdog_Elapsed(object? sender, ElapsedEventArgs e
if (ReadTDP != TDP || forcedUpdate)
RequestTDP((PowerType)idx, TDP, true);
- await Task.Delay(20);
+ await Task.Delay(20).ConfigureAwait(false); // Avoid blocking the synchronization context
}
// are we done ?
@@ -858,7 +858,7 @@ private static async void RequestTDP(double[] values, bool immediate = false)
for (int idx = (int)PowerType.Slow; idx <= (int)PowerType.Fast; idx++)
{
RequestTDP((PowerType)idx, values[idx], immediate);
- await Task.Delay(20);
+ await Task.Delay(20).ConfigureAwait(false); // Avoid blocking the synchronization context
}
}
diff --git a/HandheldCompanion/Managers/ProcessManager.cs b/HandheldCompanion/Managers/ProcessManager.cs
index 54d3864ee..22a50109e 100644
--- a/HandheldCompanion/Managers/ProcessManager.cs
+++ b/HandheldCompanion/Managers/ProcessManager.cs
@@ -510,7 +510,7 @@ public static async void ResumeProcess(ProcessEx processEx)
ProcessUtils.NtResumeProcess(process.Handle);
});
- await Task.Delay(500);
+ await Task.Delay(500).ConfigureAwait(false); // Avoid blocking the synchronization context
// restore process windows
foreach (ProcessWindow processWindow in processEx.ProcessWindows.Values)
@@ -527,7 +527,7 @@ public static async void SuspendProcess(ProcessEx processEx)
foreach (ProcessWindow processWindow in processEx.ProcessWindows.Values)
ProcessUtils.ShowWindow(processWindow.Hwnd, (int)ProcessUtils.ShowWindowCommands.Hide);
- await Task.Delay(500);
+ await Task.Delay(500).ConfigureAwait(false); // Avoid blocking the synchronization context
ProcessUtils.NtSuspendProcess(processEx.Process.Handle);
diff --git a/HandheldCompanion/Managers/ProfileManager.cs b/HandheldCompanion/Managers/ProfileManager.cs
index 3bc6f9432..268301ae7 100644
--- a/HandheldCompanion/Managers/ProfileManager.cs
+++ b/HandheldCompanion/Managers/ProfileManager.cs
@@ -517,6 +517,12 @@ private static void ProcessProfile(string fileName, bool imported = false)
{
// too old
throw new Exception("Profile is outdated.");
+ }
+ else if (version <= Version.Parse("0.22.0.2"))
+ {
+ outputraw = outputraw.Replace(
+ "\"System.Collections.Generic.Dictionary`2[[HandheldCompanion.Inputs.ButtonFlags, HandheldCompanion],[System.Boolean, System.Private.CoreLib]], System.Private.CoreLib\"",
+ "\"System.Collections.Concurrent.ConcurrentDictionary`2[[HandheldCompanion.Inputs.ButtonFlags, HandheldCompanion],[System.Boolean, System.Private.CoreLib]], System.Collections.Concurrent\"");
}
else if (version <= Version.Parse("0.21.7.0"))
{
diff --git a/HandheldCompanion/Managers/SensorsManager.cs b/HandheldCompanion/Managers/SensorsManager.cs
index 35e4b6cc6..14b0bf60d 100644
--- a/HandheldCompanion/Managers/SensorsManager.cs
+++ b/HandheldCompanion/Managers/SensorsManager.cs
@@ -293,7 +293,7 @@ public static async void Calibrate(Dictionary gamepadMotion
for (int i = 4; i > 0; i--)
{
dialog.UpdateContent($"Calibration will start in {i} seconds.");
- await Task.Delay(1000);
+ await Task.Delay(1000); // Captures synchronization context
}
foreach (GamepadMotion gamepadMotion in gamepadMotions.Values)
@@ -306,7 +306,7 @@ public static async void Calibrate(Dictionary gamepadMotion
// wait until device is steady
DateTime timeout = DateTime.Now.Add(TimeSpan.FromSeconds(3));
while (DateTime.Now < timeout && !gamepadMotion.GetAutoCalibrationIsSteady())
- await Task.Delay(100);
+ await Task.Delay(100); // Captures synchronization context
// device is either too shaky or stalled
bool IsSteady = gamepadMotion.GetAutoCalibrationIsSteady();
@@ -321,7 +321,7 @@ public static async void Calibrate(Dictionary gamepadMotion
dialog.UpdateContent($"Calibration device is silent or unsteady.");
// wait a bit
- await Task.Delay(2000);
+ await Task.Delay(2000); // Captures synchronization context
break;
}
@@ -332,7 +332,7 @@ public static async void Calibrate(Dictionary gamepadMotion
// give gamepad motion 3 seconds to get values
timeout = DateTime.Now.Add(TimeSpan.FromSeconds(3));
while (DateTime.Now < timeout)
- await Task.Delay(100);
+ await Task.Delay(100); // Captures synchronization context
// halt continuous calibration
gamepadMotion.PauseContinuousCalibration();
@@ -377,7 +377,7 @@ public static async void Calibrate(Dictionary gamepadMotion
dialog.UpdateContent($"Calibration succeeded: stationary sensor noise recorded. Drift correction found. Confidence: {confidence * 100.0f}%");
// wait a bit
- await Task.Delay(2000);
+ await Task.Delay(2000); // Captures synchronization context
}
Close:
diff --git a/HandheldCompanion/Managers/ToastManager.cs b/HandheldCompanion/Managers/ToastManager.cs
index 113661448..6ed4b5ad9 100644
--- a/HandheldCompanion/Managers/ToastManager.cs
+++ b/HandheldCompanion/Managers/ToastManager.cs
@@ -73,6 +73,7 @@ public static void SendToast(string title, string content = "", string img = "To
}
});
+ ToastThread.IsBackground = true;
ToastThread.Start();
}
diff --git a/HandheldCompanion/Managers/VirtualManager.cs b/HandheldCompanion/Managers/VirtualManager.cs
index 8cd354068..4615d7573 100644
--- a/HandheldCompanion/Managers/VirtualManager.cs
+++ b/HandheldCompanion/Managers/VirtualManager.cs
@@ -164,7 +164,7 @@ private static async void ProfileManager_Applied(Profile profile, UpdateSource s
return;
while (ControllerManager.managerStatus == ControllerManagerStatus.Busy)
- await Task.Delay(1000);
+ await Task.Delay(1000).ConfigureAwait(false); // Avoid blocking the synchronization context
switch (profile.HID)
{
@@ -184,7 +184,7 @@ private static async void ProfileManager_Discarded(Profile profile, bool swapped
return;
while (ControllerManager.managerStatus == ControllerManagerStatus.Busy)
- await Task.Delay(1000);
+ await Task.Delay(1000).ConfigureAwait(false); // Avoid blocking the synchronization context
// restore default HID mode
if (profile.HID != HIDmode.NotSelected)
diff --git a/HandheldCompanion/Platforms/LibreHardwareMonitor.cs b/HandheldCompanion/Platforms/LibreHardwareMonitor.cs
index 2821ce7ee..5971bcc8e 100644
--- a/HandheldCompanion/Platforms/LibreHardwareMonitor.cs
+++ b/HandheldCompanion/Platforms/LibreHardwareMonitor.cs
@@ -8,7 +8,6 @@ namespace HandheldCompanion.Platforms
public class LibreHardwareMonitor : IPlatform
{
private Computer computer;
- private string ProductName;
private Timer updateTimer;
private int updateInterval = 1000;
@@ -30,8 +29,6 @@ public LibreHardwareMonitor()
Name = "LibreHardwareMonitor";
IsInstalled = true;
- ProductName = MotherboardInfo.Product;
-
// watchdog to populate sensors
updateTimer = new Timer(updateInterval) { Enabled = false };
updateTimer.Elapsed += UpdateTimer_Elapsed;
@@ -175,15 +172,6 @@ private void HandleCPU_Temperatur(ISensor sensor)
if (sensor.Name == "CPU Package" || sensor.Name == "Core (Tctl/Tdie)")
{
CPUTemperatur = (float)sensor.Value;
-
- // dirty
- switch (ProductName)
- {
- case "Galileo":
- CPUTemperatur /= 2.0f;
- break;
- }
-
CPUTemperatureChanged?.Invoke(CPUTemperatur);
}
}
diff --git a/HandheldCompanion/Platforms/RTSS.cs b/HandheldCompanion/Platforms/RTSS.cs
index 1837fb48c..f199f6484 100644
--- a/HandheldCompanion/Platforms/RTSS.cs
+++ b/HandheldCompanion/Platforms/RTSS.cs
@@ -194,7 +194,7 @@ private async void ProcessManager_ForegroundChanged(ProcessEx? processEx, Proces
}
catch { }
- await Task.Delay(1000);
+ await Task.Delay(1000).ConfigureAwait(false); // Avoid blocking the synchronization context
} while (appEntry is null && foregroundId == ProcessId && KeepAlive);
if (appEntry is null)
diff --git a/HandheldCompanion/Platforms/Steam.cs b/HandheldCompanion/Platforms/Steam.cs
index 0f02daf72..2a8bef03e 100644
--- a/HandheldCompanion/Platforms/Steam.cs
+++ b/HandheldCompanion/Platforms/Steam.cs
@@ -97,7 +97,7 @@ private void ActiveUserWatcher_RegistryChanged(object? sender, RegistryChangedEv
private async void ActiveFileWatch_Changed()
{
- await Task.Delay(1000);
+ await Task.Delay(1000).ConfigureAwait(false); // Avoid blocking the synchronization context
int SteamInput = GetUseSteamControllerConfigValue();
base.SettingsValueChaned("UseSteamControllerConfig", SteamInput);
}
diff --git a/HandheldCompanion/Sensors/SerialUSBIMU.cs b/HandheldCompanion/Sensors/SerialUSBIMU.cs
index 5aec3a058..a0a8817f0 100644
--- a/HandheldCompanion/Sensors/SerialUSBIMU.cs
+++ b/HandheldCompanion/Sensors/SerialUSBIMU.cs
@@ -143,7 +143,7 @@ public async void Open()
tentative++;
LogManager.LogError("{0} could not connect. Attempt: {1} out of {2}", serial.ToString(), tentative,
maxTentative);
- await Task.Delay(500);
+ await Task.Delay(500).ConfigureAwait(false); // Avoid blocking the synchronization context
}
}
@@ -232,7 +232,7 @@ private async void DataReceivedHandler(object sender, SerialDataReceivedEventArg
return;
}
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
// Address write function code register = 0xA4, 0x03
// Register to read/write save settings 0x05
diff --git a/HandheldCompanion/UI/UIGamepad.cs b/HandheldCompanion/UI/UIGamepad.cs
index 71a5a5af6..69273f304 100644
--- a/HandheldCompanion/UI/UIGamepad.cs
+++ b/HandheldCompanion/UI/UIGamepad.cs
@@ -145,6 +145,7 @@ private void _currentWindow_GotFocus(object sender, RoutedEventArgs e)
_focused[window] = false;
// raise event
+
LostFocus?.Invoke(window);
}
}
@@ -620,8 +621,7 @@ private void InputsUpdated(ControllerState controllerState)
{
// get the associated ComboBox
comboBox = ItemsControl.ItemsControlFromItemContainer(focusedElement) as ComboBox;
-
- if (comboBox.IsDropDownOpen && comboBoxItem.IsEnabled)
+ if (comboBox is not null && comboBox.IsDropDownOpen && comboBoxItem.IsEnabled)
{
int idx = comboBox.Items.IndexOf(comboBoxItem);
if (idx == -1)
@@ -719,8 +719,8 @@ private void InputsUpdated(ControllerState controllerState)
case "ComboBoxItem":
{
- ComboBox comboBox = ItemsControl.ItemsControlFromItemContainer(focusedElement) as ComboBox;
- comboBox.IsDropDownOpen = false;
+ if (ItemsControl.ItemsControlFromItemContainer(focusedElement) is ComboBox comboBox)
+ comboBox.IsDropDownOpen = false;
}
return;
@@ -876,45 +876,47 @@ private void InputsUpdated(ControllerState controllerState)
{
if (focusedElement is ComboBoxItem comboBoxItem)
{
- ComboBox comboBox = ItemsControl.ItemsControlFromItemContainer(focusedElement) as ComboBox;
- if (comboBox.IsDropDownOpen)
+ if (ItemsControl.ItemsControlFromItemContainer(focusedElement) is ComboBox comboBox)
{
- int idx = comboBox.Items.IndexOf(comboBoxItem);
- if (idx == -1)
- idx = comboBox.Items.IndexOf(comboBoxItem.Content);
-
- while (true) // Loop to skip disabled items
+ if (comboBox.IsDropDownOpen)
{
- switch (direction)
+ int idx = comboBox.Items.IndexOf(comboBoxItem);
+ if (idx == -1)
+ idx = comboBox.Items.IndexOf(comboBoxItem.Content);
+
+ while (true) // Loop to skip disabled items
{
- case WPFUtils.Direction.Up:
- idx--;
+ switch (direction)
+ {
+ case WPFUtils.Direction.Up:
+ idx--;
+ break;
+
+ case WPFUtils.Direction.Down:
+ idx++;
+ break;
+ }
+
+ // Ensure index is within bounds
+ if (idx < 0 || idx >= comboBox.Items.Count)
+ {
+ // We've reached the top or bottom, so stop the loop
break;
+ }
- case WPFUtils.Direction.Down:
- idx++;
- break;
- }
+ // Get the ComboBoxItem at the new index
+ focusedElement = (ComboBoxItem)comboBox.ItemContainerGenerator.ContainerFromIndex(idx);
- // Ensure index is within bounds
- if (idx < 0 || idx >= comboBox.Items.Count)
- {
- // We've reached the top or bottom, so stop the loop
- break;
- }
-
- // Get the ComboBoxItem at the new index
- focusedElement = (ComboBoxItem)comboBox.ItemContainerGenerator.ContainerFromIndex(idx);
+ // Check if the focused element is enabled
+ if (focusedElement != null && focusedElement.IsEnabled)
+ {
+ // If the element is enabled, focus it and break out of the loop
+ Focus(focusedElement, comboBox, true);
+ break;
+ }
- // Check if the focused element is enabled
- if (focusedElement != null && focusedElement.IsEnabled)
- {
- // If the element is enabled, focus it and break out of the loop
- Focus(focusedElement, comboBox, true);
- break;
+ // If the element is not enabled, continue to the next item in the loop
}
-
- // If the element is not enabled, continue to the next item in the loop
}
}
return;
diff --git a/HandheldCompanion/UI/UISounds.cs b/HandheldCompanion/UI/UISounds.cs
index e51a82875..76fed7394 100644
--- a/HandheldCompanion/UI/UISounds.cs
+++ b/HandheldCompanion/UI/UISounds.cs
@@ -62,7 +62,7 @@ private static async void SoundTimer_Elapsed(object? sender, ElapsedEventArgs e)
// wait here until playback stops or should stop
while (waveOut.PlaybackState == PlaybackState.Playing)
- await Task.Delay(1);
+ await Task.Delay(1).ConfigureAwait(false); // Avoid blocking the synchronization context
}
}
}
diff --git a/HandheldCompanion/ViewModels/HotkeyViewModel.cs b/HandheldCompanion/ViewModels/HotkeyViewModel.cs
index 5c89699cf..04abbc0ab 100644
--- a/HandheldCompanion/ViewModels/HotkeyViewModel.cs
+++ b/HandheldCompanion/ViewModels/HotkeyViewModel.cs
@@ -466,7 +466,7 @@ public HotkeyViewModel(Hotkey hotkey)
{
// todo: improve me
// we need to make sure the key that was pressed to trigger the listening event isn't recorded
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
InputsManager.StartListening(hotkey.ButtonFlags, InputsChordTarget.Input);
});
@@ -485,7 +485,7 @@ public HotkeyViewModel(Hotkey hotkey)
{
// todo: improve me
// we need to make sure the key that was pressed to trigger the listening event isn't recorded
- await Task.Delay(100);
+ await Task.Delay(100).ConfigureAwait(false); // Avoid blocking the synchronization context
InputsManager.StartListening(hotkey.ButtonFlags, InputsChordTarget.Output);
});
diff --git a/HandheldCompanion/Views/Pages/ControllerPage.xaml.cs b/HandheldCompanion/Views/Pages/ControllerPage.xaml.cs
index 28faaad14..53404c8de 100644
--- a/HandheldCompanion/Views/Pages/ControllerPage.xaml.cs
+++ b/HandheldCompanion/Views/Pages/ControllerPage.xaml.cs
@@ -151,7 +151,7 @@ private void ControllerManager_Working(ControllerManagerStatus status, int attem
case ControllerManagerStatus.Succeeded:
{
dialog.UpdateContent(Properties.Resources.ControllerPage_ControllerManagment_Done);
- await Task.Delay(2000);
+ await Task.Delay(2000); // Captures synchronization context
dialog.Hide();
}
break;
diff --git a/HandheldCompanion/Views/Pages/SettingsPage.xaml.cs b/HandheldCompanion/Views/Pages/SettingsPage.xaml.cs
index 9c9cb8f82..12f82ed37 100644
--- a/HandheldCompanion/Views/Pages/SettingsPage.xaml.cs
+++ b/HandheldCompanion/Views/Pages/SettingsPage.xaml.cs
@@ -410,7 +410,10 @@ private void UpdateManager_Updated(UpdateStatus status, UpdateFile updateFile, o
private void B_CheckUpdate_Click(object? sender, RoutedEventArgs? e)
{
- new Thread(() => { UpdateManager.StartProcess(); }).Start();
+ new Thread(() =>
+ {
+ UpdateManager.StartProcess();
+ }).Start();
}
private void cB_Language_SelectionChanged(object? sender, SelectionChangedEventArgs? e)
@@ -579,8 +582,8 @@ private void cB_QuickToolsDevicePath_SelectionChanged(object sender, SelectionCh
if (cB_QuickToolsDevicePath.SelectedItem is DesktopScreen desktopScreen)
{
- SettingsManager.SetProperty("QuickToolsDevicePath", desktopScreen.DevicePath);
SettingsManager.SetProperty("QuickToolsDeviceName", desktopScreen.FriendlyName);
+ SettingsManager.SetProperty("QuickToolsDevicePath", desktopScreen.DevicePath);
}
}
}
\ No newline at end of file
diff --git a/HandheldCompanion/Views/SplashScreen.xaml b/HandheldCompanion/Views/SplashScreen.xaml
index 64bd50c85..2e2aae93c 100644
--- a/HandheldCompanion/Views/SplashScreen.xaml
+++ b/HandheldCompanion/Views/SplashScreen.xaml
@@ -12,8 +12,6 @@
Height="450"
ui:ThemeManager.IsThemeAware="True"
ui:WindowHelper.SystemBackdropType="Mica"
- ui:WindowHelper.UseAcrylicBackdrop="True"
- ui:WindowHelper.UseAeroBackdrop="True"
ui:WindowHelper.UseModernWindowStyle="True"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
@@ -30,10 +28,7 @@
Text="HC"
TextAlignment="Center" />
-
-
-
-
+
+ Background="Red"
+ Foreground="White" />
diff --git a/HandheldCompanion/Views/Windows/MainWindow.xaml.cs b/HandheldCompanion/Views/Windows/MainWindow.xaml.cs
index 16670ff12..cb3a9afcf 100644
--- a/HandheldCompanion/Views/Windows/MainWindow.xaml.cs
+++ b/HandheldCompanion/Views/Windows/MainWindow.xaml.cs
@@ -92,14 +92,11 @@ public MainWindow(FileVersionInfo _fileVersionInfo, Assembly CurrentAssembly)
// get last version
Version LastVersion = Version.Parse(SettingsManager.GetString("LastVersion"));
- bool FirstStart = LastVersion == Version.Parse("0.0.0.0");
- if (FirstStart)
- {
+ bool FirstStart = LastVersion == Version.Parse("0.0.0.0");
#if !DEBUG
- SplashScreen.Show();
+ SplashScreen.Show();
#endif
- }
-
+
InitializeComponent();
this.Tag = "MainWindow";
@@ -522,7 +519,7 @@ private async void OnSystemStatusChanged(SystemManager.SystemStatus status, Syst
{
// when device resumes from sleep
// use device-specific delay
- await Task.Delay(CurrentDevice.ResumeDelay);
+ await Task.Delay(CurrentDevice.ResumeDelay); // Captures synchronization context
// resume manager(s)
InputsManager.Start();
@@ -554,7 +551,7 @@ private async void OnSystemStatusChanged(SystemManager.SystemStatus status, Syst
// when device goes to sleep
// suspend manager(s)
VirtualManager.Suspend(true);
- await Task.Delay(CurrentDevice.ResumeDelay);
+ await Task.Delay(CurrentDevice.ResumeDelay); // Captures synchronization context
TimerManager.Stop();
SensorsManager.Stop();
diff --git a/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml.cs b/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml.cs
index f0d4bbcc5..53cb415a1 100644
--- a/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml.cs
+++ b/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml.cs
@@ -230,6 +230,8 @@ private void UpdateLocation()
// Find the corresponding Screen object
targetScreen = Screen.AllScreens.FirstOrDefault(screen => screen.DeviceName.Equals(friendlyScreen.screen.DeviceName));
+ if (targetScreen is null)
+ return;
// UI thread
Application.Current.Dispatcher.Invoke(() =>
diff --git a/HandheldCompanion/XInputPlus/XInputPlus.cs b/HandheldCompanion/XInputPlus/XInputPlus.cs
index cd552ae2f..0d7eb50f1 100644
--- a/HandheldCompanion/XInputPlus/XInputPlus.cs
+++ b/HandheldCompanion/XInputPlus/XInputPlus.cs
@@ -146,7 +146,7 @@ private static async void ProcessManager_ProcessStarted(ProcessEx processEx, boo
if (attempt == 10)
return;
- await Task.Delay(500);
+ await Task.Delay(500).ConfigureAwait(false); // Avoid blocking the synchronization context
}
bool x64bit = Is64bitProcess(processEx.Process);
diff --git a/hidapi.net/HidDevice.cs b/hidapi.net/HidDevice.cs
index e3d9db31e..81f0355ce 100644
--- a/hidapi.net/HidDevice.cs
+++ b/hidapi.net/HidDevice.cs
@@ -86,7 +86,7 @@ public byte[] Read(int timeout = 100)
}
public Task ReadAsync(byte[] data) => Task.Run(() => Read(data));
- public int Read(byte[] buffer, int timeout = 100)
+ public int Read(byte[] buffer, int timeout = 20)
{
if (buffer.Length < _inputBufferLen)
throw new ArgumentException("Buffer length is lower than input buffer length.");
@@ -161,7 +161,8 @@ public void BeginRead()
_reading = true;
_readThread = new Thread(new ThreadStart(ReadLoop))
{
- IsBackground = true
+ IsBackground = true,
+ Priority = ThreadPriority.Highest
};
_readThread.Start();
}
diff --git a/hidapi.net/hidapi.dll b/hidapi.net/hidapi.dll
index 02145e5d0..4eded6eeb 100644
Binary files a/hidapi.net/hidapi.dll and b/hidapi.net/hidapi.dll differ
diff --git a/steam-hidapi.net/GordonController.cs b/steam-hidapi.net/GordonController.cs
index 77036adba..bcc79a666 100644
--- a/steam-hidapi.net/GordonController.cs
+++ b/steam-hidapi.net/GordonController.cs
@@ -20,7 +20,11 @@ public GordonController(ushort vid, ushort pid, short index) : base(vid, pid, in
{
_hidDevice = new HidDevice(_vid, _pid, 64, index)
{
- OnInputReceived = input => Task.Run(() => OnInputReceived(input))
+ OnInputReceived = input =>
+ {
+ OnInputReceived(input);
+ return Task.CompletedTask;
+ }
};
}
diff --git a/steam-hidapi.net/NeptuneController.cs b/steam-hidapi.net/NeptuneController.cs
index 017a5a73b..56201ede6 100644
--- a/steam-hidapi.net/NeptuneController.cs
+++ b/steam-hidapi.net/NeptuneController.cs
@@ -18,7 +18,11 @@ public NeptuneController(ushort vid, ushort pid, short index) : base(vid, pid, i
{
_hidDevice = new HidDevice(_vid, _pid, 64, index)
{
- OnInputReceived = input => Task.Run(() => OnInputReceived(input))
+ OnInputReceived = input =>
+ {
+ OnInputReceived(input);
+ return Task.CompletedTask;
+ }
};
}
@@ -76,7 +80,7 @@ internal async void ConfigureLoop()
while (_active)
{
SetLizardMode(_lizard);
- await Task.Delay(1000);
+ await Task.Delay(1000).ConfigureAwait(false);
}
}