Browse Source

use first key in second row as default toggle (previous default: key with grave symbol; no change for US kbd)

Fabian Peter Hammerle 4 years ago
parent
commit
2e105eb1d3
5 changed files with 64 additions and 8 deletions
  1. 6 4
      rescriptoon/__init__.py
  2. 10 4
      rescriptoon/_cli.py
  3. 19 0
      rescriptoon/_keys.py
  4. 6 0
      tests/_cli_test.py
  5. 23 0
      tests/_keys_test.py

+ 6 - 4
rescriptoon/__init__.py

@@ -57,13 +57,15 @@ def _x_wait_for_event(xdisplay, timeout_seconds):
 
 
 class Overlay:
-    def __init__(self, toggle_keysym: int):
-        self._xdisplay = Xlib.display.Display()
-        self._toggle_keycode: int = self._xdisplay.keysym_to_keycode(toggle_keysym)
+    def __init__(self, display: Xlib.display.Display, toggle_keycode: int):
+        self._xdisplay = display
+        self._toggle_keycode = toggle_keycode
         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)
+                "ignoring mapping for toggle key %d (%s)",
+                toggle_keycode,
+                self._toggle_key_label,
             )
         self._keycode_mappings[self._toggle_keycode] = ToggleOverlayAction()
         self._active_key_registry = {}

+ 10 - 4
rescriptoon/_cli.py

@@ -19,25 +19,29 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 import argparse
 import logging
 
-from Xlib import X, XK
+import Xlib.display
+from Xlib import XK, X
 
 import rescriptoon
+from rescriptoon._keys import USKeyCode, invert_string_to_keysym
 
-_DEFAULT_TOGGLE_KEYSYM_NAME = "grave"
+_DEFAULT_TOGGLE_KEYCODE: int = USKeyCode.grave.value
 
 _VERBOSITY_LEVELS = [logging.WARNING, logging.INFO, logging.DEBUG]
 
 
 def main() -> None:
+    display = Xlib.display.Display()
     argparser = argparse.ArgumentParser(
         description="Attach rescriptoon to running Toontown Rewritten engines.",
     )
+    default_toggle_keysym = display.keycode_to_keysym(_DEFAULT_TOGGLE_KEYCODE, index=0)
     argparser.add_argument(
         "--toggle",
         "-t",
         metavar="KEYSYM_NAME",
         dest="toggle_keysym_name",
-        default=_DEFAULT_TOGGLE_KEYSYM_NAME,
+        default=invert_string_to_keysym(default_toggle_keysym),
         help="key to turn extended keyboard controls on / off."
         + " any keysym name may be used"
         + " (see XStringToKeysym & X11/keysymdef.h, "
@@ -62,4 +66,6 @@ def main() -> None:
         raise ValueError(
             "controls toggle: unknown keysym name '{}'".format(args.toggle_keysym_name)
         )
-    rescriptoon.Overlay(toggle_keysym=toggle_keysym).run()
+    rescriptoon.Overlay(
+        display=display, toggle_keycode=display.keysym_to_keycode(toggle_keysym)
+    ).run()

+ 19 - 0
rescriptoon/_keys.py

@@ -58,3 +58,22 @@ _KEYSYM_LABELS = {
 
 def keysym_to_label(keysym: int) -> typing.Optional[str]:
     return _KEYSYM_LABELS.get(keysym, XK.keysym_to_string(keysym))
+
+
+def invert_string_to_keysym(keysym: int) -> typing.Optional[str]:
+    """
+    Surprisingly, XK.keysym_to_string does not invert XK.string_to_keysym:
+    >>> XK.keysym_to_string(XK.XK_grave)
+    '`'
+    >>> XK.string_to_keysym("`")
+    0
+    >>> XK.string_to_keysym("grave")
+    96
+    >>> string_to_keysym_inverted(keysym=XK.XK_grave)
+    'grave'
+    """
+    for string, ksym in vars(XK).items():
+        if keysym == ksym:
+            assert string.startswith("XK_")
+            return string[3:]
+    return None

+ 6 - 0
tests/_cli_test.py

@@ -0,0 +1,6 @@
+# pylint: disable=protected-access
+from rescriptoon._cli import _DEFAULT_TOGGLE_KEYCODE
+
+
+def test__default_toggle_keycode():
+    assert _DEFAULT_TOGGLE_KEYCODE == 49

+ 23 - 0
tests/_keys_test.py

@@ -52,3 +52,26 @@ def test_us_keycode():
 )
 def test_keysym_to_label(keysym, label):
     assert rescriptoon._keys.keysym_to_label(keysym) == label
+
+
+@pytest.mark.parametrize(
+    "keysym",
+    [
+        # pylint: disable=no-member
+        XK.XK_w,
+        XK.XK_grave,
+        XK.XK_semicolon,
+        XK.XK_plus,
+    ],
+)
+def test_invert_string_to_keysym(keysym):
+    string = rescriptoon._keys.invert_string_to_keysym(keysym)
+    assert string
+    assert XK.string_to_keysym(string) == keysym
+
+
+@pytest.mark.parametrize("string", ["w", "grave", "semicolon", "plus"])
+def test_invert_string_to_keysym_2(string):
+    keysym = XK.string_to_keysym(string)
+    assert keysym != XK.NoSymbol
+    assert rescriptoon._keys.invert_string_to_keysym(keysym) == string