Windows has an internal mechanism that decides when to show the screensaver (or shut the screen off) by checking for user interactivity and other tasks (someone's watching a video, etc.).
Is there an Win API that allows me to ask whether or not the user is active, or when was the last time they were active?
It is called the "idle timer". You can get its value by pinvoking CallNtPowerInformation(), asking for SystemPowerInformation. The returned SYSTEM_POWER_INFORMATION.TimeRemaining field tells you how much time is left on the idle timer. The SystemExecutionState request tells you if any thread has called SetThreadExecutionState() to stop the timer, as is done by apps that show videos.
using System;
using System.Runtime.InteropServices;
public static class PowerInfo {
public static int GetIdleTimeRemaining() {
var info = new SYSTEM_POWER_INFORMATION();
int ret = GetSystemPowerInformation(SystemPowerInformation, IntPtr.Zero, 0, out info, Marshal.SizeOf(info));
if (ret != 0) throw new System.ComponentModel.Win32Exception(ret);
return info.TimeRemaining;
}
public static int GetExecutionState() {
int state = 0;
int ret = GetSystemExecutionState(SystemExecutionState, IntPtr.Zero, 0, out state, 4);
if (ret != 0) throw new System.ComponentModel.Win32Exception(ret);
return state;
}
private struct SYSTEM_POWER_INFORMATION {
public int MaxIdlenessAllowed;
public int Idleness;
public int TimeRemaining;
public byte CoolingMode;
}
private const int SystemPowerInformation = 12;
private const int SystemExecutionState = 16;
[DllImport("powrprof.dll", EntryPoint = "CallNtPowerInformation", CharSet = CharSet.Auto)]
private static extern int GetSystemPowerInformation(int level, IntPtr inpbuf, int inpbuflen, out SYSTEM_POWER_INFORMATION info, int outbuflen);
[DllImport("powrprof.dll", EntryPoint = "CallNtPowerInformation", CharSet = CharSet.Auto)]
private static extern int GetSystemExecutionState(int level, IntPtr inpbuf, int inpbuflen, out int state, int outbuflen);
}