Scope Esc cancel listener to active recording
This commit is contained in:
parent
e5d709a393
commit
64c8c26bce
6 changed files with 105 additions and 7 deletions
|
|
@ -42,6 +42,9 @@ class X11Adapter:
|
|||
self.indicator = None
|
||||
self.status_icon = None
|
||||
self.menu = None
|
||||
self._cancel_listener_lock = threading.Lock()
|
||||
self._cancel_listener_stop_event: threading.Event | None = None
|
||||
self._cancel_listener_callback: Callable[[], None] | None = None
|
||||
if AppIndicator3 is not None:
|
||||
self.indicator = AppIndicator3.Indicator.new(
|
||||
"aman",
|
||||
|
|
@ -72,9 +75,35 @@ class X11Adapter:
|
|||
|
||||
def start_cancel_listener(self, callback: Callable[[], None]) -> None:
|
||||
mods, keysym = self._parse_hotkey("Escape")
|
||||
thread = threading.Thread(target=self._listen, args=(mods, keysym, callback), daemon=True)
|
||||
with self._cancel_listener_lock:
|
||||
if self._cancel_listener_stop_event is not None:
|
||||
self._cancel_listener_callback = callback
|
||||
return
|
||||
stop_event = threading.Event()
|
||||
self._cancel_listener_stop_event = stop_event
|
||||
self._cancel_listener_callback = callback
|
||||
|
||||
thread = threading.Thread(
|
||||
target=self._listen,
|
||||
args=(mods, keysym, self._dispatch_cancel_listener, stop_event),
|
||||
daemon=True,
|
||||
)
|
||||
thread.start()
|
||||
|
||||
def stop_cancel_listener(self) -> None:
|
||||
with self._cancel_listener_lock:
|
||||
stop_event = self._cancel_listener_stop_event
|
||||
self._cancel_listener_stop_event = None
|
||||
self._cancel_listener_callback = None
|
||||
if stop_event is not None:
|
||||
stop_event.set()
|
||||
|
||||
def _dispatch_cancel_listener(self) -> None:
|
||||
with self._cancel_listener_lock:
|
||||
callback = self._cancel_listener_callback
|
||||
if callback is not None:
|
||||
callback()
|
||||
|
||||
def inject_text(
|
||||
self,
|
||||
text: str,
|
||||
|
|
@ -126,7 +155,14 @@ class X11Adapter:
|
|||
finally:
|
||||
self.request_quit()
|
||||
|
||||
def _listen(self, mods: int, keysym: int, callback: Callable[[], None]) -> None:
|
||||
def _listen(
|
||||
self,
|
||||
mods: int,
|
||||
keysym: int,
|
||||
callback: Callable[[], None],
|
||||
stop_event: threading.Event | None = None,
|
||||
) -> None:
|
||||
local_stop = stop_event or threading.Event()
|
||||
disp = None
|
||||
root = None
|
||||
keycode = None
|
||||
|
|
@ -134,14 +170,18 @@ class X11Adapter:
|
|||
disp = display.Display()
|
||||
root = disp.screen().root
|
||||
keycode = self._grab_hotkey(disp, root, mods, keysym)
|
||||
while True:
|
||||
while not local_stop.is_set():
|
||||
if disp.pending_events() == 0:
|
||||
time.sleep(0.05)
|
||||
continue
|
||||
ev = disp.next_event()
|
||||
if ev.type == X.KeyPress and ev.detail == keycode:
|
||||
state = ev.state & ~(X.LockMask | X.Mod2Mask)
|
||||
if state == mods:
|
||||
callback()
|
||||
except Exception as exc:
|
||||
logging.error("hotkey listener stopped: %s", exc)
|
||||
if not local_stop.is_set():
|
||||
logging.error("hotkey listener stopped: %s", exc)
|
||||
finally:
|
||||
if root is not None and keycode is not None and disp is not None:
|
||||
try:
|
||||
|
|
@ -149,6 +189,11 @@ class X11Adapter:
|
|||
disp.sync()
|
||||
except Exception:
|
||||
pass
|
||||
if disp is not None:
|
||||
try:
|
||||
disp.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _parse_hotkey(self, hotkey: str):
|
||||
mods = 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue