|
@@ -1,5 +1,9 @@
|
|
import copy
|
|
import copy
|
|
import time
|
|
import time
|
|
|
|
+try:
|
|
|
|
+ import psutil
|
|
|
|
+except ImportError:
|
|
|
|
+ psutil = False
|
|
try:
|
|
try:
|
|
import Xlib.display
|
|
import Xlib.display
|
|
from Xlib import X, XK
|
|
from Xlib import X, XK
|
|
@@ -35,7 +39,15 @@ def x_find_window_by_pid(display, pid):
|
|
|
|
|
|
class ExtendedControls:
|
|
class ExtendedControls:
|
|
|
|
|
|
- def __init__(self, engine_process, toggle_keysym_name):
|
|
|
|
|
|
+ def __init__(self, engine_pid, toggle_keysym_name):
|
|
|
|
+ if not psutil:
|
|
|
|
+ raise Exception('\n'.join([
|
|
|
|
+ 'Extended keyboard controls require the python lib psutil to be installed.',
|
|
|
|
+ 'Depending on your system run',
|
|
|
|
+ '\t$ sudo apt-get install python3-psutil',
|
|
|
|
+ 'or',
|
|
|
|
+ '\t$ pip3 install --user psutil',
|
|
|
|
+ ]))
|
|
if not Xlib:
|
|
if not Xlib:
|
|
raise Exception('\n'.join([
|
|
raise Exception('\n'.join([
|
|
'Extended keyboard controls require xlib for python to be installed.',
|
|
'Extended keyboard controls require xlib for python to be installed.',
|
|
@@ -44,7 +56,7 @@ class ExtendedControls:
|
|
'or',
|
|
'or',
|
|
'\t$ pip3 install --user xlib',
|
|
'\t$ pip3 install --user xlib',
|
|
]))
|
|
]))
|
|
- self._engine_process = engine_process
|
|
|
|
|
|
+ self._engine_pid = engine_pid
|
|
self._xdisplay = Xlib.display.Display()
|
|
self._xdisplay = Xlib.display.Display()
|
|
self._toggle_keysym = XK.string_to_keysym(toggle_keysym_name)
|
|
self._toggle_keysym = XK.string_to_keysym(toggle_keysym_name)
|
|
if self._toggle_keysym == X.NoSymbol:
|
|
if self._toggle_keysym == X.NoSymbol:
|
|
@@ -61,12 +73,16 @@ class ExtendedControls:
|
|
self._engine_window = None
|
|
self._engine_window = None
|
|
self._enabled = False
|
|
self._enabled = False
|
|
|
|
|
|
|
|
+ @property
|
|
|
|
+ def engine_running(self):
|
|
|
|
+ return psutil.pid_exists(self._engine_pid)
|
|
|
|
+
|
|
def _wait_for_engine_window(self, timeout_seconds=20, search_interval_seconds=2):
|
|
def _wait_for_engine_window(self, timeout_seconds=20, search_interval_seconds=2):
|
|
start_epoch = time.time()
|
|
start_epoch = time.time()
|
|
- while self._engine_process.poll() is None and (time.time() - start_epoch) <= timeout_seconds:
|
|
|
|
|
|
+ while self.engine_running and (time.time() - start_epoch) <= timeout_seconds:
|
|
windows = x_find_window_by_pid(
|
|
windows = x_find_window_by_pid(
|
|
self._xdisplay,
|
|
self._xdisplay,
|
|
- self._engine_process.pid,
|
|
|
|
|
|
+ self._engine_pid,
|
|
)
|
|
)
|
|
assert len(windows) <= 1
|
|
assert len(windows) <= 1
|
|
if len(windows) == 1:
|
|
if len(windows) == 1:
|
|
@@ -85,7 +101,7 @@ class ExtendedControls:
|
|
keysym_name = XK.keysym_to_string(self._toggle_keysym)
|
|
keysym_name = XK.keysym_to_string(self._toggle_keysym)
|
|
print("INFO Extended Controls are currently disabled."
|
|
print("INFO Extended Controls are currently disabled."
|
|
+ " Press key '{}' to enable.".format(keysym_name))
|
|
+ " Press key '{}' to enable.".format(keysym_name))
|
|
- while self._engine_process.poll() is None:
|
|
|
|
|
|
+ while self.engine_running:
|
|
# TODO don't block here, engine might have already been stopped
|
|
# TODO don't block here, engine might have already been stopped
|
|
self._handle_xevent(self._xdisplay.next_event())
|
|
self._handle_xevent(self._xdisplay.next_event())
|
|
|
|
|