update
This commit is contained in:
125
AzA march 2026 - Kopie (18)/aza_global_paste.py
Normal file
125
AzA march 2026 - Kopie (18)/aza_global_paste.py
Normal file
@@ -0,0 +1,125 @@
|
||||
# -*- 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()
|
||||
Reference in New Issue
Block a user