Hello community, here is the log from the commit of package mate-applet-dock for openSUSE:Factory checked in at 2015-10-24 10:29:36 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/mate-applet-dock (Old) and /work/SRC/openSUSE:Factory/.mate-applet-dock.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "mate-applet-dock" Changes: -------- --- /work/SRC/openSUSE:Factory/mate-applet-dock/mate-applet-dock.changes 2015-08-03 17:21:50.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.mate-applet-dock.new/mate-applet-dock.changes 2015-10-24 10:30:20.000000000 +0200 @@ -1,0 +2,18 @@ +Wed Oct 21 14:05:01 UTC 2015 - [email protected] + +- Update to 0.64: + * Fix a bug that would sometimes prevent a window from being + focused when a dock icon was clicked. + * Many changes to improve detection of .desktop files from + running applications and linking to dock icons. + * Right click options (e.g. 'Open new Window' and Open new + incognito window with Chromium) are now read from .desktop + files and appear on the dock icon right click menu. + * Custom launchers now set the Type field of the .desktop files + they create to 'Application' and also set the NoDisplay field + to 'true' so that the launcher is not displayed in the MATE menu. + * Customer launchers now write .desktop files that do not contain + spaces in the filename, as per the GNOME developer docs. + * Application icons can now be sourced from ~/.local/share/icons/. + +------------------------------------------------------------------- Old: ---- dock-applet-0.63.tar.gz New: ---- dock-applet-0.64.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ mate-applet-dock.spec ++++++ --- /var/tmp/diff_new_pack.xQzHft/_old 2015-10-24 10:30:21.000000000 +0200 +++ /var/tmp/diff_new_pack.xQzHft/_new 2015-10-24 10:30:21.000000000 +0200 @@ -18,7 +18,7 @@ %define _name dock-applet Name: mate-applet-dock -Version: 0.63 +Version: 0.64 Release: 0 Summary: Dock applet for the MATE panel License: GPL-2.0+ @@ -42,7 +42,7 @@ * Pin and unpin apps to the dock. * Rearrange application icons on the dock. * Launch apps by clicking on their icons in the dock. - * Minimize/unminimize running app windows by clicking the + * Minimise/unminimise running app windows by clicking the applications dock icon. * Detect changes in the current icon theme and update the dock accordingly. ++++++ dock-applet-0.63.tar.gz -> dock-applet-0.64.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/ChangeLog new/dock-applet-0.64/ChangeLog --- old/dock-applet-0.63/ChangeLog 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/ChangeLog 2015-10-15 11:32:08.000000000 +0200 @@ -88,3 +88,19 @@ configuration. This allows e.g. an easy way to restore the applet after an accidental deletion from the panel, and also a way to move applet configurations from one computer to another. + +V0.64 Fixed bug that would sometimes prevent a window from being focused + when a dock icon was clicked + Many changes to Improve detection of .desktop files from running apps + and linking to dock icons + Right click options (e.g. 'Open new Window' and Open new incognito + window with Chrome) are now read from .desktop files and appear on + the dock icon right click menu + Custom launchers now set the Type field of the .desktop files they + create to 'Application' and also set the NoDisplay field to 'true' + so that the launcher is not displayed in the MATE menu + Customer launchers now write .desktop files that do not contain spaces + in the filename, as per the GNOME developer docs + App icons can now be sourced from ~/.local/share/icons (e.g + popcorn-time puts its icon here) + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/NEWS new/dock-applet-0.64/NEWS --- old/dock-applet-0.63/NEWS 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/NEWS 2015-10-15 11:32:08.000000000 +0200 @@ -3,3 +3,4 @@ allows custom launchers to be added to the dock, and fixes a bug when minimising and then maximising an app's windows. Full details are in the ChangeLog +15 Oct 2015 - V0.64 uploaded to github diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/README.md new/dock-applet-0.64/README.md --- old/dock-applet-0.63/README.md 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/README.md 2015-10-15 11:32:08.000000000 +0200 @@ -31,8 +31,11 @@ make sudo make install + ``` +Depending on the distro, it may be necessary to install gir1.2-wnck-1.0 and glib2 development packages first. + ### Installation on Ubuntu Mate on a Pi 2 This is a little more involved. First download gir1.2-wnck-1.0 for arm architechure from [here](http://launchpadlibrarian.net/160438738/gir1.2-wnck-1.0_2.30.7-0ubuntu4_armhf.deb) and install it with sudo dpkg -i. Then install other dependencies - sudo apt-get install git autoreconf libglib2.0-dev @@ -47,6 +50,8 @@ gir1.2-wnck-1.0 +libglib2-dev + ### Obligatory screen shots Running on Arch with a Unity style layout diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/configure.ac new/dock-applet-0.64/configure.ac --- old/dock-applet-0.63/configure.ac 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/configure.ac 2015-10-15 11:32:08.000000000 +0200 @@ -1,4 +1,4 @@ -AC_INIT([Dock Applet], [0.63]) +AC_INIT([Dock Applet], [0.64]) AM_INIT_AUTOMAKE AM_PATH_PYTHON([3.0]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/src/dock.in new/dock-applet-0.64/src/dock.in --- old/dock-applet-0.63/src/dock.in 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/src/dock.in 2015-10-15 11:32:08.000000000 +0200 @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + """Provide functionality relating to an application dock Manage a list of pinned and non-pinned dock apps. @@ -37,6 +39,7 @@ import gi gi.require_version("Gtk", "2.0") +gi.require_version("MatePanelApplet", "4.0") from gi.repository import Gtk from gi.repository import Gdk from gi.repository import MatePanelApplet @@ -50,6 +53,7 @@ from gi.repository import GLib import os import os.path +from time import sleep import docked_app import dock_prefs @@ -132,6 +136,7 @@ self.indicator = 0 self.multi_ind = False self.show_all_apps = True + self.click_restore_last_active = True self.read_settings() self.dock_action_group = None @@ -170,7 +175,7 @@ if xml_settings[0] == True: # the settings were read correctly, so set everything up - + pinned_apps = [] for pinned_app in xml_settings[1]: pinned_apps.append(pinned_app) @@ -178,22 +183,35 @@ self.indicator = xml_settings[2] self.show_all_apps = xml_settings[3] self.multi_ind = xml_settings[4] + self.click_restore_last_active = xml_settings[5] - # now, immediately write the settings to dconf so the dock can access them + # now, immediately write the settings to dconf and back to the config file + # so the dock can access them + self.settings.set_value("pinned-apps", GLib.Variant('as', pinned_apps)) self.settings.set_int("indicator-type", self.indicator) self.settings.set_boolean("multi-ind", self.multi_ind) self.settings.set_boolean("apps-from-all-workspaces", self.show_all_apps) self.settings.set_boolean("first-run", False) + self.settings.set_boolean("click-restore-last-active", self.click_restore_last_active) + dock_xml.write_xml(self.xml_conf, pinned_apps, self.indicator, \ + self.show_all_apps, self.multi_ind, self.click_restore_last_active) md.destroy() return - else: - md.destroy() + else: + + # the xml was not read + # this could be due to an error or because new versions of the applets have added + # configuration options not yet in the user's xml file. To recover, simply close + # the dialog and assume a default set of options + md.destroy() + self.indicator = self.settings.get_int("indicator-type") self.multi_ind = self.settings.get_boolean("multi-ind") self.show_all_apps = self.settings.get_boolean("apps-from-all-workspaces") + self.click_restore_last_active = self.settings.get_boolean("click-restore-last-active") def write_settings(self): """Write the current dock settings. @@ -216,10 +234,11 @@ self.settings.set_int("indicator-type", self.indicator) self.settings.set_boolean("multi-ind", self.multi_ind) self.settings.set_boolean("apps-from-all-workspaces", self.show_all_apps) + self.settings.set_boolean("click-restore-last-active", self.click_restore_last_active) self.settings.set_boolean("first-run", False) dock_xml.write_xml(self.xml_conf, pinned_apps, self.indicator, \ - self.show_all_apps, self.multi_ind) + self.show_all_apps, self.multi_ind, self.click_restore_last_active) def set_actions_for_app(self, app): """Show or hide actions in the context menu so that only relevant ones are @@ -246,10 +265,41 @@ If the app does not have a desktop file, show an option allowing a custom launcher to be created + Show any right click options specified in the app's desktop file + Args: app : The DockedApp """ + df_shortcut_1_action = self.dock_action_group.get_action("df_shortcut_1_action") + df_shortcut_2_action = self.dock_action_group.get_action("df_shortcut_2_action") + df_shortcut_3_action = self.dock_action_group.get_action("df_shortcut_3_action") + df_shortcut_4_action = self.dock_action_group.get_action("df_shortcut_4_action") + + act_exists, act_name, act_cmd_line = app.get_rc_action(1) + df_shortcut_1_action.set_visible(act_exists) + if act_exists == True: + df_shortcut_1_action.set_label(act_name) + df_shortcut_1_action.set_icon_name(app.icon_name) + + act_exists, act_name, act_cmd_line = app.get_rc_action(2) + df_shortcut_2_action.set_visible(act_exists) + if act_exists == True: + df_shortcut_2_action.set_label(act_name) + df_shortcut_2_action.set_icon_name(app.icon_name) + + act_exists, act_name, act_cmd_line = app.get_rc_action(3) + df_shortcut_3_action.set_visible(act_exists) + if act_exists == True: + df_shortcut_3_action.set_label(act_name) + df_shortcut_3_action.set_icon_name(app.icon_name) + + act_exists, act_name, act_cmd_line = app.get_rc_action(4) + df_shortcut_4_action.set_visible(act_exists) + if act_exists == True: + df_shortcut_4_action.set_label(act_name) + df_shortcut_4_action.set_icon_name(app.icon_name) + pin_action = self.dock_action_group.get_action("pin_action") unpin_action = self.dock_action_group.get_action("unpin_action") move_up_action = self.dock_action_group.get_action("move_up_action") @@ -305,8 +355,24 @@ """Set up the actions and right click menu for the applet """ + # actions named df_shortcut_<x>_action are used for implementing shortcuts/actions + # specified in an app's .desktop file + self.dock_action_group = Gtk.ActionGroup("DockActions") - self.dock_action_group.add_actions([("pin_action", Gtk.STOCK_ADD, \ + self.dock_action_group.add_actions([ + ("df_shortcut_1_action", None, + "df_shortcut_1_action", None, "df_shortcut_1_action",\ + self.df_shortcut_1), \ + ("df_shortcut_2_action", None, + "df_shortcut_2_action", None, "df_shortcut_2_action",\ + self.df_shortcut_2), \ + ("df_shortcut_3_action", None, + "df_shortcut_3_action", None, "df_shortcut_3_action",\ + self.df_shortcut_3), \ + ("df_shortcut_4_action", None, + "df_shortcut_4_action", None, "df_shortcut_4_action",\ + self.df_shortcut_4), \ + ("pin_action", Gtk.STOCK_ADD, \ "_Pin app to the dock", None, "Pin app to the dock", \ self.pin_app), \ ("unpin_action", Gtk.STOCK_REMOVE, \ @@ -336,7 +402,11 @@ "_Close", None, "Close", self.close_win) \ ]) - menu_xml = '<menuitem name="close_win" action="close_win_action"/><separator/>' + menu_xml = '<menuitem name="df_shortcut_1_action" action="df_shortcut_1_action"/><separator/>' + menu_xml += '<menuitem name="df_shortcut_2_action" action="df_shortcut_2_action"/><separator/>' + menu_xml += '<menuitem name="df_shortcut_3_action" action="df_shortcut_3_action"/><separator/>' + menu_xml += '<menuitem name="df_shortcut_4_action" action="df_shortcut_4_action"/><separator/>' + menu_xml += '<menuitem name="close_win" action="close_win_action"/><separator/>' menu_xml += '<menuitem name="move_up" action="move_up_action"/>' menu_xml += '<menuitem name="move_down" action="move_down_action"/>' menu_xml += '<menuitem name="move_left" action="move_left_action"/>' @@ -349,6 +419,34 @@ self.applet.setup_menu(menu_xml, self.dock_action_group) + def df_shortcut_1(self, data=None): + """Perform the app's 1st .desktop file specified shortcut/action + """ + + if self.right_clicked_app is not None: + self.right_clicked_app.run_rc_action(1) + + def df_shortcut_2(self, data=None): + """Perform the app's 1st .desktop file specified shortcut/action + """ + + if self.right_clicked_app is not None: + self.right_clicked_app.run_rc_action(2) + + def df_shortcut_3(self, data=None): + """Perform the app's 1st .desktop file specified shortcut/action + """ + + if self.right_clicked_app is not None: + self.right_clicked_app.run_rc_action(3) + + def df_shortcut_4(self, data=None): + """Perform the app's 1st .desktop file specified shortcut/action + """ + + if self.right_clicked_app is not None: + self.right_clicked_app.run_rc_action(4) + def unpin_app(self, data=None): """Unpin the right clicked app from the dock. @@ -457,6 +555,7 @@ self.prefs_win.set_indicator(self.indicator) self.prefs_win.set_multi_ind(self.multi_ind) self.prefs_win.set_show_unpinned_apps_on_all_ws(self.show_all_apps) + self.prefs_win.set_click_restore_last_active(self.click_restore_last_active) else: self.prefs_win.show_all() @@ -486,11 +585,13 @@ if (self.indicator != self.prefs_win.get_indicator_type()) or \ (self.multi_ind != self.prefs_win.get_multi_ind()) or \ - (self.show_all_apps != self.prefs_win.get_show_unpinned_apps_on_all_ws()): + (self.show_all_apps != self.prefs_win.get_show_unpinned_apps_on_all_ws()) or \ + (self.click_restore_last_active != self.prefs_win.get_click_restore_last_active()): self.indicator = self.prefs_win.get_indicator_type() self.multi_ind = self.prefs_win.get_multi_ind() self.show_all_apps = self.prefs_win.get_show_unpinned_apps_on_all_ws() + self.click_restore_last_active = self.prefs_win.get_click_restore_last_active() self.write_settings() # redraw everything here for app in self.app_list: @@ -561,14 +662,31 @@ else: self.ccl_win.hide() - dfname = os.path.expanduser("~/.local/share/applications/mda_%s.desktop" %self.ccl_win.name) + + # the gnome developer docs at + # https://developer.gnome.org/integration-guide/stable/desktop-files.html.en + # state that .desktop filenames should not contain spaces, so.... + dfname = self.ccl_win.name.replace(" ", "-") + + dfname = os.path.expanduser("~/.local/share/applications/mda-%s.desktop" %dfname) + dfile = open(dfname, "w") dfile.write("[Desktop Entry]\n") dfile.write("Name=%s\n" %self.ccl_win.name) + dfile.write("Type=Application\n") dfile.write("Comment=%s\n" %self.ccl_win.comment) dfile.write("Exec=%s\n" %self.ccl_win.command) dfile.write("Icon=%s\n" %self.ccl_win.icon_filename) dfile.write("StartupWMClass=%s\n" %self.ccl_win.wm_class) + + # Code below can be uncommented if adding terminal apps to the dock ever + # becomes a needed thing + #term_app = "%s" %self.ccl_win.is_terminal_app + #dfile.write("Terminal=%s\n" %term_app.lower()) + + # we don't want this launcher displayed in the MATe menu + dfile.write("NoDisplay=true\n") + dfile.close() # create a docked app from the .desktop we just created and add it to the dock @@ -758,6 +876,7 @@ if app.desktop_file == dock_app.desktop_file: # copy the running app's info to the pinned dock item self.copy_wnck_info_to_app(app, dock_app, wnck_window) + break else: # it's not a pinned app so add it to the app list @@ -811,13 +930,13 @@ new_wm_class_name = new_cg.get_res_class() new_app = new_win.get_application() for app in self.app_list: -# if app.wm_class_name == new_wm_class_name: - for aai in app.app_info: - if new_app == aai.app: - app.is_active = True - app.last_active_win = new_win - app.queue_draw() - break + if app.wm_class_name == new_wm_class_name: + for aai in app.app_info: + if new_app == aai.app: + app.is_active = True + app.last_active_win = new_win + app.queue_draw() + break def window_opened(self, wnck_screen, wnck_window): """Event handler for the window_opened event @@ -870,6 +989,11 @@ # set the minimize target for the new window app.set_icon_geometry() + + # if the mouse pointer is over the app's dock icon, regenerate the list + # of right click menu items to take acount of the new window + if app.has_mouse: + self.set_actions_for_app(app) break if in_dock == False: @@ -948,13 +1072,15 @@ else: do_redraw = True - # was the closed window was the last active window for the app ? - if app.last_active_win == wnck_window: - app.last_active_win = None + # was the closed window was the last active window for the app ? + if app.last_active_win == wnck_window: + app.last_active_win = None if do_redraw: app.queue_draw() + if app.has_mouse: + self.set_actions_for_app(app) break except ValueError: @@ -1054,6 +1180,9 @@ # or ... # look in /usr/share/pixmaps for an icon of any type with # the same name as the app + # then ... + # look in ~/.local/share/icons for an icon with the same name + # and extension as the icon # # 2 .. sloooow - iterate through each installed icon theme and try to # find the app - not implement for now @@ -1074,12 +1203,15 @@ elif os.path.isfile("/usr/share/pixmaps/%s.png" %icon_name.lower()): icon_file = icon_name.lower() + ".png" - if icon_file != "": pixbuf = GdkPixbuf.Pixbuf.new_from_file("/usr/share/pixmaps/%s"%icon_file) else: - pixbuf = self.applet.render_icon(Gtk.STOCK_EXECUTE, stock_size, None) - dock_app.icon_filename = "STOCK_EXECUTE" + icon_file = os.path.expanduser("~/.local/share/icons/%s" %dock_app.icon_name) + if os.path.isfile(icon_file): + pixbuf= GdkPixbuf.Pixbuf.new_from_file(icon_file) + else: + pixbuf = self.applet.render_icon(Gtk.STOCK_EXECUTE, stock_size, None) + dock_app.icon_filename = "STOCK_EXECUTE" # scale the icon to the size that is available # Note - we're allowing for a 3 pixel border all around the icon, hence using size-6 @@ -1378,4 +1510,107 @@ if self.app_win_list is not None: self.app_win_list.hide() + def minimize_or_restore_windows(self, app, event): + """ Minimize or restore an app's windows in response to a left click of + it's dock icon + + the action to perform (minimizing, moving workspace, activating) + is decided as follows: + if (the app's windows are all minimized) or + (the app s one or more unminimized window but is not the active app) + then + restore the app's last active window or all windows (based on the + user's settings). If the active window is on a different workspace + then activate that workspace + else: + the app is currently the active app so all of the app + windows will be minimized + but first, hide any app window list that is being shown and stop the + window list timer + + Args: + app: the docked app whose windows are to be minimized or restored + event : the mouse click event + + """ + + self.stop_win_list_timer() + self.hide_win_list() + + win_list = app.get_wnck_windows() + + restore_win = (not app.has_unminimized_windows()) or \ + (app.has_unminimized_windows() and (app.is_active==False)) + if restore_win: + last_active_win = app.last_active_win + + # the last active window may be set to None (e.g. if the app's active window has been closed + # and no other window has been made active afterwards). Therefore, if there is no active last window + # activate the app's first window + if last_active_win is None: + last_active_win = win_list[0] + + # if we're restoring all windows, do this now before we finally activate the last active window + if self.click_restore_last_active == False: + for window in win_list: + win_type = window.get_window_type() + if ((win_type == Wnck.WindowType.NORMAL) or \ + (win_type == Wnck.WindowType.DIALOG)) and \ + (not window.is_skip_tasklist()) and \ + (window != last_active_win): + window.activate(event.time) + sleep(0.01) # allow the window manager time to activate + # the window + + app.last_active_win = last_active_win + + if last_active_win is not None: + wnck_screen = last_active_win.get_screen() + wnck_aws = wnck_screen.get_active_workspace() + wnck_ws = last_active_win.get_workspace() + + if wnck_aws != wnck_ws: + wnck_ws.activate(event.time) + sleep(0.01) + + # rarely, the last active win does not end up as the active window if we + # activate here, so instead a workaround which seems to do the trick + # is use a timer as below + GObject.timeout_add(20, win_activation_timer, [last_active_win, event.time+20]) + + else: + #minimize all windows and do the last active window last of all + + last_active_win = app.last_active_win + + for window in win_list: + win_type = window.get_window_type() + if ((win_type == Wnck.WindowType.NORMAL) or \ + (win_type == Wnck.WindowType.DIALOG)) and \ + (not window.is_skip_tasklist()) and \ + (window != last_active_win): + window.minimize() + sleep(0.01) + + app.last_active_win = last_active_win + if last_active_win is not None: + last_active_win.minimize() + sleep(0.01) + +def win_activation_timer(args): + """ Timer function to be called by GObject.timeout_add and which + will activate a specified wnck window + + Args: + args - a tuple containing two items + args[0] - the wnck window to activate + args[1] - the event time we want to specfiy + + Returns: + False - to cancel the timer + """ + + args[0].activate(args[1]) + sleep(0.01) + return (False) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/src/dock_applet.in new/dock-applet-0.64/src/dock_applet.in --- old/dock-applet-0.63/src/dock_applet.in 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/src/dock_applet.in 2015-10-15 11:32:08.000000000 +0200 @@ -34,10 +34,10 @@ import os import sys sys.path.insert(1, '@pythondir@') -from time import sleep import gi gi.require_version("Gtk", "2.0") +gi.require_version("MatePanelApplet", "4.0") from gi.repository import Gtk from gi.repository import MatePanelApplet from gi.repository import Gdk @@ -108,125 +108,24 @@ if event.button == 1: # hide the window list window - the_dock.hide_win_list() app = the_dock.get_app_at_mouse(event.x, event.y) if app is not None: + #TODO + # move this code into docked_app.in ... + # if the app is not running start the app # if the app is running and the shift key is being pressed, start another # instance of the app start_app = app.is_running() == False start_app = start_app | (event.state & Gdk.ModifierType.SHIFT_MASK) != 0 if start_app: - the_de = DesktopEntry.DesktopEntry(app.desktop_file) - run_it = the_de.getExec() - if run_it is not None: - - # hack for Linux Mint: - # Mint has several shortcuts for starting caja so that it can - # be started in a specific directory e.g. home, /, etc - # However, the main caja.desktop is responsible for starting the - # user's desktop and this is the .desktop file the applet finds first. - # When the caja icon on the applet is clicked, caja is run as a desktop - # window and no new file browser appears. - # To get around this, we can simply check the command that is going to be - # run and change it so that a caja window opens in the user's home directory, - # which is the behaviour they'll probably be expecting.... - if run_it == "/usr/bin/startcaja": - run_it = "caja" - - # remove any command line arguments - if "%" in run_it: - i = run_it.rfind("%") - run_it = run_it[0:i-1] - - app_info = Gio.AppInfo.create_from_commandline(run_it, - None, - Gio.AppInfoCreateFlags.NONE) - alc = Gdk.AppLaunchContext() - alc.set_desktop(-1) # use default screen & desktop - app_info.launch() - # set the app icon pulsing - throbber = docked_app.PulseTimer(app) - + app.start_app() else: - # the action to perform (minimizing, moving workspace, activating) - # is decided as follows: - # if (the app's windows are all minimized) or - # (the app s one or more unminimized window but is not the active app) - # then - # restore the app's last active window. If the active window is on a - # different workspace then activate that workspace - # else: - # the app is currently the active app so all of the app - # windows will be minimized - # - # but first, hide any app window list that is being shown and stop the - # window list time - - the_dock.stop_win_list_timer() - the_dock.hide_win_list() + the_dock.minimize_or_restore_windows(app, event) - win_list = app.get_wnck_windows() - - restore_win = (not app.has_unminimized_windows()) or \ - (app.has_unminimized_windows() and (app.is_active==False)) - - if restore_win: - last_active_win = app.last_active_win - - if last_active_win is not None: - wnck_screen = last_active_win.get_screen() - wnck_aws = wnck_screen.get_active_workspace() - wnck_ws = last_active_win.get_workspace() - - if wnck_aws != wnck_ws: - wnck_ws.activate(event.time) - sleep(0.01) - - # rarely, the last active win does not end up as the active window if we - # activate here, so instead a workaround which seems to do the trick - # is use a timer as below - GObject.timeout_add(20, win_activation_timer, [last_active_win, event.time+20]) - - else: - #minimize all windows and do the last active window last of all - - last_active_win = app.last_active_win - - for window in win_list: - win_type = window.get_window_type() - if ((win_type == Wnck.WindowType.NORMAL) or \ - (win_type == Wnck.WindowType.DIALOG)) and \ - (not window.is_skip_tasklist()) and \ - (window != last_active_win): - window.minimize() - sleep(0.01) - - app.last_active_win = last_active_win - if last_active_win is not None: - last_active_win.minimize() - sleep(0.01) - - -def win_activation_timer(args): - """ Timer function to be called by GObject.timeout_add and which - will activate a specified wnck window - - Args: - args - a tuple containing two items - args[0] - the wnck window to activate - args[1] - the event time we want to specfiy - - Returns: - False - to cancel the timer - """ - - args[0].activate(args[1]) - sleep(0.01) - return (False) def applet_enter_notify(widget, event, the_dock): """Enter notify event for the applet diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/src/dock_custom_launcher.in new/dock-applet-0.64/src/dock_custom_launcher.in --- old/dock-applet-0.63/src/dock_custom_launcher.in 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/src/dock_custom_launcher.in 2015-10-15 11:32:08.000000000 +0200 @@ -132,7 +132,7 @@ self.__lbl_cmd.set_use_markup(True) self.__lbl_cmd.set_label("<b>" +"Command:" + "</b>") self.__lbl_cmd.set_alignment(1, 0.5) - + self.__entry_cmd = Gtk.Entry() self.__entry_cmd.set_width_chars(40) self.__btn_cmd = Gtk.Button(label = "Browse...") @@ -140,6 +140,14 @@ self.__hbox_cmd.pack_start(self.__entry_cmd, True, True, 0) self.__hbox_cmd.pack_end(self.__btn_cmd, False, False, 0) + self.__lbl_term = Gtk.Label() + self.__lbl_term.set_use_markup(True) + self.__lbl_term.set_label("<b>" + "Run in terminal:" + "</b>") + self.__lbl_term.set_alignment(1, 0.5) + + self.__cbtn_term = Gtk.CheckButton() + self.__cbtn_term.set_alignment(1, 0.5) + self.__lbl_comment = Gtk.Label() self.__lbl_comment.set_use_markup(True) self.__lbl_comment.set_label("<b>" +"Comment:" + "</b>") @@ -166,6 +174,16 @@ Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, Gtk.AttachOptions.SHRINK, 2, 2) + # Code below can be uncommented if adding terminal apps to the dock ever + # becomes a needed thing + #self.__table_layout.attach(self.__lbl_term, 0, 1, 2, 3, + # Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, Gtk.AttachOptions.SHRINK, + # 2, 2) + # + #self.__table_layout.attach(self.__cbtn_term, 1, 2, 2, 3, + # Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, Gtk.AttachOptions.SHRINK, + # 2, 2) + self.__table_layout.attach(self.__lbl_comment, 0, 1, 2, 3, Gtk.AttachOptions.SHRINK, Gtk.AttachOptions.SHRINK, 2, 2) @@ -382,6 +400,25 @@ wm_class = property(get_wm_class, set_wm_class) + def get_is_term(self): + """ Gets whether or not the app is meant to be run in a terminal + + Returns: True if the app is to be run in a terminal, False otherwise + """ + + return self.__cbtn_term.get_active() + + def set_is_term(self, is_term): + """ Sets whether or not the app is to be run in a terminal + + Args: + is_term: boolean + """ + + self.__cbtn_term.set_active(is_term) + + is_terminal_app = property(get_is_term, set_is_term) + def help_btn_press(self, widget, event): """ Event handler for the Help button press event @@ -413,6 +450,7 @@ dclw.icon_filename = "/usr/share/pixmaps/ericWeb.png" dclw.command = "/usr/bin/gvim" dclw.wm_class = "Dock_custom_launcher.py" + dclw.is_terminal_app = False Gtk.main() if __name__ == "__main__": diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/src/dock_prefs.in new/dock-applet-0.64/src/dock_prefs.in --- old/dock-applet-0.63/src/dock_prefs.in 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/src/dock_prefs.in 2015-10-15 11:32:08.000000000 +0200 @@ -157,12 +157,37 @@ self.__frame_unpinned_apps_align.add(self.__table_unpinned_apps) self.__frame_unpinned_apps.add(self.__frame_unpinned_apps_align) + self.__frame_click_action = Gtk.Frame(label="Mouse click action") + lbl = self.__frame_click_action.get_label_widget() + lbl.set_use_markup(True) + lbl.set_label("<b>" +"Dock click action" + "</b>") + self.__frame_click_action.set_shadow_type(Gtk.ShadowType.NONE) + + self.__rb_restore_last_active = Gtk.RadioButton(label="Restore clicked app's last active window only") + self.__rb_restore_all = Gtk.RadioButton(group=self.__rb_restore_last_active, \ + label="Restore all of clicked app's windows") + self.__table_click_action = Gtk.Table(rows=2, columns=1, homogeneous=False) + self.__table_click_action.attach(self.__rb_restore_last_active, 0, 1, 0, 1, + Gtk.AttachOptions.FILL, Gtk.AttachOptions.SHRINK, + 2, 2) + self.__table_click_action.attach(self.__rb_restore_all, 0, 1, 1, 2, + Gtk.AttachOptions.FILL, Gtk.AttachOptions.SHRINK, + 2, 2) + + self.__frame_click_action_align = Gtk.Alignment(xalign=0.5, yalign=0.5, + xscale=1.0, yscale=1.0) + self.__frame_click_action_align.set_padding(0, 0, 12, 0) + self.__frame_click_action_align.add(self.__table_click_action) + self.__frame_click_action.add(self.__frame_click_action_align) + + # create ui elements for multiple indicators for open windows self.__cb_multi_ind = Gtk.CheckButton(label="Display an indicator for each open window") self.__cb_multi_ind.set_tooltip_text("Display an indicator (max 4) for each open window") self.__vbox.pack_start(self.__frame_ind_type, True, True, 4) self.__vbox.pack_start(self.__frame_unpinned_apps, True, True, 4) + self.__vbox.pack_start(self.__frame_click_action, True, True, 4) self.__vbox.pack_start(self.__cb_multi_ind, True, True, 4) self.__vbox.pack_start(Gtk.HSeparator(), True, True, 4) @@ -291,6 +316,27 @@ else: self.__rb_unpinned_cur_ws.set_active(True) + def get_click_restore_last_active(self): + """Gets whether to restore only a running app's last active window when its dock + icon is clicked and all windows are minimized + + Returns: boolean + """ + + return self.__rb_restore_last_active.get_active() + + def set_click_restore_last_active(self, restore_last_active): + """Sets whether to restore only a running app's last active window when its dock + icon is clicked and all windows are minimized + + Args: restore_last_active - boolean + """ + + if restore_last_active == True: + self.__rb_restore_last_active.set_active(True) + else: + self.__rb_restore_all.set_active(True) + def main(): """main function - debug code can go here""" dpw = DockPrefsWindow(Gtk.main_quit) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/src/dock_xml.in new/dock-applet-0.64/src/dock_xml.in --- old/dock-applet-0.63/src/dock_xml.in 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/src/dock_xml.in 2015-10-15 11:32:08.000000000 +0200 @@ -34,7 +34,8 @@ import xml.etree.ElementTree as ET -def write_xml (filename, desktop_files, light_ind, unpinned_from_all, multi_ind): +def write_xml (filename, desktop_files, light_ind, unpinned_from_all, multi_ind, + click_restore_last_active): """ Write the xml file using the specified information The xml file will be in the following format: @@ -48,6 +49,7 @@ <light_ind>int</> <unpinned_from_all>True or False</> <multi_ind>True or False</> + <click_restore_last_active>True or False</> </root> Args: @@ -60,6 +62,9 @@ are to be shown multi_ind : Whether indicators for each of an app's open windows are to be shown + click_restore_last_active: whether clicking a running app's dock icon restores + only the last active window or all windows + Returns: Boolean - True if the file was written successfully, False otherwise @@ -76,11 +81,14 @@ ind_el = ET.Element("ind_type", light = "%d" %light_ind) ufa_el = ET.Element("unpinned_from_all", show_all = "%s" %unpinned_from_all) mi_el = ET.Element("multi_ind", show_multi = "%s" %multi_ind) + crla_el = ET.Element("click_restore_last_active", + restore_last_active_only = "%s" %click_restore_last_active) root.append (pa_el) root.append (ind_el) root.append (ufa_el) root.append (mi_el) + root.append (crla_el) try: ET.ElementTree(root).write(filename, xml_declaration=True) @@ -103,6 +111,7 @@ an interger - the light indicator setting a boolean - the unpinned from all setting a boolean - the multiple indicators setting + a boolean - the restore last active settings """ @@ -117,25 +126,35 @@ for df in pinned_apps: df_list.append(df.get("name")) + # note - values may be missing from the config file e.g. if a new version of the applet + # adds a new configuration settings. If this happens, we just assume a default option + # rather than reporting an error + # ind_el = root.find("ind_type") if ind_el is not None: light_ind = int(ind_el.get("light")) else: - return [False] # indicator type should always be there... + light_ind = True ufa_el = root.find("unpinned_from_all") if ufa_el is not None: show_all = ufa_el.get("show_all") == "True" else: - return [False] + show_all = True mi_el = root.find("multi_ind") if mi_el is not None: multi_ind = mi_el.get("show_multi") == "True" else: - return [False] + multi_ind = False + + crla_el = root.find("click_restore_last_active") + if crla_el is not None: + click_restore_last_active = crla_el.get("restore_last_active_only") == "True" + else: + click_restore_last_active = True - return [True, df_list, light_ind, show_all, multi_ind] + return [True, df_list, light_ind, show_all, multi_ind, click_restore_last_active] def main(): """Main function. @@ -143,7 +162,7 @@ Debugging code can go here """ - write_xml ("/home/robin/tmp/text.xml", ["thing.desktop","blah.desktop"], 99, False, True) + # write_xml ("/home/robin/tmp/text.xml", ["thing.desktop","blah.desktop"], 99, False, True, False) results = read_xml ("/home/robin/tmp/text.xml") if results[0] == True: for df in results[1]: @@ -152,6 +171,7 @@ print ("Use light ind = %d" %results[2]) print ("Show unpinned on all = %s" %results[3]) print ("Multi ind = %s" %results[4]) + print ("Click restore all = %s" %results[5]) else: print ("Error reading file....") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/src/docked_app.in new/dock-applet-0.64/src/docked_app.in --- old/dock-applet-0.63/src/docked_app.in 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/src/docked_app.in 2015-10-15 11:32:08.000000000 +0200 @@ -45,6 +45,7 @@ import gi gi.require_version("Gtk", "2.0") +gi.require_version("MatePanelApplet", "4.0") from gi.repository import Gtk from gi.repository import MatePanelApplet from gi.repository import Gdk @@ -53,8 +54,8 @@ from gi.repository import Wnck #from gi.repository import GdkPixbuf -#from gi.repository import Gio -#from gi.repository import GLib +from gi.repository import Gio +from gi.repository import GLib from gi.repository import GObject import cairo import math @@ -62,6 +63,9 @@ import os import os.path import subprocess +import re +from urllib.parse import urljoin +from urllib.request import pathname2url from collections import namedtuple @@ -71,7 +75,7 @@ ColorTup = namedtuple('ColorTup', ['r', 'g', 'b']) AppInfoTup = namedtuple('AppInfoTup', ['app', 'pid', 'windows']) - +ActionTup = namedtuple('ActionTup', ['disp_name', 'command', 'act_name', 'is_action']) def im_get_comp_color(filename): """Find the complimentary colour of the average colour of an image. @@ -226,9 +230,10 @@ Attributes: app_info : list of AppInfoTups to hold details of all running processes - the app has + the app has wnck_class : the WnckClass object relating to the app app_name : e.g. Google Chrome, used for tooltips and the applet right click menu etc + rc_actions : list of ActionTups to hold details of right click actions the app supports cmd_line : the command line and arguments used to start the app icon_name : name of the app icon icon_filename : the filename of the app icon @@ -266,6 +271,7 @@ self.app_info = [] self.wnck_class = None self.app_name = "" + self.rc_actions = [] self.cmd_line = "" self.icon_name = "" self.icon_filename = "" @@ -362,6 +368,7 @@ return False # now that we have the .desktop file, we can get the icon etc + return self.read_info_from_desktop_file() def set_app_name(self, app_name): @@ -495,13 +502,14 @@ In addition to <self.wm_class_name>.desktop looks for the following variations of name for the desktop flie: - lowercase<self.wm_class_name>.desktop - uppercase<self.wm_class_name>.desktop <self.app_name>.desktop lowercase<self.app_name>.desktop + camel cased<self.app_name>.desktop <self.app_name> with space characters replaced by '-'.desktop lowercase<self.app_name> with space characters replaced by "-",desktop <self.wm_class_name>.desktop + lowercase<self.wm_class_name>.desktop + uppercase<self.wm_class_name>.desktop If the destop file is found, self.desktop_file is set accordingly, otherwise self.desktop_file is set to None @@ -516,37 +524,44 @@ for the_dir, dir_list, file_list in os.walk(srch_dir): - dfname = the_dir + self.wm_class_name + ".desktop" + dfname = the_dir + self.app_name + ".desktop" if os.path.isfile(dfname): self.desktop_file = dfname return True - dfname = the_dir + self.wm_class_name.lower() + ".desktop" + dfname = the_dir + self.app_name.lower() + ".desktop" if os.path.isfile(dfname): self.desktop_file = dfname return True - dfname = the_dir + self.wm_class_name.upper() + ".desktop" + # camel case + dfname = the_dir + re.sub(r"\w+", lambda m:m.group(0).capitalize(), self.app_name) \ + + ".desktop" if os.path.isfile(dfname): self.desktop_file = dfname return True - dfname = the_dir + self.app_name + ".desktop" + dfname = the_dir + self.app_name.replace(" ", "-") + ".desktop" if os.path.isfile(dfname): self.desktop_file = dfname return True - dfname = the_dir + self.app_name.lower() + ".desktop" + dfname = the_dir + self.app_name.replace(" ", "-").lower() + ".desktop" if os.path.isfile(dfname): self.desktop_file = dfname return True - dfname = the_dir + self.app_name.replace(" ", "-") + ".desktop" + dfname = the_dir + self.wm_class_name + ".desktop" if os.path.isfile(dfname): self.desktop_file = dfname return True - dfname = the_dir + self.app_name.replace(" ", "-").lower() + ".desktop" + dfname = the_dir + self.wm_class_name.lower() + ".desktop" + if os.path.isfile(dfname): + self.desktop_file = dfname + return True + + dfname = the_dir + self.wm_class_name.upper() + ".desktop" if os.path.isfile(dfname): self.desktop_file = dfname return True @@ -567,6 +582,10 @@ the Exec field is found within self.cmd_line the StartupWMClass is the same as self.wm_class_name + Note: if StartupWMClass is present in a .desktop file and it + does not match the app's wm_class, the .desktop file is not + a match, no matter what the values of the name and exec fields are + If a match is found, self.desktop_file is set accordingly Note - the app must be running, and self.pid, self.cmd_line and @@ -590,6 +609,12 @@ for name in name_parts: name = name.strip() + # split the command line into the command and various arguments + # note: strings that contain spaces will obviously be split into + # more than one part, but that's not a problem as we don't care + # about string aguments + cmd_parts=self.cmd_line.split() + # search search_dir and any sub-directories it contains for .desktop files for the_dir, dir_list, file_list in os.walk(srch_dir): for the_file in file_list: @@ -608,11 +633,19 @@ # remove command line args from the Exec field of the .desktop de_exec = the_de.getExec() + exec_found = False if (de_exec is not None) and (de_exec != ""): - de_exec = de_exec.split(None, 1)[0] - exec_found = self.cmd_line.find(de_exec) != -1 - else: - exec_found = False + de_exec = de_exec.split() + + for exec_part in de_exec: + try: + unused_var = cmd_parts.index(exec_part) + exec_found = True + except ValueError: + pass + + if exec_found: + break # we can now search within self.cmd_line for de_exec # Note: we don't test for equality because some apps are launched via @@ -621,10 +654,26 @@ # .desktop file the Exec field is '/usr/bin/software-center' whilst # it's command line while running is 'usr/bin/python /usr/bin/software-center' - if (name_part_found == True) or (exec_found == True) or \ - (the_de.getStartupWMClass() == self.wm_class_name): - self.desktop_file = os.path.join(the_dir, the_file) - return True + # check the wm_classes + wm_class_mismatch = False + de_wm_class = the_de.getStartupWMClass() + if ((de_wm_class is not None) and (de_wm_class != "")): + if ((self.wm_class_name is not None) and (self.wm_class_name != "")) and \ + (de_wm_class.lower() == self.wm_class_name.lower()): + + # this is all we need to match, so.... + self.desktop_file = os.path.join(the_dir, the_file) + return True + else: + wm_class_mismatch = True + + # we now check the name and executable, as long as there was no + # mismatch between wm_classes + if wm_class_mismatch == False: + if (name_part_found == True) or \ + (exec_found == True): + self.desktop_file = os.path.join(the_dir, the_file) + return True self.desktop_file = None return False @@ -753,6 +802,7 @@ Will try to read the icon name and app name from the desktop file Will also get the executeable path if we don't already have this + Will read the details of any right click menu options the .desktop file defines Returns: True if successful, False otherwise @@ -760,11 +810,40 @@ if self.desktop_file: dfile = DesktopEntry.DesktopEntry(self.desktop_file) - self.icon_name = dfile.getIcon() self.app_name = dfile.getName() + self.icon_name = dfile.getIcon() + + # if the desktop file does not specify an icon name, use the app name instead + if (self.icon_name is None) or (self.icon_name == ""): + self.icon_name = self.app_name.lower() + if self.cmd_line == "": self.cmd_line = dfile.getExec() + # now read the right click actions the app supports. These can be specified in + # two ways - by a key named 'X-Ayatana-Desktop-Shortcuts' or by an Actions key + # + # Note: we differentiate between actions and shortcuts, because actions can + # be run via Gio.DesktopAppInfo whereas shortcuts we need to run ourselves + xads = dfile.get('X-Ayatana-Desktop-Shortcuts') + if (xads is not None) and (xads != ""): + #the shortcut ids are in the the form of a semi-colon separated string + for rca in xads.split(";"): + rcname = dfile.get("Name", group = "%s Shortcut Group" %rca) + rcexec = dfile.get("Exec", group = "%s Shortcut Group" %rca) + if (rcname != "") and (rcexec !=""): + new_action = ActionTup(disp_name = rcname, command = rcexec, + act_name = rca, is_action = False) + self.rc_actions.append(new_action) + + for action in dfile.getActions(): + rcname = dfile.get("Name", group ="Desktop Action %s" %action) + rcexec = dfile.get("Exec", group = "Desktop Action %s" %action) + if (rcname != "") and (rcexec !=""): + new_action = ActionTup(disp_name = rcname, command = rcexec, + act_name = action, is_action = True) + self.rc_actions.append(new_action) + return True return False @@ -954,6 +1033,104 @@ rht, ght, bht = self.highlight_color = get_avg_color(pixbuf) self.highlight_color = ColorTup(r=rht, g=ght, b=bht) + def start_app(self): + """Start the app or open a new window if it's already running + """ + the_de = DesktopEntry.DesktopEntry(self.desktop_file) + run_it = the_de.getExec() + if run_it is not None: + + # hack for Linux Mint: + # Mint has several shortcuts for starting caja so that it can + # be started in a specific directory e.g. home, /, etc + # However, the main caja.desktop is responsible for starting the + # user's desktop and this is the .desktop file the applet finds first. + # When the caja icon on the applet is clicked, caja is run as a desktop + # window and no new file browser appears. + # To get around this, we can simply check the command that is going to be + # run and change it so that a caja window opens in the user's home directory, + # which is the behaviour they'll probably be expecting.... + if run_it == "/usr/bin/startcaja": + run_it = "caja" + + # remove any command line arguments + if "%" in run_it: + i = run_it.rfind("%") + run_it = run_it[0:i-1] + + # start the app + self.run_cmd_line (run_it) + else: + + the_dae = Gio.DesktopAppInfo.new_from_filename(self.desktop_file) + alc = Gdk.AppLaunchContext() + alc.set_desktop(-1) # use default screen & desktop + the_dae.launch(None, alc) + # set the app icon pulsing + throbber = PulseTimer(self) + + def run_cmd_line(self, cmd_line): + """Run a command line. To be used when starting an app for the first time or when running + an action/shortcut specfied in the app's .desktop file + + Args: + cmd_line - the command to run + """ + + # the command line may contain escape sequences, so unescape them.... + cmd_line =bytearray(cmd_line, "UTF-8") + cmd_line = cmd_line.decode("unicode-escape") + + app_info = Gio.AppInfo.create_from_commandline(cmd_line, + None, + Gio.AppInfoCreateFlags.NONE) + alc = Gdk.AppLaunchContext() + alc.set_desktop(-1) # use default screen & desktop + app_info.launch() + # set the app icon pulsing + throbber = PulseTimer(self) + + def run_rc_action(self, act_no): + """ run the right click action specified by act_no + + Args: + act_no - integer, the action number to run + """ + + if len(self.rc_actions) >= act_no: + act = self.rc_actions[act_no-1] + if act.is_action == True: + # Gio.DesktopAppInfo give a more convenient and complete way to + # run actions + the_dae = Gio.DesktopAppInfo.new_from_filename(self.desktop_file) + alc = Gdk.AppLaunchContext() + alc.set_desktop(-1) # use default screen & desktop + the_dae.launch_action(act.act_name,alc) + else: + self.run_cmd_line(self.rc_actions[act_no-1].command) + + # set the app icon pulsing + throbber = PulseTimer(self) + + def get_rc_action(self, act_no): + """ return a specified right click action's details + + Args: + act_no - integer, the specified action number + + Returns: + bool - True if the action exists, False otherwise + string - the name of the action (i.e. the text to appear in the right click menu) + string - the command line to the be run + """ + + if len(self.rc_actions) >= act_no: + return (True, self.rc_actions[act_no-1].disp_name, + self.rc_actions[act_no-1].command) + + else: + return (False, "", "") + def main(): """Main function. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dock-applet-0.63/src/org.mate.panel.applet.dock.gschema.xml new/dock-applet-0.64/src/org.mate.panel.applet.dock.gschema.xml --- old/dock-applet-0.63/src/org.mate.panel.applet.dock.gschema.xml 2015-07-22 10:18:26.000000000 +0200 +++ new/dock-applet-0.64/src/org.mate.panel.applet.dock.gschema.xml 2015-10-15 11:32:08.000000000 +0200 @@ -26,5 +26,10 @@ <summary>Whether this is the first time the applet has been run</summary> <description>Whether this is the first time this particular instance of the applet has been run</description> </key> + <key type="b" name="click-restore-last-active"> + <default>true</default> + <summary>Specifies what to do when a running app's dock icon is click</summary> + <description>If set to true, the app's last running window is made active again. If false all of the app's windows are restored/unminimizes and the last active window is made active again</description> + </key> </schema> </schemalist>
