diff --git a/.nuget/nuget.exe b/.nuget/nuget.exe new file mode 100644 index 0000000..9133156 Binary files /dev/null and b/.nuget/nuget.exe differ diff --git a/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs b/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs index 843c069..30fac20 100644 --- a/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs +++ b/vibrance.GUI/AMD/AmdDynamicVibranceProxy.cs @@ -96,6 +96,88 @@ public void SetNeverChangeColorSettings(bool neverChangeColorSettings) _vibranceInfo.neverChangeColorSettings = neverChangeColorSettings; } + public void SetProfileToggleEnabled(bool profileToggleEnabled) + { + _vibranceInfo.isProfileToggleEnabled = profileToggleEnabled; + _vibranceInfo.isProfileToggleOn = true; + } + + public void SetProfileToggleState(bool isProfileToggleOn) + { + _vibranceInfo.isProfileToggleOn = isProfileToggleOn; + } + + public bool IsProfileToggleEnabled() + { + return _vibranceInfo.isProfileToggleEnabled; + } + + public bool IsProfileToggleOn() + { + return _vibranceInfo.isProfileToggleOn; + } + + public void ApplyProfileToggle(IntPtr windowHandle, string processName, bool isProfileToggleOn) + { + if (_applicationSettings.Count == 0) + { + return; + } + + ApplicationSetting applicationSetting = _applicationSettings.FirstOrDefault(x => string.Equals(x.Name, processName, StringComparison.OrdinalIgnoreCase)); + if (applicationSetting == null) + { + return; + } + + Screen screen = Screen.FromHandle(windowHandle); + if (screen == null) + { + return; + } + + _gameScreen = screen; + + if (isProfileToggleOn) + { + if (_vibranceInfo.userVibranceSettingDefault != applicationSetting.IngameLevel) + { + if (_vibranceInfo.affectPrimaryMonitorOnly) + { + _amdAdapter.SetSaturationOnDisplay(applicationSetting.IngameLevel, screen.DeviceName); + } + else + { + _amdAdapter.SetSaturationOnAllDisplays(applicationSetting.IngameLevel); + } + } + + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && + DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) + { + DeviceGammaRampHelper.SetGammaRamp(screen, applicationSetting.Gamma, applicationSetting.Brightness, applicationSetting.Contrast); + _vibranceInfo.isColorSettingApplied = true; + } + } + else + { + _amdAdapter.SetSaturationOnAllDisplays(_vibranceInfo.userVibranceSettingDefault); + + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == true) + { + if (_vibranceInfo.affectPrimaryMonitorOnly && _gameScreen != null && _gameScreen.DeviceName.Equals(screen.DeviceName)) + { + DeviceGammaRampHelper.SetGammaRamp(_gameScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma); + } + else + { + Screen.AllScreens.ToList().ForEach(currentScreen => DeviceGammaRampHelper.SetGammaRamp(currentScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma)); + } + _vibranceInfo.isColorSettingApplied = false; + } + } + } + public void SetWindowsColorSettings(int brightness, int contrast, int gamma) { _vibranceInfo.userColorSettings.brightness = brightness; @@ -158,6 +240,7 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e) { if (_applicationSettings.Count > 0) { + bool shouldApplyProfileSettings = !_vibranceInfo.isProfileToggleEnabled || _vibranceInfo.isProfileToggleOn; ApplicationSetting applicationSetting = _applicationSettings.FirstOrDefault(x => string.Equals(x.Name, e.ProcessName, StringComparison.OrdinalIgnoreCase)); if (applicationSetting != null) { @@ -165,7 +248,7 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e) _gameScreen = screen; //apply application specific saturation - if (_vibranceInfo.userVibranceSettingDefault != applicationSetting.IngameLevel) + if (shouldApplyProfileSettings && _vibranceInfo.userVibranceSettingDefault != applicationSetting.IngameLevel) { if (_vibranceInfo.affectPrimaryMonitorOnly) { @@ -188,7 +271,7 @@ private void OnWinEventHook(object sender, WinEventHookEventArgs e) } //test if color settings change is needed - if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && + if (shouldApplyProfileSettings && _vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) { DeviceGammaRampHelper.SetGammaRamp(screen, applicationSetting.Gamma, applicationSetting.Brightness, applicationSetting.Contrast); @@ -247,4 +330,4 @@ private static void PerformResolutionChange(Screen screen, ResolutionModeWrapper ResolutionHelper.ChangeResolutionEx(resolutionSettings, screen.DeviceName); } } -} \ No newline at end of file +} diff --git a/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs b/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs index 6a843e9..463a16e 100644 --- a/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs +++ b/vibrance.GUI/NVIDIA/NvidiaDynamicVibranceProxy.cs @@ -193,6 +193,7 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e) { if (_applicationSettings.Count > 0) { + bool shouldApplyProfileSettings = !_vibranceInfo.isProfileToggleEnabled || _vibranceInfo.isProfileToggleOn; ApplicationSetting applicationSetting = _applicationSettings.FirstOrDefault(x => string.Equals(x.Name, e.ProcessName, StringComparison.OrdinalIgnoreCase)); if (applicationSetting != null) { @@ -206,7 +207,7 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e) _gameScreen = screen; //test if digital vibrance change is needed - if (!equalsDVCLevel(displayHandle, applicationSetting.IngameLevel)) + if (shouldApplyProfileSettings && !equalsDVCLevel(displayHandle, applicationSetting.IngameLevel)) { _vibranceInfo.defaultHandle = displayHandle; setDVCLevel(_vibranceInfo.defaultHandle, applicationSetting.IngameLevel); @@ -223,7 +224,7 @@ private static void OnWinEventHook(object sender, WinEventHookEventArgs e) } //test if color settings change is needed - if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && + if (shouldApplyProfileSettings && _vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) { DeviceGammaRampHelper.SetGammaRamp(screen, applicationSetting.Gamma, applicationSetting.Brightness, applicationSetting.Contrast); @@ -345,6 +346,99 @@ public void SetNeverChangeColorSettings(bool neverChangeColorSettings) _vibranceInfo.neverChangeColorSettings = neverChangeColorSettings; } + public void SetProfileToggleEnabled(bool profileToggleEnabled) + { + _vibranceInfo.isProfileToggleEnabled = profileToggleEnabled; + _vibranceInfo.isProfileToggleOn = true; + } + + public void SetProfileToggleState(bool isProfileToggleOn) + { + _vibranceInfo.isProfileToggleOn = isProfileToggleOn; + } + + public bool IsProfileToggleEnabled() + { + return _vibranceInfo.isProfileToggleEnabled; + } + + public bool IsProfileToggleOn() + { + return _vibranceInfo.isProfileToggleOn; + } + + public void ApplyProfileToggle(IntPtr windowHandle, string processName, bool isProfileToggleOn) + { + if (_applicationSettings.Count == 0) + { + return; + } + + ApplicationSetting applicationSetting = _applicationSettings.FirstOrDefault(x => string.Equals(x.Name, processName, StringComparison.OrdinalIgnoreCase)); + if (applicationSetting == null) + { + return; + } + + int displayHandle = GetApplicationDisplayHandle(windowHandle); + if (displayHandle == -1) + { + return; + } + + Screen screen = Screen.FromHandle(windowHandle); + if (screen == null) + { + return; + } + + _gameScreen = screen; + + if (isProfileToggleOn) + { + if (!equalsDVCLevel(displayHandle, applicationSetting.IngameLevel)) + { + _vibranceInfo.defaultHandle = displayHandle; + setDVCLevel(_vibranceInfo.defaultHandle, applicationSetting.IngameLevel); + } + + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == false && + DeviceGammaRampHelper.IsGammaRampEqualToWindowsValues(_vibranceInfo, applicationSetting) == false) + { + DeviceGammaRampHelper.SetGammaRamp(screen, applicationSetting.Gamma, applicationSetting.Brightness, applicationSetting.Contrast); + _vibranceInfo.isColorSettingApplied = true; + } + } + else + { + if (_vibranceInfo.affectPrimaryMonitorOnly && !equalsDVCLevel(_vibranceInfo.defaultHandle, _vibranceInfo.userVibranceSettingDefault)) + { + if (_gameScreen != null && !_gameScreen.DeviceName.Equals(screen.DeviceName)) + { + return; + } + setDVCLevel(_vibranceInfo.defaultHandle, _vibranceInfo.userVibranceSettingDefault); + } + else if (!_vibranceInfo.affectPrimaryMonitorOnly && !_vibranceInfo.displayHandles.TrueForAll(handle => equalsDVCLevel(handle, _vibranceInfo.userVibranceSettingDefault))) + { + _vibranceInfo.displayHandles.ForEach(handle => setDVCLevel(handle, _vibranceInfo.userVibranceSettingDefault)); + } + + if (_vibranceInfo.neverChangeColorSettings == false && _vibranceInfo.isColorSettingApplied == true) + { + if (_vibranceInfo.affectPrimaryMonitorOnly && _gameScreen != null && _gameScreen.DeviceName.Equals(screen.DeviceName)) + { + DeviceGammaRampHelper.SetGammaRamp(_gameScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma); + } + else + { + Screen.AllScreens.ToList().ForEach(currentScreen => DeviceGammaRampHelper.SetGammaRamp(currentScreen, _vibranceInfo.userColorSettings.brightness, _vibranceInfo.userColorSettings.contrast, _vibranceInfo.userColorSettings.gamma)); + } + _vibranceInfo.isColorSettingApplied = false; + } + } + } + public void SetWindowsColorSettings(int brightness, int contrast, int gamma) { _vibranceInfo.userColorSettings.brightness = brightness; diff --git a/vibrance.GUI/common/Definitions.cs b/vibrance.GUI/common/Definitions.cs index d550a11..8f5156e 100644 --- a/vibrance.GUI/common/Definitions.cs +++ b/vibrance.GUI/common/Definitions.cs @@ -19,6 +19,8 @@ public struct VibranceInfo public bool affectPrimaryMonitorOnly; public bool neverChangeResolution; public bool neverChangeColorSettings; + public bool isProfileToggleEnabled; + public bool isProfileToggleOn; public bool isColorSettingApplied; public bool isResolutionChangeApplied; public ColorSettings userColorSettings; diff --git a/vibrance.GUI/common/ISettingsController.cs b/vibrance.GUI/common/ISettingsController.cs index ab6d61a..3a894c0 100644 --- a/vibrance.GUI/common/ISettingsController.cs +++ b/vibrance.GUI/common/ISettingsController.cs @@ -6,9 +6,10 @@ namespace vibrance.GUI.common internal interface ISettingsController { bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitorOnly, string neverSwitchResolution, string neverChangeColorSettings, List applicationSettings, - string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel); + string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel, string profileToggleEnabled, string profileToggleHotkey, string profileToggleState); bool SetVibranceSetting(string szKeyName, string value); void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution, - out bool neverChangeColorSettings, out List applicationSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel); + out bool neverChangeColorSettings, out List applicationSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel, + out bool profileToggleEnabled, out string profileToggleHotkey, out bool profileToggleState); } -} \ No newline at end of file +} diff --git a/vibrance.GUI/common/IVibranceProxy.cs b/vibrance.GUI/common/IVibranceProxy.cs index efe55c2..dbd699b 100644 --- a/vibrance.GUI/common/IVibranceProxy.cs +++ b/vibrance.GUI/common/IVibranceProxy.cs @@ -17,9 +17,14 @@ public interface IVibranceProxy void SetNeverSwitchResolution(bool neverSwitchResolution); void SetNeverChangeColorSettings(bool neverChangeColorSettings); void SetWindowsColorSettings(int brightness, int contrast, int gamma); + void SetProfileToggleEnabled(bool profileToggleEnabled); + void SetProfileToggleState(bool isProfileToggleOn); + bool IsProfileToggleEnabled(); + bool IsProfileToggleOn(); + void ApplyProfileToggle(IntPtr windowHandle, string processName, bool isProfileToggleOn); void SetWindowsColorBrightness(int brightness); void SetWindowsColorContrast(int contrast); void SetWindowsColorGamma(int gamma); } -} \ No newline at end of file +} diff --git a/vibrance.GUI/common/SettingsController.cs b/vibrance.GUI/common/SettingsController.cs index 90a1b6c..3fd5228 100644 --- a/vibrance.GUI/common/SettingsController.cs +++ b/vibrance.GUI/common/SettingsController.cs @@ -37,6 +37,9 @@ private static extern bool WritePrivateProfileString(string lpAppName, const string SzKeyNameBrightnessWindowsLevel = "brightnessWindowsLevel"; const string SzKeyNameContrastWindowsLevel = "contrastWindowsLevel"; const string SzKeyNameGammaWindowsLevel = "gammaWindowsLevel"; + const string SzKeyNameProfileToggleEnabled = "profileToggleEnabled"; + const string SzKeyNameProfileToggleHotkey = "profileToggleHotkey"; + const string SzKeyNameProfileToggleState = "profileToggleState"; private string _fileName = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).ToString() + "\\vibranceGUI\\vibranceGUI.ini"; @@ -44,7 +47,7 @@ private static extern bool WritePrivateProfileString(string lpAppName, public bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitorOnly, string neverSwitchResolution, string neverChangeColorSettings, List applicationSettings, - string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel) + string brightnessWindowsLevel, string contrastWindowsLevel, string gammaWindowsLevel, string profileToggleEnabled, string profileToggleHotkey, string profileToggleState) { if (!PrepareFile()) { @@ -58,6 +61,9 @@ public bool SetVibranceSettings(string windowsLevel, string affectPrimaryMonitor WritePrivateProfileString(SzSectionName, SzKeyNameBrightnessWindowsLevel, brightnessWindowsLevel, _fileName); WritePrivateProfileString(SzSectionName, SzKeyNameContrastWindowsLevel, contrastWindowsLevel, _fileName); WritePrivateProfileString(SzSectionName, SzKeyNameGammaWindowsLevel, gammaWindowsLevel, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameProfileToggleEnabled, profileToggleEnabled, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameProfileToggleHotkey, profileToggleHotkey ?? string.Empty, _fileName); + WritePrivateProfileString(SzSectionName, SzKeyNameProfileToggleState, profileToggleState, _fileName); try { @@ -105,7 +111,8 @@ private bool PrepareFile() } public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution, - out bool neverChangeColorSettings, out List applicationSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel) + out bool neverChangeColorSettings, out List applicationSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel, + out bool profileToggleEnabled, out string profileToggleHotkey, out bool profileToggleState) { int defaultLevel = 0; int maxLevel = 0; @@ -130,6 +137,9 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran brightnessWindowsLevel = 50; contrastWindowsLevel = 50; gammaWindowsLevel = 100; + profileToggleEnabled = false; + profileToggleHotkey = string.Empty; + profileToggleState = true; return; } @@ -199,6 +209,30 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran Convert.ToUInt32(szValueGammaWindowsLevel.Capacity), _fileName); + StringBuilder szValueProfileToggleEnabled = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameProfileToggleEnabled, + "false", + szValueProfileToggleEnabled, + Convert.ToUInt32(szValueProfileToggleEnabled.Capacity), + _fileName); + + StringBuilder szValueProfileToggleHotkey = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameProfileToggleHotkey, + string.Empty, + szValueProfileToggleHotkey, + Convert.ToUInt32(szValueProfileToggleHotkey.Capacity), + _fileName); + + StringBuilder szValueProfileToggleState = new StringBuilder(1024); + GetPrivateProfileString(SzSectionName, + SzKeyNameProfileToggleState, + "true", + szValueProfileToggleState, + Convert.ToUInt32(szValueProfileToggleState.Capacity), + _fileName); + try { vibranceWindowsLevel = int.Parse(szValueInactive.ToString()); @@ -208,6 +242,9 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran brightnessWindowsLevel = int.Parse(szValueBrightnessWindowsLevel.ToString()); contrastWindowsLevel = int.Parse(szValueContrastWindowsLevel.ToString()); gammaWindowsLevel = int.Parse(szValueGammaWindowsLevel.ToString()); + profileToggleEnabled = bool.Parse(szValueProfileToggleEnabled.ToString()); + profileToggleHotkey = szValueProfileToggleHotkey.ToString(); + profileToggleState = bool.Parse(szValueProfileToggleState.ToString()); } catch (Exception) { @@ -219,6 +256,9 @@ public void ReadVibranceSettings(GraphicsAdapter graphicsAdapter, out int vibran brightnessWindowsLevel = 50; contrastWindowsLevel = 50; gammaWindowsLevel = 100; + profileToggleEnabled = false; + profileToggleHotkey = string.Empty; + profileToggleState = true; return; } diff --git a/vibrance.GUI/common/VibranceGUI.Designer.cs b/vibrance.GUI/common/VibranceGUI.Designer.cs index 096c31b..4dac357 100644 --- a/vibrance.GUI/common/VibranceGUI.Designer.cs +++ b/vibrance.GUI/common/VibranceGUI.Designer.cs @@ -36,6 +36,9 @@ private void InitializeComponent() this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.backgroundWorker = new System.ComponentModel.BackgroundWorker(); this.checkBoxAutostart = new System.Windows.Forms.CheckBox(); + this.checkBoxProfileToggleEnabled = new System.Windows.Forms.CheckBox(); + this.labelProfileToggleHotkey = new System.Windows.Forms.Label(); + this.textBoxProfileToggleHotkey = new System.Windows.Forms.TextBox(); this.groupBoxSettings = new System.Windows.Forms.GroupBox(); this.checkBoxNeverChangeResolutions = new System.Windows.Forms.CheckBox(); this.checkBoxPrimaryMonitorOnly = new System.Windows.Forms.CheckBox(); @@ -137,8 +140,46 @@ private void InitializeComponent() this.checkBoxAutostart.UseVisualStyleBackColor = true; this.checkBoxAutostart.CheckedChanged += new System.EventHandler(this.checkBoxAutostart_CheckedChanged); // + // checkBoxProfileToggleEnabled + // + this.checkBoxProfileToggleEnabled.AutoSize = true; + this.checkBoxProfileToggleEnabled.Location = new System.Drawing.Point(315, 29); + this.checkBoxProfileToggleEnabled.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.checkBoxProfileToggleEnabled.Name = "checkBoxProfileToggleEnabled"; + this.checkBoxProfileToggleEnabled.Size = new System.Drawing.Size(256, 24); + this.checkBoxProfileToggleEnabled.TabIndex = 17; + this.checkBoxProfileToggleEnabled.Text = "Enable profile toggle hotkey"; + this.toolTip.SetToolTip(this.checkBoxProfileToggleEnabled, "Enable a global hotkey that toggles profile settings on the active application."); + this.checkBoxProfileToggleEnabled.UseVisualStyleBackColor = true; + this.checkBoxProfileToggleEnabled.CheckedChanged += new System.EventHandler(this.checkBoxProfileToggleEnabled_CheckedChanged); + // + // labelProfileToggleHotkey + // + this.labelProfileToggleHotkey.AutoSize = true; + this.labelProfileToggleHotkey.Location = new System.Drawing.Point(311, 65); + this.labelProfileToggleHotkey.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.labelProfileToggleHotkey.Name = "labelProfileToggleHotkey"; + this.labelProfileToggleHotkey.Size = new System.Drawing.Size(237, 20); + this.labelProfileToggleHotkey.TabIndex = 18; + this.labelProfileToggleHotkey.Text = "Profile toggle hotkey (press keys)"; + this.labelProfileToggleHotkey.Visible = false; + // + // textBoxProfileToggleHotkey + // + this.textBoxProfileToggleHotkey.Location = new System.Drawing.Point(315, 89); + this.textBoxProfileToggleHotkey.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.textBoxProfileToggleHotkey.Name = "textBoxProfileToggleHotkey"; + this.textBoxProfileToggleHotkey.ReadOnly = true; + this.textBoxProfileToggleHotkey.Size = new System.Drawing.Size(269, 26); + this.textBoxProfileToggleHotkey.TabIndex = 19; + this.textBoxProfileToggleHotkey.Visible = false; + this.textBoxProfileToggleHotkey.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBoxProfileToggleHotkey_KeyDown); + // // groupBoxSettings // + this.groupBoxSettings.Controls.Add(this.textBoxProfileToggleHotkey); + this.groupBoxSettings.Controls.Add(this.labelProfileToggleHotkey); + this.groupBoxSettings.Controls.Add(this.checkBoxProfileToggleEnabled); this.groupBoxSettings.Controls.Add(this.checkBoxNeverChangeResolutions); this.groupBoxSettings.Controls.Add(this.checkBoxPrimaryMonitorOnly); this.groupBoxSettings.Controls.Add(this.groupBox3); @@ -543,6 +584,9 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; private System.ComponentModel.BackgroundWorker backgroundWorker; private System.Windows.Forms.CheckBox checkBoxAutostart; + private System.Windows.Forms.CheckBox checkBoxProfileToggleEnabled; + private System.Windows.Forms.Label labelProfileToggleHotkey; + private System.Windows.Forms.TextBox textBoxProfileToggleHotkey; private System.Windows.Forms.GroupBox groupBoxSettings; private System.Windows.Forms.GroupBox groupBox3; private System.Windows.Forms.Label labelWindowsLevel; @@ -575,4 +619,3 @@ private void InitializeComponent() private System.Windows.Forms.TrackBar trackBarBrightness; } } - diff --git a/vibrance.GUI/common/VibranceGUI.cs b/vibrance.GUI/common/VibranceGUI.cs index f1973d5..675b9e6 100644 --- a/vibrance.GUI/common/VibranceGUI.cs +++ b/vibrance.GUI/common/VibranceGUI.cs @@ -25,6 +25,11 @@ public partial class VibranceGUI : Form private const string AppName = "vibranceGUI"; private const string TwitterLink = "https://twitter.com/juvlarN"; private const string PaypalDonationLink = "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JDQFNKNNEW356"; + private const int WmHotkey = 0x0312; + private const int ProfileToggleHotkeyId = 1; + private const uint HotkeyModAlt = 0x0001; + private const uint HotkeyModControl = 0x0002; + private const uint HotkeyModShift = 0x0004; private bool _allowVisible; private List _applicationSettings; @@ -32,6 +37,18 @@ public partial class VibranceGUI : Form private readonly Dictionary>> _windowsResolutionSettings; private readonly bool _isForcedExecution; + private bool _isLoadingSettings; + private bool _isProfileToggleHotkeyRegistered; + private string _profileToggleHotkey; + + [DllImport("user32.dll")] + private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); + + [DllImport("user32.dll")] + private static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); public VibranceGUI( Func, Dictionary>>, IVibranceProxy> getProxy, @@ -126,6 +143,9 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) int brightnessWindowsLevel = 50; int contrastWindowsLevel = 50; int gammaWindowsLevel = 100; + bool profileToggleEnabled = false; + string profileToggleHotkey = string.Empty; + bool profileToggleState = true; while (!this.IsHandleCreated) { @@ -136,12 +156,12 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { this.Invoke((MethodInvoker)delegate { - ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel); + ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel, out profileToggleEnabled, out profileToggleHotkey, out profileToggleState); }); } else { - ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel); + ReadVibranceSettings(out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, out neverChangeColorSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel, out profileToggleEnabled, out profileToggleHotkey, out profileToggleState); } if (_v.GetVibranceInfo().isInitialized) @@ -157,6 +177,23 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) _v.SetNeverSwitchResolution(neverSwitchResolution); _v.SetNeverChangeColorSettings(neverChangeColorSettings); _v.SetWindowsColorSettings(brightnessWindowsLevel, contrastWindowsLevel, gammaWindowsLevel); + bool isProfileToggleFeatureEnabled = profileToggleEnabled && !string.IsNullOrWhiteSpace(profileToggleHotkey); + _v.SetProfileToggleEnabled(isProfileToggleFeatureEnabled); + if (isProfileToggleFeatureEnabled) + { + _v.SetProfileToggleState(profileToggleState); + } + if (this.InvokeRequired) + { + this.Invoke((MethodInvoker)delegate + { + UpdateProfileToggleHotkey(profileToggleHotkey, isProfileToggleFeatureEnabled); + }); + } + else + { + UpdateProfileToggleHotkey(profileToggleHotkey, isProfileToggleFeatureEnabled); + } } } @@ -233,6 +270,9 @@ private void ForceSaveVibranceSettings() int brightnessWindowsLevel = 50; int contrastWindowsLevel = 50; int gammaWindowsLevel = 100; + bool profileToggleEnabled = false; + string profileToggleHotkey = string.Empty; + bool profileToggleState = true; this.Invoke((MethodInvoker)delegate { windowsLevel = trackBarWindowsLevel.Value; @@ -242,8 +282,11 @@ private void ForceSaveVibranceSettings() brightnessWindowsLevel = trackBarBrightness.Value; contrastWindowsLevel = trackBarContrast.Value; gammaWindowsLevel = trackBarGamma.Value; + profileToggleEnabled = checkBoxProfileToggleEnabled.Checked; + profileToggleHotkey = textBoxProfileToggleHotkey.Text; + profileToggleState = _v.IsProfileToggleOn(); }); - SaveVibranceSettings(windowsLevel, affectPrimaryMonitorOnly, neverSwitchResolution, neverChangeColorSettings, brightnessWindowsLevel, contrastWindowsLevel, gammaWindowsLevel); + SaveVibranceSettings(windowsLevel, affectPrimaryMonitorOnly, neverSwitchResolution, neverChangeColorSettings, brightnessWindowsLevel, contrastWindowsLevel, gammaWindowsLevel, profileToggleEnabled, profileToggleHotkey, profileToggleState); } private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) @@ -341,6 +384,53 @@ private void checkBoxAutostart_CheckedChanged(object sender, EventArgs e) notifyIcon.ShowBalloonTip(250); } + private void checkBoxProfileToggleEnabled_CheckedChanged(object sender, EventArgs e) + { + if (_v == null || _isLoadingSettings) + { + return; + } + + bool enabled = checkBoxProfileToggleEnabled.Checked; + bool shouldEnable = enabled && !string.IsNullOrWhiteSpace(textBoxProfileToggleHotkey.Text); + _v.SetProfileToggleEnabled(shouldEnable); + if (!enabled) + { + _v.SetProfileToggleState(true); + } + ToggleProfileHotkeyControls(enabled); + UpdateProfileToggleHotkey(textBoxProfileToggleHotkey.Text, shouldEnable); + + if (!this.settingsBackgroundWorker.IsBusy) + { + this.settingsBackgroundWorker.RunWorkerAsync(); + } + } + + private void textBoxProfileToggleHotkey_KeyDown(object sender, KeyEventArgs e) + { + e.SuppressKeyPress = true; + if (!checkBoxProfileToggleEnabled.Checked) + { + return; + } + + string hotkey = BuildHotkeyString(e); + if (string.IsNullOrWhiteSpace(hotkey)) + { + return; + } + + textBoxProfileToggleHotkey.Text = hotkey; + bool shouldEnable = checkBoxProfileToggleEnabled.Checked && !string.IsNullOrWhiteSpace(hotkey); + _v.SetProfileToggleEnabled(shouldEnable); + UpdateProfileToggleHotkey(hotkey, shouldEnable); + if (!this.settingsBackgroundWorker.IsBusy) + { + this.settingsBackgroundWorker.RunWorkerAsync(); + } + } + private void checkBoxNeverChangeColorSettings_CheckedChanged(object sender, EventArgs e) { @@ -361,6 +451,164 @@ private void checkBoxNeverChangeColorSettings_CheckedChanged(object sender, Even } } + private void ToggleProfileHotkeyControls(bool enabled) + { + labelProfileToggleHotkey.Visible = enabled; + textBoxProfileToggleHotkey.Visible = enabled; + } + + private void UpdateProfileToggleHotkey(string hotkey, bool enabled) + { + _profileToggleHotkey = hotkey ?? string.Empty; + if (!enabled) + { + UnregisterProfileToggleHotkey(); + return; + } + + RegisterProfileToggleHotkey(); + } + + private void RegisterProfileToggleHotkey() + { + UnregisterProfileToggleHotkey(); + if (string.IsNullOrWhiteSpace(_profileToggleHotkey)) + { + return; + } + + if (!TryParseHotkey(_profileToggleHotkey, out uint modifiers, out uint key)) + { + return; + } + + _isProfileToggleHotkeyRegistered = RegisterHotKey(this.Handle, ProfileToggleHotkeyId, modifiers, key); + } + + private void UnregisterProfileToggleHotkey() + { + if (_isProfileToggleHotkeyRegistered) + { + UnregisterHotKey(this.Handle, ProfileToggleHotkeyId); + _isProfileToggleHotkeyRegistered = false; + } + } + + private string BuildHotkeyString(KeyEventArgs e) + { + List parts = new List(); + if (e.Control) + { + parts.Add("Ctrl"); + } + if (e.Alt) + { + parts.Add("Alt"); + } + if (e.Shift) + { + parts.Add("Shift"); + } + + Keys keyCode = e.KeyCode; + if (keyCode == Keys.ControlKey || keyCode == Keys.Menu || keyCode == Keys.ShiftKey) + { + return string.Empty; + } + + parts.Add(keyCode.ToString()); + return string.Join("+", parts); + } + + 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; + } + + protected override void WndProc(ref Message m) + { + if (m.Msg == WmHotkey && m.WParam.ToInt32() == ProfileToggleHotkeyId) + { + ToggleProfileForActiveWindow(); + } + base.WndProc(ref m); + } + + private void ToggleProfileForActiveWindow() + { + if (_v == null || !_v.IsProfileToggleEnabled()) + { + return; + } + + IntPtr foregroundWindow = GetForegroundWindow(); + if (foregroundWindow == IntPtr.Zero) + { + return; + } + + uint processId; + if (GetWindowThreadProcessId(foregroundWindow, out processId) == 0 || processId == 0) + { + return; + } + + string processName; + try + { + using (Process process = Process.GetProcessById((int)processId)) + { + processName = process.ProcessName; + } + } + catch (Exception ex) + { + Log(ex); + return; + } + + bool newToggleState = !_v.IsProfileToggleOn(); + _v.SetProfileToggleState(newToggleState); + _v.ApplyProfileToggle(foregroundWindow, processName, newToggleState); + } + + [DllImport("user32.dll", SetLastError = true)] + private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); + private void twitterToolStripTextBox_Click(object sender, EventArgs e) { Process.Start(TwitterLink); @@ -383,6 +631,7 @@ private void SetGuiEnabledFlag(bool flag) this.buttonRemoveProgram.Enabled = flag; this.checkBoxNeverChangeResolutions.Enabled = flag; this.checkBoxNeverChangeColorSettings.Enabled = flag; + this.checkBoxProfileToggleEnabled.Enabled = flag; }); } @@ -397,6 +646,7 @@ private void CleanUp() { _v.HandleDvcExit(); _v.SetShouldRun(false); + UnregisterProfileToggleHotkey(); _v.UnloadLibraryEx(); } } @@ -436,17 +686,20 @@ public static void Log(string msg) } private void ReadVibranceSettings(out int vibranceWindowsLevel, out bool affectPrimaryMonitorOnly, out bool neverSwitchResolution, - out bool neverChangeColorSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel) + out bool neverChangeColorSettings, out int brightnessWindowsLevel, out int contrastWindowsLevel, out int gammaWindowsLevel, + out bool profileToggleEnabled, out string profileToggleHotkey, out bool profileToggleState) { _registryController = new RegistryController(); this.checkBoxAutostart.Checked = _registryController.IsProgramRegistered(AppName); SettingsController settingsController = new SettingsController(); settingsController.ReadVibranceSettings(_v.GraphicsAdapter, out vibranceWindowsLevel, out affectPrimaryMonitorOnly, out neverSwitchResolution, - out neverChangeColorSettings, out _applicationSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel); + out neverChangeColorSettings, out _applicationSettings, out brightnessWindowsLevel, out contrastWindowsLevel, out gammaWindowsLevel, + out profileToggleEnabled, out profileToggleHotkey, out profileToggleState); if (this.IsHandleCreated) { + _isLoadingSettings = true; //no null check needed, SettingsController will always return matching values. labelWindowsLevel.Text = TrackbarLabelHelper.ResolveVibranceLabelLevel(_graphicsAdapter, vibranceWindowsLevel); @@ -454,6 +707,13 @@ private void ReadVibranceSettings(out int vibranceWindowsLevel, out bool affectP checkBoxPrimaryMonitorOnly.Checked = affectPrimaryMonitorOnly; checkBoxNeverChangeResolutions.Checked = neverSwitchResolution; checkBoxNeverChangeColorSettings.Checked = neverChangeColorSettings; + checkBoxProfileToggleEnabled.Checked = profileToggleEnabled; + textBoxProfileToggleHotkey.Text = profileToggleHotkey; + ToggleProfileHotkeyControls(profileToggleEnabled); + _profileToggleHotkey = profileToggleHotkey; + _isLoadingSettings = false; + _v.SetProfileToggleState(profileToggleState); + UpdateProfileToggleHotkey(profileToggleHotkey, profileToggleEnabled); foreach (ApplicationSetting application in _applicationSettings.ToList()) { if (!File.Exists(application.FileName)) @@ -477,7 +737,7 @@ private void ReadVibranceSettings(out int vibranceWindowsLevel, out bool affectP } } - private void SaveVibranceSettings(int windowsLevel, bool affectPrimaryMonitorOnly, bool neverSwitchResolution, bool neverChangeColorSettings, int brightnessWindowsLevel, int contrastWindowsLevel, int gammaWindowsLevel) + private void SaveVibranceSettings(int windowsLevel, bool affectPrimaryMonitorOnly, bool neverSwitchResolution, bool neverChangeColorSettings, int brightnessWindowsLevel, int contrastWindowsLevel, int gammaWindowsLevel, bool profileToggleEnabled, string profileToggleHotkey, bool profileToggleState) { SettingsController settingsController = new SettingsController(); @@ -489,7 +749,10 @@ private void SaveVibranceSettings(int windowsLevel, bool affectPrimaryMonitorOnl _applicationSettings, brightnessWindowsLevel.ToString(), contrastWindowsLevel.ToString(), - gammaWindowsLevel.ToString() + gammaWindowsLevel.ToString(), + profileToggleEnabled.ToString(), + profileToggleHotkey, + profileToggleState.ToString() ); } @@ -636,4 +899,4 @@ private void buttonProcessExplorer_Click(object sender, EventArgs e) ex.Show(); } } -} \ No newline at end of file +}