launch notification



Hi,

I typed this in a couple months ago; I was going to try implementing
it before posting, but since that doesn't seem to be happening
quickly, I'm posting it before I lose it in the depths of my home
directory. ;-) I have some comments/revisions of my own in mind
already, but no time to deal with it right now.

Havoc

Informal draft writeup of how to handle application launching in the X
environment. Needs conversion into an actual spec.

Executive summary of end-user benefits
===

 - allow busy cursor launch feedback mode
 - allow launch feedback mode where you put an animation 
   over the icon they clicked to cause the launch
 - allow cancellation of a launch-in-progress
 - allow WindowMaker-style (single-instance) launch buttons to work nicely
 - allow task lists to display the currently-in-progress launches
 - allow choice of which program displays the launch feedback
 - avoid ending up with two conflicting launch feedbacks at once (e.g.
   two different animations on the launcher icon)
 - allow launch feedback for launches inside a single process
   (for example opening a file manager window by clicking
   on a directory icon)
 - generic spec works across desktops

Design Goals
===

 - as close to 100% reliable operation as possible. 
   "If everything implements the spec properly, then everything 
    will work properly."

 - have a single program provide launch indication for the whole
   desktop, regardless of who is launching it; this provides
   consistency

 - easy to support correctly in applications, so we can 
   add native support to all toolkits and legacy apps
   (complexity burden placed on desktop components rather
   than individual apps)

 - ensure we have a path away from LD_PRELOAD hacks and such - i.e., a
   way to avoid such hacks for apps that support the protocol
   natively, so that once most apps support it natively, we can drop
   the hacks
 
 - allow apps to control the indicator; for example, an app may want 
   to map a window of some kind without removing the indicator, 
   or remove the indicator before mapping a window.

 - allow the window manager to keep track of when apps are launched
   and which windows belong to a given launch attempt - this allows
   the WM to for example put an app on the workspace which was active 
   at launch time

 - allow the WM to be notified when an app has reached its final
   start-up state. For example, if a word processor launches a splash
   screen, then the main window, then both the splash screen and the
   main window could be placed on the workspace which was active at
   launch-time. However, this needs to happen without forcing all
   windows from that app to always be on the launch workspace. So the WM
   needs to know when an app's windows should no longer be treated in
   a special way.
 
 - allow a similar feedback mechanism and WM special-casing for 
   opening new windows within an application. For example, when
   opening a new word processor window, it might be nice to 
   keep it on the workspace where "New" was selected from the menu.
   (Of course it would be nicer if opening a new window were fast, 
   but for some apps that may not always be true. Consider 
   opening a large document, for example.)

 - allow indication that is sensitive to where and how the 
   launching occurred; for example a sparkle at the launch point.
   This should work even if the launch point is inside a 
   user-reconfigurable window.

 - allow apps to open new windows, or just plain start up, without
   progress indication. This would normally be done for programs that
   users may not think of as apps; say a panel applet. The main point
   here is that toolkits should be able to provide API to control the
   launch feedback, and the spec has to allow toolkits to implement
   that

 - allow the user to cancel a launch-in-progress, for example if the
   progress indicator is a dialog, they could press the Stop button; 
   if it's a busy cursor, the window manager might provide a keybinding.

Proposed solution overview
===

There is a single "launch manager" active per-screen at any given
time. The launch manager may be the window manager, or it may be a
separate process. A launch manager displays the primary user feedback
for a "launch sequence."  A launch sequence typically begins when the
user asks to launch an application or open a new document, and ends
when the app or document finishes loading.

Each launch sequence is identified by a unique ID. The launching
program initially notifies the launch manager that a launch ID exists
and gives the launch manager pertinent information about how to
display progress. Subsequent information about the status of the
launch is provided to the launch manager as appropriate, by the
launching program and also the launched application.

Launch Manager
===

The launch manager owns a manager selection (see ICCCM 2.8) on each
screen that it manages. The name of the selection is
_NET_LAUNCH_MANAGER. 

The launch manager and the window manager may be the same process.
However, window managers that do this are encouraged to have a mode
where they allow a separate process to own the _NET_LAUNCH_MANAGER
selection and handle launch management.

Only one launch manager runs at a time, because the launch manager is
primarily responsible for providing launch feedback. If a given 
type of feedback would break down if two applications implemented it
simultaneously, then that type of feedback must be provided 
by the launch manager.

For example, only one application can set the mouse cursor; only one
application can display an animation over the launcher icon.  On the
other hand, two task lists or task menus could each display a task
button for launches-in-progress.

If a launch manager gives up the _NET_LAUNCH_MANAGER selection, it
should finish managing active launch sequences. The new launch manager
should not try to manage launch sequences that predate it.

_NET_LAUNCH_MANAGER must support the following targets:

  NAME    UTF8_STRING

   The name of the launch manager

Launch Sequence
===

A launch sequence is an instance of launching something. For example,
running a program or opening a new window. Each launch sequence
involves a launcher (the program doing the launching) and a launchee
(whatever is being launched). 

Launch sequences are identified by a launch sequence ID. The launch
sequence ID is a string, generated as follows:

  LAUNCHER/LAUNCHEE/XTIMESTAMP/UNIQUENESS

The elements are:

 - name of launcher; no rigorous semantics
 - name of launchee; no rigorous semantics; can be same as launcher
 - X server timestamp from the event causing the launch (or last event
   received by the launcher) - obviously, do not use CurrentTime
 - a uniqueness string; launchers should use this to ensure the
   launch sequence ID is unique if they launch two or more copies
   of the same application at the same time

The launcher/launchee names "namespace" the subsequent fields, and are
intended to be helpful when debugging. The X timestamp makes it very
likely that the launch ID is unique across the X display. The
uniqueness string ensures uniqueness for sequences from a given
launcher process.

It is remotely possible that two launcher process have the same name,
launch the same program, at the same time, and with the same
uniqueness string. Launchers are encouraged to use something other
than a monotonically increasing serial number for the uniqueness
string, as an extra safety net. For example, they might include their
process ID or some random digits.

The launch sequence ID should be a valid UTF-8 string.

The elements of the sequence ID may not contain the '/' separator
character, since that would render the ID unparseable. That said, no
application should rely on parsing the sequence ID; its format is only
specified as a debugging aid, and to ensure that IDs are unique.

An example sequence ID is:
 gnome-panel/kword/54193275/xw45c2z-342

Launch Sequence Window
===

Each launch sequence has a number of attributes that need to be
communicated between the launcher program, the launch manager, and the 
program being launched. The easiest way to share a hash table between 
X clients is to use an X window.

Each launch sequence thus has a corresponding X window, created by the
launcher program, where launch sequence properties can be set
and launch-related messages can be sent.

The launch sequence window must be an immediate child of the root
window.

The following property MUST be set on this window before initiating
a launch:

 - _NET_LAUNCH_ID  UTF8_STRING

   The launch sequence ID

The following properties are optional, but if set must be set before
initiating the launch, and unless otherwise noted should be left
unchanged throughout the launch sequence:

 - _NET_LAUNCHER_TYPE CARDINAL/32

   An integer indicating the context of the launch:

     #define _NET_LAUNCHER_TYPE_OTHER        0
     #define _NET_LAUNCHER_TYPE_DOCK_ICON    1
     #define _NET_LAUNCHER_TYPE_DESKTOP_ICON 2
     #define _NET_LAUNCHER_TYPE_MENU         3
     #define _NET_LAUNCHER_TYPE_KEY_SHORTCUT 4

   If the property is unset, OTHER should be assumed.

   Rationale: the launch manager may choose to special-case some of
   these. For example, you can't display an animation over the top of
   a menu or key shortcut, but you can over a desktop or dock icon.

 - _NET_LAUNCHER_GEOMETRY CARDINAL[4]/32

   x, y, width, height geometry of the icon the user 
   clicked to begin the launch. The coordinates 
   are relative to _NET_LAUNCH_GEOMETRY_WINDOW if 
   that property is set, otherwise to the root window.

   This property may be updated during the launch sequence, 
   to reflect e.g. moving the launch icon.

 - _NET_LAUNCH_GEOMETRY_WINDOW WINDOW/32

   Window that _NET_LAUNCHER_GEOMETRY is relative to.

   If this window is not the root window, the launch manager
   should track movement of the window around the screen.
   That is, if displaying an animation on the launch icon, 
   if the user moves the window containing the launch icon, 
   the animation should also move.

 - _NET_LAUNCHER_SUPPORTS_CANCEL CARDINAL/32

   Contains 1 if the launcher supports cancelling this 
   launch sequence, 0 if not. If the property is unset, 
   0 should be assumed. Cancelling a launch sequence 
   means ending the operation that in progress, for example
   killing the application being launched.

 - _NET_LAUNCH_TYPE CARDINAL/32

    An integer indicating the sort of thing being launched:

     #define _NET_LAUNCHER_TYPE_OTHER       0
     #define _NET_LAUNCHER_TYPE_APPLICATION 1
     #define _NET_LAUNCHER_TYPE_DOCUMENT    2

    If unset, OTHER should be assumed. OTHER most likely results in a
    suboptimal user interface, so launchers are encouraged to set this
    property if one of the standard types makes sense.

    Rationale: when displaying launch progress, the launch manager may
    need to use this information. For example, it may want to say
    "Opening document Foo..." for documents and "Launching Foo..." for
    applications, in a progress dialog.

 - _NET_LAUNCH_NAME UTF8_STRING

   The user-visible name of the launch sequence; normally the name of
   the application being launched, or the name of the document being
   loaded. _NET_LAUNCH_TYPE aids the launch manager in interpreting
   this name.

 - _NET_LAUNCH_DESKTOP CARDINAL/32

   The active workspace from the _NET_CURRENT_DESKTOP property (see
   extended window manager hints specification).  

   Implementation note: to set this hint without races, the launcher
   program would have to track _NET_CURRENT_DESKTOP by selecting for
   property notifies, and use the most-recently-notified value when
   creating the launch sequence window. However, having lots of apps  
   select for PropertyNotify on the root window is probably bad.
   Instead, it seems reasonable to accept the race; users who want to 
   be sure the app comes up on the right workspace can wait for the 
   launch feedback indicator to appear before switching workspaces, 
   if they do that then things will always work.

 - _NET_LAUNCH_LEGACY_RESOURCE_CLASS STRING

        A class (as for the first part of the WM_CLASS hint).

   _NET_LAUNCH_LEGACY_RESOURCE_NAME STRING

        A name (as for the second part of the WM_CLASS hint).

   _NET_LAUNCH_LEGACY_NAME  STRING

        A window title (as for WM_NAME)    

   If one or more of these three properties are set, then the launchee
   is a legacy X client. If they are set, the following must be known
   to the launcher via some reliable mechanism:

    - the legacy X client will create at least one new toplevel
      managed window
    - the toplevel managed window it creates will have the 
      given class/name/title
    - the legacy X client does not support this specification

   If one of these properties is set, then the launch manager is
   responsible for completing the launch sequence by setting
   _NET_LAUNCH_COMPLETE when the legacy launchee maps a toplevel X
   window that matches the given resource class, name, and title. If
   multiple properties are set, they must all be matched; that is, if
   both a legacy class and a legacy title are given, then the launch
   sequence ends only after mapping a window matching both the class
   and the title.

The following property may be set at any time by any client:

 - _NET_LAUNCH_CANCELLED CARDINAL/32

   The value of this property is irrelevant; if the property exists,
   the user has asked to cancel the launch. This property may be
   set by any X client in response to user input.

   If the launcher program set _NET_LAUNCHER_SUPPORTS_CANCEL, then 
   it should listen for PropertyNotify on this property, and cancel
   the launch if a PropertyNotify is received.

   If the launcher program did not set _NET_LAUNCHER_SUPPORTS_CANCEL,
   it may ignore _NET_LAUNCH_CANCELLED

   The launch manager should not end launch feedback when
   _NET_LAUNCH_CANCELLED is set; instead, it should wait for the 
   cancellation to take effect.

The following property may be set by the launchee to indicate that
it's displaying launch progress to the user:

 - _NET_LAUNCH_PULSE CARDINAL/32

   The value of this property is irrelevant. If set, then the launchee
   is making progress on starting up.  Launchees are encouraged to
   re-set _NET_LAUNCH_PULSE at regular intervals, indicating that
   progress continues. This property should be set before showing a
   splash screen, for example. See implementation notes for more
   details.

   The purpose of this property is to allow the launch manager to 
   feel confident that the application is moving forward, and avoid 
   e.g. putting up a "the launchee appears to be stopped" dialog 
   on top of the launchee's splash screen.

The following property should be set by the launchee once it considers
itself fully started up, or by the launcher after cancellation:

 - _NET_LAUNCH_COMPLETE CARDINAL/32

   The launchee program should set this property on the launch 
   window when the launch sequence is complete. The launchee should 
   map all windows that are part of an application's initial 
   state BEFORE it sets this property. After launching is complete, 
   window managers will not place newly-mapped windows on the 
   launch workspace.

   The launcher program should set this property on the launch 
   window after cancelling the launch.

   Launch feedback should be ended if _NET_LAUNCH_COMPLETE has been
   set.

   The launcher program must destroy the launch sequence window 
   after this property is set.

Launch initiation
===

Before initiating a launch, the launcher program should create a 
launch sequence window and set its initial properties.
Then, it should send a client message to the root window
as follows:

 _NET_INITIATE_LAUNCH
   window = launch sequence window
   message_type = _NET_INITIATE_LAUNCH 
   format = 32
   data.l[0] = timestamp; /* X timestamp of event (mouse click, etc.) causing
                           * launch, or CurrentTime if unavailable
                           */
   data.l[1] = 0;         /* reserved, always set to 0 */


Launch termination, launch sequence window destruction
===
   
If a PropertyNotify for _NET_LAUNCH_COMPLETE is received on the launch
sequence window, then launching is complete. Launching is considered
to have ended at the time in the PropertyNotify event.

The launch sequence window may be destroyed at any time, either on
purpose by the launcher application, or because the launcher
application crashes. Clients monitoring a launch sequence should take
this into account.

 - When reading the initial values from the launch sequence window, 
   a BadWindow error indicates that the window was already destroyed.
   In this case, the launch sequence should be ignored. Launch 
   feedback should only be initiated if all the initial properties
   of the launch sequence window are read successfully.

 - Once launch feedback has been initiated, a DestroyNotify on the
   launch sequence window indicates that the launch sequence is
   complete. However, normally a PropertyNotify from
   _NET_LAUNCH_COMPLETE will have been received before the window was
   destroyed. Because DestroyNotify events have no timestamp, the time
   of completion should be taken from the PropertyNotify on
   _NET_LAUNCH_COMPLETE. If _NET_LAUNCH_COMPLETE was never set, the 
   time of completion is unknown.

Launch cancellation
===

If _NET_LAUNCH_CANCELLED is set, then the launcher program should
stop launching whatever was being launched, then set
_NET_LAUNCH_COMPLETE, then destroy the launch sequence window.

Communicating from a launcher process to a launchee process
===

To communicate the launch sequence information from a launcher process
to a launchee process, when possible two environment variables should 
be used:

 DESKTOP_LAUNCH_ID
   Launch sequence ID
 DESKTOP_LAUNCH_WINDOW
   Launch sequence window ID in hex format, e.g. "0x1a0000d"

Launchees don't actually need to know their launch sequence ID to
implement this specification, because their only real responsibility
is to set _NET_LAUNCH_COMPLETE on the launch sequence window.  However
the launch ID may be useful in debugging or for future extensions.

Mechanisms other than the environment variable may be used in some
cases.  Keep in mind that launcher and launchee are allowed to be in
the same process, for example when opening a document from the File
menu in an application.

Desktop entry extensions
===

[These should be included in the desktop entry spec, not in the
 launcher spec]

To share information about launchee applications between desktops, the 
following fields are supported in .desktop files:
 
  LaunchFeedbackSupported  boolean

    If not present, assumed to be FALSE. If present and TRUE, the
    to-be-launched app supports this specification and can be expected
    to set _NET_LAUNCH_COMPLETE on the window specified in the
    DESKTOP_LAUNCH_WINDOW environment variable.

  LaunchLegacyClass  string

    If present, specifies a class for
    _NET_LAUNCH_LEGACY_RESOURCE_CLASS and that property should be 
    set by the launcher.

  LaunchLegacyName   string

    If present, specifies a resource name for
    _NET_LAUNCH_LEGACY_RESOURCE_NAME and that property should be set
    by the launcher.

  LaunchLegacyTitle  string

    If present, specifies a title for _NET_LAUNCH_LEGACY_NAME
    and that property should be set by the launcher.

FIXME The three LaunchLegacy properties are in UTF-8 encoding in the
.desktop file, but have type STRING in X. What do we do about that?

The LaunchLegacy properties are mutually exclusive with
LaunchFeedbackSupported=1. If a .desktop file claims that launch
feedback is supported, and also gives the legacy fields, then 
the legacy fields should be used and the launcher should assume that
launch feedback is not supported.

Implementation Notes
===

The launch feedback provided by the launch manager should be something
relatively unobtrusive; examples are changing the cursor, or a small
animation at the launcher icon.

Progress dialogs or splash screens should be provided by the launchee
application, rather than by the launch manager.

The launchee application should complete the launch sequence after it
has its first user-interaction-allowing window onscreen. (That is,
a splash screen should not end the launch sequence, but a dialog or
main window should.)

One possible solution to the "stuck cursor" problem seen with
current launch feedback solutions:

 After a timeout, the launch manager might replace the unobtrusive
 feedback (cursor, etc.) with a dialog that has a Stop button; when
 clicked, the Stop button sets _NET_LAUNCH_CANCELLED if
 _NET_LAUNCHER_SUPPORTS_CANCEL, and otherwise simply sets
 _NET_LAUNCH_COMPLETE to give up on the whole launch feedback thing.

 If a launch manager did something like this, the dialog should be
 avoided if _NET_LAUNCH_PULSE has been set on the launch sequence
 window recently. _NET_LAUNCH_PULSE indicates that the launchee is
 moving forward and perhaps displaying a splash screen already.

Launchers should attempt to detect launchee failures and end the
launch sequence if appropriate; for example, if a launched application
exits with a nonzero exit code, it would be a good idea to set
_NET_LAUNCH_COMPLETE and end launch feedback. The launcher is
responsible for displaying an error dialog to the user in this case.

Launchers should not however end feedback if a launched process exits
normally, because the process may have been a wrapper script, may have
asked an already-open application to create a new window, etc.

Only the launch manager should "time out" a launchee and decide to end
launch feedback; the launcher application should never do this, it
should only end the launch sequence if it has a good reason to believe
the launchee crashed.

Task lists are encouraged to provide a button for each launch
sequence, and support launch cancellation from this button. This
allows users to get rid of the busy cursor if it's stuck.
Alternatively, a task list integrated with the launch manager could
for example pop up the aforementioned dialog-with-stop-button 
if you clicked on the button for the launch sequence.

If displaying an animated busy cursor, the launch manager should
"spin" the cursor when _NET_LAUNCH_PULSE is updated. Launchees are
encouraged to update _NET_LAUNCH_PULSE in tune with their own splash
screen progress bar or the like.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]