From 2c1dae14fc07a34f2a226ae86bd129068a40bff2 Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Tue, 21 Apr 2026 16:22:47 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20for=C8=9Beaz=C4=83=20SetForegroundWindow?= =?UTF-8?q?=20prin=20ALT-key=20pentru=20anti=20focus-stealing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pygetwindow.activate() raporta succes dar Windows refuza silent ridicarea ferestrei TS (confirmat în audit: window_focused cu titlul corect, dar screenshot-ul manual tot prindea app-ul de deasupra). Trucul standard: keybd_event(ALT) resetează focus-lock-ul, apoi SetForegroundWindow via ctypes pe hwnd direct. Fallback la win.activate() dacă lipsește _hWnd. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/atm/main.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/atm/main.py b/src/atm/main.py index d43778b..e2e3483 100644 --- a/src/atm/main.py +++ b/src/atm/main.py @@ -202,6 +202,12 @@ def _focus_window_by_title(needle: str) -> str | None: Returnează titlul găsit sau None (niciun match, Win32 a refuzat activate, sau `pygetwindow` lipsește — caz normal pe Linux/WSL unde rulează doar testele). + + pygetwindow.activate() folosește SetForegroundWindow, care Windows îl + refuză silent când procesul apelant nu e cel care deține focus-ul + (protecția anti focus-stealing introdusă în Win2000). Trucul standard: + trimiți un ALT press/release ca să resetezi lock-ul, apoi restore + + SetForegroundWindow prin ctypes pe hwnd direct. """ try: import pygetwindow as gw # type: ignore[import-untyped] @@ -213,10 +219,22 @@ def _focus_window_by_title(needle: str) -> str | None: if not matches: return None win = matches[0] + hwnd = getattr(win, "_hWnd", None) + if hwnd is None: + try: + win.activate() + return win.title + except Exception: + return None try: - if win.isMinimized: - win.restore() - win.activate() + import ctypes + user32 = ctypes.windll.user32 + # VK_MENU=0x12 (ALT), KEYEVENTF_KEYUP=0x02 — unlocks focus protection. + user32.keybd_event(0x12, 0, 0, 0) + user32.keybd_event(0x12, 0, 0x02, 0) + user32.ShowWindow(hwnd, 9) # SW_RESTORE + user32.BringWindowToTop(hwnd) + user32.SetForegroundWindow(hwnd) return win.title except Exception: return None