diff --git a/NeedABreak/App.xaml.cs b/NeedABreak/App.xaml.cs index 52a05dc..676fed1 100644 --- a/NeedABreak/App.xaml.cs +++ b/NeedABreak/App.xaml.cs @@ -41,8 +41,12 @@ public partial class App : Application #endif public static int Delay { get; set; } = 5400; // Seconds (put a low value here to facilitate debugging) private static Timer timer = Delay > 120 ? new Timer(60000) : new Timer(10000); - private static DateTime suspendTime; // Time when App was suspended - public static bool IsSuspended { get; set; } + private static DateTime suspendTime; // Time when App was suspended +#if DEBUG + private static Timer _debugTimer = new Timer(1000); +#endif + + public static bool IsSuspended { get; set; } public static SuspensionCause SuspensionCause { get; set; } @@ -77,11 +81,22 @@ public App() InitStartTime(); timer.Elapsed += Timer_Elapsed; timer.Start(); - Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; - Logger.Debug("App ctor end"); - } - - public static ILog Logger { get; private set; } + Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; +#if DEBUG + _debugTimer.Elapsed += _debugTimer_Elapsed; + _debugTimer.Start(); +#endif + Logger.Debug("App ctor end"); + } + +#if DEBUG + private void _debugTimer_Elapsed(object sender, ElapsedEventArgs e) + { + System.Diagnostics.Debug.WriteLine(UserActivity.GetInactiveTime()); + } +#endif + + public static ILog Logger { get; private set; } private async void Timer_Elapsed(object sender, ElapsedEventArgs e) { @@ -140,6 +155,8 @@ private static async Task TimesUp() timer.Stop(); } + await WaitForUserToBeIdleAsync(); + await Current.Dispatcher.InvokeAsync(async () => { var mainWindow = GetMainWindow(); @@ -148,7 +165,18 @@ await mainWindow.StartLockWorkStationAsync() }); } - private static async Task TimesAlmostUp() + /// + /// Wait for user to be idle in order to avoid annoying him. + /// + /// + private static Task WaitForUserToBeIdleAsync() + { + var userActivity = new UserActivity(TimeSpan.Zero); + + return userActivity.WaitForUserToBeIdleAsync(); + } + + private static async Task TimesAlmostUp() { await Current.Dispatcher.InvokeAsync(() => { diff --git a/NeedABreak/NeedABreak.csproj b/NeedABreak/NeedABreak.csproj index 2497f80..c6d37ba 100644 --- a/NeedABreak/NeedABreak.csproj +++ b/NeedABreak/NeedABreak.csproj @@ -146,6 +146,7 @@ + Designer MSBuild:Compile diff --git a/NeedABreak/Utils/UserActivity.cs b/NeedABreak/Utils/UserActivity.cs new file mode 100644 index 0000000..55bfb43 --- /dev/null +++ b/NeedABreak/Utils/UserActivity.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace NeedABreak.Utils +{ + public class UserActivity + { + private TimeSpan _idleTime; + + /// + /// UserActivity constructor + /// + /// time after which the user will be considered idle. + public UserActivity(TimeSpan idleTime) + { + if (idleTime == TimeSpan.Zero) + { + idleTime = TimeSpan.FromSeconds(3); + } + + _idleTime = idleTime; + } + + [StructLayout(LayoutKind.Sequential)] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in PascalCase", Justification = "")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "")] + public struct LASTINPUTINFO + { + public uint cbSize; + public uint dwTime; + } + + [DllImport("user32.dll")] + static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); + + public static TimeSpan GetInactiveTime() + { + LASTINPUTINFO info = new LASTINPUTINFO(); + info.cbSize = (uint)Marshal.SizeOf(info); + + if (GetLastInputInfo(ref info)) + { + return TimeSpan.FromMilliseconds(Environment.TickCount - info.dwTime); + } + else + { + return TimeSpan.Zero; + } + } + + public async Task WaitForUserToBeIdleAsync() + { + TimeSpan inactiveTime = GetInactiveTime(); + + while (inactiveTime < _idleTime) + { + await Task.Delay(1000); + inactiveTime = GetInactiveTime(); + } + } + } +}