Lenses

Revision 15 as of 2011-04-04 19:37:20

Clear message

Unity > Places

Unity Lenses Architecture

Warning /!\ Lenses used to be known as Places. When referring to code and APIs we still use the term Places, but the user-visible name is Lenses. The Places name will be retired in 11.10.

This page summarizes the Unity Lenses architecture as agreed by Neil and Mikkel.

  • == Glossary ==

To minimize the confusion let's all try and stick to the following glossary (.svg source):

unity-glossary.png

Introduction

Neil has created a presentation/introduction for developers.

Unity_Places_Developer_Guide.pdf

Here are some ideas we have for Unity places.

Plan for Natty

Lenses are something that we can put in extras.ubuntu.com since they're small and can be quick moving and we want people making lots of them. This gives us the rest of the development cycle and Natty's lifecycle for people to submit Places that people can run on their stable release without digging around for PPAs.

  • Quickly needs to be adapted for /opt-like things, after feature freeze: Didrocks

Place Daemons

Lens Daemons from 1000 Feet

A lens daemon expose a list of place entries over DBus. Each entry holds enough data and metadata for Unity to render it. Each place entry has it's own icon in the places bar.

Each lens has a DBus API that exposes it's sections, groups, and core datamodel. It also defines which rendering mode Unity must use to render each group. Rendering modes includes can include fx. tiled, cover flow, and how many rows to show.

Registration

Places are registered in Unity by adding a special .place-file into $prefix/share/unity/places. The .place file is a keyfile that contains the following

[Place]
DBusName=Well known bus name the place can be found under
DBusObjectPath=DBus object path the place object lives at

[Entry:Stuff]
DBusObjectPath=DBus path for the place entry (must be a direct child of Places' DBusPath)
Icon=Icon for the place entry
Name=Display name for the entry
Description=Short description of what the entry provides. Suitable for display as tooltip or other
SearchHint=Message that will be displayed in the search box
ShowGlobal=true|false (defaults to true)
ShowEntry=true|false (defaults to true)
Shortcut=a


[Entry:OtherStuff]
...

The contents of the .place-file allows Unity to draw an icon in the places bar. The actual place daemon will be started lazily.

The [Place] group in the key file contains the basic info necessary for DBus-activating the place daemon.

Each [Entry:*] group contains the info necessary for Unity to render an icon in the places bar. Note that it can not be guaranteed this entry info is precise. When the daemon comes up some entries may be added or removed compared to this info.

Warning /!\ Show`Global determines whether the Lens shows up in the user's Dash or not. Currently we don't have a method for allowing users to determine this, so we recommend that all Lens authors set this to false so as not to clutter a user's Dash with all the places they have installed. We'll sort this out in 11.10.

A place that requires ShowEntry=False is the Control Center place which is searchable from the home screen, but not otherwise displayed. The Shortcut key defines which keyboard key you must press together with <super> to open the place. In the example above the user must press <super>-a to activate the place. The <super> key to launch apps shortcut is defined in compiz itself.

Example Code

You can find a full working example of a place implementation in launchpad.net/unity-place-sample.

The full source code for the files- and applications places can be found on launchpad.net/unity-place-files and launchpad.net/unity-place-applications. These are quite a lot more complex than the sample above, but exercises the full feature set described in this specification if you would like to see working examples.

Renderers

Each group is rendered by some specific "renderer" inside the Unity shell. The renderer is defined with a CamelCased namespaced type string, ala GLib GTypes, eg. UnityDefaultRenderer. If the renderer type is the empty string the group or entry should not be displayed.

Each place entry has a default renderer specified (in its renderer_info.default_renderer property). This may be overridden on a per-group basis by the groups model specified (in its renderer_info.groups_model).

Examples of renderers could include the default tiled rendering, coverflow, or a webkit-backed HTML renderer. At some point we will also make renderers a pluggable part of the Unity shell.

UnityDefaultRenderer

Renders rows in the results model using the icon_hint column with the display_name column underneath it. The icon should be a serialized GIcon (using g_icon_to_string()). Falls back to using the icon for the mimetype column if the icon_hint is not set. Renders one row of icons by default. FIXME: We need a way to set a hint for showing N rows or all rows.

UnityEmptySectionRenderer

Used to convey to the user that the current section is empty. The first row of the results model contains the message to the user in the display_name column. Any subsequent rows contain optional alternative actions the user may activate. These actions are URI encoded, so fx. a Try searching for 'pony' on Google-alternative might be encoded with http://www.google.com/#q=pony in the uri column of the second row and the string "Try searching for <i>pony</i> on Google" in the display_name column.

UnityEmptySearchRenderer

Used exactly like UnityEmptySectionRenderer but informs the user that the current search did not match anything.

UnityShowcaseRenderer

Used for the Most Used category in the applications place. Has a slightly larger icon than the default renderer.

UnityFileInfoRenderer

Used in files place to show search results. Expects a valid URI, and will show extra information such as the parent folder and whatever data is in the comment column of the results.

DBus API for Place Daemons

Data Structures

RendererInfo

There are a few datastructures we pass over the wire. Firstly we have RendererInfo struct with signature (sss{ss}). We use R as shorthand for this struct:

  string default_renderer   (name defining the default rendering mode for this place entry)
  string groups_model   (DBus name of a Dee.Model)
  string results_model  (DBus name of a Dee.Model)
  map<string,string> renderer_hints
  • Info (!) If the entry wide renderer needs to be changed (fx. after the view calls SetActiveSection() to have a specialized "photo collection view" or something) the entry emits the RendererInfoChanged signal with the updated renderer info.

If default_renderer is the empty string then the contents of the entry should be ignored by the Unity shell. This way place entries can control whether they appear in the global search and/xor/nor in the places bar. This behaviour reflects the ShowGlobal and ShowEntry keys in the Entry group of the .place file.

RendererInfo Hints

You can specify the following hints to a renderer:

  • ExpandedGroups - a space separated list of integer values specifying a set of group ids for groups which should always by fully expanded (ie all rows rendered). Fx "0 3 4" would mean that group ids 0, 3, and 4 should always have all their members visible.

PlaceEntryInfo

And a PlaceEntryInfo struct with signature (sssuasbs{ss}RR). We use P as a shorthand signature:

  string   dbus_path, (DBus path to the Entry object)
  string   name,
  string   icon,
  uint     position,  (the position to render the entry at in the places bar)
  string[] mimetypes, (mimetypes accepted for drag-n-drop)
  bool     sensitive,
  string   sections_model (DBus name of a Dee.Model)
  map<string,string> hints,
  RendererInfo entry_renderer_info
  RendererInfo global_renderer_info

PlaceEntryInfo Hints

  • The following hints are defined for the PlaceEntryInfo

    • UnitySectionStyle - if set to "breadcrumb" the sections_model should be displayed as a breadcrumb trail instead of as separate buttons

    • UnityPlaceBrowserPath - if set, will contain a DBus object path pointing to an object on the place daemon implementing the interface com.canonical.Unity.PlaceBrowser

    • UnityActiveSection - optionally indicates which section the place daemon is currently showing. The value is the section id encoded in a string, eg "3".This is used when returning from browsing mode to a particular section. This hint is not set when the section changes because of a call to SetActiveSection().

    • UnityExtraAction - contains a string serialized GIcon which should be rendered as a button. When clicked Unity should call com.canonical.Unity.Activation.Active() with the argument being the string ".". An example usage is a "Browse This Folder in Nautilus" button rendered at the right of the path bar when in folder browsing mode. FIXME: This is an oversimplified way of extending the model with capabilities, designed this way to keep wire compatibility. We should definitely revisit this for Natty

com.canonical.Unity.Place

The place daemon exposes the interface com.canonical.Unity.Place on the advertised DBusName and DBusObjectPath found in its .place file:

  method  GetEntries (out aP)
  signal  EntryAdded (out P)
  signal  EntryRemoved (out s) (the DBus path to the Entry object)

com.canonical.Unity.PlaceEntry

Each listed entry exposes the interface com.canonical.Unity.PlaceEntry

  /* Global search from the home screen. Populates the models
   * defined in EntryInfo.entry_renderer_info */
  method SetGlobalSearch (in s search_string,
                          in {ss} hints,
                          out u hit_count)

  /* Set whether or not this section is currently being displayed */
  method SetActive (in b active);

  /* Search withing the currently active section */
  method SetSearch (in s search_string,
                    in {ss} hints);

  /* Request that a given section be represented in the model
   * defined by EntryInfo.entry_renderer_info */
  method SetActiveSection (in u active_section_id); (defaults to 0)

  signal EntryRendererInfoChanged (R renderer_info);

  signal GlobalRendererInfoChanged (R renderer_info);

  /* Emitted fx. when the hints change or the name of the sections model change.
   * Both may occur fx. when browsing into a folder.
   * The included struct is the fields of the PlaceEntryInfo struct, but
   * without the two RenderingInfo structs */
  signal PlaceEntryInfoChanged (in (sssuasbs{ss}) place_entry_info);

  /* Optionally emitted by a place entry once it has completed all operations for
   * a SetSearch, SetGlobalSearch, or SetActiveSection request and fully updated
   * the result model(s) accordingly. Places are not required to emit this signal
   * and the Unity shell must assume that they do */
  signal SearchFinished (in u section, in s search, in a{ss} hints)

Results Model

The value defined in PlaceEntryInfo.results_model is the bus name of a Dee.Model that holds the live results to be displayed in the main view. The columns of this model are specific for the renderer_name defined in the RendererInfo struct. The column types for the "UnityDefaultRenderer" is:

  s uri
  s icon_hint
  u group_id
  s mimetype
  s display_name
  s comment

Groups Model

The bus name of the groups model is defined in PlaceEntryInfo.groups_model. This is another Dee.Model. It contains the description on how to render the individual group found in the results model.

The group_id in the results model maps to the row index in the groups model. The columns of the groups model are:

  s group_renderer  (a Unity-specific rendering mode for this group)
  s display_name
  s icon_hint

Sections Model

Yet another Dee.Model which is defined by the name in PlaceEntryInfo.sections_model. This model defines the section headers for the entry displayed just below the places bar.

The row index in the model is used as the section_id - see the PlaceEntry.SetActiveSections method. The default active sections is always section 0.

The model columns are:

  s display_name
  s icon

Activation Hooks

Places can register "activation hooks" for certain types of URIs and/or mimetypes. This is done by defining a [Activation] group in the .place file like:

// normal .place stuff

[Activation]
URIPattern=Regex that URIs must match in order to trigger this activation
MimetypePattern=Regex that mimetypes must match in order to trigger this activation
Priority=0 // G_PRIORITY_{LOW,HIGHT,DEFAULT}

The activation service exposes a com.canonical.Unity.Activation interface on the same bus name and object path as the place service specified in the [Place] group.

com.canonical.Unity.Activation

  /**
   * Try to activate a URI
   * @uri: The URI to activate
   *
   * Returns: 0 if the URI was not activated, 1 if it was activated and dash
   *          should not hide, and 2 if the URI was activated and the dash
   *          should hide
   */
  Activate (in s uri, out u handled)

Browsing. Aka Back/Forward

Browsing buttons can be presented by the Unity rendering shell if the UnityPlaceBrowserPath hint is set on the PlaceEntryInfo struct. The UnityPlaceBrowserPath hint contains the DBus object path for an object in the place daemon implementing the com.canonical.Unity.PlaceBrowser interfafce.

This hint will be set by the model when you activate a folder (which causes the model to browse into that folder) - in which case also the UnitySectionStyle hint will be set to "breadcrumb".

When the place daemon leaves browsing mode, it will often return to some specific section. In order to tell the Unity rendering shell which section to highlight the place daemon sets the hint UnityActiveSection to the id of the active section.

com.canonical.Unity.PlaceBrowser

The browsing is centered around a "states" object represented by a a(bs). The array consists of two states. The 0th state being the "GoBack state" and the 1st being the "GoForward state". The (bs) state struct is interpreted as:

  • b : Whether or not this state is enabled or not. If False this state should be rendered as "disabled". Fx. when there's nothing in your backwards history.

  • s : A string optionally used as a tooltip or comment on what happens if you activate that state. Eg. "Go back to http://youtube.com"

  GoBack (out a(bs) state)
  GoForward (out a(bs) state)
  GetState (out a(bs) state)