mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Merge pull request #36 from yusufipk/generic-desktop-shortcuts
Stop telling every desktop that it is KDE
This commit is contained in:
+73
-11
@@ -174,38 +174,69 @@ class Bindings(DikteTest):
|
||||
|
||||
|
||||
class Chooser(DikteTest):
|
||||
"""Which desktop is asked to register the shortcut."""
|
||||
"""Which mechanism the session gets, and everything keyed off that."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.patch_attr(hotkey.sys, "platform", "linux")
|
||||
self.addCleanup(hotkey._REGISTERED.clear)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def under(self, desktop, has_gsettings=True):
|
||||
"""A session that says it is this desktop, with or without gsettings."""
|
||||
def under(self, desktop, tools=True):
|
||||
"""A session that says it is this desktop, with or without its tools."""
|
||||
with mock.patch.dict(os.environ, {"XDG_CURRENT_DESKTOP": desktop}), \
|
||||
mock.patch.object(hotkey.shutil, "which",
|
||||
return_value="/usr/bin/gsettings"
|
||||
if has_gsettings else None):
|
||||
return_value="/usr/bin/tool" if tools else None):
|
||||
yield
|
||||
|
||||
def test_gnome_when_the_session_says_so_and_gsettings_is_there(self):
|
||||
with self.under("GNOME"):
|
||||
self.assertEqual(hotkey.backend(), hotkey.GNOME)
|
||||
self.assertEqual(hotkey.desktop_name(), "GNOME")
|
||||
|
||||
def test_kde_otherwise(self):
|
||||
def test_kde_when_the_session_says_so_and_kwriteconfig_is_there(self):
|
||||
with self.under("KDE"):
|
||||
self.assertEqual(hotkey.backend(), hotkey.KDE)
|
||||
self.assertEqual(hotkey.desktop_name(), "KDE")
|
||||
|
||||
def test_a_gnome_session_with_no_gsettings_falls_back(self):
|
||||
"""Nothing to write the binding with, so KDE's file is the only try."""
|
||||
with self.under("GNOME", has_gsettings=False):
|
||||
self.assertEqual(hotkey.desktop_name(), "KDE")
|
||||
def test_a_desktop_with_no_registry_is_the_listeners(self):
|
||||
"""The bug this replaced: i3 was told KDE, and KWin was not running."""
|
||||
for desktop in ("i3", "XFCE", "X-Cinnamon", "sway", "MATE", ""):
|
||||
with self.subTest(desktop=desktop), self.under(desktop):
|
||||
self.assertEqual(hotkey.backend(), hotkey.LISTENER)
|
||||
|
||||
def test_the_desktop_that_has_no_registry_is_called_by_its_own_name(self):
|
||||
with self.under("i3"):
|
||||
self.assertEqual(hotkey.desktop_name(), "i3")
|
||||
with self.under("XFCE:GNOME-Flashback", tools=False):
|
||||
self.assertEqual(hotkey.desktop_name(), "XFCE")
|
||||
with self.under(""):
|
||||
self.assertEqual(hotkey.desktop_name(), "This desktop")
|
||||
|
||||
def test_a_gnome_session_with_no_gsettings_falls_back_to_the_listener(self):
|
||||
"""Nothing to write the binding with, and KDE's file is not an answer:
|
||||
KWin is no more running here than it is on i3."""
|
||||
with self.under("GNOME", tools=False):
|
||||
self.assertEqual(hotkey.backend(), hotkey.LISTENER)
|
||||
|
||||
def test_the_desktop_is_matched_loosely(self):
|
||||
for desktop in ("GNOME", "ubuntu:GNOME", "gnome"):
|
||||
with self.subTest(desktop=desktop), self.under(desktop):
|
||||
self.assertEqual(hotkey.desktop_name(), "GNOME")
|
||||
self.assertEqual(hotkey.backend(), hotkey.GNOME)
|
||||
for desktop in ("KDE", "KDE:plasma", "plasma"):
|
||||
with self.subTest(desktop=desktop), self.under(desktop):
|
||||
self.assertEqual(hotkey.backend(), hotkey.KDE)
|
||||
|
||||
def test_only_a_registry_is_installed_into_and_only_kwin_waits(self):
|
||||
with self.under("KDE"):
|
||||
self.assertTrue(hotkey.installs_shortcuts())
|
||||
self.assertTrue(hotkey.shortcut_needs_restart())
|
||||
with self.under("GNOME"):
|
||||
self.assertTrue(hotkey.installs_shortcuts())
|
||||
self.assertFalse(hotkey.shortcut_needs_restart())
|
||||
with self.under("i3"):
|
||||
self.assertFalse(hotkey.installs_shortcuts())
|
||||
self.assertFalse(hotkey.shortcut_needs_restart())
|
||||
|
||||
def test_installing_goes_to_whichever_it_is(self):
|
||||
with self.under("GNOME"), \
|
||||
@@ -220,6 +251,20 @@ class Chooser(DikteTest):
|
||||
hotkey.install_shortcut("Ctrl+Space", "dikte toggle")
|
||||
kde.assert_called_once()
|
||||
|
||||
def test_a_desktop_with_no_registry_installs_nothing_anywhere(self):
|
||||
with self.under("i3"), \
|
||||
mock.patch.object(hotkey, "install_kde_shortcut") as kde, \
|
||||
mock.patch.object(hotkey, "install_gnome_shortcut") as gnome:
|
||||
ok, message = hotkey.install_shortcut("Ctrl+Space", "dikte toggle")
|
||||
self.assertEqual(hotkey.shortcut_status(), "Ctrl+Space")
|
||||
hotkey.remove_shortcut()
|
||||
self.assertIsNone(hotkey.shortcut_status())
|
||||
kde.assert_not_called()
|
||||
gnome.assert_not_called()
|
||||
self.assertTrue(ok)
|
||||
self.assertIn("i3", message)
|
||||
self.assertNotIn("log out", message)
|
||||
|
||||
def test_removing_and_reading_back_go_to_the_same_one(self):
|
||||
with self.under("GNOME"), \
|
||||
mock.patch.object(hotkey, "remove_gnome_shortcut") as remove, \
|
||||
@@ -230,6 +275,17 @@ class Chooser(DikteTest):
|
||||
remove.assert_called_once()
|
||||
status.assert_called_once()
|
||||
|
||||
def test_only_kde_has_a_list_of_conflicts_to_read(self):
|
||||
"""A leftover kglobalshortcutsrc from a Plasma the user has since left
|
||||
would otherwise refuse combinations nothing is holding."""
|
||||
rc = self.path("kglobalshortcutsrc")
|
||||
rc.write_text(SHORTCUTS_RC, encoding="utf-8")
|
||||
self.patch_attr(hotkey, "SHORTCUTS_FILE", rc)
|
||||
with self.under("KDE"):
|
||||
self.assertTrue(hotkey.conflicting_shortcuts("Meta+W"))
|
||||
with self.under("i3"):
|
||||
self.assertEqual(hotkey.conflicting_shortcuts("Meta+W"), [])
|
||||
|
||||
|
||||
@linux_only
|
||||
class GnomeAccelerator(DikteTest):
|
||||
@@ -372,6 +428,12 @@ class KdeShortcut(DikteTest):
|
||||
self.rc = self.path("kglobalshortcutsrc")
|
||||
self.patch_attr(hotkey, "APPLICATIONS_DIR", self.apps)
|
||||
self.patch_attr(hotkey, "SHORTCUTS_FILE", self.rc)
|
||||
# A Plasma session with kwriteconfig6 on it, whatever the machine
|
||||
# running the suite happens to be logged into.
|
||||
session = mock.patch.dict(os.environ, {"XDG_CURRENT_DESKTOP": "KDE"})
|
||||
session.start()
|
||||
self.addCleanup(session.stop)
|
||||
self.patch_attr(hotkey.shutil, "which", lambda _name: "/usr/bin/tool")
|
||||
|
||||
def test_installing_writes_a_desktop_file_kwin_will_launch(self):
|
||||
with mock.patch.object(subprocess, "run", return_value=FakeCompleted()):
|
||||
|
||||
+66
-2
@@ -6,6 +6,7 @@ save, so a setting added to one half and not the other is silently reset the
|
||||
next time anybody presses Save. That is the failure this catches.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from typing import ClassVar
|
||||
@@ -107,13 +108,21 @@ class Settings(DikteTest):
|
||||
# one. Everything else about the window is the same on both.
|
||||
changed = CHANGED
|
||||
platform = "linux"
|
||||
# A session with no shortcut registry, which is what most Linux desktops
|
||||
# are. The subclasses below stand on the other two. Pinned rather than
|
||||
# inherited from whatever the machine running the suite is logged into,
|
||||
# since half the shortcut tab is built from the answer.
|
||||
desktop = "i3"
|
||||
tools: ClassVar[tuple] = ()
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
# No pactl, no model lists over the network, and no modal dialogue
|
||||
# waiting for somebody to press OK.
|
||||
self.enterContext(mock.patch.object(sys, "platform", self.platform))
|
||||
self.enterContext(only_these_tools())
|
||||
self.enterContext(only_these_tools(*self.tools))
|
||||
self.enterContext(mock.patch.dict(
|
||||
os.environ, {"XDG_CURRENT_DESKTOP": self.desktop}))
|
||||
self.enterContext(mock.patch.object(QMessageBox, "information"))
|
||||
self.enterContext(mock.patch.object(settings_ui.SettingsWindow,
|
||||
"_load_models"))
|
||||
@@ -254,6 +263,31 @@ class Settings(DikteTest):
|
||||
window = self.window(cfg.Config())
|
||||
self.assertEqual(set(window._shortcut_rows), set(hotkey.SHORTCUTS))
|
||||
|
||||
def shortcut_tab_text(self, window):
|
||||
"""Everything the shortcut tab says, as one string."""
|
||||
return "\n".join(
|
||||
widget.text() for widget in
|
||||
window.findChildren(settings_ui.QLabel)
|
||||
+ window.findChildren(settings_ui.QLineEdit)
|
||||
+ window.findChildren(settings_ui.QPushButton)
|
||||
)
|
||||
|
||||
def test_the_shortcut_tab_talks_about_this_session_and_no_other(self):
|
||||
"""A desktop with no registry is told the truth: nothing is installed
|
||||
anywhere, Dikte is listening, and here is the command to bind if the
|
||||
desktop should own the keys instead. It used to be promised a KWin that
|
||||
was not running."""
|
||||
window = self.window(cfg.Config())
|
||||
text = self.shortcut_tab_text(window)
|
||||
self.assertIn("i3 keeps no shortcut registry", text)
|
||||
self.assertNotIn("KWin", text)
|
||||
self.assertIn("dikte.py toggle", text)
|
||||
# Not a choice to offer where it is the only mechanism there is.
|
||||
self.assertTrue(window.evdev_enabled.isHidden())
|
||||
self.assertFalse([button for button in
|
||||
window.findChildren(settings_ui.QPushButton)
|
||||
if "install" in button.text().lower()])
|
||||
|
||||
def test_emptying_a_shortcut_turns_it_off_but_not_the_toggle(self):
|
||||
"""The application is unusable without the toggle, so that one box
|
||||
falls back. The rest stay empty, which is how they are switched off.
|
||||
@@ -415,7 +449,16 @@ class MacSettings(Settings):
|
||||
def test_the_listener_is_not_offered_as_a_choice(self):
|
||||
"""It is the whole mechanism there; turning it off would leave nothing."""
|
||||
window = self.window(cfg.Config())
|
||||
self.assertFalse(window.evdev_enabled.isVisible())
|
||||
self.assertTrue(window.evdev_enabled.isHidden())
|
||||
|
||||
def test_the_shortcut_tab_talks_about_this_session_and_no_other(self):
|
||||
"""Carbon holds the keys here, so there is no command to bind and no
|
||||
/dev/input to be let into."""
|
||||
window = self.window(cfg.Config())
|
||||
text = self.shortcut_tab_text(window)
|
||||
self.assertIn("Dikte asks macOS for these combinations", text)
|
||||
self.assertNotIn("KWin", text)
|
||||
self.assertNotIn("dikte.py toggle", text)
|
||||
|
||||
def test_the_paste_keys_on_offer_are_the_ones_a_mac_uses(self):
|
||||
window = self.window(cfg.Config())
|
||||
@@ -424,6 +467,27 @@ class MacSettings(Settings):
|
||||
self.assertEqual(offered, paste.MACOS.shortcuts)
|
||||
|
||||
|
||||
class KdeSettings(Settings):
|
||||
"""The same window on the one desktop that keeps a registry and makes you
|
||||
wait for it. Nothing here is about KDE: it is the rest of the window,
|
||||
checked on the platform where Install, Remove and the listener's own
|
||||
checkbox are all on screen."""
|
||||
|
||||
desktop = "KDE"
|
||||
tools: ClassVar[tuple] = ("kwriteconfig6",)
|
||||
|
||||
def test_the_shortcut_tab_talks_about_this_session_and_no_other(self):
|
||||
window = self.window(cfg.Config())
|
||||
text = self.shortcut_tab_text(window)
|
||||
self.assertIn("KWin only reads shortcut settings at startup", text)
|
||||
self.assertIn("Install as a KDE shortcut", text)
|
||||
self.assertNotIn("keeps no shortcut registry", text)
|
||||
self.assertNotIn("dikte.py toggle", text)
|
||||
# Here it is a choice: the wait for the next login, or the key press
|
||||
# reaching the focused application as well.
|
||||
self.assertFalse(window.evdev_enabled.isHidden())
|
||||
|
||||
|
||||
class Overlay(DikteTest):
|
||||
def overlay(self, **kwargs):
|
||||
widget = overlay_module.Overlay(**kwargs)
|
||||
|
||||
Reference in New Issue
Block a user