#!/usr/bin/env python3 """Windows virtual cursor overlay. The first Windows implementation drew a 168x30 text banner beside the system cursor. Apart from looking unlike the macOS feature, that window followed the user's pointer as well as Computer Use and was not per-monitor-DPI aware, so it could float over the wrong application and at the wrong coordinates. This process renders the same visual language as the native macOS helper: a blue pointer with a white keyline, breathing halo, idle bob, and click ripple. It observes the low-level mouse stream and follows injected movement only. The real Windows pointer still has to move because Windows has no ``postToPid`` equivalent, but the virtual cursor is co-located with that pointer during agent movement and stays at the agent's last point if the user takes the mouse. The parent sends one JSON line for each action and closes stdin at turn end. The window is per-pixel-alpha, topmost, click-through, absent from Alt-Tab, and never activates. Visual failures remain advisory and never block input. """ from __future__ import annotations import argparse import ctypes import json import math import os import sys import threading import time from ctypes import wintypes from PIL import Image, ImageChops, ImageDraw, ImageFilter user32 = ctypes.windll.user32 gdi32 = ctypes.windll.gdi32 kernel32 = ctypes.windll.kernel32 WS_EX_LAYERED = 0x00080000 WS_EX_TRANSPARENT = 0x00000020 WS_EX_TOPMOST = 0x00000008 WS_EX_TOOLWINDOW = 0x00000080 WS_EX_NOACTIVATE = 0x08000000 WS_POPUP = 0x80000000 SW_HIDE = 0 SW_SHOWNOACTIVATE = 4 HWND_TOPMOST = wintypes.HWND(-1) SWP_NOACTIVATE = 0x0010 WM_DESTROY = 0x0002 WM_CLOSE = 0x0010 WM_NCHITTEST = 0x0084 WM_TIMER = 0x0113 WM_MOUSEMOVE = 0x0200 WM_LBUTTONDOWN = 0x0201 WM_LBUTTONUP = 0x0202 WM_RBUTTONDOWN = 0x0204 WM_RBUTTONUP = 0x0205 WM_MBUTTONDOWN = 0x0207 WM_MBUTTONUP = 0x0208 WM_MOUSEWHEEL = 0x020A WM_MOUSEHWHEEL = 0x020E HTTRANSPARENT = -1 WH_MOUSE_LL = 14 HC_ACTION = 0 LLMHF_INJECTED = 0x00000001 LLMHF_LOWER_IL_INJECTED = 0x00000002 ULW_ALPHA = 0x00000002 AC_SRC_OVER = 0x00 AC_SRC_ALPHA = 0x01 DIB_RGB_COLORS = 0 BI_RGB = 0 GW_HWNDNEXT = 2 GWL_EXSTYLE = -20 MONITOR_DEFAULTTONEAREST = 2 MDT_EFFECTIVE_DPI = 0 INPUT_TAG_ENV = "CC_HAHA_COMPUTER_USE_INPUT_TAG" # Windows 10 1703+. Negative pseudo-handles are the documented ABI values. DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = ctypes.c_void_p(-4) # Logical-point geometry mirrors VirtualCursorStyle.swift. The overlay is # scaled to the current monitor's DPI before it reaches UpdateLayeredWindow. CANVAS_SIZE = 76 HOTSPOT = (32.0, 30.0) ARROW_HEIGHT = 22.0 ARROW_POINTS = ( (0.0, 0.0), (0.0, 16.5), (4.0, 12.7), (6.6, 18.5), (9.2, 17.4), (6.6, 11.6), (11.6, 11.2), ) HALO_DIAMETER = ARROW_HEIGHT * 2.4 IDLE_BOB_AMPLITUDE = 1.5 IDLE_BOB_PERIOD = 1.8 HALO_BREATH_PERIOD = 2.4 TIMER_ID = 1 TIMER_INTERVAL_MS = 16 class POINT(ctypes.Structure): _fields_ = [("x", wintypes.LONG), ("y", wintypes.LONG)] class SIZE(ctypes.Structure): _fields_ = [("cx", wintypes.LONG), ("cy", wintypes.LONG)] class RECT(ctypes.Structure): _fields_ = [ ("left", wintypes.LONG), ("top", wintypes.LONG), ("right", wintypes.LONG), ("bottom", wintypes.LONG), ] class BLENDFUNCTION(ctypes.Structure): _fields_ = [ ("BlendOp", ctypes.c_ubyte), ("BlendFlags", ctypes.c_ubyte), ("SourceConstantAlpha", ctypes.c_ubyte), ("AlphaFormat", ctypes.c_ubyte), ] class BITMAPINFOHEADER(ctypes.Structure): _fields_ = [ ("biSize", wintypes.DWORD), ("biWidth", wintypes.LONG), ("biHeight", wintypes.LONG), ("biPlanes", wintypes.WORD), ("biBitCount", wintypes.WORD), ("biCompression", wintypes.DWORD), ("biSizeImage", wintypes.DWORD), ("biXPelsPerMeter", wintypes.LONG), ("biYPelsPerMeter", wintypes.LONG), ("biClrUsed", wintypes.DWORD), ("biClrImportant", wintypes.DWORD), ] class RGBQUAD(ctypes.Structure): _fields_ = [ ("rgbBlue", ctypes.c_ubyte), ("rgbGreen", ctypes.c_ubyte), ("rgbRed", ctypes.c_ubyte), ("rgbReserved", ctypes.c_ubyte), ] class BITMAPINFO(ctypes.Structure): _fields_ = [("bmiHeader", BITMAPINFOHEADER), ("bmiColors", RGBQUAD * 1)] class MSLLHOOKSTRUCT(ctypes.Structure): _fields_ = [ ("pt", POINT), ("mouseData", wintypes.DWORD), ("flags", wintypes.DWORD), ("time", wintypes.DWORD), ("dwExtraInfo", ctypes.c_size_t), ] LRESULT = ctypes.c_ssize_t WNDPROC = ctypes.WINFUNCTYPE( LRESULT, wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM ) HOOKPROC = ctypes.WINFUNCTYPE( LRESULT, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM ) class WNDCLASS(ctypes.Structure): _fields_ = [ ("style", wintypes.UINT), ("lpfnWndProc", WNDPROC), ("cbClsExtra", ctypes.c_int), ("cbWndExtra", ctypes.c_int), ("hInstance", wintypes.HINSTANCE), ("hIcon", wintypes.HICON), ("hCursor", wintypes.HANDLE), ("hbrBackground", wintypes.HBRUSH), ("lpszMenuName", wintypes.LPCWSTR), ("lpszClassName", wintypes.LPCWSTR), ] def _enable_per_monitor_dpi_awareness() -> None: """Make pointer, window, and screenshot coordinates all physical pixels.""" try: setter = user32.SetProcessDpiAwarenessContext setter.argtypes = [wintypes.HANDLE] setter.restype = wintypes.BOOL if setter(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2): return except (AttributeError, OSError): pass try: shcore = ctypes.windll.shcore shcore.SetProcessDpiAwareness.argtypes = [ctypes.c_int] shcore.SetProcessDpiAwareness.restype = ctypes.c_long if shcore.SetProcessDpiAwareness(2) in (0, 0x80070005): return except (AttributeError, OSError): pass try: user32.SetProcessDPIAware() except (AttributeError, OSError): pass def _configure_win32() -> None: kernel32.GetModuleHandleW.argtypes = [wintypes.LPCWSTR] kernel32.GetModuleHandleW.restype = wintypes.HINSTANCE user32.RegisterClassW.argtypes = [ctypes.POINTER(WNDCLASS)] user32.RegisterClassW.restype = wintypes.WORD user32.CreateWindowExW.argtypes = [ wintypes.DWORD, wintypes.LPCWSTR, wintypes.LPCWSTR, wintypes.DWORD, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, wintypes.HWND, wintypes.HANDLE, wintypes.HINSTANCE, wintypes.LPVOID, ] user32.CreateWindowExW.restype = wintypes.HWND user32.DefWindowProcW.argtypes = [ wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM, ] user32.DefWindowProcW.restype = LRESULT user32.DestroyWindow.argtypes = [wintypes.HWND] user32.DestroyWindow.restype = wintypes.BOOL user32.PostQuitMessage.argtypes = [ctypes.c_int] user32.PostQuitMessage.restype = None user32.PostMessageW.argtypes = [ wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM, ] user32.PostMessageW.restype = wintypes.BOOL user32.GetMessageW.argtypes = [ ctypes.POINTER(wintypes.MSG), wintypes.HWND, wintypes.UINT, wintypes.UINT, ] user32.GetMessageW.restype = ctypes.c_int user32.TranslateMessage.argtypes = [ctypes.POINTER(wintypes.MSG)] user32.TranslateMessage.restype = wintypes.BOOL user32.DispatchMessageW.argtypes = [ctypes.POINTER(wintypes.MSG)] user32.DispatchMessageW.restype = LRESULT user32.ShowWindow.argtypes = [wintypes.HWND, ctypes.c_int] user32.ShowWindow.restype = wintypes.BOOL user32.SetWindowPos.argtypes = [ wintypes.HWND, wintypes.HWND, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, wintypes.UINT, ] user32.SetWindowPos.restype = wintypes.BOOL user32.SetTimer.argtypes = [wintypes.HWND, ctypes.c_size_t, wintypes.UINT, wintypes.LPVOID] user32.SetTimer.restype = ctypes.c_size_t user32.KillTimer.argtypes = [wintypes.HWND, ctypes.c_size_t] user32.KillTimer.restype = wintypes.BOOL user32.SetWindowsHookExW.argtypes = [ ctypes.c_int, HOOKPROC, wintypes.HINSTANCE, wintypes.DWORD, ] user32.SetWindowsHookExW.restype = wintypes.HANDLE user32.CallNextHookEx.argtypes = [ wintypes.HANDLE, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM, ] user32.CallNextHookEx.restype = LRESULT user32.UnhookWindowsHookEx.argtypes = [wintypes.HANDLE] user32.UnhookWindowsHookEx.restype = wintypes.BOOL user32.UpdateLayeredWindow.argtypes = [ wintypes.HWND, wintypes.HDC, ctypes.POINTER(POINT), ctypes.POINTER(SIZE), wintypes.HDC, ctypes.POINTER(POINT), wintypes.DWORD, ctypes.POINTER(BLENDFUNCTION), wintypes.DWORD, ] user32.UpdateLayeredWindow.restype = wintypes.BOOL user32.GetDpiForWindow.argtypes = [wintypes.HWND] user32.GetDpiForWindow.restype = wintypes.UINT user32.MonitorFromPoint.argtypes = [POINT, wintypes.DWORD] user32.MonitorFromPoint.restype = wintypes.HANDLE user32.WindowFromPoint.argtypes = [POINT] user32.WindowFromPoint.restype = wintypes.HWND user32.GetForegroundWindow.argtypes = [] user32.GetForegroundWindow.restype = wintypes.HWND user32.GetWindowThreadProcessId.argtypes = [wintypes.HWND, ctypes.POINTER(wintypes.DWORD)] user32.GetWindowThreadProcessId.restype = wintypes.DWORD user32.GetTopWindow.argtypes = [wintypes.HWND] user32.GetTopWindow.restype = wintypes.HWND user32.GetWindow.argtypes = [wintypes.HWND, wintypes.UINT] user32.GetWindow.restype = wintypes.HWND user32.IsWindowVisible.argtypes = [wintypes.HWND] user32.IsWindowVisible.restype = wintypes.BOOL user32.IsIconic.argtypes = [wintypes.HWND] user32.IsIconic.restype = wintypes.BOOL user32.GetWindowRect.argtypes = [wintypes.HWND, ctypes.POINTER(RECT)] user32.GetWindowRect.restype = wintypes.BOOL user32.GetWindowLongW.argtypes = [wintypes.HWND, ctypes.c_int] user32.GetWindowLongW.restype = ctypes.c_long gdi32.CreateCompatibleDC.argtypes = [wintypes.HDC] gdi32.CreateCompatibleDC.restype = wintypes.HDC gdi32.DeleteDC.argtypes = [wintypes.HDC] gdi32.DeleteDC.restype = wintypes.BOOL gdi32.CreateDIBSection.argtypes = [ wintypes.HDC, ctypes.POINTER(BITMAPINFO), wintypes.UINT, ctypes.POINTER(ctypes.c_void_p), wintypes.HANDLE, wintypes.DWORD, ] gdi32.CreateDIBSection.restype = wintypes.HBITMAP gdi32.SelectObject.argtypes = [wintypes.HDC, wintypes.HANDLE] gdi32.SelectObject.restype = wintypes.HANDLE gdi32.DeleteObject.argtypes = [wintypes.HANDLE] gdi32.DeleteObject.restype = wintypes.BOOL try: shcore = ctypes.windll.shcore shcore.GetDpiForMonitor.argtypes = [ wintypes.HANDLE, ctypes.c_int, ctypes.POINTER(wintypes.UINT), ctypes.POINTER(wintypes.UINT), ] shcore.GetDpiForMonitor.restype = ctypes.c_long except (AttributeError, OSError): pass _enable_per_monitor_dpi_awareness() _configure_win32() def _pid_for_window(hwnd: int | None) -> int | None: if not hwnd: return None pid = wintypes.DWORD() user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid)) return int(pid.value) or None def _input_tag() -> int | None: try: value = int(os.environ[INPUT_TAG_ENV]) & 0xFFFFFFFF return value or None except (KeyError, TypeError, ValueError): return None def _dpi_at_point(point: tuple[int, int], hwnd: int) -> int: """Return the DPI of the destination monitor before moving the overlay.""" try: monitor = user32.MonitorFromPoint( POINT(point[0], point[1]), MONITOR_DEFAULTTONEAREST, ) dpi_x = wintypes.UINT() dpi_y = wintypes.UINT() if monitor and ctypes.windll.shcore.GetDpiForMonitor( monitor, MDT_EFFECTIVE_DPI, ctypes.byref(dpi_x), ctypes.byref(dpi_y), ) == 0: return int(dpi_x.value) or 96 except (AttributeError, OSError): pass return int(user32.GetDpiForWindow(hwnd)) or 96 def _point_from_activity(command: str, payload: dict) -> tuple[int, int] | None: if command == "drag": point = payload.get("to") or {} if "x" in point and "y" in point: return int(point["x"]), int(point["y"]) return None if command in {"click", "move_mouse", "scroll"}: if "x" in payload and "y" in payload: return int(payload["x"]), int(payload["y"]) return None def _premultiplied_bgra(image: Image.Image) -> bytes: red, green, blue, alpha = image.split() return Image.merge("RGBA", ( ImageChops.multiply(blue, alpha), ImageChops.multiply(green, alpha), ImageChops.multiply(red, alpha), alpha, )).tobytes() def _render_cursor(scale: float, now: float, click: tuple[float, int] | None) -> Image.Image: """Render one anti-aliased frame using the native helper's dimensions.""" size = max(1, round(CANVAS_SIZE * scale)) antialias = 3 factor = scale * antialias image = Image.new("RGBA", (size * antialias, size * antialias), (0, 0, 0, 0)) breath = (math.sin((now / HALO_BREATH_PERIOD) * math.tau - math.pi / 2) + 1) / 2 halo_scale = 0.86 + breath * 0.28 halo_alpha = 0.5 + breath * 0.5 arrow_scale = ARROW_HEIGHT / 19.0 bob = math.sin((now / IDLE_BOB_PERIOD) * math.tau) * IDLE_BOB_AMPLITUDE tip_x = HOTSPOT[0] * factor tip_y = HOTSPOT[1] * factor arrow_points = [ ( tip_x + x * arrow_scale * factor, tip_y + (y * arrow_scale + bob) * factor, ) for x, y in ARROW_POINTS ] arrow_width = max(x for x, _ in ARROW_POINTS) * arrow_scale halo_center = ( tip_x + arrow_width * factor / 2, tip_y + ARROW_HEIGHT * factor / 2, ) halo_radius = HALO_DIAMETER * halo_scale * factor / 2 halo = Image.new("RGBA", image.size, (0, 0, 0, 0)) halo_draw = ImageDraw.Draw(halo) halo_draw.ellipse( ( halo_center[0] - halo_radius, halo_center[1] - halo_radius, halo_center[0] + halo_radius, halo_center[1] + halo_radius, ), fill=(38, 140, 255, round(107 * halo_alpha)), ) halo = halo.filter(ImageFilter.GaussianBlur(max(1, round(7 * factor)))) image = Image.alpha_composite(image, halo) if click is not None: started, kind = click progress = min(1.0, max(0.0, (now - started) / 0.38)) if progress < 1: ripple = ImageDraw.Draw(image) radius = (7 + 21 * progress) * factor alpha = round(230 * (1 - progress)) color = (255, 149, 0, alpha) if kind == WM_RBUTTONDOWN else (77, 158, 255, alpha) width = max(1, round(2.5 * factor)) ripple.ellipse( (tip_x - radius, tip_y - radius, tip_x + radius, tip_y + radius), outline=color, width=width, ) pulse = 1.0 - 0.2 * math.sin(progress * math.pi) arrow_points = [ (tip_x + (x - tip_x) * pulse, tip_y + (y - tip_y) * pulse) for x, y in arrow_points ] shadow = Image.new("RGBA", image.size, (0, 0, 0, 0)) shadow_draw = ImageDraw.Draw(shadow) shadow_draw.polygon( [(x, y + factor) for x, y in arrow_points], fill=(0, 0, 0, 90), ) shadow = shadow.filter(ImageFilter.GaussianBlur(max(1, round(3 * factor)))) image = Image.alpha_composite(image, shadow) arrow = ImageDraw.Draw(image) outline_width = max(1, round(1.5 * factor)) arrow.polygon(arrow_points, fill="#0075f2") arrow.line( [*arrow_points, arrow_points[0]], fill="white", width=outline_width, joint="curve", ) return image.resize((size, size), Image.Resampling.LANCZOS) class VirtualCursorOverlay: def __init__(self) -> None: self.hwnd: int | None = None self._stop = threading.Event() self._lock = threading.Lock() self._agent_position: tuple[int, int] | None = None self._destination: tuple[int, int] | None = None self._target_pid: int | None = None self._requested_visible = False self._hidden_for_user = False self._click: tuple[float, int] | None = None self._shown = False self._mouse_hook: int | None = None self._input_tag = _input_tag() self._wndproc = WNDPROC(self._on_message) self._hookproc = HOOKPROC(self._on_mouse_hook) def _on_message(self, hwnd, msg, wparam, lparam): if msg == WM_NCHITTEST: return HTTRANSPARENT if msg == WM_TIMER and int(wparam) == TIMER_ID: self._tick() return 0 if msg == WM_CLOSE: user32.DestroyWindow(hwnd) return 0 if msg == WM_DESTROY: user32.PostQuitMessage(0) return 0 return user32.DefWindowProcW(hwnd, msg, wparam, lparam) def _on_mouse_hook(self, code, wparam, lparam): if code == HC_ACTION: info = ctypes.cast(lparam, ctypes.POINTER(MSLLHOOKSTRUCT)).contents injected = bool(info.flags & (LLMHF_INJECTED | LLMHF_LOWER_IL_INJECTED)) agent_injected = ( injected and self._input_tag is not None and int(info.dwExtraInfo) & 0xFFFFFFFF == self._input_tag ) event = int(wparam) with self._lock: if agent_injected: self._agent_position = (int(info.pt.x), int(info.pt.y)) if self._target_pid is None: self._target_pid = self._pid_at_point(self._agent_position) self._requested_visible = self._target_pid is not None self._hidden_for_user = False if event in {WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN}: self._click = (time.monotonic(), event) elif event in { WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEWHEEL, WM_MOUSEHWHEEL, }: # Physical input means the user has taken the shared Windows # pointer. Keep our logical position but hide until the next # injected event, so the overlay never follows their hand. self._hidden_for_user = True return user32.CallNextHookEx(self._mouse_hook, code, wparam, lparam) def _pid_at_point(self, point: tuple[int, int]) -> int | None: # This is called before the first reveal for each destination, so the # direct API resolves the controlled window rather than this overlay. hwnd = user32.WindowFromPoint(POINT(*point)) if hwnd and int(hwnd) != int(self.hwnd or 0): return _pid_for_window(hwnd) return self._top_window_pid_at(point) def _top_window_pid_at(self, point: tuple[int, int]) -> int | None: hwnd = user32.GetTopWindow(None) while hwnd: if int(hwnd) != int(self.hwnd or 0) and user32.IsWindowVisible(hwnd) and not user32.IsIconic(hwnd): style = int(user32.GetWindowLongW(hwnd, GWL_EXSTYLE)) rect = RECT() if not (style & WS_EX_TRANSPARENT) and user32.GetWindowRect(hwnd, ctypes.byref(rect)): if rect.left <= point[0] < rect.right and rect.top <= point[1] < rect.bottom: pid = _pid_for_window(hwnd) if pid and pid != os.getpid(): return pid hwnd = user32.GetWindow(hwnd, GW_HWNDNEXT) return None def _target_is_visible(self, target_pid: int, destination: tuple[int, int]) -> bool: foreground_pid = _pid_for_window(user32.GetForegroundWindow()) return foreground_pid == target_pid or self._top_window_pid_at(destination) == target_pid def _on_activity(self, message: dict) -> None: command = str(message.get("command") or "") payload = message.get("payload") if not isinstance(payload, dict): payload = {} point = _point_from_activity(command, payload) raw_target_pid = message.get("targetPid") target_pid = int(raw_target_pid) if isinstance(raw_target_pid, int) and raw_target_pid > 0 else None with self._lock: if point is not None: # Keep the cursor visible between related actions. Hiding here # made every movement reappear only after the first injected # frame, which looked like a jump into the middle of the path. # `_pid_at_point` already skips this transparent overlay. self._destination = point self._target_pid = target_pid or self._pid_at_point(point) if self._agent_position is None: current = POINT() if user32.GetCursorPos(ctypes.byref(current)): self._agent_position = (int(current.x), int(current.y)) self._requested_visible = self._target_pid is not None self._hidden_for_user = False elif target_pid is not None: self._target_pid = target_pid def _read_parent(self) -> None: try: for line in sys.stdin: try: message = json.loads(line) if isinstance(message, dict): self._on_activity(message) except (TypeError, ValueError): continue except Exception: pass self.stop() def create(self) -> None: hinst = kernel32.GetModuleHandleW(None) class_name = "CcHahaVirtualCursorOverlay" wc = WNDCLASS() wc.lpfnWndProc = self._wndproc wc.hInstance = hinst wc.lpszClassName = class_name wc.hbrBackground = 0 wc.hCursor = 0 user32.RegisterClassW(ctypes.byref(wc)) self.hwnd = user32.CreateWindowExW( WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE, class_name, None, WS_POPUP, 0, 0, CANVAS_SIZE, CANVAS_SIZE, None, None, hinst, None, ) if not self.hwnd: raise OSError("CreateWindowExW failed for the virtual cursor") self._mouse_hook = user32.SetWindowsHookExW(WH_MOUSE_LL, self._hookproc, None, 0) if not self._mouse_hook: raise OSError("SetWindowsHookExW failed for the virtual cursor") if not user32.SetTimer(self.hwnd, TIMER_ID, TIMER_INTERVAL_MS, None): raise OSError("SetTimer failed for the virtual cursor") def _tick(self) -> None: if not self.hwnd: return with self._lock: position = self._agent_position destination = self._destination target_pid = self._target_pid visible = self._requested_visible and not self._hidden_for_user click = self._click if visible and position and destination and target_pid: visible = self._target_is_visible(target_pid, destination) else: visible = False if not visible: if self._shown: user32.ShowWindow(self.hwnd, SW_HIDE) self._shown = False return assert position is not None dpi = _dpi_at_point(position, self.hwnd) scale = max(1.0, dpi / 96.0) image = _render_cursor(scale, time.monotonic(), click) left = round(position[0] - HOTSPOT[0] * scale) top = round(position[1] - HOTSPOT[1] * scale) self._update_layered_image(image, left, top) if not self._shown: user32.ShowWindow(self.hwnd, SW_SHOWNOACTIVATE) self._shown = True def _update_layered_image(self, image: Image.Image, left: int, top: int) -> None: assert self.hwnd is not None width, height = image.size bmi = BITMAPINFO() bmi.bmiHeader.biSize = ctypes.sizeof(BITMAPINFOHEADER) bmi.bmiHeader.biWidth = width bmi.bmiHeader.biHeight = -height # top-down DIB, same orientation as Pillow bmi.bmiHeader.biPlanes = 1 bmi.bmiHeader.biBitCount = 32 bmi.bmiHeader.biCompression = BI_RGB bits = ctypes.c_void_p() memory_dc = gdi32.CreateCompatibleDC(None) bitmap = gdi32.CreateDIBSection( memory_dc, ctypes.byref(bmi), DIB_RGB_COLORS, ctypes.byref(bits), None, 0, ) if not memory_dc or not bitmap or not bits.value: if bitmap: gdi32.DeleteObject(bitmap) if memory_dc: gdi32.DeleteDC(memory_dc) return previous = gdi32.SelectObject(memory_dc, bitmap) try: pixels = _premultiplied_bgra(image) ctypes.memmove(bits, pixels, len(pixels)) destination = POINT(left, top) size = SIZE(width, height) source = POINT(0, 0) blend = BLENDFUNCTION(AC_SRC_OVER, 0, 255, AC_SRC_ALPHA) user32.UpdateLayeredWindow( self.hwnd, None, ctypes.byref(destination), ctypes.byref(size), memory_dc, ctypes.byref(source), 0, ctypes.byref(blend), ULW_ALPHA, ) user32.SetWindowPos( self.hwnd, HWND_TOPMOST, left, top, width, height, SWP_NOACTIVATE, ) finally: if previous: gdi32.SelectObject(memory_dc, previous) gdi32.DeleteObject(bitmap) gdi32.DeleteDC(memory_dc) def stop(self) -> None: self._stop.set() if self.hwnd: user32.PostMessageW(self.hwnd, WM_CLOSE, 0, 0) def run(self) -> int: self.create() threading.Thread(target=self._read_parent, daemon=True).start() # The TypeScript bridge waits for this handshake before dispatching the # first SendInput action, so the low-level hook cannot miss its movement. print("READY", flush=True) msg = wintypes.MSG() while not self._stop.is_set() and user32.GetMessageW(ctypes.byref(msg), None, 0, 0) > 0: user32.TranslateMessage(ctypes.byref(msg)) user32.DispatchMessageW(ctypes.byref(msg)) if self.hwnd: user32.KillTimer(self.hwnd, TIMER_ID) if self._mouse_hook: user32.UnhookWindowsHookEx(self._mouse_hook) self._mouse_hook = None return 0 def main() -> int: parser = argparse.ArgumentParser() # Kept for compatibility with already-running parents from the previous # runtime; labels are intentionally no longer rendered. parser.add_argument("--label", default=None, help=argparse.SUPPRESS) parser.parse_args() if sys.platform != "win32": print("win_cursor_badge.py is Windows-only", file=sys.stderr) return 1 return VirtualCursorOverlay().run() if __name__ == "__main__": raise SystemExit(main())