Skip to content

Commit 789d7e6

Browse files
committed
Fix detection of resume from standby
1 parent 41e428f commit 789d7e6

File tree

5 files changed

+91
-13
lines changed

5 files changed

+91
-13
lines changed

src/COM/PowerSetting.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4+
5+
using System;
6+
using System.Runtime.InteropServices;
7+
using System.Windows.Forms;
8+
9+
namespace WinDynamicDesktop.COM
10+
{
11+
[StructLayout(LayoutKind.Sequential)]
12+
public struct POWERBROADCAST_SETTING
13+
{
14+
public Guid PowerSetting;
15+
public int DataLength;
16+
// Variable length data follows
17+
}
18+
19+
internal class PowerSetting
20+
{
21+
private static readonly Guid GUID_CONSOLE_DISPLAY_STATE =
22+
new Guid("6fe69556-704a-47a0-8f24-c28d936fda47");
23+
24+
private static IntPtr hPowerNotify;
25+
private static int? lastDisplayState = null;
26+
27+
[DllImport("user32.dll")]
28+
private static extern IntPtr RegisterPowerSettingNotification(
29+
IntPtr hRecipient, ref Guid PowerSettingGuid, int Flags);
30+
31+
[DllImport("user32.dll")]
32+
private static extern bool UnregisterPowerSettingNotification(IntPtr Handle);
33+
34+
public static void RegisterWindow(IntPtr windowHandle)
35+
{
36+
Guid guid = GUID_CONSOLE_DISPLAY_STATE;
37+
hPowerNotify = RegisterPowerSettingNotification(windowHandle, ref guid, 0);
38+
39+
if (hPowerNotify != IntPtr.Zero)
40+
{
41+
Application.ApplicationExit += (object sender, EventArgs e) =>
42+
{
43+
UnregisterPowerSettingNotification(hPowerNotify);
44+
};
45+
}
46+
else
47+
{
48+
LoggingHandler.LogMessage("Failed to register for power notifications");
49+
}
50+
}
51+
52+
public static bool IsExitingStandby(nint msgPtr)
53+
{
54+
var powerSetting = Marshal.PtrToStructure<POWERBROADCAST_SETTING>(msgPtr);
55+
56+
if (powerSetting.PowerSetting.Equals(GUID_CONSOLE_DISPLAY_STATE))
57+
{
58+
IntPtr dataPtr = new(msgPtr.ToInt64() + Marshal.SizeOf<POWERBROADCAST_SETTING>());
59+
int displayState = Marshal.ReadInt32(dataPtr);
60+
61+
bool stateChanged = lastDisplayState.HasValue && lastDisplayState.Value != displayState;
62+
lastDisplayState = displayState;
63+
64+
// If state changed and display is turning on, assume we are exiting standby
65+
return stateChanged && displayState == 1;
66+
}
67+
68+
return false;
69+
}
70+
}
71+
}

src/EventScheduler.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ public async void RunAndUpdateLocation(bool forceImageUpdate = false, Action loc
145145
}
146146
}
147147

148+
public void HandleResumeFromStandby()
149+
{
150+
OnPowerModeChanged(null, new PowerModeChangedEventArgs(PowerModes.Resume));
151+
}
152+
148153
private bool UpdateDisplayList()
149154
{
150155
if (JsonConfig.IsNullOrEmpty(JsonConfig.settings.activeThemes) ||
@@ -269,7 +274,7 @@ private void OnDisplaySettingsChanged(object sender, EventArgs e)
269274

270275
private void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
271276
{
272-
if ((e == null || e.Mode == PowerModes.Resume) && (UpdateDisplayList() ||
277+
if (e.Mode == PowerModes.Resume && (UpdateDisplayList() ||
273278
(nextUpdateTime.HasValue && DateTime.Now >= nextUpdateTime.Value)))
274279
{
275280
LoggingHandler.LogMessage("Scheduler event triggered by resume from sleep");

src/HiddenForm.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System;
66
using System.Runtime.InteropServices;
77
using System.Windows.Forms;
8+
using WinDynamicDesktop.COM;
89

910
namespace WinDynamicDesktop
1011
{
@@ -15,11 +16,8 @@ internal class HiddenForm : Form
1516
private const int WM_QUERYENDSESSION = 0x11;
1617
private const int WM_ENDSESSION = 0x16;
1718
private const int WM_POWERBROADCAST = 0x0218;
18-
private const int PBT_APMRESUMESUSPEND = 0x0007;
19-
private const int PBT_APMRESUMEAUTOMATIC = 0x0012;
19+
private const int PBT_POWERSETTINGCHANGE = 0x8013;
2020

21-
public static Microsoft.Win32.PowerModeChangedEventHandler OnPowerModeChanged;
22-
2321
[DllImport("user32.dll")]
2422
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hwndNewParent);
2523

@@ -65,10 +63,9 @@ protected override void WndProc(ref Message m)
6563
m.Result = IntPtr.Zero;
6664
break;
6765
case WM_POWERBROADCAST:
68-
int pbt = m.WParam.ToInt32();
69-
if (pbt == PBT_APMRESUMEAUTOMATIC || pbt == PBT_APMRESUMESUSPEND)
66+
if (m.WParam.ToInt32() == PBT_POWERSETTINGCHANGE && PowerSetting.IsExitingStandby(m.LParam))
7067
{
71-
OnPowerModeChanged(null, null);
68+
AppContext.scheduler.HandleResumeFromStandby();
7269
}
7370
break;
7471
}
@@ -80,6 +77,11 @@ private void HiddenForm_Load(object source, EventArgs e)
8077
{
8178
const int HWND_MESSAGE = -1;
8279
SetParent(this.Handle, new IntPtr(HWND_MESSAGE));
80+
81+
if (UwpDesktop.IsWinRtSupported())
82+
{
83+
PowerSetting.RegisterWindow(this.Handle);
84+
}
8385
}
8486
}
8587
}

src/ThemeDialog.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ private void ThemeDialog_Load(object sender, EventArgs e)
229229
meatballButton.DropDownItems.Add(new ToolStripSeparator());
230230
meatballButton.DropDownItems.AddRange(LockScreenChanger.GetMenuItems());
231231

232-
if (UwpDesktop.IsMultiDisplaySupported())
232+
if (UwpDesktop.IsWinRtSupported())
233233
{
234234
string[] displayNames = ThemeDialogUtils.GetDisplayNames();
235235
for (int i = 0; i < displayNames.Length; i++)

src/UwpDesktop.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ public static bool IsRunningAsUwp()
3838
return _isRunningAsUwp.Value;
3939
}
4040

41-
public static bool IsMultiDisplaySupported()
41+
public static bool IsUwpSupported()
4242
{
43-
return Environment.OSVersion.Version.Major >= 8;
43+
return Environment.OSVersion.Version.Major >= 10;
4444
}
4545

46-
public static bool IsUwpSupported()
46+
public static bool IsWinRtSupported()
4747
{
48-
return Environment.OSVersion.Version.Major >= 10;
48+
return Environment.OSVersion.Version.Major >= 8;
4949
}
5050

5151
public static PlatformHelper GetHelper()

0 commit comments

Comments
 (0)