Files
upstream-mirror 87aaa2add8
Some checks failed
Build / Test on macos-latest (py-3.9) (push) Has been cancelled
Build / Test on ubuntu-24.04 (py-3.9) (push) Has been cancelled
Build / Test on windows-latest (py-3.9) (push) Has been cancelled
CodeQL / Analyze (python) (push) Failing after 1m36s
snapshot of https://github.com/ActivityWatch/aw-watcher-afk.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 00:21:02 +05:00

55 lines
1.9 KiB
Python

import ctypes
import time
from ctypes import POINTER, Structure, c_ulonglong
from ctypes.wintypes import BOOL, DWORD, UINT
ULONGLONG = c_ulonglong
class LastInputInfo(Structure):
_fields_ = [("cbSize", UINT), ("dwTime", DWORD)]
def _getLastInputTick() -> int:
prototype = ctypes.WINFUNCTYPE(BOOL, POINTER(LastInputInfo)) # type: ignore[attr-defined]
paramflags = ((1, "lastinputinfo"),)
c_GetLastInputInfo = prototype(("GetLastInputInfo", ctypes.windll.user32), paramflags) # type: ignore
lastinput = LastInputInfo()
lastinput.cbSize = ctypes.sizeof(LastInputInfo)
if 0 == c_GetLastInputInfo(lastinput):
raise OSError("GetLastInputInfo failed")
return lastinput.dwTime
def _getTickCount64() -> int:
"""Use GetTickCount64 to avoid 32-bit overflow after ~49.7 days of uptime."""
prototype = ctypes.WINFUNCTYPE(ULONGLONG) # type: ignore[attr-defined]
paramflags = ()
c_GetTickCount64 = prototype(("GetTickCount64", ctypes.windll.kernel32), paramflags) # type: ignore
return c_GetTickCount64()
def seconds_since_last_input() -> float:
tick_count = _getTickCount64()
last_input_tick = _getLastInputTick() # 32-bit DWORD from GetLastInputInfo
# GetLastInputInfo returns a 32-bit DWORD tick count that wraps at 2^32 ms.
# GetTickCount64 returns 64-bit. To compute the difference correctly, we
# compare only the lower 32 bits when the values are close (normal case),
# and handle the wraparound when dwTime > lower 32 bits of tick_count.
tick_lower32 = tick_count & 0xFFFFFFFF
if tick_lower32 >= last_input_tick:
diff_ms = tick_lower32 - last_input_tick
else:
# 32-bit wraparound: tick_count's lower bits wrapped past dwTime
diff_ms = (0x100000000 - last_input_tick) + tick_lower32
return diff_ms / 1000
if __name__ == "__main__":
while True:
time.sleep(1)
print(seconds_since_last_input())