From 5ed1de0fcfd28798aa7e4f8ba84a3c1bf95218d3 Mon Sep 17 00:00:00 2001 From: Serge <5920850+seerge@users.noreply.github.com> Date: Wed, 3 May 2023 16:49:12 +0200 Subject: [PATCH] Added option to keep dGPU off on usb-c --- app/ASUSWmi.cs | 5 + app/AnimeMatrix/AnimeMatrixDevice.cs | 99 +++++++-------- ...Keyboard.Designer.cs => Extra.Designer.cs} | 114 ++++++++++-------- app/{Keyboard.cs => Extra.cs} | 33 ++++- app/{Keyboard.resx => Extra.resx} | 0 app/Fans.cs | 18 ++- app/Gpu/NvidiaGpuControl.cs | 7 +- app/HardwareMonitor.cs | 8 +- app/Program.cs | 12 +- app/Properties/Strings.Designer.cs | 18 +++ app/Properties/Strings.resx | 6 + app/Properties/Strings.zh-TW.resx | 2 +- app/Settings.cs | 55 +++++++-- app/old-ps1-script/ghelper.zip | Bin 13720 -> 0 bytes 14 files changed, 244 insertions(+), 133 deletions(-) rename app/{Keyboard.Designer.cs => Extra.Designer.cs} (81%) rename app/{Keyboard.cs => Extra.cs} (82%) rename app/{Keyboard.resx => Extra.resx} (100%) delete mode 100644 app/old-ps1-script/ghelper.zip diff --git a/app/ASUSWmi.cs b/app/ASUSWmi.cs index 58c7a25c..68995f8f 100644 --- a/app/ASUSWmi.cs +++ b/app/ASUSWmi.cs @@ -14,6 +14,11 @@ public class ASUSWmi public const int KB_Light_Up = 0xc4; public const int KB_Light_Down = 0xc5; + public const int ChargerMode = 0x0012006C; + + public const int ChargerUSB = 2; + public const int ChargerBarrel = 1; + public const uint CPU_Fan = 0x00110013; public const uint GPU_Fan = 0x00110014; public const uint Mid_Fan = 0x00110031; diff --git a/app/AnimeMatrix/AnimeMatrixDevice.cs b/app/AnimeMatrix/AnimeMatrixDevice.cs index 026091e0..4b7f4a87 100644 --- a/app/AnimeMatrix/AnimeMatrixDevice.cs +++ b/app/AnimeMatrix/AnimeMatrixDevice.cs @@ -6,6 +6,9 @@ using System.Drawing.Drawing2D; using System.Text; using System.Globalization; using System; +using System.Drawing; +using OSD; +using System.Diagnostics; namespace Starlight.AnimeMatrix { @@ -107,9 +110,6 @@ namespace Starlight.AnimeMatrix MaxColumns = 33; dx = 1; - //FullRows = 7; - //FullEvenRows = 3; - MaxRows = 55; LedCount = 1245; @@ -177,17 +177,8 @@ namespace Starlight.AnimeMatrix { return (y + 1) / 2 - 3; } - case AnimeType.GA402: - if (y < 11) - { - return 0; - } - else - { - return (y) / 2 - 5; - } default: - throw new ArgumentException("Invalid anime type", nameof(_model)); + return (int)Math.Ceiling(Math.Max(0, y - 11) / 2F); } } @@ -197,10 +188,8 @@ namespace Starlight.AnimeMatrix { case AnimeType.GA401: return 33; - case AnimeType.GA402: - return 34; default: - throw new ArgumentException("Invalid anime type", nameof(_model)); + return 34; } } @@ -221,36 +210,15 @@ namespace Starlight.AnimeMatrix default: return 36 - y / 2; } - case AnimeType.GA402: - return Width(y) - FirstX(y); default: - throw new ArgumentException("Invalid anime type", nameof(_model)); + return Width(y) - FirstX(y); } } - /* - public int XStart(int row) - { - return (int)Math.Ceiling(Math.Max(0, row - FullRows) / 2.0); - } - - public int XEnd(int row) - { - if (row <= FullEvenRows) - { - if (row % 2 == 1) return MaxColumns + 2; - else return MaxColumns; - } - return MaxColumns; - } - */ public int RowToLinearAddress(int y) { - EnsureRowInRange(y); - int ret = 0; - for (var i = 0; i < y; i++) ret += Pitch(i); @@ -259,13 +227,10 @@ namespace Starlight.AnimeMatrix public void SetLedPlanar(int x, int y, byte value) { - EnsureRowInRange(y); + if (!IsRowInRange(y)) return; if (x >= FirstX(y) && x < Width(y)) - { SetLedLinear(RowToLinearAddress(y) - FirstX(y) + x + dx, value); - //Debug.Write((RowToLinearAddress(y) - FirstX(y) + x + dx).ToString() + " "); - } } public void WakeUp() @@ -366,9 +331,9 @@ namespace Starlight.AnimeMatrix int second = DateTime.Now.Second; if (CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern.Contains("H")) - PresentText(DateTime.Now.ToString("H" + ((second % 2 == 0)?":":" ") + "mm")); + PresentTextDiagonal(DateTime.Now.ToString("H" + ((second % 2 == 0)?":":" ") + "mm")); else - PresentText(DateTime.Now.ToString("h" + ((second % 2 == 0) ? ":" : " ") + "mm"), DateTime.Now.ToString("tt")); + PresentTextDiagonal(DateTime.Now.ToString("h" + ((second % 2 == 0) ? ":" : " ") + "mmtt")); } public void PresentText(string text1, string text2 = "") @@ -442,12 +407,52 @@ namespace Starlight.AnimeMatrix } } - private void EnsureRowInRange(int row) + + public void SetLedDiagonal(int x, int y, byte color, int delta = 10) { - if (row < 0 || row >= MaxRows) + //x+=delta; + y-=delta; + + int dx = (x - y)/2; + int dy = x + y; + SetLedPlanar(dx, dy, color); + } + + public void PresentTextDiagonal(string text) + { + int maxX = (int)Math.Sqrt(MaxRows * MaxRows + MaxColumns * MaxColumns); + + using (Bitmap bmp = new Bitmap(maxX, MaxRows)) { - throw new IndexOutOfRangeException($"Y-coordinate should fall in range of [0, {MaxRows - 1}]."); + using (Graphics g = Graphics.FromImage(bmp)) + { + g.CompositingQuality = CompositingQuality.HighQuality; + g.SmoothingMode = SmoothingMode.AntiAlias; + + using (Font font = new Font("Calibri", 16F, GraphicsUnit.Pixel)) + { + SizeF textSize = g.MeasureString(text, font); + g.DrawString(text, font, Brushes.White, 4, 0); + } + } + + for (int y = 0; y < bmp.Height; y++) + { + for (int x = 0; x < bmp.Width; x++) + { + var pixel = bmp.GetPixel(x, y); + var color = (pixel.R + pixel.G + pixel.B) / 3; + SetLedDiagonal(x, y, (byte)color); + } + } } + + Present(); + } + + private bool IsRowInRange(int row) + { + return (row >= 0 && row < MaxRows); } private bool IsAddressableLed(int address) diff --git a/app/Keyboard.Designer.cs b/app/Extra.Designer.cs similarity index 81% rename from app/Keyboard.Designer.cs rename to app/Extra.Designer.cs index 66da7efe..eb4caf0c 100644 --- a/app/Keyboard.Designer.cs +++ b/app/Extra.Designer.cs @@ -3,7 +3,7 @@ using GHelper.Properties; namespace GHelper { - partial class Keyboard + partial class Extra { /// /// Required designer variable. @@ -31,7 +31,7 @@ namespace GHelper /// private void InitializeComponent() { - groupBox1 = new GroupBox(); + groupBindings = new GroupBox(); pictureHelp = new PictureBox(); textFNF4 = new TextBox(); comboFNF4 = new RComboBox(); @@ -52,39 +52,40 @@ namespace GHelper checkBoot = new CheckBox(); checkAwake = new CheckBox(); groupOther = new GroupBox(); + checkUSBC = new CheckBox(); checkNoOverdrive = new CheckBox(); checkKeyboardAuto = new CheckBox(); checkTopmost = new CheckBox(); - groupBox1.SuspendLayout(); + groupBindings.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)pictureHelp).BeginInit(); groupLight.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)trackBrightness).BeginInit(); groupOther.SuspendLayout(); SuspendLayout(); // - // groupBox1 + // groupBindings // - groupBox1.Controls.Add(pictureHelp); - groupBox1.Controls.Add(textFNF4); - groupBox1.Controls.Add(comboFNF4); - groupBox1.Controls.Add(labelFNF4); - groupBox1.Controls.Add(textM4); - groupBox1.Controls.Add(textM3); - groupBox1.Controls.Add(comboM4); - groupBox1.Controls.Add(labelM4); - groupBox1.Controls.Add(comboM3); - groupBox1.Controls.Add(labelM3); - groupBox1.Dock = DockStyle.Top; - groupBox1.Location = new Point(10, 10); - groupBox1.Name = "groupBox1"; - groupBox1.Size = new Size(840, 242); - groupBox1.TabIndex = 0; - groupBox1.TabStop = false; - groupBox1.Text = Properties.Strings.KeyBindings; + groupBindings.Controls.Add(pictureHelp); + groupBindings.Controls.Add(textFNF4); + groupBindings.Controls.Add(comboFNF4); + groupBindings.Controls.Add(labelFNF4); + groupBindings.Controls.Add(textM4); + groupBindings.Controls.Add(textM3); + groupBindings.Controls.Add(comboM4); + groupBindings.Controls.Add(labelM4); + groupBindings.Controls.Add(comboM3); + groupBindings.Controls.Add(labelM3); + groupBindings.Dock = DockStyle.Top; + groupBindings.Location = new Point(10, 10); + groupBindings.Name = "groupBindings"; + groupBindings.Size = new Size(844, 242); + groupBindings.TabIndex = 0; + groupBindings.TabStop = false; + groupBindings.Text = "Key Bindings"; // // pictureHelp // - pictureHelp.BackgroundImage = Properties.Resources.icons8_help_64; + pictureHelp.BackgroundImage = Resources.icons8_help_64; pictureHelp.BackgroundImageLayout = ImageLayout.Zoom; pictureHelp.Cursor = Cursors.Hand; pictureHelp.Location = new Point(744, 57); @@ -141,7 +142,7 @@ namespace GHelper comboM4.BorderColor = Color.White; comboM4.ButtonColor = Color.FromArgb(255, 255, 255); comboM4.FormattingEnabled = true; - comboM4.Items.AddRange(new object[] { Properties.Strings.PerformanceMode, Properties.Strings.OpenGHelper, Properties.Strings.Custom }); + comboM4.Items.AddRange(new object[] { Strings.PerformanceMode, Strings.OpenGHelper, Strings.Custom }); comboM4.Location = new Point(93, 112); comboM4.Name = "comboM4"; comboM4.Size = new Size(312, 40); @@ -161,7 +162,7 @@ namespace GHelper comboM3.BorderColor = Color.White; comboM3.ButtonColor = Color.FromArgb(255, 255, 255); comboM3.FormattingEnabled = true; - comboM3.Items.AddRange(new object[] { Properties.Strings.Default, Properties.Strings.VolumeMute, Properties.Strings.PlayPause, Properties.Strings.PrintScreen, Properties.Strings.ToggleAura, Properties.Strings.Custom }); + comboM3.Items.AddRange(new object[] { Strings.Default, Strings.VolumeMute, Strings.PlayPause, Strings.PrintScreen, Strings.ToggleAura, Strings.Custom }); comboM3.Location = new Point(93, 54); comboM3.Name = "comboM3"; comboM3.Size = new Size(312, 40); @@ -189,11 +190,10 @@ namespace GHelper groupLight.Dock = DockStyle.Top; groupLight.Location = new Point(10, 252); groupLight.Name = "groupLight"; - groupLight.Size = new Size(840, 395); + groupLight.Size = new Size(844, 395); groupLight.TabIndex = 1; groupLight.TabStop = false; - groupLight.Text = Properties.Strings.KeyboardBacklight; - //groupLight.AutoSize = true; + groupLight.Text = "Keyboard Backlight"; // // labelBrightness // @@ -201,16 +201,16 @@ namespace GHelper labelBrightness.Name = "labelBrightness"; labelBrightness.Size = new Size(197, 49); labelBrightness.TabIndex = 0; - labelBrightness.Text = Properties.Strings.Brightness; + labelBrightness.Text = "Brightness"; // // trackBrightness // trackBrightness.Location = new Point(228, 294); - trackBrightness.Name = "trackBrightness"; - trackBrightness.Size = new Size(600, 30); - trackBrightness.TabIndex = 1; - trackBrightness.Minimum = 0; trackBrightness.Maximum = 3; + trackBrightness.Name = "trackBrightness"; + trackBrightness.Size = new Size(600, 90); + trackBrightness.TabIndex = 1; + trackBrightness.TickStyle = TickStyle.TopLeft; // // labelSpeed // @@ -220,7 +220,7 @@ namespace GHelper labelSpeed.Name = "labelSpeed"; labelSpeed.Size = new Size(198, 32); labelSpeed.TabIndex = 40; - labelSpeed.Text = Properties.Strings.AnimationSpeed; + labelSpeed.Text = "Animation Speed"; // // comboKeyboardSpeed // @@ -245,7 +245,7 @@ namespace GHelper checkShutdown.Name = "checkShutdown"; checkShutdown.Size = new Size(154, 36); checkShutdown.TabIndex = 3; - checkShutdown.Text = Properties.Strings.Shutdown; + checkShutdown.Text = Strings.Shutdown; checkShutdown.UseVisualStyleBackColor = true; // // checkSleep @@ -255,7 +255,7 @@ namespace GHelper checkSleep.Name = "checkSleep"; checkSleep.Size = new Size(105, 36); checkSleep.TabIndex = 2; - checkSleep.Text = Properties.Strings.Sleep; + checkSleep.Text = Strings.Sleep; checkSleep.UseVisualStyleBackColor = true; // // checkBoot @@ -265,7 +265,7 @@ namespace GHelper checkBoot.Name = "checkBoot"; checkBoot.Size = new Size(96, 36); checkBoot.TabIndex = 1; - checkBoot.Text = Properties.Strings.Boot; + checkBoot.Text = Strings.Boot; checkBoot.UseVisualStyleBackColor = true; // // checkAwake @@ -275,21 +275,32 @@ namespace GHelper checkAwake.Name = "checkAwake"; checkAwake.Size = new Size(115, 36); checkAwake.TabIndex = 0; - checkAwake.Text = Properties.Strings.Awake; + checkAwake.Text = Strings.Awake; checkAwake.UseVisualStyleBackColor = true; // // groupOther // + groupOther.Controls.Add(checkUSBC); groupOther.Controls.Add(checkNoOverdrive); groupOther.Controls.Add(checkKeyboardAuto); groupOther.Controls.Add(checkTopmost); groupOther.Dock = DockStyle.Top; - groupOther.Location = new Point(10, 626); + groupOther.Location = new Point(10, 647); groupOther.Name = "groupOther"; - groupOther.Size = new Size(840, 225); + groupOther.Size = new Size(844, 293); groupOther.TabIndex = 2; groupOther.TabStop = false; - groupOther.Text = Properties.Strings.Other; + groupOther.Text = "Other"; + // + // checkUSBC + // + checkUSBC.AutoSize = true; + checkUSBC.Location = new Point(25, 210); + checkUSBC.Name = "checkUSBC"; + checkUSBC.Size = new Size(659, 36); + checkUSBC.TabIndex = 4; + checkUSBC.Text = "Keep GPU disabled on USB-C charger in Optimized mode"; + checkUSBC.UseVisualStyleBackColor = true; // // checkNoOverdrive // @@ -298,7 +309,7 @@ namespace GHelper checkNoOverdrive.Name = "checkNoOverdrive"; checkNoOverdrive.Size = new Size(307, 36); checkNoOverdrive.TabIndex = 3; - checkNoOverdrive.Text = Properties.Strings.DisableOverdrive; + checkNoOverdrive.Text = Strings.DisableOverdrive; checkNoOverdrive.UseVisualStyleBackColor = true; // // checkKeyboardAuto @@ -309,7 +320,7 @@ namespace GHelper checkKeyboardAuto.Name = "checkKeyboardAuto"; checkKeyboardAuto.Size = new Size(712, 36); checkKeyboardAuto.TabIndex = 2; - checkKeyboardAuto.Text = Properties.Strings.KeyboardAuto; + checkKeyboardAuto.Text = Strings.KeyboardAuto; checkKeyboardAuto.UseVisualStyleBackColor = true; // // checkTopmost @@ -319,28 +330,28 @@ namespace GHelper checkTopmost.Name = "checkTopmost"; checkTopmost.Size = new Size(390, 36); checkTopmost.TabIndex = 1; - checkTopmost.Text = Properties.Strings.WindowTop; + checkTopmost.Text = Strings.WindowTop; checkTopmost.UseVisualStyleBackColor = true; // - // Keyboard + // Extra // AutoScaleDimensions = new SizeF(13F, 32F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(860, 890); + ClientSize = new Size(864, 953); Controls.Add(groupOther); Controls.Add(groupLight); - Controls.Add(groupBox1); + Controls.Add(groupBindings); FormBorderStyle = FormBorderStyle.FixedSingle; MaximizeBox = false; MdiChildrenMinimizedAnchorBottom = false; MinimizeBox = false; - Name = "Keyboard"; + Name = "Extra"; Padding = new Padding(10); ShowIcon = false; ShowInTaskbar = false; - Text = Properties.Strings.ExtraSettings; - groupBox1.ResumeLayout(false); - groupBox1.PerformLayout(); + Text = "Extra Settings"; + groupBindings.ResumeLayout(false); + groupBindings.PerformLayout(); ((System.ComponentModel.ISupportInitialize)pictureHelp).EndInit(); groupLight.ResumeLayout(false); groupLight.PerformLayout(); @@ -352,7 +363,7 @@ namespace GHelper #endregion - private GroupBox groupBox1; + private GroupBox groupBindings; private Label labelM3; private RComboBox comboM3; private RComboBox comboM4; @@ -376,5 +387,6 @@ namespace GHelper private PictureBox pictureHelp; private TrackBar trackBrightness; private Label labelBrightness; + private CheckBox checkUSBC; } } \ No newline at end of file diff --git a/app/Keyboard.cs b/app/Extra.cs similarity index 82% rename from app/Keyboard.cs rename to app/Extra.cs index f7e8258b..cc929eca 100644 --- a/app/Keyboard.cs +++ b/app/Extra.cs @@ -3,7 +3,7 @@ using System.Diagnostics; namespace GHelper { - public partial class Keyboard : RForm + public partial class Extra : RForm { Dictionary customActions = new Dictionary @@ -15,6 +15,7 @@ namespace GHelper {"aura", Properties.Strings.ToggleAura}, {"ghelper", Properties.Strings.OpenGHelper}, {"screen", Properties.Strings.ToggleScreen}, + {"miniled", Properties.Strings.ToggleMiniled}, {"custom", Properties.Strings.Custom} }; @@ -52,9 +53,29 @@ namespace GHelper }; } - public Keyboard() + public Extra() { InitializeComponent(); + + groupBindings.Text = Properties.Strings.KeyBindings; + groupLight.Text = Properties.Strings.KeyboardBacklight; + groupOther.Text = Properties.Strings.Other; + + checkAwake.Text = Properties.Strings.Awake; + checkSleep.Text = Properties.Strings.Sleep; + checkBoot.Text = Properties.Strings.Boot; + checkShutdown.Text = Properties.Strings.Shutdown; + + labelSpeed.Text = Properties.Strings.AnimationSpeed; + labelBrightness.Text = Properties.Strings.Brightness; + + checkKeyboardAuto.Text = Properties.Strings.KeyboardAuto; + checkNoOverdrive.Text = Properties.Strings.DisableOverdrive; + checkTopmost.Text = Properties.Strings.WindowTop; + checkUSBC.Text = Properties.Strings.OptimizedUSBC; + + Text = Properties.Strings.ExtraSettings; + InitTheme(); SetKeyCombo(comboM3, textM3, "m3"); @@ -89,6 +110,9 @@ namespace GHelper checkNoOverdrive.Checked = (Program.config.getConfig("no_overdrive") == 1); checkNoOverdrive.CheckedChanged += CheckNoOverdrive_CheckedChanged; + checkUSBC.Checked = (Program.config.getConfig("optimized_usbc") == 1); + checkUSBC.CheckedChanged += CheckUSBC_CheckedChanged; + int kb_brightness = Program.config.getConfig("keyboard_brightness"); trackBrightness.Value = (kb_brightness >= 0 && kb_brightness <= 3) ? kb_brightness : 3; @@ -97,6 +121,11 @@ namespace GHelper } + private void CheckUSBC_CheckedChanged(object? sender, EventArgs e) + { + Program.config.setConfig("optimized_usbc", (checkUSBC.Checked ? 1 : 0)); + } + private void TrackBrightness_Scroll(object? sender, EventArgs e) { Program.config.setConfig("keyboard_brightness", trackBrightness.Value); diff --git a/app/Keyboard.resx b/app/Extra.resx similarity index 100% rename from app/Keyboard.resx rename to app/Extra.resx diff --git a/app/Fans.cs b/app/Fans.cs index 4b50649e..aa75a51f 100644 --- a/app/Fans.cs +++ b/app/Fans.cs @@ -86,13 +86,21 @@ namespace GHelper private void InitGPUClocks() { + try + { + using (var _gpuControl = new NvidiaGpuControl()) + { + panelGPU.Visible = _gpuControl.IsValid; - panelGPU.Visible = HardwareMonitor.GpuControl.IsNvidia; + trackGPUCore.Value = Math.Min(Program.config.getConfig("GPUCore"), 300); + trackGPUMemory.Value = Math.Min(Program.config.getConfig("GPUMemory"), 300); + VisualiseGPUClocks(); + } + } catch (Exception ex) + { + panelGPU.Visible=false; + } - trackGPUCore.Value = Math.Min(Program.config.getConfig("GPUCore"), 300); - trackGPUMemory.Value = Math.Min(Program.config.getConfig("GPUMemory"), 300); - - VisualiseGPUClocks(); } private void ButtonResetGPU_Click(object? sender, EventArgs e) diff --git a/app/Gpu/NvidiaGpuControl.cs b/app/Gpu/NvidiaGpuControl.cs index 0360591d..c1ecbf05 100644 --- a/app/Gpu/NvidiaGpuControl.cs +++ b/app/Gpu/NvidiaGpuControl.cs @@ -56,14 +56,9 @@ public class NvidiaGpuControl : IGpuControl return null; PhysicalGPU internalGpu = _internalGpu!; - IUtilizationDomainInfo? gpuUsage = GPUApi.GetUsages(internalGpu.Handle).GPU; - if (gpuUsage == null) - return null; - - return - (int)gpuUsage?.Percentage; + return (int?)gpuUsage?.Percentage; } diff --git a/app/HardwareMonitor.cs b/app/HardwareMonitor.cs index f5a5bf53..08d7f50d 100644 --- a/app/HardwareMonitor.cs +++ b/app/HardwareMonitor.cs @@ -124,22 +124,22 @@ public static class HardwareMonitor return false; } - public static void RecreateGpuTemperatureProviderWithDelay() + public static void RecreateGpuControlWithDelay(int delay = 5) { // Re-enabling the discrete GPU takes a bit of time, // so a simple workaround is to refresh again after that happens Task.Run(async () => { - await Task.Delay(TimeSpan.FromSeconds(5)); - RecreateGpuTemperatureProvider(); + await Task.Delay(TimeSpan.FromSeconds(delay)); + RecreateGpuControl(); }); } - public static void RecreateGpuTemperatureProvider() + public static void RecreateGpuControl() { try { diff --git a/app/Program.cs b/app/Program.cs index e867d14f..80e8a0bc 100644 --- a/app/Program.cs +++ b/app/Program.cs @@ -120,7 +120,7 @@ namespace GHelper SetAutoModes(); - HardwareMonitor.RecreateGpuTemperatureProvider(); + HardwareMonitor.RecreateGpuControl(); // Subscribing for system power change events SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; @@ -172,10 +172,10 @@ namespace GHelper - public static void SetAutoModes() + public static void SetAutoModes(bool monitor = true) { - if (Math.Abs(DateTimeOffset.Now.ToUnixTimeMilliseconds() - lastAuto) < 2000) return; + if (Math.Abs(DateTimeOffset.Now.ToUnixTimeMilliseconds() - lastAuto) < 3000) return; lastAuto = DateTimeOffset.Now.ToUnixTimeMilliseconds(); isPlugged = SystemInformation.PowerStatus.PowerLineStatus; @@ -184,7 +184,8 @@ namespace GHelper settingsForm.SetBatteryChargeLimit(config.getConfig("charge_limit")); settingsForm.AutoPerformance(); - bool switched = settingsForm.AutoGPUMode(); + bool switched = false; + if (monitor) switched = settingsForm.AutoGPUMode(); if (!switched) { @@ -270,6 +271,9 @@ namespace GHelper case "screen": NativeMethods.TurnOffScreen(Program.settingsForm.Handle); break; + case "miniled": + settingsForm.BeginInvoke(settingsForm.ToogleMiniled); + break; case "aura": settingsForm.BeginInvoke(settingsForm.CycleAuraMode); break; diff --git a/app/Properties/Strings.Designer.cs b/app/Properties/Strings.Designer.cs index 7fbf076d..f8ab3328 100644 --- a/app/Properties/Strings.Designer.cs +++ b/app/Properties/Strings.Designer.cs @@ -699,6 +699,15 @@ namespace GHelper.Properties { } } + /// + /// Looks up a localized string similar to Keep GPU disabled on USB-C charger in Optimized mode. + /// + internal static string OptimizedUSBC { + get { + return ResourceManager.GetString("OptimizedUSBC", resourceCulture); + } + } + /// /// Looks up a localized string similar to Other. /// @@ -861,6 +870,15 @@ namespace GHelper.Properties { } } + /// + /// Looks up a localized string similar to Toggle Miniled (if supported). + /// + internal static string ToggleMiniled { + get { + return ResourceManager.GetString("ToggleMiniled", resourceCulture); + } + } + /// /// Looks up a localized string similar to Toggle Screen. /// diff --git a/app/Properties/Strings.resx b/app/Properties/Strings.resx index e5913e81..64b2d1e9 100644 --- a/app/Properties/Strings.resx +++ b/app/Properties/Strings.resx @@ -330,6 +330,9 @@ Switch to Eco on battery and to Standard when plugged + + Keep GPU disabled on USB-C charger in Optimized mode + Other @@ -384,6 +387,9 @@ Toggle Aura + + Toggle Miniled (if supported) + Toggle Screen diff --git a/app/Properties/Strings.zh-TW.resx b/app/Properties/Strings.zh-TW.resx index 8497a41f..ed21cbdb 100644 --- a/app/Properties/Strings.zh-TW.resx +++ b/app/Properties/Strings.zh-TW.resx @@ -367,7 +367,7 @@ 關機時 - 安静模式 + 安靜模式 睡眠時 diff --git a/app/Settings.cs b/app/Settings.cs index ec80cfd7..a72d331d 100644 --- a/app/Settings.cs +++ b/app/Settings.cs @@ -25,7 +25,7 @@ namespace GHelper public string perfName = "Balanced"; public Fans fans; - public Keyboard keyb; + public Extra keyb; static AnimeMatrixDevice mat; static long lastRefresh; @@ -186,10 +186,7 @@ namespace GHelper if (gitVersion.CompareTo(appVersion) > 0) { - BeginInvoke(delegate - { - SetVersionLabel(Properties.Strings.DownloadUpdate + ": " + tag, url); - }); + SetVersionLabel(Properties.Strings.DownloadUpdate + ": " + tag, url); } else { @@ -294,7 +291,7 @@ namespace GHelper break; case 1: Logger.WriteLine("Monitor Power On"); - Program.SetAutoModes(); + Program.SetAutoModes(false); break; case 2: Logger.WriteLine("Monitor Dimmed"); @@ -561,7 +558,7 @@ namespace GHelper { if (keyb == null || keyb.Text == "") { - keyb = new Keyboard(); + keyb = new Extra(); keyb.Show(); } else @@ -692,13 +689,18 @@ namespace GHelper SetScreen(60, 0); } - private void ButtonMiniled_Click(object? sender, EventArgs e) + public void ToogleMiniled() { int miniled = (Program.config.getConfig("miniled") == 1) ? 0 : 1; Program.config.setConfig("miniled", miniled); SetScreen(-1, -1, miniled); } + private void ButtonMiniled_Click(object? sender, EventArgs e) + { + ToogleMiniled(); + } + public void SetScreen(int frequency = -1, int overdrive = -1, int miniled = -1) { @@ -853,6 +855,7 @@ namespace GHelper gpuTemp = $": {HardwareMonitor.gpuTemp}°C "; } + Program.settingsForm.BeginInvoke(delegate { labelCPUFan.Text = "CPU" + cpuTemp + HardwareMonitor.cpuFan; @@ -921,10 +924,12 @@ namespace GHelper customPower = limit_cpu; } + /* if (Program.wmi.DeviceGet(ASUSWmi.PPT_APUC2) >= 0) { Program.wmi.DeviceSet(ASUSWmi.PPT_APUC2, 87, "PowerLimit C2"); } + */ Program.settingsForm.BeginInvoke(SetPerformanceLabel); @@ -1137,11 +1142,18 @@ namespace GHelper } + public static bool IsPlugged() + { + bool optimizedUSBC = Program.config.getConfig("optimized_usbc") != 1; + + return SystemInformation.PowerStatus.PowerLineStatus == PowerLineStatus.Online && + (optimizedUSBC || Program.wmi.DeviceGet(ASUSWmi.ChargerMode) != ASUSWmi.ChargerUSB); + + } + public bool AutoGPUMode() { - var Plugged = SystemInformation.PowerStatus.PowerLineStatus; - bool GpuAuto = Program.config.getConfig("gpu_auto") == 1; bool ForceGPU = Program.config.ContainsModel("503"); @@ -1156,14 +1168,17 @@ namespace GHelper return false; else { + + if (ReEnableGPU()) return true; + if (eco == 1) - if ((GpuAuto && Plugged == PowerLineStatus.Online) || (ForceGPU && GpuMode == ASUSWmi.GPUModeStandard)) + if ((GpuAuto && IsPlugged()) || (ForceGPU && GpuMode == ASUSWmi.GPUModeStandard)) { SetEcoGPU(0); return true; } if (eco == 0) - if ((GpuAuto && Plugged != PowerLineStatus.Online) || (ForceGPU && GpuMode == ASUSWmi.GPUModeEco)) + if ((GpuAuto && !IsPlugged()) || (ForceGPU && GpuMode == ASUSWmi.GPUModeEco)) { if (HardwareMonitor.IsUsedGPU()) @@ -1181,6 +1196,20 @@ namespace GHelper } + public bool ReEnableGPU() + { + if (Screen.AllScreens.Length <= 1) return false; + if (Program.config.getConfig("gpu_reenable") != 1) return false; + + Logger.WriteLine("Re-enabling gpu for 503 model"); + + Thread.Sleep(1000); + SetEcoGPU(1); + Thread.Sleep(1000); + SetEcoGPU(0); + return true; + } + private void UltimateUI(bool ultimate) { if (!ultimate) @@ -1269,7 +1298,7 @@ namespace GHelper Program.wmi.DeviceSet(ASUSWmi.GPUEco, eco, "GPUEco"); if (eco == 0) - HardwareMonitor.RecreateGpuTemperatureProviderWithDelay(); + HardwareMonitor.RecreateGpuControlWithDelay(); Program.settingsForm.BeginInvoke(delegate { diff --git a/app/old-ps1-script/ghelper.zip b/app/old-ps1-script/ghelper.zip deleted file mode 100644 index 770c2e12a30605331660863e65f891fcc8b3d5bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13720 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