-
Notifications
You must be signed in to change notification settings - Fork 52
Upgrade to .NET 4.8 and add profile toggle hotkey feature #153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/add-color-settings
Are you sure you want to change the base?
Upgrade to .NET 4.8 and add profile toggle hotkey feature #153
Conversation
Upgraded project to target .NET Framework 4.8, updated NuGet packages (CommonServiceLocator, Costura.Fody, Fody), and refreshed .gitignore. Enhanced FodyWeavers.xsd with new options for runtime and unmanaged assemblies. Regenerated designer files with updated tooling. Improved project configuration for modern .NET and Visual Studio compatibility.
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Co-authored-by: harisonw <87620631+harisonw@users.noreply.github.com>
Clears focus from the hotkey textbox after setting a profile toggle hotkey to improve user experience. Also adds the System namespace to IVibranceProxy.cs for completeness.
|
@juv - cant assign to you |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request upgrades the project from .NET Framework 4.0 to 4.8 and introduces a profile toggle hotkey feature that allows users to temporarily enable/disable profile settings via a global hotkey.
Changes:
- Upgraded target framework from .NET 4.0 to .NET 4.8 and updated NuGet dependencies (Costura.Fody 4.1.0 → 6.0.0, Fody 6.3.0 → 6.9.3, CommonServiceLocator 1.3 → 2.0.7)
- Added profile toggle hotkey feature with UI controls, state persistence, and integration into both NVIDIA and AMD vibrance proxy implementations
- Updated project configuration files and auto-generated designer files to reflect the framework upgrade
Reviewed changes
Copilot reviewed 11 out of 15 changed files in this pull request and generated 48 comments.
Show a summary per file
| File | Description |
|---|---|
| vibrance.GUI/vibrance.GUI.csproj | Updated target framework to v4.8, upgraded NuGet package references, and modified MSBuild tooling version |
| vibrance.GUI/packages.config | Updated package versions to be compatible with .NET 4.8 |
| vibrance.GUI/App.config | Changed supported runtime to .NET Framework 4.8 |
| vibrance.GUI/common/VibranceGUI.cs | Added profile toggle hotkey registration, WndProc override, hotkey parsing, and toggle logic with P/Invoke declarations |
| vibrance.GUI/common/VibranceGUI.Designer.cs | Added UI controls for profile toggle feature (checkbox, label, textbox) |
| vibrance.GUI/common/SettingsController.cs | Extended settings persistence to include profile toggle configuration (enabled state, hotkey string, toggle state) |
| vibrance.GUI/common/ISettingsController.cs | Updated interface signatures to include profile toggle parameters |
| vibrance.GUI/common/IVibranceProxy.cs | Added interface methods for profile toggle feature management |
| vibrance.GUI/common/Definitions.cs | Added profile toggle state fields to VibranceInfo struct |
| vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs | Implemented profile toggle methods and integrated toggle state check into OnWinEventHook |
| vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs | Implemented profile toggle methods and integrated toggle state check into OnWinEventHook |
| vibrance.GUI/FodyWeavers.xsd | Updated schema to reflect Costura.Fody 6.0.0 capabilities |
| vibrance.GUI/Properties/Settings.Designer.cs | Auto-generated file updated for new framework version |
| vibrance.GUI/Properties/Resources.Designer.cs | Auto-generated file updated for new framework version |
| .gitignore | Added .vs/ directory to gitignore (Visual Studio directory) |
Files not reviewed (3)
- vibrance.GUI/Properties/Resources.Designer.cs: Language not supported
- vibrance.GUI/Properties/Settings.Designer.cs: Language not supported
- vibrance.GUI/common/VibranceGUI.Designer.cs: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private bool TryParseHotkey(string hotkey, out uint modifiers, out uint key) | ||
| { | ||
| modifiers = 0; | ||
| key = 0; | ||
| if (string.IsNullOrWhiteSpace(hotkey)) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| string[] parts = hotkey.Split(new[] { '+' }, StringSplitOptions.RemoveEmptyEntries); | ||
| foreach (string part in parts) | ||
| { | ||
| string normalized = part.Trim(); | ||
| if (string.Equals(normalized, "Ctrl", StringComparison.OrdinalIgnoreCase) || | ||
| string.Equals(normalized, "Control", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| modifiers |= HotkeyModControl; | ||
| continue; | ||
| } | ||
| if (string.Equals(normalized, "Alt", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| modifiers |= HotkeyModAlt; | ||
| continue; | ||
| } | ||
| if (string.Equals(normalized, "Shift", StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| modifiers |= HotkeyModShift; | ||
| continue; | ||
| } | ||
|
|
||
| if (Enum.TryParse(normalized, true, out Keys parsedKey)) | ||
| { | ||
| key = (uint)parsedKey; | ||
| } | ||
| } | ||
|
|
||
| return key != 0; |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TryParseHotkey method doesn't properly handle invalid hotkey strings where multiple non-modifier keys appear. If a hotkey string contains multiple keys like "Ctrl+A+B", the method will accept the last valid key ("B") and silently ignore the first one. This could lead to unexpected behavior where the parsed hotkey doesn't match what the user sees in the textbox. Consider validating that only one non-modifier key exists in the string.
| } | ||
| else | ||
| { | ||
| _amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault); |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When toggling off the profile, the AMD implementation always calls SetSaturationOnAllDisplays regardless of the affectPrimaryMonitorOnly setting. This is inconsistent with the NVIDIA implementation which respects this setting. The code should check affectPrimaryMonitorOnly and call SetSaturationOnDisplay for the specific screen when that setting is enabled, similar to how the NVIDIA version handles it in lines 414-424 of NvidiaDynamicVibranceProxy.cs.
| _amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault); | |
| if (_vibranceInfo.affectPrimaryMonitorOnly && _gameScreen != null && _gameScreen.DeviceName.Equals(screen.DeviceName)) | |
| { | |
| _amdAdapter.SetSaturationOnDisplay(_vibranceInfo.userVibranceSettingDefault, _gameScreen.DeviceName); | |
| } | |
| else | |
| { | |
| _amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault); | |
| } |
| return; | ||
| } | ||
|
|
||
| _isProfileToggleHotkeyRegistered = RegisterHotKey(this.Handle, ProfileToggleHotkeyId, modifiers, key); |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RegisterHotKey function's return value is stored but never checked for failure. If hotkey registration fails (e.g., because another application is already using that hotkey combination), the user won't receive any feedback. Consider logging a warning or showing a notification when hotkey registration fails.
| _isProfileToggleHotkeyRegistered = RegisterHotKey(this.Handle, ProfileToggleHotkeyId, modifiers, key); | |
| bool registrationSucceeded = RegisterHotKey(this.Handle, ProfileToggleHotkeyId, modifiers, key); | |
| _isProfileToggleHotkeyRegistered = registrationSucceeded; | |
| if (!registrationSucceeded) | |
| { | |
| MessageBox.Show( | |
| "Failed to register the profile toggle hotkey. It may already be in use by another application.", | |
| "Hotkey Registration Failed", | |
| MessageBoxButtons.OK, | |
| MessageBoxIcon.Warning); | |
| } |
| public void SetProfileToggleEnabled(bool profileToggleEnabled) | ||
| { | ||
| _vibranceInfo.isProfileToggleEnabled = profileToggleEnabled; | ||
| _vibranceInfo.isProfileToggleOn = true; |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SetProfileToggleEnabled unconditionally resets isProfileToggleOn to true. This could override the user's saved toggle state when disabling and re-enabling the feature, or when changing settings. The state should only be reset when the feature is being disabled, not when it's being enabled.
| _vibranceInfo.isProfileToggleOn = true; | |
| if (!profileToggleEnabled) | |
| { | |
| _vibranceInfo.isProfileToggleOn = true; | |
| } |
| public void SetProfileToggleEnabled(bool profileToggleEnabled) | ||
| { | ||
| _vibranceInfo.isProfileToggleEnabled = profileToggleEnabled; | ||
| _vibranceInfo.isProfileToggleOn = true; |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SetProfileToggleEnabled unconditionally resets isProfileToggleOn to true. This could override the user's saved toggle state when disabling and re-enabling the feature, or when changing settings. The state should only be reset when the feature is being disabled, not when it's being enabled.
| _vibranceInfo.isProfileToggleOn = true; | |
| if (!profileToggleEnabled) | |
| { | |
| _vibranceInfo.isProfileToggleOn = true; | |
| } |
| _vibranceInfo.displayHandles.ForEach(handle => setDVCLevel(handle, _vibranceInfo.userVibranceSettingDefault)); | ||
| } | ||
|
|
||
| if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == true) |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expression 'A == true' can be simplified to 'A'.
|
|
||
| //test if color settings change is needed | ||
| if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && | ||
| if (shouldApplyProfileSettings && _vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expression 'A == false' can be simplified to '!A'.
| if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && | ||
| DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expression 'A == false' can be simplified to '!A'.
| if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && | |
| DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) | |
| if (!_vibranceInfo.neverChangeColorSettings && !_vibranceInfo.isColorSettingApplied && | |
| !DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting)) |
| setDVCLevel(_vibranceInfo.defaultHandle, applicationSetting.IngameLevel); | ||
| } | ||
|
|
||
| if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expression 'A == false' can be simplified to '!A'.
|
|
||
| //test if color settings change is needed | ||
| if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && | ||
| if (shouldApplyProfileSettings && _vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expression 'A == false' can be simplified to '!A'.
Upgrade the project to target .NET Framework 4.8, update NuGet dependencies, and enhance project configuration. Introduce a profile toggle hotkey feature with UI components and state persistence.
Half 'Vibe Coded' as C#/.net is not a stack I've used before - code seems fairly sensible to my uneducated glance though and the feature is working really well from my testing