source: trunk/third/startup-notification/doc/startup-notification.txt @ 21546

Revision 21546, 14.8 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21545, which included commits to RCS files with non-trunk default branches.
Line 
1Startup notification protocol
2===
3
4This document specifies a mechanism allowing a desktop environment to
5track application startup, to provide user feedback and other
6features.
7
8Version: 0.1
9Revised: October 20, 2002
10Authors: Lubos Lunak, Havoc Pennington
11
12Terms
13===
14
15Launch:   a "startup event" such as opening a new window, opening a new
16          application, or adding a panel applet. Note that the
17          launch may or may not involve creating a new UNIX process.
18Launcher: code which starts up a launch
19Launchee: code which is started up by the launcher
20
21X Messages
22===
23
24"X messages" are a mechanism for sending text strings between X
25clients.
26
27To send a string as an X message, a client does the following:
28
29 - Creates an X window to be used to identify the message
30   uniquely. This window need not be mapped, and may be
31   a child of any window.
32
33 - Interns atoms type_atom and type_atom_begin indicating
34   the type of message.
35
36 - Decides on a target_xwindow; this is the root window
37   for "broadcast" messages, or a specific client's window.
38
39 - Send a series of client messages to the target X window, where each
40   client message contains a portion of the string. The client
41   messages should have the window field set to the X window
42   identifying the message, the format field set to 8, and
43   the message_type field set to the type of message, type_atom_begin
44   for the first client message and type_atom for any following client
45   messages.
46
47   The last byte used in the last client message must be nul, and no
48   intermediate bytes may be nul. The nul byte identifies
49   the end of the message.
50
51   Client messages must be sent to the chosen target_xwindow, with the
52   event mask PropertyChangeMask.
53
54   (FIXME this is a bad choice of mask, as we get a bunch of annoying
55   PropertyNotify events; but which mask would be better?)
56
57   Attachment "A" contains example code.
58
59 - Destroys the unique X window used to identify the message.
60   The window can be destroyed immediately, it is only used
61   for its window ID.
62
63Implementations may impose a maximum length of message they are
64willing to accept. Typically this length will be reasonably low,
65perhaps 4K of data.
66
67Key-value strings
68===
69
70The specific strings sent during startup notification encode a message
71type, followed by a list of key-value pairs. Here is an example:
72
73  new: NAME="Hello World" PID=252
74
75A string listing key-value pairs works as follows:
76
77 - the entire string must be valid UTF-8. Invalid strings should be
78   discarded as corrupt, as accepting bad data leads to
79   interoperability problems. (Learn from web browsers.)
80
81   Although the string is UTF-8, parsing is specified in terms of
82   bytes not characters in the below specification.
83
84 - all bytes up to the first ':' byte indicate the type of the
85   message. If the message contains no ':' byte it should be discarded
86   as corrupt.
87
88 - To find the start of a key, the ':' byte delimiting the message
89   type must be skipped. Any space (' ') bytes following it must also
90   be skipped. (Other kinds of whitespace must not be skipped.)  The
91   first non-' ' byte after the ':' byte is the start of the first
92   key.
93
94 - All bytes until the next '=' byte form the name of the
95   key. The '=' byte should be discarded, as it delimits the
96   key from the value.
97
98 - Parsing of the value begins with the byte immediately following the
99   '=' byte.  The value is parsed
100   as follows.
101
102   There are two dimensions, "escaped" and "quoted", creating 4
103   states:
104
105     - escaped = TRUE quoted = TRUE
106         . the current byte is appended literally, and the escaped
107           flag is set to FALSE
108
109     - escaped = TRUE quoted = FALSE
110         . the current byte is appended literally, and the escaped
111           flag is set to FALSE
112
113     - escaped = FALSE quoted = FALSE
114         . if the current byte is a double quote '"' it is
115           discarded, and the quoted flag is set to TRUE
116         . if the current byte is a backslash '\', it is
117           discarded, and the escaped flag is set to TRUE
118         . if the current byte is a space ' ' byte or nul byte,
119           the end of the value has been reached
120         . any other byte, INCLUDING tabs, newlines, etc., must be
121           appended literally.
122
123     - escaped = FALSE quoted = TRUE:
124         . if the current byte is a double quote '"'
125           it is discarded, and the quoted flag is
126           set to FALSE
127         . if the current byte is a backslash '\'
128           it is discarded, and the escaped flag
129           is set to TRUE
130         . otherwise the current byte is appended literally
131
132   If a nul byte is seen in a state other than escaped = FALSE
133   quoted = FALSE, it is an error, and the message should be discarded
134   as corrupt.
135
136   Note that the escaping here is simpler than either C string literal
137   escaping, or shell quoting. Unlike C string literals, "\n" means
138   "the letter n," not "newline"; unlike quoted shell strings, "\e"
139   means "the letter e," not "backslash followed by the letter e."
140
141   Note that an empty string can be represented by simply not
142   including a value before the first whitespace, as in FOO:
143      FOO= NAME=Hello
144   or by empty quotes as in BAR:
145      BAR="" NAME=Hello
146
147 - Once the end of the value has been reached, any space (' ') bytes
148   should be skipped. The first non-' ' byte is the first byte of the
149   next key.
150
151Note that keys are case-sensitive, Foo and FOO are different keys.
152
153
154Startup notification
155===
156
157The startup notification protocol involves sending X messages with the
158message_type atom _NET_STARTUP_INFO_BEGIN/_NET_STARTUP_INFO to the
159root window.  In multihead setups, the messages should go to the root
160window of the X screen where the launchee application is being
161launched.
162
163As a general convention, any key-value pairs in startup notification
164messages that aren't understood by a given client should be ignored by
165that client. Also, any keys or message types not documented here must
166be prefixed by the two bytes "X-" as in "X-myproperty" or
167"X-mymessage".
168
169All messages in the startup notification protocol refer to a "startup
170sequence"; a "startup sequence" reflects a single launch event.
171
172Here are the message types ("message types" here means the type at the
173beginning of the message string, not the type of the X message):
174 
175  new:    message indicating that a new startup sequence has been
176          initiated. The key-value pairs in this message indicate the
177          properties of the startup sequence. If this startup sequence
178          already exists, "new:" message is equivalent to "change:"
179          (i.e. the values are updated instead of creating a new
180          startup sequence).
181         
182
183  change: message changing a startup sequence. Clients should update
184          information about the matching startup sequence to the newly
185          provides information. "change" messages contain
186          a subset of the keys allowed in a "new" message. Not all
187          attributes of the startup sequence are allowed to change
188          over time.
189         
190          "change:" messages not be taken as a "new:" message,
191          i.e. they should not cause any feedback or similar.
192         
193          If a client has not seen a "new:" message for the same sequence,
194          then it should remember the information for later use in case
195          a "new:" message comes later. "change:" messages without
196          a following "new:" message can be discarded after a reasonable
197          timeout (>= 1 minute). Rationale: The application
198          may want to send certain information like timestamp or description
199          first, before handling control to library code deciding
200          if there should be actually any feedback for the launch.
201
202
203  remove: message ending a startup sequence. Once this message
204          has been seen for a given sequence, any further
205          messages referring to the sequence should be ignored.
206         
207All messages must include these keys:
208
209  ID
210 
211          uniquely identifies a startup sequence; should be some globally
212          unique string (for example, hostname+pid+"_TIME"+current time).
213          The string should be in the form of <unique>_TIME<timestamp>,
214          where the timestamp is the X server timestamp of the user
215          action that caused the launch. See the TIMESTAMP key
216          for details.
217
218The following keys are required in a "new" message and may be included
219in either a "new" or a "changed" message:
220
221  NAME   
222
223          some human-readable name of the item being started;
224          for example, "Control Center" or "Untitled Document";
225          this name should be localized.
226
227  SCREEN
228
229          the X screen number the startup sequence is on
230
231The following keys may be provided optionally in either a "new" or a
232"changed" message:
233
234  BIN     
235         
236          name of the executable being started, argv[0]
237         
238  ICON   
239 
240          a string to be interpreted exactly as the "Icon" field
241          in desktop entries is interpreted.
242
243  DESKTOP
244
245          the desktop on which the application should appear,
246          counting from 0, as in _NET_WM_DESKTOP. However,
247          this value should never override a _NET_WM_DESKTOP
248          property set on window that's being mapped.
249          This desktop is relative to the screen provided by
250          the SCREEN key.
251
252  TIMESTAMP
253
254          X server timestamp of the user action that caused this
255          launch. For example window manager that doesn't allow
256          stealing of focus by newly mapped windows while the user
257          works in an application can use this timestamp for windows
258          that have matching _NET_STARTUP_ID property if they don't
259          have any _NET_WM_USER_TIME property set or if it's older.
260          See the description of _NET_WM_USER_TIME in the WM spec
261          for details.
262         
263          This key is obsoleted by including the timestamp directly
264          in the ID field.
265
266  DESCRIPTION   
267
268          a short description suitable for display in a dialog that
269          indicates what's happening. For example "Opening document
270          Foo" or "Launching KWord" - the description should be in
271          "foo-ing whatever" format, describing the current status.
272
273  WMCLASS
274
275          a string to match against the "resource name" or "resource
276          class" hints. If this key is present, the launchee will most
277          likely not send a "remove" message on its own. If the
278          desktop environment detects a toplevel window mapped with
279          this name or class, it should send a "remove" message for
280          the startup sequence. Note that the class hint is in
281          Latin-1, so the value of this key must be converted to
282          Latin-1 before strcmp'ing it with the window class/name.
283          (Though in all known cases only ASCII is involved so it
284          doesn't matter.)
285         
286  SILENT
287         
288          a boolean (1/0) value. When set to 1, there should be
289          no visual feedback. This can be used to suspend
290          the visual feedback temporarily, e.g. when
291          application shows a dialog during its startup before
292          mapping the main window. Another use is for launch
293          sequences for applications that are neither compliant
294          nor their WMClass is known, but which should preferably
295          have their window mapped on the desktop specified by
296          the value of DESKTOP.
297
298Some details of the startup sequence:
299
300 - "new" and "change" messages are sent by the launcher code
301
302 - the launchee code is responsible for sending a "remove"
303   message to end the launch sequence, unless the WMCLASS
304   key was set.
305
306 - the "new" message must be the first message. Other message
307   types should be ignored by all clients unless those clients
308   have seen a "new" message with the same ID.
309
310 - "change" messages can be sent at any time between "new" and
311   "remove"
312
313 
314Communicating from a launcher process to a launchee process
315===
316
317To communicate the startup sequence information from a launcher
318process to a launchee process, when possible an environment variable
319should be used:
320
321 DESKTOP_STARTUP_ID
322   value of the "ID" field in the "new" message
323
324It is suggested to unset this environment variable in the launchee
325as soon as it's read, to avoid possible reuse by some process started
326later by launchee.
327Mechanisms other than the environment variable may be used as well, as
328long as they are reliable. The environment variable is only used when
329the launchee code is in a process started by the launcher code; if
330they are in the same process the environment variable may not be
331relevant.
332
333Desktop entry spec extensions
334===
335
336StartupNotify=BOOLEAN
337
338  If true, it is KNOWN that the application will send a "remove"
339  message when started with the DESKTOP_LAUNCH_ID environment variable
340  set.
341
342StartupWMClass=STRING
343
344  If true, it is KNOWN that the application will map at least one
345  window with the given string as its WM class or WM name hint.
346
347EWMH spec extensions
348===
349
350_NET_STARTUP_ID, UTF8_STRING
351
352  The ID used for the startup sequence for the window. If set
353  on a group leader window, applies to all application windows
354  in that group that do not set their own _NET_STARTUP_ID.
355
356
357Launchee failures
358===
359
360The launcher process is responsible for detecting launchee failures
361such as a crash and should end the launch sequence in such case.
362In case launchee fails to end the launch sequence, clients should
363treat the launch sequence as ended withing a reasonable time.
364
365
366A. Sample code to send X message
367===
368
369This code omits creation/destruction of "xwindow" which is the unique
370identifier window for the message. It should be created just before
371this code and destroyed just after.
372   
373       XEvent xevent;
374       const char *src;
375       const char *src_end;
376       char *dest;
377       char *dest_end;
378
379       xevent.xclient.type = ClientMessage;
380       xevent.xclient.message_type = type_atom_begin;
381       xevent.xclient.display = xdisplay;
382       xevent.xclient.window = xwindow;
383       xevent.xclient.format = 8;
384
385       src = message;
386       src_end = message + strlen (message) + 1; /* +1 to include nul byte */
387
388       while (src != src_end)
389         {
390           dest = &xevent.xclient.data.b[0];
391           dest_end = dest + 20;
392
393           if (src == message)
394             {
395               *dest = '\0';
396               ++dest;
397             }
398
399           while (dest != dest_end &&
400                  src != src_end)
401             {
402               *dest = *src;
403               ++dest;
404               ++src;
405             }
406
407           XSendEvent (xdisplay,
408                       target_xwindow,
409                       False,
410                       PropertyChangeMask,
411                       xevent);
412
413           xevent.xclient.message_type = type_atom_begin;
414         }
415
416Change history
417===
418
419Changes since 0.1:
420
421- TIMESTAMP field is obsoleted by including the timestamp directly in the ID.
422- data from "change:" messages should be used even if they precede the matching "new:" message
Note: See TracBrowser for help on using the repository browser.