summaryrefslogtreecommitdiffstats
path: root/systemtray/systemtray-spec.xml
blob: 4b97b1e79f587dd2d8ad9860f2f67ab263dfebf9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
<?xml version="1.0"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
]>
<article id="index">
  <articleinfo>
    <title>System Tray Protocol Specification</title>
    <releaseinfo>Version 0.3</releaseinfo>
    <pubdate>10 January 2009</pubdate>
    <authorgroup>
      <author>
	<firstname>Havoc</firstname>
	<surname>Pennington</surname>
	<affiliation>
	  <address>
	    <email>hp@redhat.com</email>
	  </address>
	</affiliation>
      </author>
    </authorgroup>
  </articleinfo>

  <sect1 id="overview">
    <title>Overview</title>
    <para>
     The "system tray" is an application running on a given X screen
     that can display small icons provided by running
     applications. Windows XP calls this feature the "notification area."
     <footnote><para>According to the MSDN documentation for the
     <literal>Shell_NotifyIcon()</literal> function,
     "The taskbar notification area is sometimes erroneously called
     the 'tray.'" So presumably "notification area" is the official
     term on Windows. Parts of the docs also call it the "status
     area."</para></footnote> Inspired by KDE, this specification 
     uses the term "system tray."
    </para>
    <para>
     From a UI standpoint, the system tray is normally used for
     transient icons that indicate some special state, while
     full-blown "applets" are used for permanent dock/panel
     features. For example, a system tray icon might appear to tell
     the user that they have new mail, or have an incoming instant
     message, or something along those lines.
    </para>
    <para>
     The basic idea is that creating an icon in the notification 
     area is less annoying than popping up a dialog. However it's 
     also harder to notice, so Windows XP adds a feature allowing
     tray icons to pop up small message balloons. (Users can disable
     these via a hidden registry setting.) This specification 
     also supports the balloon feature.
    </para>
  </sect1>

  <sect1 id="definitions">
    <title>Definitions</title>
    <variablelist>
      <varlistentry>
	<term>System tray</term>
	<listitem>
	  <para>
            The system tray is an X client which owns a special 
            manager selection on a given screen and provides
            container windows.
	  </para>
	</listitem>
      </varlistentry>
      <varlistentry>
	<term>Selection owner window</term>
	<listitem>
	  <para>
            The selection owner window is the window belonging to the
            System Tray that owns the manager selection (as in
            <literal>XGetSelectionOwner()</literal>/<literal>XSetSelectionOwner()</literal>.
            Note that this probably is not the same window that's used 
            to contain the system tray icons.
	  </para>
	</listitem>
      </varlistentry>
      <varlistentry>
	<term>Tray icon</term>
	<listitem>
	  <para>
            The tray icon is a window to be embedded in the
            system tray.
	  </para>
	</listitem>
      </varlistentry>
    </variablelist>
  </sect1>

  <sect1 id="locating">
    <title>Locating the system tray</title>
    <para>
      On startup, the system tray must acquire a manager selection
      called <literal>_NET_SYSTEM_TRAY_Sn</literal>, replacing
      <literal>n</literal> with the screen number the tray wants to
      use. The conventions for manager selections are defined in the 
      ICCCM.
    </para>
    <para>
      Because the selection owner window should be destroyed when the
      manager selection is lost, normally the selection owner window
      will not be the same as any of the user-visible windows provided
      by the system tray.
    </para>
    <para>
      A system tray that fails to get the selection or loses the 
      selection should assume that another system tray is running, 
      and let the selection owner handle tray icons.
    </para>
    <para>
      An application wishing to provide an icon to the system tray
      should first locate the system tray by requesting the owner
      window of the manager selection. If the manager selection has no
      owner, clients may use the method described in the ICCCM
      (watching for a <literal>MANAGER</literal> client message) to be
      notified when a system tray appears. 
    </para>
  </sect1>

  <sect1 id="messages">
    <title>Opcode messages</title>
      <para>
        Tray icons can send "opcodes" to 
        the system tray. These are X client messages, sent with
        <literal>NoEventMask</literal>, a
        <literal>message_type</literal> of
        <literal>_NET_SYSTEM_TRAY_OPCODE</literal>, and format 32. 
        The first data field in the message is a timestamp (the stamp
        of the current event, if available, otherwise CurrentTime).
        The second data field is an integer indicating the op code 
        of the message:
         <programlisting>
#define SYSTEM_TRAY_REQUEST_DOCK    0
#define SYSTEM_TRAY_BEGIN_MESSAGE   1
#define SYSTEM_TRAY_CANCEL_MESSAGE  2
         </programlisting>
        The content remaining three data fields depends on the type of
        message being sent. If they are unused by a particular
        message, they should always be set to 0.
      </para>
      <para> 
        Here is an example of how to send a client message:
      <programlisting><!--
-->#include &lt;X11/Xlib.h&gt;

void send_message(
     Display* dpy, /* display */
     Window w,     /* sender (tray icon window) */
     long message, /* message opcode */
     long data1    /* message data 1 */
     long data2    /* message data 2 */
     long data3    /* message data 3 */
){
    XEvent ev;
  
    memset(&amp;ev, 0, sizeof(ev));
    ev.xclient.type = ClientMessage;
    ev.xclient.window = w;
    ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False );
    ev.xclient.format = 32;
    ev.xclient.data.l[0] = x_time;
    ev.xclient.data.l[1] = message;
    ev.xclient.data.l[2] = data1;
    ev.xclient.data.l[3] = data2;
    ev.xclient.data.l[4] = data3;

    trap_errors();
    XSendEvent(dpy, w, False, NoEventMask, &amp;ev);
    XSync(dpy, False);
    if (untrap_errors()) {
	/* Handle failure */
    }
}<!--
    --></programlisting>

     </para>

  </sect1>

  <sect1 id="docking">
    <title>Docking a tray icon</title>
    <para>
      A tray icon must support the "client" or "plug" side of the
      XEMBED specification. XEMBED is a protocol for cross-toolkit
      widget embedding.
    </para>
    <para>
      To begin the docking process, the tray icon application sends
      a client message event to the manager selection owner window, 
      as described in <xref linkend="messages"/>. This event 
      should contain the <literal>SYSTEM_TRAY_REQUEST_DOCK</literal>
      opcode, <literal>xclient.data.l[2]</literal> should contain 
      the X window ID of the tray icon to be docked.
    </para>
    <para>
      At this point the "embedding life cycle" explained in the XEMBED
      specification begins. The XEMBED specification explains how the 
      embedding application will interact with the embedded tray 
      icon, and how the embedder/embedded relationship may be ended.
    </para>
    <para>
      Tray icons may be assigned any size by the system tray, and 
      should do their best to cope with any size effectively.
    </para>
  </sect1>

  <sect1 id="visuals">
    <title>Visual and background pixmap handling</title>
    <para>
      If the _NET_SYSTEM_TRAY_VISUAL property (see below) is present,
      tray icon windows should be created using that visual. If the
      property is not present, then tray icon windows should be
      created using the default visual of the screen.
    </para>
    <para>
      Historically, to allow the appearance of icons with transparent
      backgrounds on servers that did not support visuals with an
      alpha channel or the Composite extension, a convention was
      adopted where a background pixmap was set on the XEMBED embedder
      window, aligned properly to match the contents of the embedder
      window's parent, the tray icon window was set to have a
      background of ParentRelative, and drawing of the icon done on
      top of this background.
    </para>
    <para>
      Setting the background of a window to ParentRelative when the
      depth of the window does not match the depth of the window's
      parent, or reparenting a window with a ParentRelative
      background into a parent with a non-matching depth produces a
      BadMatch error, so the embedder window must be created to match
      the visual of the tray icon window, even if the tray icon window
      does not have the visual provided in _NET_SYSTEM_TRAY_VISUAL. If
      convenient, the tray manager may set an appropriate background
      pixmap on the embedder window to provide the appearance of
      transparency. However, the preferred method of transparency is
      to use a visual with an alpha channel in _NET_SYSTEM_TRAY_VISUAL.
    </para>
  </sect1>

  <sect1 id="hints">
    <title>Tray icon hints</title>
    <para>
     Tray icons should set the following hints to help the system 
     tray provide a nice user interface. The name and icon hints 
     are used if the system tray needs to refer to a tray icon;
     for example, the system tray may present a list of tray 
     icons and let the user reorder them or change their properties.
    </para>

    <sect2><title>_NET_WM_NAME</title>
      <programlisting><![CDATA[
_NET_WM_NAME, UTF8_STRING
]]></programlisting>
	<para>
         This hint should be set as it would be for a normal toplevel
         window, as defined in the Extended Window Manager Hints
         Specification (EWMH).  The hint MUST be in UTF-8 encoding. It
         provides a human-readable, localized name for the tray icon.
	</para>
    </sect2>

    <sect2><title>WM_CLASS</title>
      <programlisting><![CDATA[
WM_CLASS, STRING
]]></programlisting>
	<para>
         This hint should be set as it would be for a normal toplevel
         window, as defined in the ICCCM. The system tray can use it
         to distinguish different kinds of tray icon. This is useful
         for example if the system tray wants to save and restore the
         positions of the icons in the tray.
	</para>
    </sect2>

	<sect2>
		<title>_NET_WM_ICON</title>
		<programlisting><![CDATA[
_NET_WM_ICON CARDINAL[][2+n]/32
]]></programlisting>
		<para>
         This hint should be set as it would be for a normal toplevel
         window, as defined in the Extended Window Manager Hints
         Specification (EWMH). See that specification for the format
         of the icon data.
		</para>
	</sect2>

  </sect1>

  <sect1 id="manager-hints">
    <title>Tray manager hints</title>
    <para>
The tray manager should set the following hints on the selection
owner window.
    </para>

    <sect2>
      <title>_NET_SYSTEM_TRAY_ORIENTATION</title>
      <programlisting><![CDATA[
_NET_SYSTEM_TRAY_ORIENTATION orientation CARDINAL/32
]]>
  #define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
  #define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1
      </programlisting>

      <para>
The property should be set by the tray manager to indicate the current
orientation of the tray. Tray icons may use this hint in order to
maintain the icon's aspect ratio and also as an indication of how the
icon contents should be laid out.
      </para>

    </sect2>

    <sect2>
      <title>_NET_SYSTEM_TRAY_VISUAL</title>
      <programlisting><![CDATA[
_NET_SYSTEM_TRAY_VISUAL visual_id VISUALID/32
]]>
      </programlisting>

      <para>
The property should be set by the tray manager to indicate the preferred
visual for icon windows. To avoid ambiguity about the colormap to use
this visual must either be the default visual for the screen or it
must be a TrueColor visual. If this property is set to a visual with
an alpha channel, the tray manager must use the Composite extension to
composite the icon against the background using PictOpOver.
      </para>

    </sect2>
  </sect1>

  <sect1 id="balloon">
    <title>Balloon messages</title>
    <para>
      Tray icons may ask the system tray to display a balloon message 
      to the user. The system tray coordinates balloon messages 
      to ensure that they have a consistent look-and-feel, and to 
      avoid displaying multiple balloon messages at once.
    </para>
    <para>
      A balloon message is a short text message to be displayed to 
      the user. The message may have a timeout; if so, the message
      will be taken down after the timeout expires. Messages are
      displayed in a queue, as only one can appear at a time; 
      if a message has a timeout, the timer begins when the message
      is first displayed. Users may be allowed to close messages at
      any time, and may be allowed to disable all message display.
    </para>
    <para>
      System trays may display balloon messages in any way they 
      see fit; for example, instead of popping up a balloon, they 
      could choose to put a special indicator around icons with 
      pending messages, and display the message on mouseover.
    </para>
    <para>
      Balloon messages are sent from the tray icon to the system tray
      selection owner window as a series of client messages. The first
      client message is an opcode message, and contains the usual timestamp,
      and the op code <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal>.
      <literal>xclient.data.l[2]</literal> contains the timeout in
      thousandths of a second or zero for infinite timeout,
      <literal>xclient.data.l[3]</literal> contains the length 
      of the message string in bytes, not including any nul bytes, and 
      <literal>xclient.data.l[4]</literal> contains an ID number
      for the message. This ID number should never be reused by 
      the same tray icon. (The simplest way to generate the ID number 
      is to increment it with each message sent.)
    </para>
    <para>
      Following the <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal>
      op code, the tray icon should send a series of client messages
      with a <literal>message_type</literal> of
      <literal>_NET_SYSTEM_TRAY_MESSAGE_DATA</literal>. These client
      messages must have their <literal>window</literal> field set 
      to the window ID of the tray icon, and have a
      <literal>format</literal> of 8.
    </para>
    <para>
      Each <literal>_NET_SYSTEM_TRAY_MESSAGE_DATA</literal> message
      contains 20 bytes of the message string, up to the length given 
      in the <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal> opcode.
      If the message string is zero-length, then no messages need be
      sent beyond the <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal>. 
      A terminating nul byte should never be sent.
    </para>
    <para>
      System trays may receive portions of messages from several 
      tray icons at once, so are required to reassemble the messages
      based on the window ID of the tray icon.
    </para>
    <para>
      The tray icon may wish to cancel a previously-sent balloon
      message. To do so, it sends a
      <literal>SYSTEM_TRAY_CANCEL_MESSAGE</literal> opcode with
      <literal>data.l[2]</literal> set to the ID number of the message
      to cancel.
    </para>
  </sect1>

  <appendix id="changes">
    <title>Change history</title>
    <formalpara>
      <title>Version 0.3, 10 January 2009, Owen Taylor</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
              Added the _NET_SYSTEM_TRAY_VISUAL hint and a
              description of visual and background pixmap handling.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
    <formalpara>
      <title>Version 0.2, 23 November 2004, Mark McLoughlin</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
              Added the _NET_SYSTEM_TRAY_ORIENTATION hint.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
    <formalpara>
      <title>Version 0.1, 20 April 2002, Havoc Pennington</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
              Created initial draft.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
  </appendix>
</article>