"""Windows API helpers for window management (ctypes, no extra dependencies).""" from __future__ import annotations import ctypes import ctypes.wintypes as wt import sys if sys.platform != "win32": # Stub for non-Windows development/testing def find_window_by_pid(pid: int) -> int | None: return None def move_and_maximize(hwnd: int, x: int, y: int, w: int, h: int) -> None: pass def is_window_alive(hwnd: int) -> bool: return False else: _user32 = ctypes.windll.user32 # type: ignore[attr-defined] # Constants _HWND_TOP = 0 _SW_RESTORE = 9 _SW_MAXIMIZE = 3 _SWP_SHOWWINDOW = 0x0040 _SWP_FRAMECHANGED = 0x0020 _GW_OWNER = 4 # Callback type for EnumWindows _WNDENUMPROC = ctypes.WINFUNCTYPE(ctypes.c_bool, wt.HWND, wt.LPARAM) def find_window_by_pid(pid: int) -> int | None: """Return the first visible top-level HWND belonging to *pid*.""" found: list[int] = [] def _cb(hwnd: int, _: int) -> bool: if not _user32.IsWindowVisible(hwnd): return True # Skip windows with an owner (child dialogs, etc.) if _user32.GetWindow(hwnd, _GW_OWNER): return True lp_pid = wt.DWORD() _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(lp_pid)) if lp_pid.value == pid: found.append(hwnd) return False # stop enumeration return True _user32.EnumWindows(_WNDENUMPROC(_cb), 0) return found[0] if found else None def find_window_by_title_hint(hint: str) -> int | None: """Return the first visible top-level HWND whose title contains *hint*.""" if not hint: return None found: list[int] = [] def _cb(hwnd: int, _: int) -> bool: if not _user32.IsWindowVisible(hwnd): return True buf = ctypes.create_unicode_buffer(512) _user32.GetWindowTextW(hwnd, buf, 512) if hint.lower() in buf.value.lower(): found.append(hwnd) return False return True _user32.EnumWindows(_WNDENUMPROC(_cb), 0) return found[0] if found else None def move_and_maximize(hwnd: int, x: int, y: int, w: int, h: int) -> None: """Move a window to (x, y, w, h) then maximize it on that monitor.""" _user32.ShowWindow(hwnd, _SW_RESTORE) _user32.SetWindowPos( hwnd, _HWND_TOP, x, y, w, h, _SWP_SHOWWINDOW | _SWP_FRAMECHANGED, ) _user32.ShowWindow(hwnd, _SW_MAXIMIZE) _user32.SetForegroundWindow(hwnd) def is_window_alive(hwnd: int) -> bool: return bool(_user32.IsWindow(hwnd))