diff -Nru mate-dock-applet-0.78/ChangeLog mate-dock-applet-0.79/ChangeLog --- mate-dock-applet-0.78/ChangeLog 2017-06-04 07:26:07.000000000 +0000 +++ mate-dock-applet-0.79/ChangeLog 2017-06-21 08:26:12.000000000 +0000 @@ -1,3 +1,18 @@ +V0.79 The applet no longer swallows key presses. This means it now works happily + alongside other apps that also use the key, e.g. the Brisk menu, the Advanced + Mate Menu or Albert. + + Fixed crashes relating to Pango when window list and action_list contents needed + to be ellipsized. + +V0.78 Added five new types of indicators + + Added a new option to specify the amount of space between icons in the dock + + Added a new option to specify how a dock icon reacts when an app requires + attention. The icon can now either flash (the default) or display an + exclamation mark over the icon. + V0.77 Extended drag and support in Gtk3 version of the applet: Apps can be added to the dock by dragging them off menu applets (Main Menu, Menu Bar, Advanced Menu, Brisk Menu) and onto the diff -Nru mate-dock-applet-0.78/configure.ac mate-dock-applet-0.79/configure.ac --- mate-dock-applet-0.78/configure.ac 2017-06-04 07:26:07.000000000 +0000 +++ mate-dock-applet-0.79/configure.ac 2017-06-21 08:26:12.000000000 +0000 @@ -1,4 +1,4 @@ -AC_INIT([Dock Applet], [0.78]) +AC_INIT([Dock Applet], [0.79]) AM_INIT_AUTOMAKE AM_PATH_PYTHON([3.0]) diff -Nru mate-dock-applet-0.78/debian/changelog mate-dock-applet-0.79/debian/changelog --- mate-dock-applet-0.78/debian/changelog 2017-06-05 08:29:13.000000000 +0000 +++ mate-dock-applet-0.79/debian/changelog 2017-06-22 10:53:44.000000000 +0000 @@ -1,4 +1,11 @@ -mate-dock-applet (0.78-1~webupd8~trusty) trusty; urgency=medium +mate-dock-applet (0.79-1~webupd8~trusty1) trusty; urgency=medium + + * New upstream bugfix release + * New dependency: python3-xlib + + -- Alin Andrei Thu, 22 Jun 2017 12:53:44 +0200 + +mate-dock-applet (0.78-1~webupd8~xenial) xenial; urgency=medium * New upstream release diff -Nru mate-dock-applet-0.78/debian/control mate-dock-applet-0.79/debian/control --- mate-dock-applet-0.78/debian/control 2017-03-22 13:58:59.000000000 +0000 +++ mate-dock-applet-0.79/debian/control 2017-06-22 10:53:44.000000000 +0000 @@ -14,7 +14,7 @@ Homepage: https://github.com/robint99/dock-applet Vcs-Browser: https://anonscm.debian.org/git/pkg-mate/mate-dock-applet.git Vcs-Git: https://anonscm.debian.org/git/pkg-mate/mate-dock-applet.git -Standards-Version: 3.9.7 +Standards-Version: 3.9.8 X-Python3-Version: >= 3.2 Package: mate-dock-applet @@ -31,6 +31,8 @@ python-wnck, python3, python3-gi-cairo, + python3-cairo, + python3-xlib, python3-pil, python3-scipy, python3-xdg, diff -Nru mate-dock-applet-0.78/README.md mate-dock-applet-0.79/README.md --- mate-dock-applet-0.78/README.md 2017-06-04 07:26:07.000000000 +0000 +++ mate-dock-applet-0.79/README.md 2017-06-21 08:26:12.000000000 +0000 @@ -47,7 +47,7 @@ * Python3 * Python wnck bindings (gir1.2-wnck-1.0 for Gtk2 versions of the applet, gir1.2-wnck-3.0 for Gtk3) -* Python bindings to the keybinder library (gir1.2-keybinder-0.0 for Gtk2, gir1.2-keybinder-3.0 for Gtk3) +* Python implementation of Xlib (python-xlib) * GLib development files (libglib2.0-dev) * Python Imaging Library (python3-pil) * Python 3 Cairo bindings (python3-cairo) diff -Nru mate-dock-applet-0.78/src/dock_action_list.in mate-dock-applet-0.79/src/dock_action_list.in --- mate-dock-applet-0.78/src/dock_action_list.in 2017-06-04 07:26:07.000000000 +0000 +++ mate-dock-applet-0.79/src/dock_action_list.in 2017-06-21 08:26:12.000000000 +0000 @@ -55,6 +55,7 @@ from gi.repository import Gdk from gi.repository import GObject from gi.repository import MatePanelApplet +from gi.repository import Pango import os import cairo diff -Nru mate-dock-applet-0.78/src/dock_applet.in mate-dock-applet-0.79/src/dock_applet.in --- mate-dock-applet-0.78/src/dock_applet.in 2017-06-04 07:26:07.000000000 +0000 +++ mate-dock-applet-0.79/src/dock_applet.in 2017-06-21 08:26:12.000000000 +0000 @@ -40,24 +40,25 @@ if build_gtk2: gi.require_version("Gtk", "2.0") gi.require_version("Wnck", "1.0") - gi.require_version("Keybinder", "0.0") else: gi.require_version("Gtk", "3.0") gi.require_version("Wnck", "3.0") - gi.require_version("Keybinder", "3.0") gi.require_version("MatePanelApplet", "4.0") import os import sys +import threading sys.path.insert(1, '@pythondir@') +from Xlib.display import Display +from Xlib import X, error from gi.repository import Gtk from gi.repository import MatePanelApplet from gi.repository import Gdk -from gi.repository import Keybinder from gi.repository import Gio from gi.repository import GObject +from gi.repository import GLib from gi.repository import Wnck import xdg.DesktopEntry as DesktopEntry @@ -79,13 +80,6 @@ "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"] -# additional shortcuts for the number pad - definitely don't work on my UK keyboards but included -# anyway in case they work for other layouts -keyb_shortcuts1 = ["KP_1", "KP_2", "KP_3", "KP_4", "KP_5", - "KP_6", "KP_7", "KP_8", "KP_9", "KP_0", - "KP_1", "KP_2", "KP_3", "KP_4", "KP_5", - "KP_6", "KP_7", "KP_8", "KP_9", "KP_0"] - def applet_button_press(widget, event, the_dock): """Button press event for the applet @@ -500,23 +494,19 @@ return True -def applet_shortcut_handler(keystring, the_dock): +def applet_shortcut_handler(keybinder, the_dock): """ Handler for global keyboard shortcut presses Start the app if it isn't already running If it is already runnning cycle through its windows ... - :param keystring: the keystring which was pressed e.g. "4" + :param keybinder: the keybinder object with the keystring which was pressed e.g. "4" :param the_dock: the dock... """ # get the position in the dock of the app we need to activate - if keystring in keyb_shortcuts: - app_no = keyb_shortcuts.index(keystring) - else: - # now look in the number pad shortcurts - print("looking in number pad shortcuts") - app_no = keyb_shortcuts1.index(keystring) + if keybinder.current_shortcut in keybinder.shortcuts: + app_no = keybinder.shortcuts.index(keybinder.current_shortcut) app = the_dock.get_app_by_pos(app_no) if app is not None: @@ -549,9 +539,6 @@ os.chdir(os.path.expanduser("~")) - # allow us to set our keyboard shortcuts... - Keybinder.init() - applet.set_events(applet.get_events() | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK @@ -603,16 +590,14 @@ applet.connect("drag-data-received", applet_drag_data_received, the_dock) # set up keyboard shortcuts used to activate apps in the dock + keybinder = GlobalKeyBinding() for shortcut in keyb_shortcuts: - if not Keybinder.bind(shortcut, applet_shortcut_handler, the_dock): - log_it("could not bind shortcut %s" % shortcut) - for shortcut in keyb_shortcuts1: - if not Keybinder.bind(shortcut, applet_shortcut_handler, the_dock): - log_it("could not bind shortcut %s" % shortcut) + keybinder.grab(shortcut) + keybinder.connect("activate", applet_shortcut_handler, the_dock) + keybinder.start() applet.set_background_widget(applet) # hack for panel transparency - def applet_factory(applet, iid, data): """Factory routine called when an applet needs to be created @@ -634,6 +619,95 @@ return True +class GlobalKeyBinding(GObject.GObject, threading.Thread): + __gsignals__ = { + 'activate': (GObject.SignalFlags.RUN_LAST, None, ()), + } + + def __init__(self): + GObject.GObject.__init__(self) + threading.Thread.__init__(self) + self.setDaemon(True) + + self.display = Display() + self.screen = self.display.screen() + self.window = self.screen.root + self.keymap = Gdk.Keymap().get_default() + self.ignored_masks = self.get_mask_combinations(X.LockMask | X.Mod2Mask | X.Mod5Mask) + self.map_modifiers() + self.shortcuts = [] + + def get_mask_combinations(self, mask): + return [x for x in range(mask+1) if not (x & ~mask)] + + def map_modifiers(self): + gdk_modifiers = (Gdk.ModifierType.CONTROL_MASK, Gdk.ModifierType.SHIFT_MASK, Gdk.ModifierType.MOD1_MASK, + Gdk.ModifierType.MOD2_MASK, Gdk.ModifierType.MOD3_MASK, Gdk.ModifierType.MOD4_MASK, Gdk.ModifierType.MOD5_MASK, + Gdk.ModifierType.SUPER_MASK, Gdk.ModifierType.HYPER_MASK) + self.known_modifiers_mask = 0 + for modifier in gdk_modifiers: + if "Mod" not in Gtk.accelerator_name(0, modifier) or "Mod4" in Gtk.accelerator_name(0, modifier): + self.known_modifiers_mask |= modifier + + def idle(self): + self.emit("activate") + return False + + def activate(self): + GLib.idle_add(self.run) + + def grab(self, shortcut): + keycode = None + accelerator = shortcut.replace("", "") + keyval, modifiers = Gtk.accelerator_parse(accelerator) + + try: + keycode = self.keymap.get_entries_for_keyval(keyval).keys[0].keycode + except AttributeError: + # 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]) + + # Request to receive key press/release reports from other windows that may not be using modifiers + catch = error.CatchError(error.BadWindow) + self.window.change_attributes(onerror=catch, event_mask = X.KeyPressMask) + if catch.get_error(): + return False + + catch = error.CatchError(error.BadAccess) + for ignored_mask in self.ignored_masks: + mod = modifiers | ignored_mask + result = self.window.grab_key(keycode, mod, True, X.GrabModeAsync, X.GrabModeAsync, onerror=catch) + self.display.flush() + if catch.get_error(): + return False + return True + + def run(self): + self.running = True + while self.running: + event = self.display.next_event() + modifiers = event.state & self.known_modifiers_mask + self.current_shortcut = None + if event.type == X.KeyPress and [event.detail, modifiers] in self.shortcuts: + # Track this shortcut to know which app to activate + self.current_shortcut = [event.detail, modifiers] + GLib.idle_add(self.idle) + self.display.allow_events(X.AsyncKeyboard, event.time) + else: + self.display.allow_events(X.ReplayKeyboard, event.time) + + def stop(self): + self.running = False + self.ungrab() + self.display.close() + + def ungrab(self): + for shortcut in self.shortcuts: + self.window.ungrab_key(shortcut[0], X.AnyModifier, self.window) + + MatePanelApplet.Applet.factory_main("DockAppletFactory", True, MatePanelApplet.Applet.__gtype__, applet_factory, None) diff -Nru mate-dock-applet-0.78/src/dock_win_list.in mate-dock-applet-0.79/src/dock_win_list.in --- mate-dock-applet-0.78/src/dock_win_list.in 2017-06-04 07:26:07.000000000 +0000 +++ mate-dock-applet-0.79/src/dock_win_list.in 2017-06-21 08:26:12.000000000 +0000 @@ -55,6 +55,7 @@ from gi.repository import GdkPixbuf from gi.repository import Gio from gi.repository import Gdk +from gi.repository import Pango import os import cairo