Files
alro65 46dc0423a0 fix(display-manager): lazy launch by default + minimize unassigned apps
- autolaunch default: True → False (on-demand only, saves GPU on startup)
- add ProcessManager.minimize() to minimize a window to taskbar
- add win32_utils.minimize_window() (SW_MINIMIZE via user32)
- DisplayManager._minimize_unassigned(): after each app switch, minimize
  every running app not currently assigned to any screen, freeing iGPU
  resources (critical on J6412 UHD 600 with limited EUs)

Background: J6412 Intel UHD 600 has only 16 EUs @ 800 MHz. Running
AR-ECDIS (MapLibre GL) and GPS (OpenLayers) simultaneously consumes ~60%
iGPU. By minimizing inactive apps Windows suspends their GPU presentation
chain, dropping idle GPU load near zero.

AR_electronics — AR-Autopilot Project
2026-05-24 21:53:00 -04:00

90 lines
2.9 KiB
Python

"""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 minimize_window(hwnd: int) -> None:
"""Minimize a window to taskbar to free GPU resources."""
_SW_MINIMIZE = 6
_user32.ShowWindow(hwnd, _SW_MINIMIZE)
def is_window_alive(hwnd: int) -> bool:
return bool(_user32.IsWindow(hwnd))