mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
Fix some issues
This commit is contained in:
@@ -181,7 +181,7 @@ namespace PowerDisplay.Common.Drivers.DDC
|
|||||||
if (DdcCiNative.TryGetVCPFeature(monitor.Handle, VcpCodeSelectColorPreset, out uint current, out uint max))
|
if (DdcCiNative.TryGetVCPFeature(monitor.Handle, VcpCodeSelectColorPreset, out uint current, out uint max))
|
||||||
{
|
{
|
||||||
var presetName = VcpValueNames.GetFormattedName(0x14, (int)current);
|
var presetName = VcpValueNames.GetFormattedName(0x14, (int)current);
|
||||||
Logger.LogInfo($"[{monitor.Id}] Color temperature via 0x14: {presetName}");
|
Logger.LogDebug($"[{monitor.Id}] Color temperature via 0x14: {presetName}");
|
||||||
return new BrightnessInfo((int)current, 0, (int)max);
|
return new BrightnessInfo((int)current, 0, (int)max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +266,7 @@ namespace PowerDisplay.Common.Drivers.DDC
|
|||||||
if (DdcCiNative.TryGetVCPFeature(monitor.Handle, VcpCodeInputSource, out uint current, out uint max))
|
if (DdcCiNative.TryGetVCPFeature(monitor.Handle, VcpCodeInputSource, out uint current, out uint max))
|
||||||
{
|
{
|
||||||
var sourceName = VcpValueNames.GetFormattedName(0x60, (int)current);
|
var sourceName = VcpValueNames.GetFormattedName(0x60, (int)current);
|
||||||
Logger.LogInfo($"[{monitor.Id}] Input source via 0x60: {sourceName}");
|
Logger.LogDebug($"[{monitor.Id}] Input source via 0x60: {sourceName}");
|
||||||
return new BrightnessInfo((int)current, 0, (int)max);
|
return new BrightnessInfo((int)current, 0, (int)max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ namespace PowerDisplay.Common.Drivers.DDC
|
|||||||
var verifyName = VcpValueNames.GetFormattedName(0x60, (int)verifyValue);
|
var verifyName = VcpValueNames.GetFormattedName(0x60, (int)verifyValue);
|
||||||
if (verifyValue == (uint)inputSource)
|
if (verifyValue == (uint)inputSource)
|
||||||
{
|
{
|
||||||
Logger.LogInfo($"[{monitor.Id}] Input source verified: {verifyName} (0x{verifyValue:X2})");
|
Logger.LogDebug($"[{monitor.Id}] Input source verified: {verifyName} (0x{verifyValue:X2})");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -409,7 +409,7 @@ namespace PowerDisplay.Common.Drivers.DDC
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(capsString))
|
if (!string.IsNullOrEmpty(capsString))
|
||||||
{
|
{
|
||||||
Logger.LogInfo($"Got capabilities string (length: {capsString.Length})");
|
Logger.LogDebug($"Got capabilities string (length: {capsString.Length})");
|
||||||
return capsString;
|
return capsString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,21 @@ namespace PowerDisplay.Common.Services
|
|||||||
/// Centralized service for managing PowerDisplay profiles storage and retrieval.
|
/// Centralized service for managing PowerDisplay profiles storage and retrieval.
|
||||||
/// Provides unified access to profile data for PowerDisplay, Settings UI, and LightSwitch modules.
|
/// Provides unified access to profile data for PowerDisplay, Settings UI, and LightSwitch modules.
|
||||||
/// Thread-safe and AOT-compatible.
|
/// Thread-safe and AOT-compatible.
|
||||||
/// Implements <see cref="IProfileService"/> for dependency injection support.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para><b>Design Note:</b> This class provides both static and instance-based access patterns:</para>
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item><description>Static methods: Direct access for backward compatibility with existing code. Thread-safe with internal locking.</description></item>
|
||||||
|
/// <item><description>Instance methods (via <see cref="IProfileService"/>): For dependency injection consumers. Delegates to static methods internally.</description></item>
|
||||||
|
/// </list>
|
||||||
|
/// <para><b>Usage Guidelines:</b></para>
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item><description>New code should prefer DI: <c>serviceProvider.GetService<IProfileService>()</c></description></item>
|
||||||
|
/// <item><description>Or use the singleton: <c>ProfileService.Instance.LoadProfiles()</c></description></item>
|
||||||
|
/// <item><description>Static methods remain available for backward compatibility</description></item>
|
||||||
|
/// </list>
|
||||||
|
/// <para>All access patterns are thread-safe and share the same underlying lock.</para>
|
||||||
|
/// </remarks>
|
||||||
public class ProfileService : IProfileService
|
public class ProfileService : IProfileService
|
||||||
{
|
{
|
||||||
private const string LogPrefix = "[ProfileService]";
|
private const string LogPrefix = "[ProfileService]";
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using ManagedCommon;
|
||||||
|
|
||||||
|
namespace PowerDisplay.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class for Windows named event operations.
|
||||||
|
/// Provides unified event signaling with consistent error handling and logging.
|
||||||
|
/// </summary>
|
||||||
|
public static class EventHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Signals a named event. Creates the event if it doesn't exist.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventName">The name of the event to signal.</param>
|
||||||
|
/// <returns>True if the event was signaled successfully, false otherwise.</returns>
|
||||||
|
public static bool SignalEvent(string eventName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(eventName))
|
||||||
|
{
|
||||||
|
Logger.LogWarning("[EventHelper] SignalEvent called with null or empty event name");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var eventHandle = new EventWaitHandle(
|
||||||
|
false,
|
||||||
|
EventResetMode.AutoReset,
|
||||||
|
eventName);
|
||||||
|
eventHandle.Set();
|
||||||
|
Logger.LogDebug($"[EventHelper] Signaled event: {eventName}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError($"[EventHelper] Failed to signal event '{eventName}': {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,5 +34,60 @@ namespace PowerDisplay.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const string ExternalMonitorGlyph = "\uE7F4";
|
public const string ExternalMonitorGlyph = "\uE7F4";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DDC/CI protocol constants
|
||||||
|
/// </summary>
|
||||||
|
public static class Ddc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Retry delay between DDC/CI operations in milliseconds
|
||||||
|
/// </summary>
|
||||||
|
public const int RetryDelayMs = 100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of retries for DDC/CI operations
|
||||||
|
/// </summary>
|
||||||
|
public const int MaxRetries = 3;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Timeout for getting monitor capabilities in milliseconds
|
||||||
|
/// </summary>
|
||||||
|
public const int CapabilitiesTimeoutMs = 5000;
|
||||||
|
|
||||||
|
// VCP Codes
|
||||||
|
/// <summary>VCP code for Brightness (0x10)</summary>
|
||||||
|
public const byte VcpBrightness = 0x10;
|
||||||
|
|
||||||
|
/// <summary>VCP code for Contrast (0x12)</summary>
|
||||||
|
public const byte VcpContrast = 0x12;
|
||||||
|
|
||||||
|
/// <summary>VCP code for Select Color Preset / Color Temperature (0x14)</summary>
|
||||||
|
public const byte VcpColorTemperature = 0x14;
|
||||||
|
|
||||||
|
/// <summary>VCP code for Input Source (0x60)</summary>
|
||||||
|
public const byte VcpInputSource = 0x60;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process synchronization constants
|
||||||
|
/// </summary>
|
||||||
|
public static class Process
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Timeout for waiting for process ready signal in milliseconds
|
||||||
|
/// </summary>
|
||||||
|
public const int StartupTimeoutMs = 5000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Polling interval when waiting for process ready in milliseconds
|
||||||
|
/// </summary>
|
||||||
|
public const int ReadyPollIntervalMs = 100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fallback delay when event-based synchronization fails in milliseconds
|
||||||
|
/// </summary>
|
||||||
|
public const int FallbackDelayMs = 500;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ namespace PowerDisplay
|
|||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
#pragma warning restore CA1001
|
#pragma warning restore CA1001
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Event name for signaling that PowerDisplay process is ready.
|
||||||
|
/// Must match the constant in C++ PowerDisplayModuleInterface.
|
||||||
|
/// </summary>
|
||||||
|
private const string ProcessReadyEventName = "Local\\PowerToys_PowerDisplay_Ready";
|
||||||
|
|
||||||
private readonly ISettingsUtils _settingsUtils = new SettingsUtils();
|
private readonly ISettingsUtils _settingsUtils = new SettingsUtils();
|
||||||
private Window? _mainWindow;
|
private Window? _mainWindow;
|
||||||
private int _powerToysRunnerPid;
|
private int _powerToysRunnerPid;
|
||||||
@@ -106,6 +112,10 @@ namespace PowerDisplay
|
|||||||
RegisterViewModelEvent(Constants.ApplyColorTemperaturePowerDisplayEvent(), vm => vm.ApplyColorTemperatureFromSettings(), "ApplyColorTemperature");
|
RegisterViewModelEvent(Constants.ApplyColorTemperaturePowerDisplayEvent(), vm => vm.ApplyColorTemperatureFromSettings(), "ApplyColorTemperature");
|
||||||
RegisterViewModelEvent(Constants.ApplyProfilePowerDisplayEvent(), vm => vm.ApplyProfileFromSettings(), "ApplyProfile");
|
RegisterViewModelEvent(Constants.ApplyProfilePowerDisplayEvent(), vm => vm.ApplyProfileFromSettings(), "ApplyProfile");
|
||||||
|
|
||||||
|
// Signal that process is ready to receive events
|
||||||
|
// This allows the C++ module to wait for initialization instead of using hardcoded Sleep
|
||||||
|
SignalProcessReady();
|
||||||
|
|
||||||
// Monitor Runner process (backup exit mechanism)
|
// Monitor Runner process (backup exit mechanism)
|
||||||
if (_powerToysRunnerPid > 0)
|
if (_powerToysRunnerPid > 0)
|
||||||
{
|
{
|
||||||
@@ -354,5 +364,26 @@ namespace PowerDisplay
|
|||||||
_trayIconService?.Destroy();
|
_trayIconService?.Destroy();
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signal that PowerDisplay process is ready to receive events.
|
||||||
|
/// Uses a ManualReset event so the C++ module can wait on it.
|
||||||
|
/// </summary>
|
||||||
|
private static void SignalProcessReady()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var readyEvent = new EventWaitHandle(
|
||||||
|
false,
|
||||||
|
EventResetMode.ManualReset,
|
||||||
|
ProcessReadyEventName);
|
||||||
|
readyEvent.Set();
|
||||||
|
Logger.LogInfo("Signaled process ready event");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError($"Failed to signal process ready event: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
@@ -19,7 +20,7 @@ namespace PowerDisplay.ViewModels;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class MainViewModel
|
public partial class MainViewModel
|
||||||
{
|
{
|
||||||
private async Task InitializeAsync()
|
private async Task InitializeAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -27,7 +28,7 @@ public partial class MainViewModel
|
|||||||
IsScanning = true;
|
IsScanning = true;
|
||||||
|
|
||||||
// Discover monitors
|
// Discover monitors
|
||||||
var monitors = await _monitorManager.DiscoverMonitorsAsync(_cancellationTokenSource.Token);
|
var monitors = await _monitorManager.DiscoverMonitorsAsync(cancellationToken);
|
||||||
|
|
||||||
// Update UI on the dispatcher thread
|
// Update UI on the dispatcher thread
|
||||||
_dispatcherQueue.TryEnqueue(() =>
|
_dispatcherQueue.TryEnqueue(() =>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using ManagedCommon;
|
|||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
using PowerDisplay.Common.Models;
|
using PowerDisplay.Common.Models;
|
||||||
using PowerDisplay.Common.Services;
|
using PowerDisplay.Common.Services;
|
||||||
|
using PowerDisplay.Common.Utils;
|
||||||
using PowerDisplay.Serialization;
|
using PowerDisplay.Serialization;
|
||||||
using PowerToys.Interop;
|
using PowerToys.Interop;
|
||||||
|
|
||||||
@@ -621,22 +622,9 @@ public partial class MainViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void SignalMonitorsRefreshEvent()
|
private void SignalMonitorsRefreshEvent()
|
||||||
{
|
{
|
||||||
try
|
EventHelper.SignalEvent(Constants.RefreshPowerDisplayMonitorsEvent());
|
||||||
{
|
|
||||||
using (var eventHandle = new System.Threading.EventWaitHandle(
|
|
||||||
false,
|
|
||||||
System.Threading.EventResetMode.AutoReset,
|
|
||||||
Constants.RefreshPowerDisplayMonitorsEvent()))
|
|
||||||
{
|
|
||||||
eventHandle.Set();
|
|
||||||
Logger.LogInfo("Signaled refresh monitors event to Settings UI");
|
Logger.LogInfo("Signaled refresh monitors event to Settings UI");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError($"Failed to signal refresh monitors event: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Format VCP code information for display in Settings UI
|
/// Format VCP code information for display in Settings UI
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public partial class MainViewModel : INotifyPropertyChanged, IDisposable
|
|||||||
LoadProfiles();
|
LoadProfiles();
|
||||||
|
|
||||||
// Start initial discovery
|
// Start initial discovery
|
||||||
_ = InitializeAsync();
|
_ = InitializeAsync(_cancellationTokenSource.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<MonitorViewModel> Monitors
|
public ObservableCollection<MonitorViewModel> Monitors
|
||||||
|
|||||||
@@ -404,6 +404,13 @@ public partial class MonitorViewModel : INotifyPropertyChanged, IDisposable
|
|||||||
/// <param name="orientation">Orientation: 0=normal, 1=90°, 2=180°, 3=270°</param>
|
/// <param name="orientation">Orientation: 0=normal, 1=90°, 2=180°, 3=270°</param>
|
||||||
public async Task SetRotationAsync(int orientation)
|
public async Task SetRotationAsync(int orientation)
|
||||||
{
|
{
|
||||||
|
// Validate orientation range (0=normal, 1=90°, 2=180°, 3=270°)
|
||||||
|
if (orientation < 0 || orientation > 3)
|
||||||
|
{
|
||||||
|
Logger.LogWarning($"[{HardwareId}] Invalid rotation value: {orientation}. Must be 0-3.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If already at this orientation, do nothing
|
// If already at this orientation, do nothing
|
||||||
if (CurrentRotation == orientation)
|
if (CurrentRotation == orientation)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,4 +4,9 @@ namespace PowerDisplayConstants
|
|||||||
{
|
{
|
||||||
// Name of the powertoy module.
|
// Name of the powertoy module.
|
||||||
inline const std::wstring ModuleKey = L"PowerDisplay";
|
inline const std::wstring ModuleKey = L"PowerDisplay";
|
||||||
|
|
||||||
|
// Process synchronization constants
|
||||||
|
inline const wchar_t* ProcessReadyEventName = L"Local\\PowerToys_PowerDisplay_Ready";
|
||||||
|
constexpr DWORD ProcessReadyTimeoutMs = 5000;
|
||||||
|
constexpr DWORD FallbackDelayMs = 500;
|
||||||
}
|
}
|
||||||
@@ -185,6 +185,38 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper method to wait for PowerDisplay.exe process to be ready
|
||||||
|
// Uses a named event for precise synchronization instead of hardcoded Sleep
|
||||||
|
void wait_for_process_ready()
|
||||||
|
{
|
||||||
|
HANDLE readyEvent = OpenEventW(SYNCHRONIZE, FALSE, PowerDisplayConstants::ProcessReadyEventName);
|
||||||
|
if (readyEvent)
|
||||||
|
{
|
||||||
|
Logger::trace(L"Waiting for PowerDisplay process ready signal...");
|
||||||
|
DWORD waitResult = WaitForSingleObject(readyEvent, PowerDisplayConstants::ProcessReadyTimeoutMs);
|
||||||
|
CloseHandle(readyEvent);
|
||||||
|
|
||||||
|
if (waitResult == WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
Logger::trace(L"PowerDisplay process ready signal received");
|
||||||
|
}
|
||||||
|
else if (waitResult == WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
Logger::warn(L"PowerDisplay process ready timeout after {}ms", PowerDisplayConstants::ProcessReadyTimeoutMs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::warn(L"WaitForSingleObject failed with error: {}", GetLastError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback: if cannot open event, use a shorter delay
|
||||||
|
Logger::warn(L"Could not open PowerDisplay ready event, using fallback delay");
|
||||||
|
Sleep(PowerDisplayConstants::FallbackDelayMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PowerDisplayModule()
|
PowerDisplayModule()
|
||||||
{
|
{
|
||||||
@@ -332,9 +364,8 @@ public:
|
|||||||
{
|
{
|
||||||
Logger::trace(L"PowerDisplay process not running, launching before applying color temperature");
|
Logger::trace(L"PowerDisplay process not running, launching before applying color temperature");
|
||||||
launch_process();
|
launch_process();
|
||||||
// Wait for process to initialize and register event listeners
|
// Wait for process to signal ready
|
||||||
// This prevents race condition where event is set before process is ready
|
wait_for_process_ready();
|
||||||
Sleep(1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_hApplyColorTemperatureEvent)
|
if (m_hApplyColorTemperatureEvent)
|
||||||
@@ -364,8 +395,8 @@ public:
|
|||||||
{
|
{
|
||||||
Logger::trace(L"PowerDisplay process not running, launching before applying profile");
|
Logger::trace(L"PowerDisplay process not running, launching before applying profile");
|
||||||
launch_process();
|
launch_process();
|
||||||
// Wait for process to initialize and register event listeners
|
// Wait for process to signal ready
|
||||||
Sleep(1000);
|
wait_for_process_ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_hApplyProfileEvent)
|
if (m_hApplyProfileEvent)
|
||||||
|
|||||||
@@ -142,11 +142,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
{
|
{
|
||||||
// Explicitly signal PowerDisplay to refresh tray icon
|
// Explicitly signal PowerDisplay to refresh tray icon
|
||||||
// This is needed because set_config() doesn't signal SettingsUpdatedEvent to avoid UI refresh issues
|
// This is needed because set_config() doesn't signal SettingsUpdatedEvent to avoid UI refresh issues
|
||||||
using var eventHandle = new System.Threading.EventWaitHandle(
|
EventHelper.SignalEvent(Constants.SettingsUpdatedPowerDisplayEvent());
|
||||||
false,
|
|
||||||
System.Threading.EventResetMode.AutoReset,
|
|
||||||
Constants.SettingsUpdatedPowerDisplayEvent());
|
|
||||||
eventHandle.Set();
|
|
||||||
Logger.LogInfo($"ShowSystemTrayIcon changed to {value}, signaled SettingsUpdatedPowerDisplayEvent");
|
Logger.LogInfo($"ShowSystemTrayIcon changed to {value}, signaled SettingsUpdatedPowerDisplayEvent");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -396,20 +392,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void SignalSettingsUpdated()
|
private void SignalSettingsUpdated()
|
||||||
{
|
{
|
||||||
try
|
EventHelper.SignalEvent(Constants.SettingsUpdatedPowerDisplayEvent());
|
||||||
{
|
|
||||||
using var eventHandle = new System.Threading.EventWaitHandle(
|
|
||||||
false,
|
|
||||||
System.Threading.EventResetMode.AutoReset,
|
|
||||||
Constants.SettingsUpdatedPowerDisplayEvent());
|
|
||||||
eventHandle.Set();
|
|
||||||
Logger.LogInfo("Signaled SettingsUpdatedPowerDisplayEvent for feature visibility change");
|
Logger.LogInfo("Signaled SettingsUpdatedPowerDisplayEvent for feature visibility change");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError($"Failed to signal SettingsUpdatedPowerDisplayEvent: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Launch()
|
public void Launch()
|
||||||
{
|
{
|
||||||
@@ -513,7 +498,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
for (int i = Monitors.Count - 1; i >= 0; i--)
|
for (int i = Monitors.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var existingMonitor = Monitors[i];
|
var existingMonitor = Monitors[i];
|
||||||
if (updatedMonitorsDict.TryGetValue(existingMonitor.InternalName, out var updatedMonitor))
|
if (updatedMonitorsDict.TryGetValue(existingMonitor.InternalName, out var updatedMonitor)
|
||||||
|
&& updatedMonitor != null)
|
||||||
{
|
{
|
||||||
// Monitor still exists - update its properties in place
|
// Monitor still exists - update its properties in place
|
||||||
Logger.LogInfo($"[ReloadMonitors] Updating existing monitor: {existingMonitor.InternalName}");
|
Logger.LogInfo($"[ReloadMonitors] Updating existing monitor: {existingMonitor.InternalName}");
|
||||||
@@ -661,13 +647,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
profile.Name));
|
profile.Name));
|
||||||
|
|
||||||
// Signal PowerDisplay to apply profile
|
// Signal PowerDisplay to apply profile
|
||||||
using (var eventHandle = new System.Threading.EventWaitHandle(
|
EventHelper.SignalEvent(Constants.ApplyProfilePowerDisplayEvent());
|
||||||
false,
|
|
||||||
System.Threading.EventResetMode.AutoReset,
|
|
||||||
Constants.ApplyProfilePowerDisplayEvent()))
|
|
||||||
{
|
|
||||||
eventHandle.Set();
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.LogInfo($"Profile '{profile.Name}' applied successfully");
|
Logger.LogInfo($"Profile '{profile.Name}' applied successfully");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user