|
@@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
"""
|
|
|
|
|
|
-import copy
|
|
|
+import enum
|
|
|
import logging
|
|
|
import os
|
|
|
import select
|
|
@@ -24,8 +24,6 @@ import time
|
|
|
import typing
|
|
|
|
|
|
import Xlib.display
|
|
|
-from Xlib import XK, X, Xatom
|
|
|
-
|
|
|
from rescriptoon._actions import (
|
|
|
LowThrowAction,
|
|
|
RewriteKeyEventAction,
|
|
@@ -33,48 +31,12 @@ from rescriptoon._actions import (
|
|
|
ToggleOverlayAction,
|
|
|
)
|
|
|
from rescriptoon._keys import keysym_to_label
|
|
|
+from rescriptoon._mapping import get_keycode_action_mapping
|
|
|
from rescriptoon._ui import SystemTrayUnavailable, TrayIcon
|
|
|
+from Xlib import XK, X, Xatom
|
|
|
|
|
|
_TOONTOWN_ENGINE_WINDOW_NAME = "Toontown Rewritten"
|
|
|
|
|
|
-_KEYSYM_ACTION_MAPPINGS = {
|
|
|
-
|
|
|
- XK.XK_w: RewriteKeyEventAction(keysym=XK.XK_Up, target_engine_index=0),
|
|
|
- XK.XK_a: RewriteKeyEventAction(keysym=XK.XK_Left, target_engine_index=0),
|
|
|
- XK.XK_s: RewriteKeyEventAction(keysym=XK.XK_Down, target_engine_index=0),
|
|
|
- XK.XK_d: RewriteKeyEventAction(keysym=XK.XK_Right, target_engine_index=0),
|
|
|
- XK.XK_Control_L: RewriteKeyEventAction(
|
|
|
- keysym=XK.XK_Control_L, target_engine_index=0
|
|
|
- ),
|
|
|
- XK.XK_v: LowThrowAction(target_engine_index=0),
|
|
|
- XK.XK_o: RewriteKeyEventAction(keysym=XK.XK_Up, target_engine_index=1),
|
|
|
- XK.XK_k: RewriteKeyEventAction(keysym=XK.XK_Left, target_engine_index=1),
|
|
|
- XK.XK_l: RewriteKeyEventAction(keysym=XK.XK_Down, target_engine_index=1),
|
|
|
- XK.XK_semicolon: RewriteKeyEventAction(keysym=XK.XK_Right, target_engine_index=1),
|
|
|
- XK.XK_slash: RewriteKeyEventAction(keysym=XK.XK_Control_L, target_engine_index=1),
|
|
|
- XK.XK_n: LowThrowAction(target_engine_index=1),
|
|
|
- XK.XK_space: RewriteKeyEventAction(keysym=XK.XK_Control_L),
|
|
|
-
|
|
|
- XK.XK_e: SelectGagAction(
|
|
|
- gag_name="elephant trunk",
|
|
|
- target_engine_index=0,
|
|
|
- column_index=4,
|
|
|
- factor_y=-0.047,
|
|
|
- ),
|
|
|
- XK.XK_i: SelectGagAction(
|
|
|
- gag_name="elephant trunk",
|
|
|
- target_engine_index=1,
|
|
|
- column_index=4,
|
|
|
- factor_y=-0.047,
|
|
|
- ),
|
|
|
- XK.XK_f: SelectGagAction(
|
|
|
- gag_name="foghorn", target_engine_index=0, column_index=5, factor_y=-0.047
|
|
|
- ),
|
|
|
- XK.XK_j: SelectGagAction(
|
|
|
- gag_name="foghorn", target_engine_index=1, column_index=5, factor_y=-0.047
|
|
|
- ),
|
|
|
-}
|
|
|
-
|
|
|
|
|
|
def _x_walk_children_windows(
|
|
|
parent_window: "Xlib.display.Window",
|
|
@@ -101,13 +63,13 @@ def _x_wait_for_event(xdisplay, timeout_seconds):
|
|
|
class Overlay:
|
|
|
def __init__(self, toggle_keysym: int):
|
|
|
self._xdisplay = Xlib.display.Display()
|
|
|
- self._toggle_keysym = toggle_keysym
|
|
|
- self._keysym_mappings = copy.deepcopy(_KEYSYM_ACTION_MAPPINGS)
|
|
|
- if self._toggle_keysym in self._keysym_mappings:
|
|
|
+ self._toggle_keycode: int = self._xdisplay.keysym_to_keycode(toggle_keysym)
|
|
|
+ self._keycode_mappings = get_keycode_action_mapping()
|
|
|
+ if self._toggle_keycode in self._keycode_mappings:
|
|
|
logging.warning(
|
|
|
"ignoring mapping for toggle key %s", keysym_to_label(toggle_keysym)
|
|
|
)
|
|
|
- self._keysym_mappings[self._toggle_keysym] = ToggleOverlayAction()
|
|
|
+ self._keycode_mappings[self._toggle_keycode] = ToggleOverlayAction()
|
|
|
self._active_key_registry = {}
|
|
|
self._enabled = False
|
|
|
self._engine_windows = None
|
|
@@ -139,10 +101,11 @@ class Overlay:
|
|
|
logging.debug("engine window ids %r", [hex(w.id) for w in self._engine_windows])
|
|
|
if not self._engine_windows:
|
|
|
raise Exception("no toontown window found")
|
|
|
- self._grab_key(self.xdisplay.keysym_to_keycode(self._toggle_keysym),)
|
|
|
+ self._grab_key(self._toggle_keycode)
|
|
|
print("key bindings:")
|
|
|
- for keysym, action in self._keysym_mappings.items():
|
|
|
- print("{}: {}".format(keysym_to_label(keysym), action.description))
|
|
|
+ for keycode, action in self._keycode_mappings.items():
|
|
|
+ keysym: int = self._xdisplay.keycode_to_keysym(keycode, index=0)
|
|
|
+ print("{}: {}".format(keysym_to_label(keysym), action.description,))
|
|
|
self.enable()
|
|
|
while self._engine_windows_open:
|
|
|
while self.xdisplay.pending_events():
|
|
@@ -172,41 +135,48 @@ class Overlay:
|
|
|
],
|
|
|
) -> None:
|
|
|
self._update_active_key_registry(xkeyevent)
|
|
|
- keysym_in = self.xdisplay.keycode_to_keysym(xkeyevent.detail, index=0,)
|
|
|
+ keycode_in = xkeyevent.detail
|
|
|
try:
|
|
|
- action = self._keysym_mappings[keysym_in]
|
|
|
+ action = self._keycode_mappings[keycode_in]
|
|
|
except KeyError:
|
|
|
- logging.warning("received key event of unmapped keysym %d", keysym_in)
|
|
|
+ keysym_in = self.xdisplay.keycode_to_keysym(keycode_in, index=0,)
|
|
|
+ logging.warning(
|
|
|
+ "received key event of unmapped key %d (%s)",
|
|
|
+ keycode_in,
|
|
|
+ keysym_to_label(keysym_in),
|
|
|
+ )
|
|
|
return
|
|
|
action.execute(self, xkeyevent)
|
|
|
|
|
|
@property
|
|
|
- def _toggle_keysym_name(self) -> str:
|
|
|
- return XK.keysym_to_string(self._toggle_keysym)
|
|
|
+ def _toggle_keysym(self) -> int:
|
|
|
+ return self._xdisplay.keycode_to_keysym(self._toggle_keycode, index=0)
|
|
|
+
|
|
|
+ @property
|
|
|
+ def _toggle_key_label(self) -> str:
|
|
|
+ return keysym_to_label(self._toggle_keysym)
|
|
|
|
|
|
def enable(self) -> None:
|
|
|
- for keysym in self._keysym_mappings.keys():
|
|
|
- if keysym != self._toggle_keysym:
|
|
|
- self._grab_key(self.xdisplay.keysym_to_keycode(keysym),)
|
|
|
+ for keycode in self._keycode_mappings.keys():
|
|
|
+ if keycode != self._toggle_keycode:
|
|
|
+ self._grab_key(keycode)
|
|
|
self._enabled = True
|
|
|
self._draw_tray_icon()
|
|
|
logging.info(
|
|
|
- "rescriptoon is now enabled. press %s to disable.",
|
|
|
- self._toggle_keysym_name,
|
|
|
+ "rescriptoon is now enabled. press %s to disable.", self._toggle_key_label,
|
|
|
)
|
|
|
|
|
|
def _disable(self) -> None:
|
|
|
- for keysym in self._keysym_mappings.keys():
|
|
|
- if keysym != self._toggle_keysym:
|
|
|
- self._ungrab_key(self.xdisplay.keysym_to_keycode(keysym),)
|
|
|
+ for keycode in self._keycode_mappings.keys():
|
|
|
+ if keycode != self._toggle_keycode:
|
|
|
+ self._ungrab_key(keycode)
|
|
|
self._enabled = False
|
|
|
self._draw_tray_icon()
|
|
|
|
|
|
def disable(self) -> None:
|
|
|
self._disable()
|
|
|
logging.info(
|
|
|
- "rescriptoon is now disabled. press %s to enable.",
|
|
|
- self._toggle_keysym_name,
|
|
|
+ "rescriptoon is now disabled. press %s to enable.", self._toggle_key_label,
|
|
|
)
|
|
|
|
|
|
@property
|