Files
TimeTracker/src/time_tracker/platform/windows.py

90 lines
2.7 KiB
Python
Raw Normal View History

2026-03-09 21:42:02 +03:00
import win32gui
2026-03-10 00:44:46 +03:00
import win32process
2026-03-09 21:42:02 +03:00
import win32con
import win32api
import threading
from typing import Callable
2026-03-10 00:44:46 +03:00
import psutil
2026-03-09 21:42:02 +03:00
def get_active_window() -> str:
2026-03-10 00:44:46 +03:00
"""Returns a string like 'YouTube - Chrome (chrome.exe)'"""
2026-03-09 21:42:02 +03:00
try:
hwnd = win32gui.GetForegroundWindow()
2026-03-10 00:44:46 +03:00
title = win32gui.GetWindowText(hwnd) or "Unknown Window"
# Get process name
_, pid = win32process.GetWindowThreadProcessId(hwnd)
try:
proc = psutil.Process(pid)
exe_name = proc.name()
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
exe_name = "unknown.exe"
return f"{title} ({exe_name})"
except Exception:
return "Error getting window info"
2026-03-09 21:42:02 +03:00
def register_session_listener(callback: Callable[[str], None]) -> None:
"""Register a callback for Windows session lock/unlock events"""
def session_event_handler(hwnd, msg, wparam, lparam):
2026-03-10 00:44:46 +03:00
# Fallback numeric constants
WM_WTSSESSION_CHANGE = 0x02B1
WTS_SESSION_LOCK = 0x1
WTS_SESSION_UNLOCK = 0x2
if msg == WM_WTSSESSION_CHANGE:
if wparam == WTS_SESSION_LOCK:
callback("locked")
elif wparam == WTS_SESSION_UNLOCK:
callback("unlocked")
2026-03-09 22:05:48 +03:00
2026-03-09 21:42:02 +03:00
return win32gui.DefWindowProc(hwnd, msg, wparam, lparam)
def run_message_loop():
hinst = win32api.GetModuleHandle(None)
wndclass = win32gui.WNDCLASS()
wndclass.hInstance = hinst
wndclass.lpszClassName = "SessionWatcher"
wndclass.lpfnWndProc = session_event_handler
try:
win32gui.RegisterClass(wndclass)
except:
pass # Already registered
hwnd = win32gui.CreateWindow(
2026-03-10 00:44:46 +03:00
wndclass.lpszClassName,
"Session Watcher",
0, 0, 0, 0, 0,
0, 0, hinst, None
2026-03-09 21:42:02 +03:00
)
# Register for session notifications
try:
from win32ts import WTSRegisterSessionNotification
2026-03-10 00:44:46 +03:00
WTSRegisterSessionNotification(hwnd, 1)
2026-03-09 21:42:02 +03:00
except ImportError:
pass
win32gui.PumpMessages()
thread = threading.Thread(target=run_message_loop, daemon=True)
thread.start()
def get_idle_time() -> int:
"""Get the system idle time in seconds on Windows"""
from ctypes import Structure, windll, c_uint, sizeof, byref
class LASTINPUTINFO(Structure):
_fields_ = [('cbSize', c_uint), ('dwTime', c_uint)]
lastInputInfo = LASTINPUTINFO()
lastInputInfo.cbSize = sizeof(lastInputInfo)
windll.user32.GetLastInputInfo(byref(lastInputInfo))
millis = windll.kernel32.GetTickCount() - lastInputInfo.dwTime
2026-03-10 00:44:46 +03:00
return millis // 1000