diff options
author | Matthias Klumpp <matthias@tenstral.net> | 2024-07-12 03:38:12 +0200 |
---|---|---|
committer | Matthias Klumpp <matthias@tenstral.net> | 2024-07-12 03:38:12 +0200 |
commit | 5a8a5326ffbba993f0456ec9e25a9589b81b0774 (patch) | |
tree | 6771a9cebdf10a5e70a15246b7a0f3a93cfaffa6 | |
parent | 07237ff25d6171e1b548118442ddba4259a53ba5 (diff) |
Add 0.1 spec wrapped in DocBook XML
-rw-r--r-- | doc/startup-notification.xml | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/doc/startup-notification.xml b/doc/startup-notification.xml new file mode 100644 index 0000000..e81fd05 --- /dev/null +++ b/doc/startup-notification.xml @@ -0,0 +1,426 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE article> +<article + xmlns="http://docbook.org/ns/docbook" version="5.0" + xmlns:xlink="http://www.w3.org/1999/xlink" + lang="en"> + <info> + <title>Startup notification protocol</title> + + <releaseinfo>0.1</releaseinfo> + <pubdate>2002-10-20</pubdate> + + <authorgroup> + <author> + <firstname>Lubos</firstname> + <surname>Lunak</surname> + <affiliation> + <address> + <email>l.lunak@suse.cz</email> + </address> + </affiliation> + </author> + <author> + <firstname>Havoc</firstname> + <surname>Pennington</surname> + <affiliation> + <address> + <email>hp@redhat.com</email> + </address> + </affiliation> + </author> + </authorgroup> + </info> + <para> + This document specifies a mechanism allowing a desktop environment to + track application startup, to provide user feedback and other + features. + </para> + + <literallayout><![CDATA[Terms +=== + +Launch: a "startup event" such as opening a new window, opening a new + application, or adding a panel applet. Note that the + launch may or may not involve creating a new UNIX process. +Launcher: code which starts up a launch +Launchee: code which is started up by the launcher + +X Messages +=== + +"X messages" are a mechanism for sending text strings between X +clients. + +To send a string as an X message, a client does the following: + + - Creates an X window to be used to identify the message + uniquely. This window need not be mapped, and may be + a child of any window. + + - Interns atoms type_atom and type_atom_begin indicating + the type of message. + + - Decides on a target_xwindow; this is the root window + for "broadcast" messages, or a specific client's window. + + - Send a series of client messages to the target X window, where each + client message contains a portion of the string. The client + messages should have the window field set to the X window + identifying the message, the format field set to 8, and + the message_type field set to the type of message, type_atom_begin + for the first client message and type_atom for any following client + messages. + + The last byte used in the last client message must be nul, and no + intermediate bytes may be nul. The nul byte identifies + the end of the message. + + Client messages must be sent to the chosen target_xwindow, with the + event mask PropertyChangeMask. + + (FIXME this is a bad choice of mask, as we get a bunch of annoying + PropertyNotify events; but which mask would be better?) + + Attachment "A" contains example code. + + - Destroys the unique X window used to identify the message. + The window can be destroyed immediately, it is only used + for its window ID. + +Implementations may impose a maximum length of message they are +willing to accept. Typically this length will be reasonably low, +perhaps 4K of data. + +Key-value strings +=== + +The specific strings sent during startup notification encode a message +type, followed by a list of key-value pairs. Here is an example: + + new: NAME="Hello World" PID=252 + +A string listing key-value pairs works as follows: + + - the entire string must be valid UTF-8. Invalid strings should be + discarded as corrupt, as accepting bad data leads to + interoperability problems. (Learn from web browsers.) + + Although the string is UTF-8, parsing is specified in terms of + bytes not characters in the below specification. + + - all bytes up to the first ':' byte indicate the type of the + message. If the message contains no ':' byte it should be discarded + as corrupt. + + - To find the start of a key, the ':' byte delimiting the message + type must be skipped. Any space (' ') bytes following it must also + be skipped. (Other kinds of whitespace must not be skipped.) The + first non-' ' byte after the ':' byte is the start of the first + key. + + - All bytes until the next '=' byte form the name of the + key. The '=' byte should be discarded, as it delimits the + key from the value. + + - Parsing of the value begins with the byte immediately following the + '=' byte. The value is parsed + as follows. + + There are two dimensions, "escaped" and "quoted", creating 4 + states: + + - escaped = TRUE quoted = TRUE + . the current byte is appended literally, and the escaped + flag is set to FALSE + + - escaped = TRUE quoted = FALSE + . the current byte is appended literally, and the escaped + flag is set to FALSE + + - escaped = FALSE quoted = FALSE + . if the current byte is a double quote '"' it is + discarded, and the quoted flag is set to TRUE + . if the current byte is a backslash '\', it is + discarded, and the escaped flag is set to TRUE + . if the current byte is a space ' ' byte or nul byte, + the end of the value has been reached + . any other byte, INCLUDING tabs, newlines, etc., must be + appended literally. + + - escaped = FALSE quoted = TRUE: + . if the current byte is a double quote '"' + it is discarded, and the quoted flag is + set to FALSE + . if the current byte is a backslash '\' + it is discarded, and the escaped flag + is set to TRUE + . otherwise the current byte is appended literally + + If a nul byte is seen in a state other than escaped = FALSE + quoted = FALSE, it is an error, and the message should be discarded + as corrupt. + + Note that the escaping here is simpler than either C string literal + escaping, or shell quoting. Unlike C string literals, "\n" means + "the letter n," not "newline"; unlike quoted shell strings, "\e" + means "the letter e," not "backslash followed by the letter e." + + Note that an empty string can be represented by simply not + including a value before the first whitespace, as in FOO: + FOO= NAME=Hello + or by empty quotes as in BAR: + BAR="" NAME=Hello + + - Once the end of the value has been reached, any space (' ') bytes + should be skipped. The first non-' ' byte is the first byte of the + next key. + +Note that keys are case-sensitive, Foo and FOO are different keys. + + +Startup notification +=== + +The startup notification protocol involves sending X messages with the +message_type atom _NET_STARTUP_INFO_BEGIN/_NET_STARTUP_INFO to the +root window. In multihead setups, the messages should go to the root +window of the X screen where the launchee application is being +launched. + +As a general convention, any key-value pairs in startup notification +messages that aren't understood by a given client should be ignored by +that client. Also, any keys or message types not documented here must +be prefixed by the two bytes "X-" as in "X-myproperty" or +"X-mymessage". + +All messages in the startup notification protocol refer to a "startup +sequence"; a "startup sequence" reflects a single launch event. + +Here are the message types ("message types" here means the type at the +beginning of the message string, not the type of the X message): + + new: message indicating that a new startup sequence has been + initiated. The key-value pairs in this message indicate the + properties of the startup sequence. If this startup sequence + already exists, "new:" message is equivalent to "change:" + (i.e. the values are updated instead of creating a new + startup sequence). + + + change: message updating an existing startup sequence. If a client + has not seen a "new:" message for the same sequence, then + all "change:" messages should be ignored. i.e. a "change:" + message should not be taken as a "new:" message. + + "change" messages contain a subset of the keys allowed + in a "new" message. Not all attributes of the startup + sequence are allowed to change over time. + + remove: message ending a startup sequence. Once this message + has been seen for a given sequence, any further + messages referring to the sequence should be ignored. + +All messages must include these keys: + + ID + + uniquely identifies a startup sequence; should be some globally + unique string (for example, hostname+pid+current time). + +The following keys are required in a "new" message and may be included +in either a "new" or a "changed" message: + + NAME + + some human-readable name of the item being started; + for example, "Control Center" or "Untitled Document"; + this name should be localized. + + SCREEN + + the X screen number the startup sequence is on + +The following keys may be provided optionally in either a "new" or a +"changed" message: + + BIN + + name of the executable being started, argv[0] + + ICON + + a string to be interpreted exactly as the "Icon" field + in desktop entries is interpreted. + + DESKTOP + + the desktop on which the application should appear, + counting from 0, as in _NET_WM_DESKTOP. However, + this value should never override a _NET_WM_DESKTOP + property set on window that's being mapped. + This desktop is relative to the screen provided by + the SCREEN key. + + TIMESTAMP + + X server timestamp of the user action that caused this + launch. For example window manager that doesn't allow + stealing of focus by newly mapped windows while the user + works in an application can use this timestamp for windows + that have matching _NET_STARTUP_ID property if they don't + have any _NET_WM_USER_TIME property set or if it's older. + See the description of _NET_WM_USER_TIME in the WM spec + for details. + + DESCRIPTION + + a short description suitable for display in a dialog that + indicates what's happening. For example "Opening document + Foo" or "Launching KWord" - the description should be in + "foo-ing whatever" format, describing the current status. + + WMCLASS + + a string to match against the "resource name" or "resource + class" hints. If this key is present, the launchee will most + likely not send a "remove" message on its own. If the + desktop environment detects a toplevel window mapped with + this name or class, it should send a "remove" message for + the startup sequence. Note that the class hint is in + Latin-1, so the value of this key must be converted to + Latin-1 before strcmp'ing it with the window class/name. + (Though in all known cases only ASCII is involved so it + doesn't matter.) + + SILENT + + a boolean (1/0) value. When set to 1, there should be + no visual feedback. This can be used to suspend + the visual feedback temporarily, e.g. when + application shows a dialog during its startup before + mapping the main window. Another use is for launch + sequences for applications that are neither compliant + nor their WMClass is known, but which should preferably + have their window mapped on the desktop specified by + the value of DESKTOP. + +Some details of the startup sequence: + + - "new" and "change" messages are sent by the launcher code + + - the launchee code is responsible for sending a "remove" + message to end the launch sequence, unless the WMCLASS + key was set. + + - the "new" message must be the first message. Other message + types should be ignored by all clients unless those clients + have seen a "new" message with the same ID. + + - "change" messages can be sent at any time between "new" and + "remove" + + +Communicating from a launcher process to a launchee process +=== + +To communicate the startup sequence information from a launcher +process to a launchee process, when possible an environment variable +should be used: + + DESKTOP_STARTUP_ID + value of the "ID" field in the "new" message + +It is suggested to unset this environment variable in the launchee +as soon as it's read, to avoid possible reuse by some process started +later by launchee. +Mechanisms other than the environment variable may be used as well, as +long as they are reliable. The environment variable is only used when +the launchee code is in a process started by the launcher code; if +they are in the same process the environment variable may not be +relevant. + +Desktop entry spec extensions +=== + +StartupNotify=BOOLEAN + + If true, it is KNOWN that the application will send a "remove" + message when started with the DESKTOP_LAUNCH_ID environment variable + set. + +StartupWMClass=STRING + + If true, it is KNOWN that the application will map at least one + window with the given string as its WM class or WM name hint. + +EWMH spec extensions +=== + +_NET_STARTUP_ID, UTF8_STRING + + The ID used for the startup sequence for the window. If set + on a group leader window, applies to all application windows + in that group that do not set their own _NET_STARTUP_ID. + + +Launchee failures +=== + +The launcher process is responsible for detecting launchee failures +such as a crash and should end the launch sequence in such case. +In case launchee fails to end the launch sequence, clients should +treat the launch sequence as ended withing a reasonable time. + + +A. Sample code to send X message +=== + +This code omits creation/destruction of "xwindow" which is the unique +identifier window for the message. It should be created just before +this code and destroyed just after. + + XEvent xevent; + const char *src; + const char *src_end; + char *dest; + char *dest_end; + + xevent.xclient.type = ClientMessage; + xevent.xclient.message_type = type_atom_begin; + xevent.xclient.display = xdisplay; + xevent.xclient.window = xwindow; + xevent.xclient.format = 8; + + src = message; + src_end = message + strlen (message) + 1; /* +1 to include nul byte */ + + while (src != src_end) + { + dest = &xevent.xclient.data.b[0]; + dest_end = dest + 20; + + if (src == message) + { + *dest = '\0'; + ++dest; + } + + while (dest != dest_end && + src != src_end) + { + *dest = *src; + ++dest; + ++src; + } + + XSendEvent (xdisplay, + target_xwindow, + False, + PropertyChangeMask, + xevent); + + xevent.xclient.message_type = type_atom_begin; + }]]></literallayout> + +</article> |