Merge pull request #817 from IceStormNG/clamshell-detection

Automatic Clamshell Mode Toggle
This commit is contained in:
Serge
2023-07-19 12:22:22 +02:00
committed by GitHub
7 changed files with 158 additions and 0 deletions

17
app/Extra.Designer.cs generated
View File

@@ -101,6 +101,7 @@ namespace GHelper
pictureSettings = new PictureBox(); pictureSettings = new PictureBox();
labelSettings = new Label(); labelSettings = new Label();
panelSettings = new Panel(); panelSettings = new Panel();
checkAutoToggleClamshellMode = new CheckBox();
checkAutoApplyWindowsPowerMode = new CheckBox(); checkAutoApplyWindowsPowerMode = new CheckBox();
checkTopmost = new CheckBox(); checkTopmost = new CheckBox();
checkNoOverdrive = new CheckBox(); checkNoOverdrive = new CheckBox();
@@ -1003,6 +1004,7 @@ namespace GHelper
// //
panelSettings.AutoSize = true; panelSettings.AutoSize = true;
panelSettings.AutoSizeMode = AutoSizeMode.GrowAndShrink; panelSettings.AutoSizeMode = AutoSizeMode.GrowAndShrink;
panelSettings.Controls.Add(checkAutoToggleClamshellMode);
panelSettings.Controls.Add(checkAutoApplyWindowsPowerMode); panelSettings.Controls.Add(checkAutoApplyWindowsPowerMode);
panelSettings.Controls.Add(checkTopmost); panelSettings.Controls.Add(checkTopmost);
panelSettings.Controls.Add(checkNoOverdrive); panelSettings.Controls.Add(checkNoOverdrive);
@@ -1017,6 +1019,20 @@ namespace GHelper
panelSettings.Size = new Size(983, 304); panelSettings.Size = new Size(983, 304);
panelSettings.TabIndex = 46; 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
// //
checkAutoApplyWindowsPowerMode.AutoSize = true; checkAutoApplyWindowsPowerMode.AutoSize = true;
@@ -1246,5 +1262,6 @@ namespace GHelper
private PictureBox pictureService; private PictureBox pictureService;
private Slider sliderBrightness; private Slider sliderBrightness;
private PictureBox pictureLog; private PictureBox pictureLog;
private CheckBox checkAutoToggleClamshellMode;
} }
} }

View File

@@ -106,6 +106,7 @@ namespace GHelper
checkUSBC.Text = Properties.Strings.OptimizedUSBC; checkUSBC.Text = Properties.Strings.OptimizedUSBC;
checkAutoApplyWindowsPowerMode.Text = Properties.Strings.ApplyWindowsPowerPlan; checkAutoApplyWindowsPowerMode.Text = Properties.Strings.ApplyWindowsPowerPlan;
checkFnLock.Text = Properties.Strings.FnLock; checkFnLock.Text = Properties.Strings.FnLock;
checkAutoToggleClamshellMode.Text = Properties.Strings.ToggleClamshellMode;
labelBacklightKeyboard.Text = Properties.Strings.Keyboard; labelBacklightKeyboard.Text = Properties.Strings.Keyboard;
labelBacklightBar.Text = Properties.Strings.Lightbar; labelBacklightBar.Text = Properties.Strings.Lightbar;
@@ -210,6 +211,9 @@ namespace GHelper
} }
} }
checkAutoToggleClamshellMode.Checked = AppConfig.Is("toggle_clamshell_mode");
checkTopmost.Checked = AppConfig.Is("topmost"); checkTopmost.Checked = AppConfig.Is("topmost");
checkTopmost.CheckedChanged += CheckTopmost_CheckedChanged; ; checkTopmost.CheckedChanged += CheckTopmost_CheckedChanged; ;
@@ -466,5 +470,12 @@ namespace GHelper
{ {
AppConfig.Set("auto_apply_power_plan", checkAutoApplyWindowsPowerMode.Checked ? 1 : 0); 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();
}
} }
} }

View File

@@ -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();
}
}
}

View File

@@ -60,6 +60,9 @@ namespace GHelper.Mode
private static Guid GUID_SLEEP_SUBGROUP = new Guid("238c9fa8-0aad-41ed-83f4-97be242c8f20"); 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_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")] [DllImportAttribute("powrprof.dll", EntryPoint = "PowerGetActualOverlayScheme")]
public static extern uint PowerGetActualOverlayScheme(out Guid ActualOverlayGuid); public static extern uint PowerGetActualOverlayScheme(out Guid ActualOverlayGuid);
@@ -163,5 +166,40 @@ namespace GHelper.Mode
break; 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);
}
} }
} }

View File

@@ -30,6 +30,7 @@ namespace GHelper
public static ModeControl modeControl = new ModeControl(); public static ModeControl modeControl = new ModeControl();
static GPUModeControl gpuControl = new GPUModeControl(settingsForm); static GPUModeControl gpuControl = new GPUModeControl(settingsForm);
static ScreenControl screenControl = new ScreenControl(); static ScreenControl screenControl = new ScreenControl();
static ClamshellModeControl clamshellControl = new ClamshellModeControl();
public static ToastForm toast = new ToastForm(); public static ToastForm toast = new ToastForm();
@@ -99,6 +100,8 @@ namespace GHelper
// Subscribing for system power change events // Subscribing for system power change events
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged; SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
clamshellControl.RegisterDisplayEvents();
clamshellControl.ToggleLidAction();
// Subscribing for monitor power on events // Subscribing for monitor power on events
PowerSettingGuid settingGuid = new NativeMethods.PowerSettingGuid(); PowerSettingGuid settingGuid = new NativeMethods.PowerSettingGuid();
@@ -238,6 +241,7 @@ namespace GHelper
static void OnExit(object sender, EventArgs e) static void OnExit(object sender, EventArgs e)
{ {
trayIcon.Visible = false; trayIcon.Visible = false;
clamshellControl.UnregisterDisplayEvents();
NativeMethods.UnregisterPowerSettingNotification(unRegPowerNotify); NativeMethods.UnregisterPowerSettingNotification(unRegPowerNotify);
Application.Exit(); Application.Exit();
} }

View File

@@ -1177,6 +1177,15 @@ namespace GHelper.Properties {
return ResourceManager.GetString("ToggleAura", resourceCulture); return ResourceManager.GetString("ToggleAura", resourceCulture);
} }
} }
/// <summary>
/// Looks up a localized string similar to Auto Toggle Clamshell Mode.
/// </summary>
internal static string ToggleClamshellMode {
get {
return ResourceManager.GetString("ToggleClamshellMode", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggle Fn-Lock. /// Looks up a localized string similar to Toggle Fn-Lock.

View File

@@ -491,6 +491,9 @@ Do you still want to continue?</value>
<data name="ToggleAura" xml:space="preserve"> <data name="ToggleAura" xml:space="preserve">
<value>Toggle Aura</value> <value>Toggle Aura</value>
</data> </data>
<data name="ToggleClamshellMode" xml:space="preserve">
<value>Auto Toggle Clamshell Mode</value>
</data>
<data name="ToggleFnLock" xml:space="preserve"> <data name="ToggleFnLock" xml:space="preserve">
<value>Toggle Fn-Lock</value> <value>Toggle Fn-Lock</value>
</data> </data>