diff --git a/app/Extra.Designer.cs b/app/Extra.Designer.cs
index 63753dd7..7f9f1be6 100644
--- a/app/Extra.Designer.cs
+++ b/app/Extra.Designer.cs
@@ -101,6 +101,7 @@ namespace GHelper
pictureSettings = new PictureBox();
labelSettings = new Label();
panelSettings = new Panel();
+ checkAutoToggleClamshellMode = new CheckBox();
checkAutoApplyWindowsPowerMode = new CheckBox();
checkTopmost = new CheckBox();
checkNoOverdrive = new CheckBox();
@@ -1003,6 +1004,7 @@ namespace GHelper
//
panelSettings.AutoSize = true;
panelSettings.AutoSizeMode = AutoSizeMode.GrowAndShrink;
+ panelSettings.Controls.Add(checkAutoToggleClamshellMode);
panelSettings.Controls.Add(checkAutoApplyWindowsPowerMode);
panelSettings.Controls.Add(checkTopmost);
panelSettings.Controls.Add(checkNoOverdrive);
@@ -1017,6 +1019,20 @@ namespace GHelper
panelSettings.Size = new Size(983, 304);
panelSettings.TabIndex = 46;
//
+ // checkAutoToggleClamshellMode
+ //
+ checkAutoToggleClamshellMode.AutoSize = true;
+ checkAutoToggleClamshellMode.Dock = DockStyle.Top;
+ checkAutoToggleClamshellMode.Location = new Point(10, 163);
+ checkAutoToggleClamshellMode.Margin = new Padding(2);
+ checkAutoToggleClamshellMode.Name = "checkAutoToggleClamshellMode";
+ checkAutoToggleClamshellMode.Padding = new Padding(2);
+ checkAutoToggleClamshellMode.Size = new Size(481, 23);
+ checkAutoToggleClamshellMode.TabIndex = 58;
+ checkAutoToggleClamshellMode.Text = "Auto Toggle Clamshell Mode";
+ checkAutoToggleClamshellMode.UseVisualStyleBackColor = true;
+ checkAutoToggleClamshellMode.CheckedChanged += checkAutoToggleClamshellMode_CheckedChanged;
+ //
// checkAutoApplyWindowsPowerMode
//
checkAutoApplyWindowsPowerMode.AutoSize = true;
@@ -1246,5 +1262,6 @@ namespace GHelper
private PictureBox pictureService;
private Slider sliderBrightness;
private PictureBox pictureLog;
+ private CheckBox checkAutoToggleClamshellMode;
}
}
\ No newline at end of file
diff --git a/app/Extra.cs b/app/Extra.cs
index 51750467..44d8f35a 100644
--- a/app/Extra.cs
+++ b/app/Extra.cs
@@ -106,6 +106,7 @@ namespace GHelper
checkUSBC.Text = Properties.Strings.OptimizedUSBC;
checkAutoApplyWindowsPowerMode.Text = Properties.Strings.ApplyWindowsPowerPlan;
checkFnLock.Text = Properties.Strings.FnLock;
+ checkAutoToggleClamshellMode.Text = Properties.Strings.ToggleClamshellMode;
labelBacklightKeyboard.Text = Properties.Strings.Keyboard;
labelBacklightBar.Text = Properties.Strings.Lightbar;
@@ -210,6 +211,9 @@ namespace GHelper
}
}
+
+ checkAutoToggleClamshellMode.Checked = AppConfig.Is("toggle_clamshell_mode");
+
checkTopmost.Checked = AppConfig.Is("topmost");
checkTopmost.CheckedChanged += CheckTopmost_CheckedChanged; ;
@@ -466,5 +470,12 @@ namespace GHelper
{
AppConfig.Set("auto_apply_power_plan", checkAutoApplyWindowsPowerMode.Checked ? 1 : 0);
}
+
+ private void checkAutoToggleClamshellMode_CheckedChanged(object sender, EventArgs e)
+ {
+ AppConfig.Set("toggle_clamshell_mode", checkAutoToggleClamshellMode.Checked ? 1 : 0);
+ ClamshellModeControl ctrl = new ClamshellModeControl();
+ ctrl.ToggleLidAction();
+ }
}
}
diff --git a/app/Helpers/ClamshellModeControl.cs b/app/Helpers/ClamshellModeControl.cs
new file mode 100644
index 00000000..ba6362f1
--- /dev/null
+++ b/app/Helpers/ClamshellModeControl.cs
@@ -0,0 +1,76 @@
+using GHelper.Display;
+using GHelper.Mode;
+using Microsoft.Win32;
+
+namespace GHelper.Helpers
+{
+ internal class ClamshellModeControl
+ {
+ public bool IsExternalDisplayConnected()
+ {
+ var devices = ScreenInterrogatory.GetAllDevices().ToArray();
+
+ foreach (var device in devices)
+ {
+ if (device.outputTechnology != ScreenInterrogatory.DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL &&
+ device.outputTechnology != ScreenInterrogatory.DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED)
+ {
+ Logger.WriteLine("Found external screen: " + device.monitorFriendlyDeviceName + ":" + device.outputTechnology.ToString());
+
+ //Already found one, we do not have to check whether there are more
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
+ public bool IsClamshellEnabled()
+ {
+ return AppConfig.Get("toggle_clamshell_mode") != 0;
+ }
+
+ public bool IsChargerConnected()
+ {
+ return SystemInformation.PowerStatus.PowerLineStatus == PowerLineStatus.Online;
+ }
+
+ public bool IsInClamshellMode()
+ {
+ return IsExternalDisplayConnected() && IsChargerConnected();
+ }
+
+ public void ToggleLidAction()
+ {
+ if (IsInClamshellMode() && IsClamshellEnabled())
+ {
+ PowerNative.SetLidAction(0, true);
+ Logger.WriteLine("Engaging Clamshell Mode");
+ }
+ else
+ {
+ PowerNative.SetLidAction(1, true);
+ Logger.WriteLine("Disengaging Clamshell Mode");
+ }
+ }
+
+ public void UnregisterDisplayEvents()
+ {
+ SystemEvents.DisplaySettingsChanged -= SystemEvents_DisplaySettingsChanged;
+ }
+
+ public void RegisterDisplayEvents()
+ {
+ SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
+ }
+
+ private void SystemEvents_DisplaySettingsChanged(object? sender, EventArgs e)
+ {
+ Logger.WriteLine("Display configuration changed.");
+
+ if (IsClamshellEnabled())
+ ToggleLidAction();
+ }
+ }
+}
diff --git a/app/Mode/PowerNative.cs b/app/Mode/PowerNative.cs
index de323b4e..06a65bb2 100644
--- a/app/Mode/PowerNative.cs
+++ b/app/Mode/PowerNative.cs
@@ -60,6 +60,9 @@ namespace GHelper.Mode
private static Guid GUID_SLEEP_SUBGROUP = new Guid("238c9fa8-0aad-41ed-83f4-97be242c8f20");
private static Guid GUID_HIBERNATEIDLE = new Guid("9d7815a6-7ee4-497e-8888-515a05f02364");
+ private static Guid GUID_SYSTEM_BUTTON_SUBGROUP = new Guid("4f971e89-eebd-4455-a8de-9e59040e7347");
+ private static Guid GUID_LIDACTION = new Guid("5CA83367-6E45-459F-A27B-476B1D01C936");
+
[DllImportAttribute("powrprof.dll", EntryPoint = "PowerGetActualOverlayScheme")]
public static extern uint PowerGetActualOverlayScheme(out Guid ActualOverlayGuid);
@@ -163,5 +166,40 @@ namespace GHelper.Mode
break;
}
}
+
+ public static void SetLidAction(int action, bool acOnly = false)
+ {
+ /**
+ * 1: Do nothing
+ * 2: Seelp
+ * 3: Hibernate
+ * 4: Shutdown
+ */
+
+ Guid activeSchemeGuid = GetActiveScheme();
+
+ var hrAC = PowerWriteACValueIndex(
+ IntPtr.Zero,
+ activeSchemeGuid,
+ GUID_SYSTEM_BUTTON_SUBGROUP,
+ GUID_LIDACTION,
+ action);
+
+ PowerSetActiveScheme(IntPtr.Zero, activeSchemeGuid);
+
+ if (!acOnly)
+ {
+ var hrDC = PowerWriteDCValueIndex(
+ IntPtr.Zero,
+ activeSchemeGuid,
+ GUID_SYSTEM_BUTTON_SUBGROUP,
+ GUID_LIDACTION,
+ action);
+
+ PowerSetActiveScheme(IntPtr.Zero, activeSchemeGuid);
+ }
+
+ Logger.WriteLine("Changed Lid Action to " + action);
+ }
}
}
diff --git a/app/Program.cs b/app/Program.cs
index ad28f402..595a7bfa 100644
--- a/app/Program.cs
+++ b/app/Program.cs
@@ -30,6 +30,7 @@ namespace GHelper
public static ModeControl modeControl = new ModeControl();
static GPUModeControl gpuControl = new GPUModeControl(settingsForm);
static ScreenControl screenControl = new ScreenControl();
+ static ClamshellModeControl clamshellControl = new ClamshellModeControl();
public static ToastForm toast = new ToastForm();
@@ -99,6 +100,8 @@ namespace GHelper
// Subscribing for system power change events
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
+ clamshellControl.RegisterDisplayEvents();
+ clamshellControl.ToggleLidAction();
// Subscribing for monitor power on events
PowerSettingGuid settingGuid = new NativeMethods.PowerSettingGuid();
@@ -238,6 +241,7 @@ namespace GHelper
static void OnExit(object sender, EventArgs e)
{
trayIcon.Visible = false;
+ clamshellControl.UnregisterDisplayEvents();
NativeMethods.UnregisterPowerSettingNotification(unRegPowerNotify);
Application.Exit();
}
diff --git a/app/Properties/Strings.Designer.cs b/app/Properties/Strings.Designer.cs
index 31c72239..ead14e55 100644
--- a/app/Properties/Strings.Designer.cs
+++ b/app/Properties/Strings.Designer.cs
@@ -1177,6 +1177,15 @@ namespace GHelper.Properties {
return ResourceManager.GetString("ToggleAura", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to Auto Toggle Clamshell Mode.
+ ///
+ internal static string ToggleClamshellMode {
+ get {
+ return ResourceManager.GetString("ToggleClamshellMode", resourceCulture);
+ }
+ }
///
/// Looks up a localized string similar to Toggle Fn-Lock.
diff --git a/app/Properties/Strings.resx b/app/Properties/Strings.resx
index 92074f89..fc176a9c 100644
--- a/app/Properties/Strings.resx
+++ b/app/Properties/Strings.resx
@@ -491,6 +491,9 @@ Do you still want to continue?
Toggle Aura
+
+ Auto Toggle Clamshell Mode
+
Toggle Fn-Lock