← Commit history

0.9.318: Wiki #48: the 20 s idle healer measured window reachability against the primary monitor only and pulled windows on a second monitor back to the primary; it now measures against the monitor the window overlaps

John Lauer ·402342a2f3 ·1mo ago ·parent 51d7fae
1 file changed +33−4
handlers/win_focus.py+33−4
@@ -1092,6 +1092,32 @@ def _park_offscreen(hwnd) -> None:     _push_kicad_to_background(hwnd)  +class _MONITORINFO(ctypes.Structure):+    _fields_ = [("cbSize", ctypes.wintypes.DWORD), ("rcMonitor", ctypes.wintypes.RECT),+                ("rcWork", ctypes.wintypes.RECT), ("dwFlags", ctypes.wintypes.DWORD)]+++def _visible_on_any_monitor(r) -> tuple:+    """(visible_w, visible_h) of window rect r on the monitor it overlaps most;+    (0, 0) when it is off every monitor. MONITOR_DEFAULTTONULL, so a second or+    third display counts exactly like the primary."""+    try:+        _user32.MonitorFromRect.restype = ctypes.wintypes.HANDLE      # 64-bit handle, never truncated+        _user32.MonitorFromRect.argtypes = [ctypes.POINTER(ctypes.wintypes.RECT), ctypes.wintypes.DWORD]+        _user32.GetMonitorInfoW.argtypes = [ctypes.wintypes.HANDLE, ctypes.POINTER(_MONITORINFO)]+        hmon = _user32.MonitorFromRect(ctypes.byref(r), 0)+        if not hmon:+            return (0, 0)+        mi = _MONITORINFO(); mi.cbSize = ctypes.sizeof(_MONITORINFO)+        if not _user32.GetMonitorInfoW(hmon, ctypes.byref(mi)):+            return (0, 0)+        m = mi.rcMonitor+        return (min(r.right, m.right) - max(r.left, m.left), min(r.bottom, m.bottom) - max(r.top, m.top))+    except Exception:+        # Unknown: report reachable so the healer never moves a window on a guess.+        return (10**6, 10**6)++ def _sane_position(hwnd) -> None:     """0.9.160: guarantee an unparked window lands somewhere the user can reach.     A window parked before KiCad finished placing itself unparks to a garbage@@ -1102,11 +1128,14 @@ def _sane_position(hwnd) -> None:         r = ctypes.wintypes.RECT()         if not _user32.GetWindowRect(hwnd, ctypes.byref(r)):             return-        sw = _user32.GetSystemMetrics(0)-        sh = _user32.GetSystemMetrics(1)         w, h = max(r.right - r.left, 640), max(r.bottom - r.top, 480)-        visible_w = min(r.right, sw) - max(r.left, 0)-        visible_h = min(r.bottom, sh) - max(r.top, 0)+        # Wiki #48 (AdityaAngajala, 2026-09-04): "when I drag KiCad to another+        # monitor it gets dragged back to my main one after some time". This+        # ran every 20 s from the idle healer and measured reachability against+        # the PRIMARY monitor only (GetSystemMetrics 0/1), so a window fully on+        # a second monitor counted as off-screen and was moved to (120,90).+        # Measure against the monitor the window actually overlaps most.+        visible_w, visible_h = _visible_on_any_monitor(r)         if visible_w >= 200 and visible_h >= 200:             return  # genuinely reachable already         x, y = 120, 90