Writing Helpers

From Docky
Jump to: navigation, search


Writing Docky Extensions

Docky has two methods with which 3rd party developers can create new extensions. The first, and more traditional, method is through mono based plugins using Mono.Addins as a plugin infrastructure. The second method is over a dbus interface, for which a convenience python wrapper has been written. The dbus interface can be accessed through any language however.

Which Interface Should I Use?

Generally speaking, use the dbus interface unless you really need to use the more robust mono interface. As the interfaces progress, the dbus interface may almost completely replace the mono interface. They do however have a couple differences.

So in short. If you wish to modify existing items, use the dbus interface. If you wish to add new items, use the mono interface.

Archive Specification

User created extensions must be packed in a .tar archive (no .tar.bz2, .tar.* !!!). Inside this tar archive, there are 2 files and 2 folders.

- scripts
- scripts/my_extension.py
- metadata
- metadata/my_extension.py.info

The scripts file is your extension, this can have any name you'd like and must be in the folder scripts.

The info folder must be named metadata. Inside this folder, you must have a file called <extension_name>.info (where <extension_name> is the full name (including file extension) of your extension). So if your extension was named my_extension.py, your .tar archive would contain 2 files, scripts/my_extension.py and metadata/my_extension.py.info

When dealing with user created extensions, this is the bare minimum.

Metadata Specification

The .info file must contain at least 3 lines. These line are:

 Name=<extension name>
 Description=<extension description>

You can replace <extension name> and <extension description> with whatever you'd like. You may also specify an icon for your extension by adding this line:


<icon> can be 1 of 2 things. It can either start with a ./ or not. If <icon> does not start with ./, then whatever <icon> is will be an icon from the current theme with the name of <icon>. If <icon> starts with ./, then Docky will attempt to locate a file in the metadata directory with the name specified after the ./. Note that you must also then include this icon file in your .tar extension archive.

 AppName=<name of executable>

If you set the AppName, it is a hint to docks to look for that executable (similar to calling 'which <executable>' from a terminal) and if it finds it, then assume this helper can be used. If AppName is specified and the executable can not be found, it assumes the helper is not usable. These assumptions are used for filtering the list of helpers.

If you set the DBusName, Docky will look to see if that DBus path exists and launch the helper only if it does. If the path goes away, it will stop the helper.

 Name=Test Extension
 Description=This is just a test extension

This will give your extension a name of "Test Extension" and an icon from the current theme called "gtk-apply".

DBus Interface Example

The dbus interface is simple enough its easier to show with code examples. This is a python plugin that adds player controls to the banshee launcher.

We are going to start off with a fairly standard set of python declarations. We make sure to abort when any of our non-standard imports fail so not to spam the console.

 #!/usr/bin/env python 
 import atexit
 import gobject
 import glib
 import sys
 import os
 	from docky.docky import DockManagerItem, DockManagerSink
 	from signal import signal, SIGTERM
 	from sys import exit
 except ImportError, e:

Subclassing DockManagerItem as provided by the wrapper lib we are able to skip right to adding menu items and modifying the item. The format for adding menu items is self.add_menu_item(name, icon, category).

 class BansheeItem(DockManagerItem):
 	def __init__(self, sink, path):
 		DockyItem.__init__(self, sink, path)
 		self.add_menu_item("Previous", "media-skip-backward", "Banshee Controls")
 		self.add_menu_item("Toggle Playing", "media-playback-start", "Banshee Controls")
 		self.add_menu_item("Next", "media-skip-forward", "Banshee Controls")

When an added menu is pressed, this overridden method will be called. You can confirm which button was pressed by checking the menu_id.

  	def menu_pressed(self, menu_id):
 		if self.id_map[menu_id] == "Toggle Playing":
 			os.system("banshee --toggle-playing")
 		elif self.id_map[menu_id] == "Next":
 			os.system("banshee --next")
 		elif self.id_map[menu_id] == "Previous":
 			os.system("banshee --previous")

Subclassing DockManagerSink lets us get events whenever a new item is added to the dock. Further removed items are automatically disposed for us.

 class BansheeSink(DockySink):
 	def item_path_found(self, pathtoitem, item):
 		if item.GetDesktopFile().endswith ("banshee-1.desktop"):
 			self.items[pathtoitem] = BansheeItem(self, pathtoitem)
 bansheesink = BansheeSink()
 def cleanup():
 if __name__ == "__main__":
 	mainloop = gobject.MainLoop(is_running=True)
 	signal(SIGTERM, lambda signum, stack_frame: exit(1))

DBus Interface Specification

Docky implements the DockManager specificiation as well as it's own custom DBus specification.

DockManager DBus Interface Specification

DBus unique path: net.launchpad.DockManager

Object paths:

- Interface: net.launchpad.DockManager
  * Methods:
    * GetCapabilities       ()                         -> (Array of [String] capabilities)
    * GetItems              ()                         -> (Array of [Object path])
    * GetItemsByName        (String name               -> (Array of [Object path])
    * GetItemsByDesktopFile (String desktop_file_name) -> (Array of [Object path])
    * GetItemsByPID         (Int32 pid)                -> (Array of [Object path])
    * GetItemByXid          (Int64 xid)                -> (Object path)
  * Signals:
    * ItemAdded             (Object path)
    * ItemRemoved           (Object path)


- dock-item-attention
- dock-item-badge
- dock-item-icon-file
- dock-item-message
- dock-item-progress
- dock-item-tooltip
- dock-item-waiting
- menu-item-container-title
- menu-item-icon-file
- menu-item-icon-name
- menu-item-with-label
- menu-item-with-uri
- Interface: net.launchpad.DockItem
  * Methods:
    * AddMenuItem       (Dict of {String key, Variant value} menu_hints) -> (Int32 id)
    * RemoveMenuItem    (Int32 id)
    * UpdateDockItem    (Dict of {String key, Variant value} hints)
  * Properties (implementing org.freedesktop.DBus.Properties)
    * string DesktopFile
    * string Uri
  * Signals:
    * MenuItemActivated (Int32 id)

Supported menu_hints:

 - label + String
 - uri + String
 - container-title + String
 - icon-file + String
 - icon-name + String

Implementor can choose whether icon setting will be honored when the menu item is specified using the "uri" key.

Supported hints: All hints are optional.

- attention + Boolean
- badge + String
- icon-file + String
- message + String
- progress + Int
- tooltip + String
- waiting + Boolean

Custom DBus Interface Specification

Docky adds the following to the standard DockManager specification.


- x-docky-uses-menu-confirmation
- x-docky-message-has-icons
- x-docky-message-has-slots
- x-docky-get-item-pids

Object paths:

- Interface: net.launchpad.DockItem
  * Methods:
    * ConfirmMenuItem            (Int32 id)
  * Properties (implementing org.freedesktop.DBus.Properties)
    * Array of [Int32] PIDs
  * Signals:
    * MenuItemConfirmationNeeded ()

The message hint is extended to support 'slots' (0 to 2). Thus, Docky supports up to 3 messages at a time. Messages can also have icons displayed. The standard message (a string) is supported and defaults to slot 0 with no icon. Extended messages must be of the form 'slot;;message' or 'slot;;message;;icon'.

DBus unique path: org.gnome.Docky

Object paths:

- Interface: org.gnome.Docky
  * Methods:
    * ShowAbout    ()
    * ShowSettings ()
    * Quit         ()
  * Signals:
    * ShuttingDown ()
Personal tools