Merge master: the shortcut table, local models, and a Mac still in them

Four files disagreed, and all four the same way: master had turned things the
Mac branch wrote out by hand into one list to read from.

Shortcuts are the whole of it. master gave every binding a row in
hotkey.SHORTCUTS, so the Mac's DESKTOP_IDS is gone and CarbonHotkey reads the
desktop id off that row, which also gives the new cancel key a status line on a
Mac. Settings builds its four rows through master's _shortcut_row, and that one
now asks _install_buttons for Install and Remove, so macOS gets a combination
box and nothing to press, and everywhere else the button says the desktop's own
name. dikte.py starts the listener from the same table, on macOS whatever the
setting says: there is nothing installed for it to be a fallback to.

The rest is two imports and a paste list that lives in paste.Desktop now.
This commit is contained in:
yusufipk
2026-08-02 09:36:22 +03:00
41 changed files with 4888 additions and 470 deletions
+40
View File
@@ -6,6 +6,7 @@ import subprocess
import unittest
from unittest import mock
import config as cfg
import hotkey
from tests.support import DikteTest, FakeCompleted, linux_only
@@ -56,6 +57,28 @@ class ParseShortcut(unittest.TestCase):
self.assertEqual(hotkey.parse_shortcut(None), (None, None))
class Table(unittest.TestCase):
"""The one list of global shortcuts. The command line, the settings window
and install.sh read it instead of keeping a copy each, so what it has to
hold together is checked here rather than in three places."""
def test_every_shortcut_remembers_itself_in_a_real_setting(self):
for name, spec in hotkey.SHORTCUTS.items():
with self.subTest(name=name):
self.assertIn(spec.setting, cfg.DEFAULTS)
def test_no_two_share_a_desktop_entry(self):
ids = [spec.desktop_id for spec in hotkey.SHORTCUTS.values()]
self.assertEqual(len(ids), len(set(ids)))
def test_only_the_toggle_falls_back_to_a_key_of_its_own(self):
"""The rest are off until you pick one, and emptying the box is how you
turn them off again."""
self.assertEqual(hotkey.SHORTCUTS["toggle"].fallback, "Ctrl+Space")
self.assertEqual([name for name, spec in hotkey.SHORTCUTS.items()
if spec.fallback], ["toggle"])
class ModsMatch(unittest.TestCase):
"""The combination has to be exact, or Ctrl+Space fires on Ctrl+Shift+Space."""
@@ -122,6 +145,23 @@ class Bindings(DikteTest):
thread.assert_called_once()
self.assertEqual(len(listener._bindings[57]), 2)
def test_starting_and_discarding_do_not_fire_on_each_other(self):
"""The two defaults are one modifier apart on the same key code, so the
modifier set is the only thing keeping them apart."""
listener = hotkey.EvdevHotkey()
self.addCleanup(listener.stop)
with mock.patch.object(listener, "_open_devices", return_value=[99]), \
mock.patch.object(hotkey.threading, "Thread"):
listener.start({"toggle": "Ctrl+Space", "cancel": "Ctrl+Alt+Space"})
def fired(held):
return [name for mods, name in listener._bindings[57]
if hotkey.EvdevHotkey._mods_match(held, mods)]
self.assertEqual(fired({29}), ["toggle"]) # ctrl
self.assertEqual(fired({29, 56}), ["cancel"]) # ctrl + alt
self.assertEqual(fired({29, 42}), []) # ctrl + shift
class Chooser(DikteTest):
"""Which desktop is asked to register the shortcut."""