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>


Reply via email to