From 54dba61c3ed994531fe0c98a78eb784cc7db9e62 Mon Sep 17 00:00:00 2001 From: Charlie Kindel <charlie@kindel.com> Date: Mon, 28 Dec 2020 08:36:38 -0800 Subject: [PATCH] tweaks to presence monitoring --- Installer/version.txt | 2 +- src/Gma.UserActivityMonitor/NativeMethods.cs | 6 ++ src/Services/UserActivityMonitorService.cs | 107 +++++++++++++++---- 3 files changed, 94 insertions(+), 21 deletions(-) diff --git a/Installer/version.txt b/Installer/version.txt index 282a10d..367cdb9 100644 --- a/Installer/version.txt +++ b/Installer/version.txt @@ -1 +1 @@ -2.2.7.56 \ No newline at end of file +2.2.7.66 \ No newline at end of file diff --git a/src/Gma.UserActivityMonitor/NativeMethods.cs b/src/Gma.UserActivityMonitor/NativeMethods.cs index 9f0f99a..b9e7dcb 100644 --- a/src/Gma.UserActivityMonitor/NativeMethods.cs +++ b/src/Gma.UserActivityMonitor/NativeMethods.cs @@ -64,6 +64,12 @@ internal static class NativeMethods { // {3C0F4548-C03F-4c4d-B9F2-237EDE686376} public static Guid GUID_SESSION_USER_PRESENCE = new Guid(0x3c0f4548, 0xc03f, 0x4c4d, 0xb9, 0xf2, 0x23, 0x7e, 0xde, 0x68, 0x63, 0x76); + // + // Specifies if the system is entering or exiting 'away mode'. + // 98A7F580-01F7-48AA-9C0F-44352C29E5C0 + // + public static Guid GUID_SYSTEM_AWAYMODE = new Guid(0x98A7F580, 0x01F7, 0x48AA, 0x9C, 0x0F, 0x44, 0x35, 0x2C, 0x29, 0xE5, 0xC0); + // Win32 decls and defs // public const int PBT_APMQUERYSUSPEND = 0x0000; diff --git a/src/Services/UserActivityMonitorService.cs b/src/Services/UserActivityMonitorService.cs index b832941..3123145 100644 --- a/src/Services/UserActivityMonitorService.cs +++ b/src/Services/UserActivityMonitorService.cs @@ -76,7 +76,7 @@ public void Start() { Logger.Instance.Log4.Info($"ActivityMonitor: Start"); Logger.Instance.Log4.Info($"ActivityMonitor: Keyboard/mouse input detection: {InputDetection}"); Logger.Instance.Log4.Info($"ActivityMonitor: Desktop unlock detection: {UnlockDetection}"); - Logger.Instance.Log4.Info($"ActivityMonitor: Monitor Power detection: {UserPresenceDetection}"); + Logger.Instance.Log4.Info($"ActivityMonitor: Power API User Presence Detection: {UserPresenceDetection}"); Logger.Instance.Log4.Info($"ActivityMonitor: Command: {ActivityCmd}"); Logger.Instance.Log4.Info($"ActivityMonitor: Debounce Time: {DebounceTime} seconds"); @@ -89,41 +89,108 @@ public void Start() { internal void HandlePowerBroadcast(IntPtr wParam, IntPtr lParam) { - int pbt = wParam.ToInt32(); - POWERBROADCAST_SETTING pbSetting = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(lParam, typeof(POWERBROADCAST_SETTING)); + var pbt = wParam.ToInt32(); // https://docs.microsoft.com/en-us/windows/win32/power/power-setting-guids - if (pbt == PBT_POWERSETTINGCHANGE && pbSetting.PowerSetting == GUID_SESSION_USER_PRESENCE) { - // BUGBUG: Data is just a byte and we're lucky the MSB has our value in it - switch (pbSetting.Data) { - case 0: // PowerUserPresent (0) - The user is providing input to the session. - _PresencePresumedTimer.Enabled = true; - this.Activity("PowerBroadcast: The user is providing input to the session"); - break; - - case 2: // PowerUserInactive(2) - The user activity timeout has elapsed with no interaction from the user. - _PresencePresumedTimer.Enabled = false; - Logger.Instance.Log4.Info($"ActivityMonitor: PowerBroadcast: The user activity timeout has elapsed with no interaction from the user."); - break; - - default: - Logger.Instance.Log4.Error($"ActivityMonitor: PowerBroadcast: Unknown GUID_SESSION_USER_PRESENCE data {pbSetting.Data}."); - break; - } + switch (pbt) { + case PBT_POWERSETTINGCHANGE: + POWERBROADCAST_SETTING pbSetting = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(lParam, typeof(POWERBROADCAST_SETTING)); + if (pbSetting.PowerSetting == GUID_SESSION_USER_PRESENCE) { + // BUGBUG: Data is just a byte and we're lucky the MSB has our value in it + switch (pbSetting.Data) { + case 0: // PowerUserPresent (0) - The user is providing input to the session. + _PresencePresumedTimer.Enabled = true; + this.Activity("PowerBroadcast: The user is providing input to the session"); + break; + + + case 2: // PowerUserInactive(2) - The user activity timeout has elapsed with no interaction from the user. + _PresencePresumedTimer.Enabled = false; + Logger.Instance.Log4.Info($"ActivityMonitor: PowerBroadcast: The user activity timeout has elapsed with no interaction from the user."); + break; + + default: + Logger.Instance.Log4.Error($"ActivityMonitor: PowerBroadcast: Unknown GUID_SESSION_USER_PRESENCE data {pbSetting.Data}."); + break; + } + } + else if (pbSetting.PowerSetting == GUID_SYSTEM_AWAYMODE) { + // BUGBUG: Data is just a byte and we're lucky the MSB has our value in it + switch (pbSetting.Data) { + case 0: // 0x0 - The computer is exiting away mode. + this.Activity("PowerBroadcast: The computer is exiting away mode"); + break; + + + case 1: // 0x1 - The computer is entering away mode. + _PresencePresumedTimer.Enabled = false; + Logger.Instance.Log4.Info($"ActivityMonitor: PowerBroadcast: The computer is entering away mode."); + break; + + default: + Logger.Instance.Log4.Error($"ActivityMonitor: PowerBroadcast: Unknown GUID_SYSTEM_AWAYMODE data {pbSetting.Data}."); + break; + } + } + else if (pbSetting.PowerSetting == GUID_MONITOR_POWER_ON) { + // BUGBUG: Data is just a byte and we're lucky the MSB has our value in it + switch (pbSetting.Data) { + case 0: // 0x0 - The monitor is off. + _PresencePresumedTimer.Enabled = false; + this.Activity("PowerBroadcast: The monitor is off"); + break; + + + case 1: // 0x1 - The monitor is on. + Logger.Instance.Log4.Info($"ActivityMonitor: PowerBroadcast: The monitor is on"); + break; + + default: + Logger.Instance.Log4.Error($"ActivityMonitor: PowerBroadcast: Unknown GUID_MONITOR_POWER_ON data {pbSetting.Data}."); + break; + } + } + break; + + default: + Logger.Instance.Log4.Error($"ActivityMonitor: PowerBroadcast: Unknown PBT {pbt}."); + break; } + } private IntPtr _hUserPresence; + private IntPtr _hAwayMode; + private IntPtr _hMonitorPower; private void StartMonitorPowerDetection() { _hUserPresence = RegisterPowerSettingNotification(MainWindow.Instance.Handle, ref GUID_SESSION_USER_PRESENCE, DEVICE_NOTIFY_WINDOW_HANDLE); + + _hAwayMode = RegisterPowerSettingNotification(MainWindow.Instance.Handle, + ref GUID_SYSTEM_AWAYMODE, + DEVICE_NOTIFY_WINDOW_HANDLE); + + _hMonitorPower = RegisterPowerSettingNotification(MainWindow.Instance.Handle, + ref GUID_MONITOR_POWER_ON, + DEVICE_NOTIFY_WINDOW_HANDLE); } private void StopMonitorPowerDetection() { if (_hUserPresence != null) { UnregisterPowerSettingNotification(_hUserPresence); + _hUserPresence = (IntPtr)null; + } + + if (_hAwayMode != null) { + UnregisterPowerSettingNotification(_hAwayMode); + _hAwayMode = (IntPtr)null; + } + + if (_hMonitorPower != null) { + UnregisterPowerSettingNotification(_hMonitorPower); + _hMonitorPower = (IntPtr)null; } }