# -*- coding: utf-8 -*- """ Globaler Rechtsklick-Paste: Bei Rechtsklick in externen Apps wird der Zwischenablage-Inhalt eingefügt (Strg+V). Wird von Hauptfenster, Audio-Notiz und Übersetzer genutzt. """ import os import sys import time import threading import ctypes from ctypes import wintypes _user32 = None if sys.platform == "win32": try: _user32 = ctypes.windll.user32 except Exception: pass _HAS_PYNPUT_MOUSE = False try: from pynput.mouse import Button as MouseButton, Listener as MouseListener _HAS_PYNPUT_MOUSE = True except ImportError: pass def _is_own_process_window(hwnd: int) -> bool: if _user32 is None: return False try: pid = wintypes.DWORD(0) _user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid)) return int(pid.value) == int(os.getpid()) except Exception: return False def _send_ctrl_v(): if _user32 is None: return try: VK_CONTROL = 0x11 VK_V = 0x56 _user32.keybd_event(VK_CONTROL, 0, 0, 0) time.sleep(0.02) _user32.keybd_event(VK_V, 0, 0, 0) _user32.keybd_event(VK_V, 0, 2, 0) _user32.keybd_event(VK_CONTROL, 0, 2, 0) except Exception: pass def _paste_to_hwnd(hwnd: int) -> bool: if _user32 is None or not hwnd: return False try: _user32.SetForegroundWindow(hwnd) time.sleep(0.04) VK_ESCAPE = 0x1B _user32.keybd_event(VK_ESCAPE, 0, 0, 0) _user32.keybd_event(VK_ESCAPE, 0, 2, 0) time.sleep(0.03) _send_ctrl_v() return True except Exception: return False def _run_listener(): """Startet den globalen Rechtsklick-Paste-Listener (Windows).""" if sys.platform != "win32" or _user32 is None: return def on_click(x, y, button, pressed): if pressed: return if button != MouseButton.right: return try: from aza_persistence import is_global_right_click_paste_enabled if not is_global_right_click_paste_enabled(): return hwnd = _user32.GetForegroundWindow() if _is_own_process_window(hwnd): return _paste_to_hwnd(hwnd) except Exception: pass def _polling_fallback(): VK_RBUTTON = 0x02 was_down = False while True: try: from aza_persistence import is_global_right_click_paste_enabled if not is_global_right_click_paste_enabled(): time.sleep(0.5) continue is_down = bool(_user32.GetAsyncKeyState(VK_RBUTTON) & 0x8000) if was_down and not is_down: hwnd = _user32.GetForegroundWindow() if not _is_own_process_window(hwnd): _paste_to_hwnd(hwnd) was_down = is_down except Exception: pass time.sleep(0.01) if _HAS_PYNPUT_MOUSE: try: with MouseListener(on_click=on_click) as listener: listener.join() return except Exception: pass _polling_fallback() def start_global_right_click_paste_listener(): """Startet den Listener in einem Daemon-Thread.""" t = threading.Thread(target=_run_listener, daemon=True) t.start()