possible actions specification

Ryan Lortie desrt at desrt.ca
Thu Sep 2 03:32:56 PDT 2010


hi,

I've implemented what I believe to be a generally useful DBus protocol.
Currently this protocol is implemented in glib using the interface name
org.gtk.Actions.  I'd like to use the org.freedesktop.Actions interface
name.

The DBus interface represents a set of actions.  Actions have two main
functionalities.

 * they can be activated (with an optional parameter)

 * they can optionally be stateful

This roughly corresponds to GtkAction.  You can activate it, and some
actions (like GtkToggleAction) have a state which can be queried and
directly set.

Some other things to know about actions:

 * actions are exported in a simple flat group at a particular object
   path with each action having a simple string as a name (with no
   special constraints on the name)

 * actions have an "enabled" flag that can be queried; when disabled,
   attempts to invoke actions or set their state are typically ignored

 * action invocations and state sets include a 'context' parameter -- a
   dictionary mapping strings to variants ('a{sv}') -- containing useful
   contextual information like the x11 timestamp that caused the
   activation.

The interface is comprised of 5 method calls and 4 signals.

The interface makes use of maybe types.  In environments where maybe
types are not available, arrays will be used instead -- with a 0-item
array to indicate the 'Nothing' case and a 1-item array used to
indicate the 'Just' case.

The interface also makes use of an unusual convention -- conveying type
information by way of a variant containing an empty array.  For example,
to convey the type 'string', a variant containing an empty array of
strings would be sent.  I may be insane, but for some reason this seems
to me to be a lot cleaner than using the 'g' type.

The interface description follows:

Method Calls

 * List :: () -> (as)

     lists all actions, by name

 * Describe :: (s) -> (mvbmv)

     describes an action and its current state

     The first item gives the optional parameter type for activation.
     The second item is if the action is currently enabled.  The final
     item is the value of the optional state.

     The types of both the parameter and state must be serialisable
     types.  If a reference type like 'o' or 'h' is used here, for
     example, it has no special significance.

 * DescribeAll :: () -> (a(smvbmv))

     a mix of List and Describe -- describes all actions

 * Activate :: (smva{sv}) -> ()

     activates the named action with optional parameter and provided
     context information (the list of supported context items is to be
     decided)

 * SetState :: (sva{sv}) -> ()

     sets the action state with optional parameter and provided context
     information

Signals

  * Added :: (a(smvbmv))

     indicates that one or more new actions have added and gives their
     description in the same format as DescribeAll

  * Removed :: (as)

     indicates that one or more actions have been removed

  * EnabledChanged :: (sb)

     indicates that the enabled flag of an action has changed

  * StateChanged :: (sb)

     indicates that the state of an action has changed

I am reasonably convinced that it should always be possible to implement
a fully-aware consumer (read: client) of the interface by registering a
single signal watch and issuing a DescribeAll call.  DescribeAll has all
of the information needed for the client to have a full view of the
action set and the signals contain enough information to keep the client
up to date without any additional calls required.


A question I anticipate is why this interface is needed at all.  An
argument could be made that invoking actions (with parameters) should
just be done by exporting a large number of methods in the usual way
and state should be handled by using DBus properties in the usual way.

My response to this comes mostly in two forms.  One is that of scale and
feeling.  I don't believe that DBus interfaces were meant to be filled
with dozens (maybe hundreds) of methods and properties that can come and
go or be different between different versions of software.  The second
part of my response is that there are some new bits here (like the
enabled flag) that have no clear way of being represented.

The purpose of all of this is to eventually create a protocol to allow
for applications to export menus over DBus while addressing some
shortcomings of the Ayatana dbusmenu protocol.  The menu structure would
be specified in terms of actions (along with UI information like label,
icon, toggle type, etc).  If the menu item was enabled or had its radio
or toggle checked at a particular time would be decided by the state of
the underlying action -- the menu itself would only change if there were
actually changes to the structure of the menu.

The main advantage, in my mind, of separating out the actions like this
is that we have instant scriptability of any action that appears on a
menu.  There are some small additional advantages like the ability to
use a particular menu structure with more than one set of underlying
actions to determine the state of the menus (think about switching
between windows of one application on the Mac OS).

You can see an implementation of what I have described so far in a glib
branch which I plan to merge soon (subject to feedback here).  The
server-side is at the bottom of gdbusconnection.c and the client-side is
in gdbusactiongroup.c.  You can find both of these in the gio/
directory.

        http://git.gnome.org/browse/glib/log/?h=gdbus-actions

Thanks for any feedback.

Cheers



More information about the xdg mailing list