snapshot of https://github.com/ActivityWatch/aw-watcher-afk.git (master, 2026-09-16; blobs > 131072B omitted)
This commit is contained in:
54
aw_watcher_afk/windows.py
Normal file
54
aw_watcher_afk/windows.py
Normal file
@@ -0,0 +1,54 @@
|
||||
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())
|
||||
Reference in New Issue
Block a user