Skip to content

Commit

Permalink
Popup countdown before lockin only when user is idle for at least 3 s…
Browse files Browse the repository at this point in the history
…econds (#68)

* add UserActivity class

* set default idle time to 3 seconds
  • Loading branch information
bNobo authored Jun 27, 2021
1 parent a1a7dd0 commit 02bb12f
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 8 deletions.
44 changes: 36 additions & 8 deletions NeedABreak/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -140,6 +155,8 @@ private static async Task TimesUp()
timer.Stop();
}

await WaitForUserToBeIdleAsync();

await Current.Dispatcher.InvokeAsync(async () =>
{
var mainWindow = GetMainWindow();
Expand All @@ -148,7 +165,18 @@ await mainWindow.StartLockWorkStationAsync()
});
}

private static async Task TimesAlmostUp()
/// <summary>
/// Wait for user to be idle in order to avoid annoying him.
/// </summary>
/// <returns></returns>
private static Task WaitForUserToBeIdleAsync()
{
var userActivity = new UserActivity(TimeSpan.Zero);

return userActivity.WaitForUserToBeIdleAsync();
}

private static async Task TimesAlmostUp()
{
await Current.Dispatcher.InvokeAsync(() =>
{
Expand Down
1 change: 1 addition & 0 deletions NeedABreak/NeedABreak.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
<Compile Include="Utils\RegistryTool.cs" />
<Compile Include="Utils\SessionLock.cs" />
<Compile Include="Utils\TextResourceExtension.cs" />
<Compile Include="Utils\UserActivity.cs" />
<Page Include="AboutBoxWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down
66 changes: 66 additions & 0 deletions NeedABreak/Utils/UserActivity.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// UserActivity constructor
/// </summary>
/// <param name="idleTime">time after which the user will be considered idle.</param>
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 = "<Pending>")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "<Pending>")]
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();
}
}
}
}

0 comments on commit 02bb12f

Please sign in to comment.