46dc0423a0
- 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
90 lines
2.9 KiB
Python
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))
|