Files
aza/AzA march 2026 - Kopie (15)/aza_global_paste.py

126 lines
3.4 KiB
Python
Raw Normal View History

2026-04-19 20:41:37 +02:00
# -*- 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()