The GTK-Stream protocol

The GTK-Stream protocol consists in sending graphical commands (such as "create a window", "append a widget", "change a property") to the standard input of a running gtk-stream process, and listening for user input events (button clicks, file dialog selection, window closing) from the process' standard output.

GTK-Stream expects a well-formed XML document on its standard input, which it parses incrementally. This means a message will be handled as soon as it is written, and may depend on previous messages, but not on future ones.

The root element of the protocol is the <application application_id="$ID"> tag, containing zero or more messages. When this tag is closed (and the document ended), the application will exit regardless of any open windows.

GTK Stream messages

A message to GTK Stream will tell it what to do.

Add a stylesheet

  • Tag : <style>
  • Children : a text node, containing some GTK-specific CSS

Add a stylesheet to the application.

The styleshet is applied as soon as the </style> end tag is parsed, but if you want to avoid any flickering, it may be wise to define a stylesheet before opening any windows.

Examples :

  • Turn all buttons red : <style>button { color: red; }</style>
  • Add padding to all widgets with the "big" class : <style>.big { padding: 10px; }</style>

Open a window

  • Tag : <window id="$ID" title="$TITLE" width="$W" height="$H"></window>
  • Children : exactly one widget

Open a window with the given title, width and height if specified, containing the child widget.

The window may be closed using the <close-window id="$ID" /> message.

When it is closed (either programmatically or by the user), it emits a $ID:window-closed event.

Close a window

  • Tag : <close-window id="$ID" />

Close the window with the specified ID.

Modify a widget property

  • Tag : <set-prop id="$WIDGET_ID" name="$PROP_NAME" value="$NEW_VALUE" />

Set the property PROP_NAME on the named widget to a new value.

Properties can be any declared GObject property of the target widget. You can find those in the "Properties" section of the documentation for that widget (for example, here are the properties for a button)

Insert widgets into a container

  • Tag : <insert into="$ID">
  • Children : zero or more widgets

Append the given widgets to a container. Depending on the container, the widgets may need to be wrapped in the corresponding tags (for example, within a <cell> if you are adding widgets to a grid).

Remove a widget

  • Tag : <remove id="$ID" />

Remove the named widget. After that, it will no longer be visible, or receive events.

Open a file chooser dialog

  • Tag : <file-dialog id="$ID" parent="$WINDOW_ID" />

Open a file chooser dialog. It is modal by default, so the parent window will not receive events while the dialog is active.

When a file is chosen, the chooser will emit a $ID:selected:$FILE_PATH event. If the user closes the dialog without choosing a file, a $ID:none-selected event will be emitted instead.

GTK Stream Widgets

Some messages accept widgets as children. Here are the widgets that GTK Stream can create.

All widgets handle setting initial values for their properties. All properties are optional, except for the ones that appear in the description of the widget.

Non-interactive Widgets

The following are mainly used for presentation, and will not emit any events.

Labels

  • Tag : <label text="$TEXT" />

Create a label, to show a short message.

Pictures

  • Tag : <picture src="$FILE" />

Create a picture from the given file.

The file is opened by the Gtk-Stream process, which may have a different current directory than the one of the pilot application, so it is usually preferrable to specify full paths to images rather than relative ones.

Progress bars

  • Tag : <progress-bar />

Create a progress bar, with an optional id. The progress bar advancement can be updated by setting its "fraction" property

Separators

  • Tag : <separator />

Create a separator, to mark a visual distinction between two adjacent widgets.

Interactive widgets

The following widgets will usually serve as "interaction points" for the user. They will emit events according to what the user does with them.

Buttons

  • Tag : <button id="$ID" >
  • Children : another widget, for the button contents (usually a label)

Create a button, identified by an id.

When clicked, the button will emit an event of the form $ID:clicked.

  • Tag : <link id="$ID" >
  • Children : another widget, for the link contents (usually a label)

Create a link button, identified by an id.

When clicked, the button will emit an event of the form $ID:clicked, just like a <button>. The default link-opening behaviour of Gtk is inhibited, in favour of letting the pilot application choose its own behaviour.

Switches

  • Tag : <switch id="$ID" managed="$MANAGED" />

Create a switch.

When clicked, the switch will emit an event of the form $ID:switch:$NEW_STATE where $NEW_STATE is on or off.

Sometimes, switching something on takes a little while, and the user still needs to know that their interaction has been taken into account.

Setting the managed property to true does just that. A managed switch doesn't change color when switched on or off, and it is up to the pilot application to set the switch's state when the underlying logic is done with the switching.

  • Tag : <dropdown id="$ID">
  • Children : one or more <item value="$V">, each containing a widget.

Create a dropdown, offering a choice between all of the given items.

When an item is selected, the dropdown will emit an event of the form $ID:selected:$VALUE where the value is what was specified in the corresponding <item> tag.

You can activate a search functionality for the dropdown by setting enable_search="true", and search_match_mode="$MATCH_MODE" where MATCH_MODE is one of exact, prefix or substring. If you do so, the item values will be used as keys to perform the search.

Container widgets

Those widgets won't serve as interaction points, and instead will handle the layout of other widgets.

Boxes

  • Tag : <box>
  • Children : zero or more "naked" widgets, or widgets within a <box-prepend after="$ID"> to insert widgets after another child (the previous child must have been inserted beforehand).

Create a box with several child widgets contained inside.

Panes

  • Tag : <paned>
  • Children : one or more widgets

Create multiple nested panes, with adjustable handles to allow resizing.

Frames

  • Tag : <frame>
  • Children : a "naked" widget to set the content, and/or a widget within a <frame-label> to set the frame label

Create a frame, containing a widget, with an optional label if specified.

Grids

  • Tag : <grid>
  • Children : zero or more <cell x="$X" y="$Y" w="$W" h="$H">, each containing a single widget

Create a grid, and attach each child widget to it according to the coordinates of its cell.

Scrolled windows

  • Tag : <scrolled-window>
  • Children : just one widget

Wraps a widget in a scrolled window, that adds scrolling capabilities (and optionally, a frame) to widgets that don't have them natively.

Stacks

  • Tag : <stack>
  • Children : zero or more widgets

Make a stack from several widgets. You can select the visible child of the stack by setting its visible-child property to the ID of that child.

Pseudo-widgets

Some containers need additional information about their children to lay them out properly. For example, a Grid needs its children to be inserted at certain coordinates, and a Frame can contain both a "label widget" and a "content widget".

To handle those cases, widgets may be wrapped within special tags (such as <cell> or <frame-label> for the cases above) that only provide positional information within a parent.

Those tags are what GTK-Stream considers "pseudo-widgets". They may appear anywhere other widgets can, with the following caveats :

  • since they do not correspond to GTK widgets, they may not be identified with an ID, and may thus not be <remove>d (to remove a pseudo-widget, you have to simply identify and remove its underlying child)
  • for the same reason, they may not contain any GTK properties. Any property of a child widget must be specified on the child, not on the pseudo-widget that contains it