File hotkeys.patch of Package mate-applet-dock

--- src/dock_applet.in.orig	2021-08-31 18:35:16.000000000 +0300
+++ src/dock_applet.in	2023-02-22 00:03:50.000000000 +0200
@@ -72,12 +72,8 @@ from log_it import log_it as log_it
 drag_dropped = False   # nasty global var used to keep track of whether or not a drag-drop event has occurred
 
 # define a list of keyboard shortcuts to be used to activate specific apps in the dock
-# '<Super>1' to '<Super>0' will correspond to apps 1 to 10
-# '<Super><Alt>1' to '<Super><Alt>9' will correspond to apps 11 to 20
-keyb_shortcuts = ["<Super>1", "<Super>2", "<Super>3", "<Super>4", "<Super>5",
-                  "<Super>6", "<Super>7", "<Super>8", "<Super>9", "<Super>0",
-                  "<Super><Alt>1", "<Super><Alt>2", "<Super><Alt>3", "<Super><Alt>4", "<Super><Alt>5",
-                  "<Super><Alt>6", "<Super><Alt>7", "<Super><Alt>8", "<Super><Alt>9", "<Super><Alt>0"]
+# shortcuts are loaded from applets prefs gsettings with keys run-application-1..run-application-20
+keyb_shortcuts = dict(map(lambda i: ("run-application-%s" % i, ""), range(1, 21)))
 
 
 def applet_button_press(widget, event, the_dock):
@@ -560,8 +556,13 @@ def applet_drag_motion(widget, context,
 
     return True
 
+def applet_shortcut_changed(settings, key, keybinder):
+    old_shortcut = keyb_shortcuts[key]
+    new_shortcut = settings.get_string(key)
+    keybinder.ungrab(old_shortcut)
+    keybinder.grab(new_shortcut, key)
 
-def applet_shortcut_handler(keybinder, the_dock):
+def applet_shortcut_handler(keybinder, key, the_dock):
     """ Handler for global keyboard shortcut presses
 
     Start the app if it isn't already running
@@ -569,25 +570,29 @@ def applet_shortcut_handler(keybinder, t
     If it is already runnning cycle through its windows ...
 
     :param keybinder: the keybinder object with the keystring which was pressed e.g. "<Super>4"
+    :param key shortcut gsettings key id
     :param the_dock: the dock...
     """
     # get the position in the dock of the app we need to activate
-    if keybinder.current_shortcut in keybinder.shortcuts:
-        app_no = keybinder.shortcuts.index(keybinder.current_shortcut)
+    if key not in keyb_shortcuts:
+        return
+
+    app_no = int(key.split('-')[-1]) - 1
 
     app = the_dock.get_app_by_pos(app_no)
-    if app is not None:
-        start_app = app.is_running() is False
-        if start_app:
-            app.start_app()
-        else:
+    if app is None:
+        return
 
-            # if the app only has a single window minimize or restore it
-            # otherwise scroll through all available windows
-            if app.get_num_windows() == 1:
-                the_dock.minimize_or_restore_windows(app)
-            else:
-                the_dock.do_window_scroll(Gdk.ScrollDirection.DOWN, 0, app)
+    start_app = app.is_running() is False
+    if start_app:
+        app.start_app()
+    else:
+        # if the app only has a single window minimize or restore it
+        # otherwise scroll through all available windows
+        if app.get_num_windows() == 1:
+            the_dock.minimize_or_restore_windows(app)
+        else:
+            the_dock.do_window_scroll(Gdk.ScrollDirection.DOWN, 0, app)
 
 
 def applet_fill(applet):
@@ -674,8 +679,12 @@ def applet_fill(applet):
 
     # set up keyboard shortcuts used to activate apps in the dock
     keybinder = GlobalKeyBinding()
-    for shortcut in keyb_shortcuts:
-        keybinder.grab(shortcut)
+    for key in keyb_shortcuts.keys():
+        shortcut = the_dock.settings.get_string(key)
+        keyb_shortcuts[key] = shortcut
+        keybinder.grab(shortcut, key)
+        the_dock.settings.connect("changed::" + key, applet_shortcut_changed, keybinder)
+
     keybinder.connect("activate", applet_shortcut_handler, the_dock)
     keybinder.start()
 
@@ -705,7 +714,7 @@ def applet_factory(applet, iid, data):
 
 class GlobalKeyBinding(GObject.GObject, threading.Thread):
     __gsignals__ = {
-        'activate': (GObject.SignalFlags.RUN_LAST, None, ()),
+        'activate': (GObject.SignalFlags.RUN_LAST, None, (object,)),
     }
 
     def __init__(self):
@@ -719,7 +728,7 @@ class GlobalKeyBinding(GObject.GObject,
         self.keymap = Gdk.Keymap().get_default()
         self.ignored_masks = self.get_mask_combinations(X.LockMask | X.Mod2Mask | X.Mod5Mask)
         self.map_modifiers()
-        self.shortcuts = []
+        self.shortcuts = {}
 
     def get_mask_combinations(self, mask):
         return [x for x in range(mask + 1) if not (x & ~mask)]
@@ -734,13 +743,14 @@ class GlobalKeyBinding(GObject.GObject,
                 self.known_modifiers_mask |= modifier
 
     def idle(self):
-        self.emit("activate")
+        user_data = self.shortcuts.get(self.current_shortcut)
+        self.emit("activate", user_data)
         return False
 
     def activate(self):
         GLib.idle_add(self.run)
 
-    def grab(self, shortcut):
+    def _to_internal_shortcut(self, shortcut):
         keycode = None
         accelerator = shortcut.replace("<Super>", "<Mod4>")
         keyval, modifiers = Gtk.accelerator_parse(accelerator)
@@ -751,7 +761,14 @@ class GlobalKeyBinding(GObject.GObject,
             # In older Gtk3 the get_entries_for_keyval() returns an unnamed tuple...
             keycode = self.keymap.get_entries_for_keyval(keyval)[1][0].keycode
         modifiers = int(modifiers)
-        self.shortcuts.append([keycode, modifiers])
+        return (keycode, modifiers)
+
+    def grab(self, shortcut, user_data):
+        if not shortcut:
+            return
+
+        keycode, modifiers = internal_shortcut = self._to_internal_shortcut(shortcut)
+        self.shortcuts[internal_shortcut] = user_data
 
         # Request to receive key press/release reports from other windows that may not be using modifiers
         catch = error.CatchError(error.BadWindow)
@@ -775,9 +792,10 @@ class GlobalKeyBinding(GObject.GObject,
             if (hasattr(event, 'state')):
                 modifiers = event.state & self.known_modifiers_mask
                 self.current_shortcut = None
-                if event.type == X.KeyPress and [event.detail, modifiers] in self.shortcuts:
+                shortcut = (event.detail, modifiers)
+                if event.type == X.KeyPress and shortcut in self.shortcuts:
                     # Track this shortcut to know which app to activate
-                    self.current_shortcut = [event.detail, modifiers]
+                    self.current_shortcut = shortcut
                     GLib.idle_add(self.idle)
                     self.display.allow_events(X.AsyncKeyboard, event.time)
                 else:
@@ -785,12 +803,24 @@ class GlobalKeyBinding(GObject.GObject,
 
     def stop(self):
         self.running = False
-        self.ungrab()
+        self.ungrab_all()
         self.display.close()
 
-    def ungrab(self):
-        for shortcut in self.shortcuts:
-            self.window.ungrab_key(shortcut[0], X.AnyModifier, self.window)
+    def ungrab(self, shortcut):
+        if not shortcut:
+            return
+
+        internal_shortcut = self._to_internal_shortcut(shortcut)
+
+        if internal_shortcut in self.shortcuts:
+            keycode, _ = internal_shortcut
+            self.window.ungrab_key(keycode, X.AnyModifier, self.window)
+            self.shortcuts[internal_shortcut] = None
+
+    def ungrab_all(self):
+        for shortcut in self.shortcuts.keys():
+            keycode, _ = shortcut
+            self.window.ungrab_key(keycode, X.AnyModifier, self.window)
 
 
 MatePanelApplet.Applet.factory_main("DockAppletFactory", True,
openSUSE Build Service is sponsored by