Raise the browser the extension reported, and add a diagnostics script

focus.py raised the first browser in its list that happened to be running. On a
machine with both Chrome and Edge installed that is a coin flip, and losing it is
silent: coordinates measured from a tab in one browser, the click delivered into
a window of the other. It presents as selectors failing for no reason. A VPS with
both installed hit exactly this.

The extension now reports which browser is hosting it, and that travels with the
measurement, so the clicker raises the browser the coordinates actually came
from. Asking for a browser that is not running now fails honestly instead of
quietly raising a different one, and the verification step rejects the wrong
browser coming forward. Chromium, Opera and Vivaldi are recognised alongside
Chrome, Edge and Brave, on both platforms.

diagnose.py answers the question a remote desktop makes hard: whether the mouse
is really moving or the viewer simply is not drawing it. It moves the cursor and
reads the position back from the OS, so the answer does not depend on anything
being rendered, and it reports DPI mode, screen size, whether this is an RDP
session, and whether the browser can be raised at all. Nothing is clicked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-08-30 14:13:18 -05:00
co-authored by Claude Opus 5
parent 731fafda0e
commit 3ac9fe060f
7 changed files with 247 additions and 39 deletions
+138
View File
@@ -0,0 +1,138 @@
#!/usr/bin/env python3
"""Check whether this machine can actually be driven.
Run it on the box that will do the clicking, before trusting a run:
python diagnose.py
It answers the question a remote desktop makes hard — is the mouse really moving,
or is the viewer just not drawing it? The cursor position is read back from the
OS after each move, so the answer doesn't depend on anything being rendered.
Nothing is clicked. The cursor is moved and put back where it started.
"""
import sys
import time
def line(label: str, value: str) -> None:
print(f" {label:<22} {value}")
def check_platform() -> None:
print("\nPlatform")
line("os", sys.platform)
line("python", sys.version.split()[0])
if sys.platform != "win32":
return
import ctypes
# SM_REMOTESESSION: non-zero when this process is running inside an RDP
# session rather than at the physical console.
remote = ctypes.windll.user32.GetSystemMetrics(0x1000)
line("remote session", "yes — RDP/terminal services" if remote else "no — physical console")
if remote:
print(" Input injection still works over RDP, but the session's desktop")
print(" is locked when you disconnect, and clicks go nowhere until you")
print(" reconnect. Keep the window open for the duration of a run.")
def check_dpi() -> None:
print("\nDisplay")
try:
import focus
except ImportError:
line("dpi awareness", "focus.py not importable — run this from clicker/")
return
result = focus.enable_dpi_awareness()
line("dpi awareness", result or "n/a (not Windows)")
try:
import pyautogui
except ImportError:
line("screen size", "pyautogui not installed")
return
size = pyautogui.size()
line("screen size", f"{size.width}x{size.height} (as the OS reports it)")
print(" Compare against what `clicker.py locate` reports for screenSize.")
print(" A mismatch that isn't a clean scaling factor means clicks land off.")
def check_mouse() -> bool:
"""Move the cursor and read it back. Returns True if the OS agreed."""
print("\nMouse")
try:
import pyautogui
except ImportError:
line("result", "pyautogui not installed — run: pip install -r requirements.txt")
return False
pyautogui.FAILSAFE = False # a deliberate corner move would abort us
start = pyautogui.position()
line("start position", f"{start[0]},{start[1]}")
width, height = pyautogui.size()
targets = [(width // 4, height // 4), (width // 2, height // 2)]
agreed = True
for x, y in targets:
pyautogui.moveTo(x, y, duration=0.3)
time.sleep(0.1)
got = pyautogui.position()
ok = abs(got[0] - x) <= 2 and abs(got[1] - y) <= 2
agreed &= ok
line("moved to", f"{x},{y} -> OS reports {got[0]},{got[1]} {'OK' if ok else 'MISMATCH'}")
pyautogui.moveTo(start[0], start[1], duration=0.2)
print()
if agreed:
print(" The OS moved the cursor to every requested point.")
print(" If you saw nothing move, that is your viewer not drawing it —")
print(" the clicks are landing where they should.")
else:
print(" The cursor did NOT land where it was asked to.")
print(" On Windows this is usually display scaling: the process is being")
print(" fed virtualised coordinates. Check the dpi awareness line above,")
print(" and pass --scale to clicker.py to compensate.")
return agreed
def check_foreground() -> None:
print("\nForeground window")
try:
import focus
except ImportError:
line("frontmost", "focus.py not importable")
return
front = focus.frontmost()
line("frontmost", front or "could not determine on this platform")
line("browsers known", ", ".join(focus.browser_ids()) or "none for this platform")
result = focus.ensure_frontmost()
line("raise browser", f"{'OK' if result.ok else 'FAILED'}{result.detail}")
print(" With no browser named, any known one counts — that is this check")
print(" only. A real run raises the browser the extension reported, so if")
print(" this raised one you do not automate, that is not a fault.")
if not result.ok:
print(" Every click is refused while this fails: a click on an")
print(" unfocused window is consumed activating it.")
def main() -> int:
print("AutoFirmer clicker diagnostics")
check_platform()
check_dpi()
ok = check_mouse()
check_foreground()
print()
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())