XWT -- The XML Windowing Toolkit (2024)

1. Preface

This document is a reference. It is not a specification or atutorial.

This document does not guide the user gently through examples (as atutorial would), and it doesn't provide enough detail and formalityfor a third party to construct a compatible re-implementation of theXWT Core (as a specification would).

Rather, the goal of this document is to completely describe everyaspect of the environment that the XWT Core provides to clientapplications, from the bottom up. If you want to be an XWT expert,this is the right document to read. It is assumed that you are alreadyfamiliar with XML and with either JavaScript or ECMAscript. Ifyou are not familiar with ECMAscript, some reference materials areprovided in Appendix G

The shoehorn sequence (how the XWT Core gets onto theclient's computer, and how it knows where to download the initial xwarfrom) is not described in this document, since it will be differentfor every platform that XWT is ported to.

If you need to use or rely on some behavior you notice in the XWTCore, but which is not clearly defined here, please post to the users mailinglist.

2. Key Concepts

2.1 Definitions

The Core XWT itself; the native code (or Java bytecode) that runs on the client. This term does not include the shoehorn or the UI
The UI / The Application a set of files (mostly XML, JavaScript, and PNG images) bundled up in a zip archive, ending with the ".xwar" extension. Together, these files specify the appearance and behavior of the application's user interface. Sometimes we'll refer to this as the "xwar" to be clear that we're talking about the actual zip archive, rather than its visual appearance when rendered on the screen.
The Server We will use the term "the server" to refer to any other computer which the client makes XML-RPC or SOAP calls to. Note that it is possible for the client and server to be the same machine.
The Shoehorn this is a very small piece of code that is downloaded the first time a client uses XWT. It downloads the XWT core, verifies its signature, and launches it with the appropriate parameters indicating where to find the initial UI. The Shoehorn works differently on every platform, and is outside the scope of this document.
put/write In ECMAscript, when you change the value of a property on an object, you are putting to that property, or writing to it. For example, the ECMAscript expression "foo.bar = 5" puts the value 5 to the bar property on object foo.
get/read In ECMAscript, when you access the value of a property on an object, you are getting that property, or reading from it. For example, the ECMAscript expression "return (3 + foo.bar)" gets the value of bar property on object foo and then adds 3 to it before returning the result.
JavaScript
ECMAScript
We will use the terms JavaScript and ECMAScript interchangeably in this document. The XWT interpreter is not completely ECMA-compliant, however (see Appendix C for details).

2.2 Surfaces

Each top-level window in an XWT UI is called asurface. There are two kinds of surfaces: frames, whichusually have a platform-specific titlebar and border, andwindows, which never have any additional platform-specificdecorations.

Whenever we refer to the size or position of a surface, we arereferring to the size or position of the UI-accessible portion of thesurface; this does not include any platform-specific decorations. Thismeans that if you set the position of a frame to (0,0), theplatform-specific titlebar will actually be off the screen on mostplatforms (it will be above and to the left of the top-left corner ofthe screen).

Surfaces are not actual JavaScript objects; you cannot obtain areference to a surface. However, each surface is uniquely identifiedby its root box, described in the next section.

2.3 Boxes

A box is the fundamental unit from which all XWT userinterfaces are built. Boxes can contain other boxes (known aschildren). Each Surface has a single box associated with itcalled the root box; the root box and its children (and itschildren's children, and so on) form the surface's box tree.

There are three ways to think of a box: as a rendered visualization onthe screen (the "Visual Representation"), as a JavaScript object (the"Object Representation"), and as an XML tag (the "XMLRepresentation").

FIXME: diagram here

All three representations are equally valid, and being able to figureout what an action in one representation would mean in terms of the othertwo representations is crucial to a solid understanding of XWT.

The Object Representation

Each box is a full-fledged ECMAscript object, and can store key-valuepairs as properties. Some of these keys have special meaning, whichwill be explained later. Each box's numeric properties hold itschild boxes.

The Visual Representation

Each box occupies a rectangular region on the surface. The visualappearance of a surface is created by rendering each box in its tree.Unless the clip attribute is false, each box willclip its childrens' visual representations to its own, so that thechildren appear "confined to" the parent. Children are rendered aftertheir parents so they appear "on top of" their parents (they obscurethem).

Each box has two major visual components, each with subcomponents:

FIXME: diagram

  • A path, which consists of zero or more lines and curves. The path may be filled with a color, gradient, or texture, and may be stroked with a line of a given thickness and color. If the path is not specified, it defaults to the perimiter of the box.
    • The path has an associated strokecolor, which is a color
    • The path has an associated strokewidth, which is a number specifying the width of the stroke.
    • The path also has a fill, which is either a color, gradient, or texture
  • A single line of text, which can be rendered in different fonts, colors, and sizes.
    • The text has an associated font, which currently can be any font supported by the FreeType2 library.
    • The text also has an associated fontsize
    • The text is drawn in an associated textcolor

These eight components plus the size of a box fully specify itsappearance. Every single box you see in XWT is drawn only on thebasis of these components and its size.

The XML Representation

A template (discussed in the next section) is an XML file which actsas a blueprint for constructing a tree of boxes. We call thisconstruction process applying, since unlikeinstantiation, you always apply a template to a pre-existingbox, and you can apply multiple templates to the same box. Each XMLtag corresponds to a single box, or to another template which will beapplied to that box. For example, a scrollbar template, whenapplied, will construct a tree of boxes which has the visualappearance and behavior of a scrollbar.

Although it is useful to think of the XML tags as being boxes, keep inmind that the XML representation is only a blueprint for constructinga tree of JavaScript objects. Once the template has beeninstantiated, the XML is effectively "thrown away", and JavaScript code isfree to alter the boxes.

2.4 Templates

Each template is an XML document whose root elementis <xwt>. Any text content of the root element isignored, and may safely be used for comments. The root element mayhave any of the following elements as children, each of which mayappear no more than once, and which must appear in this order:

<doc> This tag contains structured documentation. The structure of the doc tag has not yet been specified; you should leave its body empty for now (or omit it entirely).
<static> The text content of this node will be treated as JavaScript code, and executed the before first time this template is referenced (either by applying it or by referring to it to via xwt.static).

FIXME: review

An object will be created and used as the root scope for executing the script. Any var declarations in this script will create private properties on that object.
<template> This element may have any number of child nodes, with any valid name or attribute set. The text content of the <template> node and of all its descendent nodes is interpreted as ECMAscript code.

Here is a sample XWT file:

<xwt xmlns="xwt.widget" xmlns:lib="xwt.lib"> This is a sample XWT file. Text up here is ignored. Copyright (C) 2004 Mustapha Mond. <static> // code here will be executed only once </static> <template cols="5"> <box id="container"/> <checkbox/> <box> /* This has to be commented out or else it will be treated as a script */ <lib:scrollbar/> </box> </template></xwt>

Applying an XML tag to a box

The following description of the box application is extremely detailedand precise; it is intended for UI designers who need to know theexact order in which each event happens. FIXME:easier description. While this whole process sounds verycomplex, it actually works pretty intuitively. The description belowis given in great detail since most applications will wind up beingunintentionally dependent on subtle features of this process.However, most of the time you can just pretend that the XML tags andthe boxes are the same thing.

To apply an XML tag X to a box B, perform the followingoperations, in this order:

  1. Allocate a fresh scope s whose parent scope is B.
  2. Process each child element or text segment of X in the order they appear in the document:

    For each text segment t:

    1. Treat t a JavaScript script, and execute it with s as the root scope.
    For each child element x of X:
    1. Create a new box b.
    2. If the name of tag x is not "box" (in the default XML namespace), prepend the tag's namespace identifier uri (if any) to the name of the tag, and use the result as a key to retrieve a property from the root stream (defined later). Interpret the resulting stream as a template and apply that template to b.
    3. (recursively) apply x to b.
    4. If x has an id attribute, declare a variable in s whose name is the value of the id attribute, prefixed with the $ character, and whose value is b
    5. Copy any $-variables created during the application of x into scope s.
    6. Append b as the last child of B.
  3. Apply any attributes on X to B, except for id. Since XML specifies that the order of attributes cannot be significant, XWT processes attributes in alphabetical order by attribute name.

    For example, if X has the attribute

    foo="bar", then the equivalent of the statement B.foo="bar"; will be performed, with the following exceptions:
    1. If the value portion of the attribute is the string "true", put the boolean true. If the value is "false", put the boolean false.
    2. If the value is a valid ECMAscript number, put it as a number (instead of a string).
    3. If the value begins with a dollar sign ($), retrieve the value of the corresponding variable in s and use that value instead.
    4. If the value begins with a dot (.), prepend the attributes' namespace identifier uri (if any) and interpret the remainder as a property to be retrieved from the root stream (defined later).

The last two steps are referred to as the initialization of thenode. There are two important aspects of this ordering to be aware of:

  • A given box will be fully initialized before its parent is given a reference to that box. This way, parents can be certain that they will never wind up accessing a box when it is in a partially-initialized state.
  • Attributes are applied after scripts are run so that the attributes will trigger any traps (defined later) placed by the script.

2.5 Life Cycle of an XWT Application

A user begins by specifying the URL of an XWT application run.Usually this is done by visiting a web page which uses theshoehorn to install the core if it is not already on the user'smachine, but you can also supply the URL on the command line.

The XWT Core downloads the xwar for the application, loads it, appliesthe main.xwt template and renders it onto the screen, runningany associated ECMAscript code.

The user interacts with the application by clicking and moving themouse, and by pressing keys on the keyboard. These actions triggerfragments of JavaScript code which are designated to handle events.This JavaScript code can then relay important information back to theserver using XML-RPC or SOAP, or it can modify the structure andproperties of the user interface to change its appearance, therebygiving feedback to the user.

DIAGRAM: graphic here showing the circular feedback cycle.

The XWT core quits when the last remaining surface has been destroyed.

3. Layout and Rendering

The size and position of every other box is determinedby its properties, its childrens' sizes, and its parent's size and position.Box layout and rendering happens in four phases: packing,constraining, placing, and rendering. The Core is careful to onlyperform a phase on a box if the box has changed in a way thatinvalidates the work done the last time that phase was performed.

Thepacking and constraining phases are performed in a single traversal ofthe tree (packing is preorder, constraining is postorder), and theplacing and rendering phases are performed in a second traversal ofthe tree (first placing, then rendering, both preorder).

For brevity, the rest of this chapter deals only with width andcolumns. Height and rows is treated identically and independently.Also, it is important to note that the term minimum width isnot the same thing as the property minwidth, although theyare closely related.

The size of the root box

When the user resizes a window, XWT changes the root box'smaxwidth and maxheight to match the size chosen bythe user and then determines the root box's size using the same sizingrules it uses for other boxes.

XWT will always attempt to prevent theuser from making the surface smaller than the root box'sminwidth and minheight. If the hshrink orvshrink flag is set, XWT will try to prevent the user fromresizing the surface at all. However, not all platforms give XWTenough control to do this.

The alignment point

When talking about positioning, we will often refer to thealignment point.

  • If the align property is "center", then the alignment point is the center of the box.
  • If the align property is "topleft", "bottomleft", "topright", or "bottomright", then the alignment point is corresponding corner of the box.
  • If the align property is "top", "bottom", "right", or "left", then the alignment point is middle of the corresponding edge of the box.

FIXME: diagram

When positioning a child box, the alignment point is determined by theparent's align property. When positioning a visualelement (a texture, path, or text string) within a box, the alignmentpoint is determined by the box's own align property.

A simple way to think about this is that whenever there are two boxesinvolved in the decision, you should use the parent's alignment point.

3.1 Packing

  1. An imaginary gridof cells is created within the parent. If the parent'scols property is set to 0, the cell grid has an infinitenumber of columns. Either cols or rows must bezero, but not both.
  2. If a child's visible property is false, it does not occupy any cells (and is not rendered). Otherwise, each child occupies a rectangular set of cells child.colspan cells wide and child.rowspan cells high.
  3. The Core iterates over the cells in the grid in the following order: if rows is 0, the Core iterates across each column before proceeding to the next row; otherwise rows come before columns.

    At each cell, the Core attempts to place the first remaining unplaced child's top-left corner in that cell (with the child occupying some set of cells extending down and to the right of that cell). If the parent has a fixed number of columns and the child's

    colspan exceeds that limit, the child is placed in column zero regardless, but only occupies the available set of cells (it does not "hang off the end" of the box).
XWT -- The XML Windowing Toolkit (1)

<box cols="3">
<box id="1" />
<box id="2" rowspan="2" />
<box id="3" colspan="2" />
<box id="4" />
<box id="5" colspan="2" />
</box>

Notes on the layout example:

  1. Box '3' doesn't fit in the gap after '2', nor in the gaps either
    side of '2' on the next row, hence it is pushed onto the 3rd row.
  2. Box '4' would fit in the gaps around '2', but must be placed after
    it's preceeding box, '3'.

3.2 Constraining

  1. Each box's minimum width is computed recursively as the maximum of:
    • Its minwidth
    • The width of the box's text (after applying the box's transform).
    • The width of the box's path (after applying the box's transform) if the box is packed.
    • The width of the bounding box enclosing the box's cells.
  2. The minimum width of each cell is computed as the minimum width of the box occupying it divided by the box's colspan.
  3. If a box's hshrink property is set to true, the box's maximum width is the same as its minimum width; otherwise it is the box's maxwidth.
  4. The maximum width of each cell is the maxwidth of the box occupying it divided by the box's colspan.

3.3 Placing

  1. Each column's actual width is set to the maximum minimum width of all the cells in that column.

    NOTE: although a column or row can be sized smaller than its "minimum width" or larger than its "maximum width", a box will never be smaller than its

    minwidth or larger than its maxwidth.
  2. Each column's maximum width is the largest maximum width of the cells in that column, but no smaller than the column's minimum width.
  3. The slack is the difference between the parent's width and the sum of its columns' actual width. The slack is divided equally among the columns. Any column which has exceeded its maximum width is set to its maximum width, and the difference is returned to the slack. This process is repeated until the slack is zero or all columns are at their maximum width.
  4. Next, the rows and columns are positioned within the parent box. The rows and columns are transformed according to the parent's transform property, and the bounding box of the resulting cells are placed such that the cells' alignment point coincides with the parent's alignment point (both alignment points are determined by the parent's align property).

    FIXME: diagram

  5. Packed boxes: Each packed box's actual position and size is then set to the aggregation of the actual sizes of the cells it spans. If this size exceeds the box's maximum width, the box is sized to its maximum width and centered horizontally within the space occupied by its cells.

    Non-packed boxes: each non-packed box is transformed according to the parent's

    transform property and then positioned so that its alignment point is (child.x, child.y) pixels from the parent's alignment point (both alignment points are determined by the parent's align property).

3.4 Rendering

Boxes are rendered in a depth-first, pre-order traversal. Note thatthis may cause a non-packed box to overlap its siblings.

  1. If the box's transform property is non-null, the coordinate space is transformed accordingly for the rest of this phase and for the rendering of all children.
  2. If the box is packed and has a non-null path, the path is translated such that the alignment point of the path's bounding box coincides with the box's alignment point (both alignment points are determined by the box's align property).
  3. If a box has a path, that path is filled with the color, gradient, or image specified by the fill property and stroked with the color and width specified by the strokecolor and strokewidth properties.
  4. If the box has a non-null text attribute, the text is rendered in font with size fontsize and color textcolor. The text is then translated such that the alignment point of the text's bounding box coincides with the box's alignment point (both alignment points are determined by the box's align property).
  5. The box's children are rendered (pre-prder traversal).

4. Box Properties

4.1 Rendering Properties

Every box has several special properties which control how it isdrawn. In general, if you put aninvalid value to a special property, no action will be taken -- theput will be ignored.

XWT -- The XML Windowing Toolkit (2)
Property Type Initially Significance
XWT -- The XML Windowing Toolkit (3)
strokecolor string clear If the value is a 5-character hex string (#RGB), 7-character hex string (#RRGGBB), 9-character hex string (#AARRGGBB), the box's stroke color will be set to that color.

If the value is one of the ICC colors (the same set of color names supported by SVG), the stroke color be set to that color.

If the value is

null, the stroke color will be set to clear (#00000000).
XWT -- The XML Windowing Toolkit (4)
strokewidth int 1 The width (in pixels) to stroke the path with.
XWT -- The XML Windowing Toolkit (5)
fill string null This property can be set to any of the values specified for strokecolor.

Alternatively, if the value written is an object, its stream will be read and interpreted as a PNG, GIF, or JPEG image, which will become the texture for this box, and the box's

minwidth and minheight properties will be automatically set to the dimensions of the image.
XWT -- The XML Windowing Toolkit (6)
path string "" The box's path. The grammar and feature set supported are identical to that specified in SVG 1.1, section 8.
XWT -- The XML Windowing Toolkit (7)
text string "" The box's text; writing null to this property sets it to "".
XWT -- The XML Windowing Toolkit (8)
font stream .xwt.font.sansserif When an object is written to this property, its stream is read using the freetype2 library, and the resulting font is used to render the box's text.
XWT -- The XML Windowing Toolkit (9)
fontsize number 10 The size (in points) to render the text.
XWT -- The XML Windowing Toolkit (10)
textcolor number black The color in which to render the font; accepts the same values as strokecolor.

4.2 Layout Properties

XWT -- The XML Windowing Toolkit (11)
Property Type Initially Significance
XWT -- The XML Windowing Toolkit (12)
shrink
hshrink
vshrink
boolean false If set to true, this box will shrink (horizontally/vertically/both) to the smallest size allowed by its children and the bounding box of its path.
XWT -- The XML Windowing Toolkit (13)
x
y
integer varies If the box is a root box, this is the (x/y)-coordinate of the surface; otherwise it is the distance between the parent's alignment point and this box's alignment point.
XWT -- The XML Windowing Toolkit (14)
globalx
globaly
integer varies The distance between this box's (left/top) edge and the root box's (left/top) edge. A put to this property has the same effect as a put to the (x/y) property, except that it is relative to the root box rather than to this box's parent. FIXME is this fakeable? How is distance measured?
XWT -- The XML Windowing Toolkit (15)
minwidth
minheight
integer 0 The desired minimum width and height.
XWT -- The XML Windowing Toolkit (16)
maxwidth
maxheight
integer xwt.maxint The desired maximum width and height.
XWT -- The XML Windowing Toolkit (17)
width
height
integer varies When read, this is the (width/height) of this box. Writing to this property is equivalent to writing to both the minimum and maximum (width/height).
XWT -- The XML Windowing Toolkit (18)
cols
rows
integer 0 The number of (columns/rows) in which to lay out the children of this box. If set to zero, the number of (columns/rows) is unconstrained. Either rows or cols must be zero. If 0 is written to cols when rows is 0, the write is ignored. If a nonzero value is written to cols when rows is nonzero, rows is set to 0, and vice versa.
XWT -- The XML Windowing Toolkit (19)
colspan
rowspan
integer 1 The number of (columns/rows) that this box spans within its parent.
XWT -- The XML Windowing Toolkit (20)
align string "center" Determines the box's alignment point for positioning its text, texture, path, and children.
XWT -- The XML Windowing Toolkit (21)
visible boolean true If set to false, this box will be rendered as if its width and height were zero. If this is a root box, the associated surface will be hidden.

When reading from this property, the value

false will be returned if this box or any of its ancestors is not visible. Thus it is possible to write true to a box's visible property and then read back false.
XWT -- The XML Windowing Toolkit (22)
packed boolean true The layout strategy for this box.

4.3 Child Control Properties

During a box initialization, script-private references to a box'sdescendants with id attributes are placed on the box. Thesereferences allow scripts on that box to easily refer to descendantnodes created by the template in which the script appears. Forexample, these two blocks of code have exactly the same effect:

<box> <box id="foo"/> $foo.color = "red";</box>
<box> <box/> var $foo = this[0]; $foo.color = "red";</box>

The following special properties control how a box's children are laidout. If a box has a non-null redirect target, reads and writes to theseproperties will be forwarded to the redirect target.

The redirect attribute is very useful for hiding theinternal structure of a widget, and for allowing widgets to act as"smart" containers for other widgets. For example, a menu widget mighthave an invisible child as its redirect target; this way, when boxesrepresenting items on the menu are added as children of the menuwidget, they do not appear until the menu is pulled down.

XWT -- The XML Windowing Toolkit (23)
Property Type Initially Significance
XWT -- The XML Windowing Toolkit (24)
numeric properties box The nth child of box b can be accessed by reading fromb[n]. The nth child can be removed by writingnull to b[n] (the child will become parentless). Anew child can be inserted before the nth child bywriting it to b[n]; if the value written is already a child ofb, it will be removed from b first. It is importantto note that this behavior is different from ECMAscript arrays --writing a non-null value to b[n] does not eliminatethe nth child; it merely shifts it over one position.

Note: Unlike most JavaScript objects, enumerating a Box'sproperties with the JavaScript

for..in construct willenumerate only the box's children and not any other properties.
XWT -- The XML Windowing Toolkit (25)
clip boolean true If true, the visual representation of this box's children will be clipped to the boundaries of this box. Note: setting this property to false imposes a substantial performance penalty.
XWT -- The XML Windowing Toolkit (26)
numchildren integer 0 The number of children this box has.
XWT -- The XML Windowing Toolkit (27)
redirect box thisbox Writing to this property sets the box's redirect target. This property cannot be read from, and can only be written to once.
XWT -- The XML Windowing Toolkit (28)
surface any null If this box has a parent, this property returns parent.surface; otherwise it returns null. This property is a simple building block that the widget library uses to implement more complex functionality such as focus control and popups.

4.4 Other Box Properties

XWT -- The XML Windowing Toolkit (29)
Property Type Initially Significance
XWT -- The XML Windowing Toolkit (30)
cursor string null The shape that the cursor should take when inside this box. Valid values are: "default", "wait", "crosshair", "text", "hand", and "move", as well as resizing cursors"east", "west", "north", "south", "northwest", "northeast", "southwest", and "southeast". Note that on some platforms, resize cursors for opposite directions (such as northwest and southeast are the same).

If a box's cursor is

null, its parent's cursor will be used. If the root box's cursor is null, the "default" cursor will be used.
XWT -- The XML Windowing Toolkit (31)
mouse.x
mouse.y
integer varies The (horizontal/vertical) distance between the mouse cursor and this box's (left/top) edge. Puts to this property are ignored. This value will not be updated if the mouse is outside the root box of the surface and no button was pressed when it left.
XWT -- The XML Windowing Toolkit (32)
mouse.inside boolean false True if the mouse is inside the rendered region of this box or any of its children. This value will be false if the mouse is inside a portion of this box which is covered up by one of this box's siblings, or one of its ancestors' descendants. Puts to this value are ignored.
XWT -- The XML Windowing Toolkit (33)
static object N/A Reading from this property will return the parent scope used to execute the <static/> block of the template in which the currently-executing code resides.
XWT -- The XML Windowing Toolkit (34)
thisbox box Returns a reference to the box itself. If null is written to this property, and this box is the root box of a surface, the box will be detached and the surface destroyed. If this box has a parent, it will be detached from its parent.
XWT -- The XML Windowing Toolkit (35)
indexof() function This property is actually a function; invoking parent.indexof(child) will return the numerical index of child in parent if child is a child of parent (or parent's redirect target), and -1 otherwise. Writing to this property has no effect.
XWT -- The XML Windowing Toolkit (36)
childadded
childremoved
These properties are meant to be trapped on FIXME defined later?. Placing a trap on childadded/childremoved lets a box receive notification when a child is added/removed. In either situation, the child will be passed as an argument to the trap function after the addition or removal has been performed.

Note that if the parent's redirect target is set to another box, these traps will only be invoked when children are manipulated by reading and writing to the parent. Reads and writes directly to the redirect target will not trigger the traps.

Note also that these traps are still triggered if a box's

redirect target is null. This is useful for boxes that need to accept children and then relocate them elsewhere.

4.5 Notification Properties

The following properties are used to notify a box of changes specificto that particular box.

XWT -- The XML Windowing Toolkit (37)
Property Significance
XWT -- The XML Windowing Toolkit (38)
Enter The value true is written to this property when the mouse enters the box.
XWT -- The XML Windowing Toolkit (39)
Leave The value true is written to this property when the mouse leaves the box.
XWT -- The XML Windowing Toolkit (40)
SizeChange The value true is put to this property after the size of this box changes.
XWT -- The XML Windowing Toolkit (41)
PosChange FIXME: relative to whom? If this box is a root box, the value true is put to this property after the surface changes position relitave to the top-left corner of its parent. If this box is not a root box, the value true is put to this property after the alignment anchor of the box changes position relitave to the top-left corner of the surface.

4.6 Root Box Properties

The following special properties are only meaningful on the root boxof a surface.

XWT -- The XML Windowing Toolkit (42)
Property Significance
XWT -- The XML Windowing Toolkit (43)
Focused The value true is put to this property on the root box when the surface gains the input focus, and false when the surface loses the input focus. Reading from this value will return true if the surface is focused and false if it is not. Putting true to this property will not cause the surface to "steal" the input focus from other windows.
XWT -- The XML Windowing Toolkit (44)
Maximized The value true is put to this property on the root box when the surface is maximized, and false when the surface is un-maximized. Reading from this value will return true if the surface is maximized and false if it is not. Putting true to this property will maximize the window, and putting false to this property will unmaximize the window.

Note that not all platforms support maximization.

XWT -- The XML Windowing Toolkit (45)
Minimized The value true is put to this property on the root box when the surface is minimized, and false when the surface is unminimized. Reading from this value will return true if the surface is minimized and false if it is not. Putting true to this property will minimize the window, and putting false will unminimize it.
XWT -- The XML Windowing Toolkit (46)
Close When the user attempts to close a surface, the value true will be put to this property. Scripts may trap this property FIXME defined later? to prevent the window from closing. Putting the value true to this property on a root box has the same effect as putting null to the thisbox property.
XWT -- The XML Windowing Toolkit (47)
icon The surface's icon. This is usually displayed on the titlebar of a window. The value should be the stream name of a PNG image. Note that not all platforms support this property.
XWT -- The XML Windowing Toolkit (48)
titlebar The surface's titlebar text. Note that not all platforms support this property. Only ASCII characters 0x20-0x7F are permitted.

6. Streams

Every object has a stream...

Every object has a stream associated with it. A stream is asequence of bytes that can be read or written to.

By default an object has an empty stream (zero bytes). However, some objects(returned from special methods on the xwt object) havestreams yielding data read from an url, file, or a component of a ziparchive. In a future release, the stream associated with a box willbe an .xwt template which, when applied, will fully reconstitute thebox's state.

...but streams are not objects

Despite the ubiquity of streams, you cannot actually reference astream, since it is not an object. Instead, you simply reference theobject it belongs to. If you are familiar with Java, this is similarto how every Java object has a monitor associated with it, but youcannot directly manipulate the monitor (you can't pass around areference to just the monitor).

In the rest of the section we will sometimes refer to "gettingproperties from a stream" or "passing a stream to a function"; this isjust shorthand for saying to perform those actions on the object thestream belongs to.

6.1 Creating Streams

Creating Streams from URLs

You can create a stream from a URL by calling

 var r = xwt.stream.url("http://...");

This will return an object whose stream draws data from the specifiedURL. Streams are loaded lazily whenever possible.

Getting Substreams

Most stream objects let you accesssubstreams using the usual JavaScript operators [] and., as well as the for..in syntax.

 // r1 and r2 are equivalent but not equal (!=) var r1 = xwt.stream.url("http://www.xwt.org/foo/bar.html"); var r2 = xwt.stream.url("http://www.xwt.org/foo")["bar.html"];

The Root Stream

The empty-string property on the xwt object is called theroot stream. You can access this object as xwt.. orxwt[""]. Additionally, any expression which starts with adot is treated as property to be retrieved from the root stream. Thefollowing three expressions are equivalent:

 xwt..foo xwt[""].foo .foo

Static Blocks

You can access variables within the static block of a template byappending a double period (..) and the variable name to thestream used to load that template:

 <!-- org/xwt/themes/monopoly/scrollbar.xwt --> <xwt> <static> foo = 12; ... // elsewhere xwt.log.print(org.xwt.themes.monopoly.scrollbar..foo); // prints "12"

6.2 Formatting Streams

If you attempt to send a stream as part of an XML-RPC call, thestream will be read in its entirity, Base64-encoded, and transmittedas a <base64/> element.

XWT supports two special URL protocols. The first is data:,which inteprets the rest of the URL as a Base64 encoded sequence ofbytes to use as a source. The other is utf8: whichinterpretets the rest of the string as a Unicode character sequence tobe UTF-8 encoded as a string of bytes to use as a source.

 var r5 = xwt.stream.url("data:WFWE876WEh99sd76f"); var r6 = xwt.stream.url("utf8:this is a test");

You can read a UTF-8 encoded string from a stream like this:

 var myString = xwt.stream.fromUTF(xwt.stream.url("utf8:this is a test"));

You can also parse XML from a stream using SAX like this:

 xwt.stream.xml.sax(xwt.stream.url("http://foo.com/foo.xml"), { beginElement : function(tagname, attributeKeyValuePairs) { ... }, endElement : function(tagname) { ... }, content : function(contentString) { ... } whitespace : function(whitespaceString) { ... } });

7. The XWT object

The xwt object is present in the top-level scope of everyscript. It has the following properties:

General

xwt.box reading from this property returns a new box
xwt.clone(o) creates a clone of object o
xwt.bless(s) returns a blessed clone of stream s

ECMA Library Objects

xwt.date reading from this property returns a new date
xwt.math this object contains the ECMA math functions
xwt.regexp(s) return a regexp object corresponding to string s
xwt.string this object contains the ECMA string manipulation functions

Logging

xwt.log.debug(m, o) log the debug message m, optionally dumping object o
xwt.log.info(m, o) log the informational message m, optionally dumping object o
xwt.log.warn(m, o) log the warning message m, optionally dumping object o
xwt.log.error(m, o) log the error message m, optionally dumping object o

User Interface

xwt.ui.browser(u) opens a new browser window with URL u
xwt.ui.key.control true if the control key is depressed
xwt.ui.key.shift true if the shift key is depressed
xwt.ui.key.alt true if the alt key is depressed
xwt.ui.key.name.alt the name of the "alt" key (usually either "alt", "meta", or "option")
xwt.ui.clipboard the contents of the clipboard; can be read and written to
xwt.ui.maxdim the maximum dimension of any UI element; usually 231, but may be smaller
xwt.ui.screen.width the width of the screen, in pixels
xwt.ui.screen.height the height of the screen, in pixels
xwt.ui.mouse.button either 0, 1, 2, or 3, indicating the mouse button currently being pressed
xwt.ui.frame when a box is written to this property, it becomes the root box of a new window
xwt.ui.window when a box is written to this property, it becomes the root box of a new frame
xwt.ui.font.serif an object whose stream is a a builtin serif font
xwt.ui.font.sansserif an object whose stream is a builtin sans-serif font
xwt.ui.font.monospace an object whose stream is a a builtin fixed-width font

Networking

xwt.net.http not yet implemented
xwt.net.rpc.xml(u) return an XML-RPC call object with endpoint URL u
xwt.net.rpc.soap(u,a,n) return a SOAP call object with endpoint URL u, SoapAction a, and XML Namespace n

Threads

xwt.thread when a function is written to this property, a new thread is forked to call it
xwt.thread.yield() yield the current thread
xwt.thread.sleep(n) sleep for n milliseconds

Streams

xwt.stream.url(u) returns a new object whose stream is drawn from URL u
xwt.stream.unzip(s) unpacks a zip archive from s's stream
xwt.stream.uncab(s) unpacks a cab archive from s's stream
xwt.stream.cache(s,k) wraps a disk-backed read cache keyed on k around s's stream
xwt.stream.watch(s,f) returns an object whose stream is drawn from s's stream, but invokes f(n,d) as it is read from.
xwt.stream.parse.xml(s, h) Use SAX to parse the XML document on stream s with handler h
xwt.stream.parse.html(s, h) Same as parse.xml(), but tries to fix broken HTML.
xwt.stream.parse.utf8(s) treat s's stream as a string encoded as a UTF-8 byte stream and return the string
xwt.stream.homedir equivalent to calling xwt.stream.url() on the file:// url of the user's home directory
xwt.stream.tempdir equivalent to calling xwt.stream.url() on the file:// url of the user's temp directory

Cryptography

xwt.crypto.rsa(k,s) not implemented yet: return a stream which rsa-decrypts stream s with key k
xwt.crypto.rc4(k,s) not implemented yet: return a stream which rc4-decrypts stream s with key k
xwt.crypto.md5(s) not implemented yet: immediately MD5-hash stream s
xwt.crypto.sha1(s) not implemented yet: immediately SHA1-hash stream s

8. Traps

8.1 Simple Traps

You can add a trap to a property by applying the ++= operatorto a function with one argument. The trap will be invoked wheneverthat property is written to.

 <box> foo ++= function(z) { xwt.log.info("foo is " + z); } </box>

If another script were to set the property "foo"on the box above to the value 5, the function above would beinvoked with the argument 5. The function would then logthe string "foo is 5".

Within a trap, the expression trapee can be used toget a reference to the box on which the trap was placed.

The expression trapname returns the name of thetrap executing the current function. This is useful when a functionis applied to multiple traps. For example:

 <box> func ++= function(z) { xwt.log.info("called trap " + trapname); } foo ++= func; bar ++= func; </box>

8.2 Removing Traps

You can remove a trap by using the --= operator with the samefunction you added as a trap:

 <box> var myfunc = function(z) { /* ... */ } // add the trap func ++= myfunc; // ... // remove the trap func --= myfunc; </box>

8.3 Multiple Traps on the Same Property

When the property is written to, each of the trap functions placedon it will be invoked in the opposite order that they were placed onthe box -- the most recently placed trap will execute first. Thislast-to-first execution of traps is called cascading. After thelast trap is invoked, the value is stored on the box (remember, boxesare objects, so they can hold properties just like all otherECMAscript objects).

8.4 Manual Cascades

There are two additional tricks you can use when placing traps. Thefirst is a manual cascade. If you want to cascade to lowertraps in the middle of a function, or you want to cascade with adifferent value than the value passed to you (in effect "lying" tolower traps), you can use cascade. For example:

 <box color="black"> color ++= function(c) { xwt.log.info("refusing to change colors!"); cascade = "black"; } </box>

This effectively creates a box whose color cannot be changed, andwhich complains loudly if you try to do so.

Do not try to do something like this:

 <box color="black"> color ++= function(z) { color = "black"; // INFINITE LOOP! BAD!!! } </box>

To prevent automatic cascading, return true from your function:

 <box color="black"> color ++= function(z) { return true; // the box's color will not change } </box>

8.4 Read Traps

The other trick is a read-trap. Read traps are just like normaltraps, except that you use a function that takes zero arguments instead of one. Read trapsalso do not automatically cascade.

 <box> doublewidth ++= function() { return 2 * width; } </box>

If another script attempts to read from the doublewidthproperty on this box, the value it gets will be twice the actual widthof the box. Note thatthe actual doublewidth property on the box never gets writtento, since the trap does not cascade.

You can manually cascade on read traps as well:

 <box> text ++= function() { return "my text is " + cascade; } </box>

Read traps are only rarely needed -- most of the time a write trapshould be enough.

8.5 Prohibited Traps

To prevent confusing and hard-to-debug behaviors, scripts may notplace traps on any of the properties described in the sections Box Layout Properties, Child-Control Properties,or Other Box Propertiesexcept for childadded, childremoved and surface.FIXME: remove?

8.6 Exceptions and Traps

If an uncaught exception is thrown from a trap, XWT will log theexception, but will not propagate it to the code whichtriggered the trap. If the trap was a read trap, the valuenull will be returned.FIXME: is this right?

8.7 Architectural Significance of Traps

Traps are the backbone of XWT. Since almost all UI programming isevent/demand driven, traps eliminate the need for separatemember/getter/setter declarations, often cutting the amount of typingyou have to do to a third of what it would normally be.

9. Cloning

Cloning is a companion technique for traps; together they canbe used to simulate any sort of environment you might need. When youcall xwt.clone(o), XWT returns a new object (called theclone) which compares with equality (==) to theoriginal object. Furthermore, both objects are "equal" as keys inhashtables, so:

 var hash = {}; var theclone = xwt.clone(o); hash[o] = 5; xwt.log.info(hash[theclone]); // prints "5"

Any writes to properties on the clone will actually write toproperties on the original object, and reads from properties on theclone will read properties on the original object. In fact, the onlything that can be used to distinguish the original from the clone istraps -- a trap placed on the clone is not placed on theoriginal object as well.

XWT self-emulation

When the core first starts up, it clones the xwt object,creates a stream for the initial xwar, and then places a trap on thecloned xwt object so that its empty-string property returnsthe xwar stream. The cloned XWT object is then passed as the third(optional) argument to xwt.apply(), making it the defaultxwt object for the scripts that are executed as part of thetemplate instantiation.

 var new_xwt = xwt.clone(xwt); var stream = xwt.bless(xwt.stream.url("http://...")); new_xwt[""] ++= function() { return stream; } xwt.apply(xwt.box, new_xwt..main, new_xwt);

Note that we called xwt.bless() on the stream before tackingit on to the new XWT object. The bless function returns a clone ofthe object passed to it, with a few traps which are explained below.Additionally, any sub-streams retrieved by accessing properties of theblessed stream will also automatically be blessed (blessed streams aremonadic).

Blessing a stream serves three purposes:

  • Blessed clones always return the appropriate static block when their empty property is accessed; this ensures that references to the static blocks of other templates work properly.
  • Blessed substreams can return their parent stream by accessing a hidden property which is reserved for internal use by XWT. This ensures that XWT can automatically add filename extensions where needed, according to the following rules:
    • If the stream is a template to be applied, the string ".xwt" is appended.
    • If the stream is an image, the string ".png" is appended. If no stream is found, ".jpeg" and ".gif" are tried, in that order.
    • If the stream is an font, the string ".ttf" is appended.
  • Every call to xwt.bless() returns a different object (which happens to be a clone of the object passed to it) with a completely separate set of static blocks.

XWT can self-emulate by using xwt.clone() on the XWT object;this technique is very similar to the use of ClassLoaders inJava. This is useful for a number of applications, includingdebuggers, IDEs, sandboxing untrusted code, remote-control, andothers. For example:

 var newLoadFunction = function(url) { /* ... */ }; var new_xwt = xwt.clone(xwt); new_xwt.load ++= function() { return newLoadFunction; } xwt.apply(xwt.box, .main, new_xwt);

10. Contexts and Threading

10.1 Contexts

From the perspective of an application writer, XWT is strictlysingle-threaded. XWT is always in exactly one of the following threecontexts:

  • Rendering Context (redrawing the screen)
  • Event Context (executing javascript traps triggered by an event)
  • Thread Context (executing a background thread spawned with xwt.thread)

There are two important restrictions on what can be done in particular contexts:

  • The box.mouse property and its subproperties (x, y, and inside) can only be read from within the Event Context, or in a thread context after a the box.mouse property on this box or an ancestor box has been written to.
  • Blocking operations (anything that accesses the network or disk) can only be performed in the Thread Context.

10.2 Background Threads

XWT offers easy access to threads. Spawning a background thread is assimple as writing a function to the xwt.thread property:

 xwt.thread = function() { xwt.log.info("this is happening in a background thread!"); }

The argument set passed to the function is currently undefined and isreserved for use in future versions of XWT. Scripts should notdepend on the number or content of these arguments.

XWT is cooperatively multitasked, so threads must not processfor too long. This was a deliberate choice; cooperativelymultitasked environments do not require complex locking primitiveslike mutexes and semaphores which are difficult for novices tounderstand. The disadvantage of cooperative multitasking is that onethread can hog the CPU. This is unlikely to happen in XWT for two reasons:first, all blocking I/O operations automatically yield the CPU,so the overall user interface never becomes unresponsive because it iswaiting for a disk or network transfer. Second, since XWT is strictlya user interface platform, XWT scripts are unlikely to perform highlycompute-intensive operations that keep the CPU busy for more than afew milliseconds.

11. Events

Every execution of the Event Context begins with an event, whichconsists of a key/value pair, and a mouse position, which consists ofan x and y coordinate. The possible keys are _Press[1-3],_Release[1-3], _Click[1-3], _DoubleClick[1-3],_Move, _KeyPressed, and _KeyReleased.

Here are two example events:

keyvaluemouse xmouse y
Press1true3277
KeyPressed"C-a"1233

An event is triggered by writing the key to the value on a box. Thistriggers any trap handlers which may be present. Once these handlershave executed, XWT figures out which child of the current box containsthe mouse (taking into account that some boxes may cover up others)and writes the key and value to that box. If none of the box'schildren contain the mouse position, XWT removes the leadingunderscore from the key name and writes the value tothat property. Once all the traps on that property haveexecuted, the value is written to the box's parent.

Intuitively, XWT delivers the underscored event to every box from theroot to the target, and then delivers the non-underscored event tothat same set of boxes in reverse order. So the event travels downthe tree to the target, and then back up to the root. The followingexample prints out "first second third fourth" in that order.

 <box> _Press1 ++= function(b) { xwt.log.info("first"); } Press1 ++= function(b) { xwt.log.info("fourth"); } <box> _Press1 ++= function(b) { xwt.log.info("second"); } Press1 ++= function(b) { xwt.log.info("third"); } </box> </box>

In general, you should use the non-underscore names to respondto user input and use the underscored names when you want to overridechild boxes' behavior or route events to particular boxes (forexample, when implementing a focus protocol). This is why theunderscored elements are delivered to parents before children (soparents can override their childrens' behavior), but non-underscoredevents are delivered to children before parents (since, visually, amouse click is usually "intended" for the leaf box underneath thecursor).

Stopping the Process

At any point in this sequence, a trap handler can choose not tocascade (by returning true from the trap handler function).This will immediately cease the propagation of the event. This is howyou would indicate that an event has been "handled".

Re-routing events

At any point in the Event Context, you can write to the mouseproperty on any box. The value written should be an object with twoproperties, x and y. For example:

 _Press1 ++= function(p) { mouse = { x: 32, y: 77 }; }

The coordinates specified are relative to the box whose mouseproperty is being written to. There is no need to supply theinside property; it is computed automatically. Writing tothe mouse property causes XWT to recompute the eventualtarget box, and also alter the values returned by mouse.x,mouse.y, and mouse.inside for any descendantsof the current box. Writing to the mouse property alsoautomatically prevents the event from returning to the box's parents-- it is equivalent to not cascading on the non-underscored event.This ensures that child boxes cannot trick their parent boxes intothinking that the mouse has moved.

If you want the event to "skip over" the boxes between the trapeeand the target, or if you want to re-route an event to a box whichis not a descendant of the current box, simply write the value tothe proper key on the target box.

 <box> _KeyPressed = function(k) { xwt.log.info("first"); } KeyPressed = function(k) { xwt.log.info("sixth"); } $recipient.target = $target; <box id="recipient"> _KeyPressed = function(k) { xwt.log.info("second"); thisbox.target.KeyPressed = k; // inhibit cascade to keep the event from going to $excluded return true; } KeyPressed = function(k) { xwt.log.info("fifth"); } <box id="excluded"> _KeyPressed = function(k) { xwt.log.info("this never happens"); } </box> </box> <box id="target"> _KeyPressed = function(k) { xwt.log.info("third"); } KeyPressed = function(k) { xwt.log.info("fourth"); } </box> </box>

Synthesizing Your Own Events

You can create "fake events" by simply writing to the mouseproperty and then writing a value to one of the underscored propertieson a box. This will have exactly the same effect as if the use hadactually pressed a key, clicked a button, or moved the mouse -- theyare indistinguishable.

Enter and Leave

XWT will trigger the Enter and Leave properties asit walks down the tree, based on the position of the mouse (or thefaked position if the mouse property has been written to).However, Enter and Leave are not events since theydo not implicitly cascade up or down the tree.

Detailed Description of Events

XWT -- The XML Windowing Toolkit (49)
Key Value Significance
XWT -- The XML Windowing Toolkit (50)
Press1 / Press2 / Press3 true Indicates that the use has pressed a mouse button. On platforms with three mouse buttons, the middle button is button 3 -- this ensures that applications written to only use two buttons (1 and 2) will work intuitively on three button platforms.
XWT -- The XML Windowing Toolkit (51)
Release1 / Release2 / Release3 true Indicates that the use has released a mouse button.
XWT -- The XML Windowing Toolkit (52)
Click1 / Click2 / Click3 true Indicates that the user has pressed and released the mouse button without moving the mouse much (exactly how much is platform-dependent).
XWT -- The XML Windowing Toolkit (53)
DoubleClick1/ DoubleClick2/ DoubleClick3 true Indicates that the user has clicked the mouse button twice within a short period of time (exactly how long is platform-dependent).
XWT -- The XML Windowing Toolkit (54)
Move true Indicates that the mouse has moved while within this box, or that the mouse while outside this box if a button was pressed while within this box and has not yet been released
XWT -- The XML Windowing Toolkit (55)
KeyPressed
KeyReleased
string A string is written to this property when a key is pressed or released

If the key was any other key, a multi-character string describing the key will be put. For simplicity, we use the VK_ constants in the Java 1.1 API java.awt.event.KeyEvent class. When a key is pressed or released, the string put will be the portion of its VK_ constant after the underscore, all in lower case.

If the shift key was depressed immediately before the event took place, then the string will be capitalized. Special keynames are also capitalized; shift+home is reported as "

HOME". Symbols are capitalized as they appear on the keyboard; for example, on an American QWERTY keyboard, shift+2 is reported as "@".

If the alt, meta, or command key was depressed immediately before this key was pressed, then the string will be prefixed with the string "

A-". If the control key was depressed while this key was pressed, then the string will be prefixed with the string "C-". If both alt and control are depressed, the string is prefixed with "C-A-".

XWT does not distinguish between a key press resulting from the user physically pushing down a key, and a 'key press' resulting from the keyboard's typematic repeat. In the rare case that an application needs to distinguish between these two events, it should watch for KeyReleased messages and maintain an internal key-state vector.

12. Networking

12.1 Security

Applications downloaded from the network (as opposed to those loadedfrom the filesystem) may only make certain kinds of connections tocertain hosts. See Appendix A for a detailed description of thesecurity policy.

12.2 HTTP

Raw HTTP connections are not yet implemented.

12.3 XML-RPC

XML-RPC objects can be created by calling xwt.net.rpc.xml(<XML-RPCURL>), and then invoking methods on that object. For example,

 Press1 += function(v) { xwt.thread = function() { color = xwt.net.rpc.xml("http://xmlrpc.xwt.org/RPC2/").color.getTodaysColor("Friday"); } }

When the user clicks the first mouse button on this box, it willcontact the server xmlrpc.xwt.org, route to the/RPC2/ handler and invoke the getTodaysColor()method on the color object with a single string argument"Friday". The return value will be used to change the colorof the box the user clicked on.

Note that in this example we spawned a background thread to handle therequest -- the Press1 event is delivered in the foregroundthread, and XML-RPC methods may only be invoked in backgroundthreads. This is to prevent the UI from "locking up" if the servertakes a long time to reply.

If the XML-RPC method faults, an object will be thrown with twoproperties: faultCode and faultString, as defined inthe XML-RPC specification. IfXWT encounters a network, transport, or session-layer error, it willthrow a String object describing the error in ahuman-readable format. Scripts should not rely on the contents ofthis string having any special structure or significance.

If an object with an associated non-empty stream is passed as anargument to an XML-RPC method, it will be sent as a <base64>element. If a <base64> element is found in the XML-RPC reply, itwill be returned as an object with a stream drawn from that byte sequence.

Each object returned by xwt.net.rpc.xml() represents a single HTTPconnection. The connection will be held open until the object isgarbage collected or the server closes the connection. If a secondcall is issued on the object before the first one returns (usuallyfrom a seperate thread), the two calls will be pipelined.This can dramatically improve performance.

XWT supports HTTP Basic and Digest authentication. To useauthentication, pass xwt.net.rpc.xml() a URL in the formhttp[s]://user:password@hostname/. XWT will use Digestauthentication if the server supports it; otherwise it will use Basicauthentication. Please be aware that many XML-RPC serverimplementations contain a broken implementation of Basicauthentication.

12.4 SOAP

SOAP methods are invoked the same way as XML-RPC methods, but with three differences:

  1. xwt.net.rpc.soap() is used instead of xwt.net.rpc.xml()
  2. Instead of specifying just the URL of the service itself, you must specify the URL, the SOAPAction argument, and the namespace to use.
  3. The actual method invocation takes only one argument, which must be an object. This is necessary since SOAP arguments are specified by name, rather than ordering.

SOAP faults are handled the same way as XML-RPC faults except that thecapitalization of the faultstring and faultcodemembers is all lower-case, to match the SOAP spec. Here is aSOAP example:

 Press1 ++= function(v) { xwt.thread = function() { color = xwt.net.rpc.soap("http://soap.xwt.org/SOAP", // endpoint "GETTODAYSCOLOR", // SOAPAction header "http://xwt.org/namespace" // namespace for SOAP-ENV ).color.getTodaysColor( { whichday : Friday } ); } }

As you can see, SOAP is much more verbose, yet does not offersubstantially improved functionality. We recommend that XML-RPC beused whenever possible, and that SOAP be reserved for legacyapplications.

The current XWT SOAP stack does not support 'document style' ormulti-ref (href) data structures.

13. Error Handling

If the XWT Core encounters an error while servicing a function calloriginating in JavaScript, the core will throw a string consisting ofan error code followed by a colon, a space, and a descriptive message.For example:

 "xwt.net.dns.unknownhostexception: unable to resolve host foo.com"

The code should be used to determine how the program should respond toan error. The codes are organized in a hierarchy, so thestring.startsWith() method can be used to determine if an error lieswithin a particular subhierarchy. The descriptive message portion ofthe string may be shown to the user.

XWT -- The XML Windowing Toolkit (56)
xwt.assertion.failed an assertion failed
XWT -- The XML Windowing Toolkit (57)
xwt.io General I/O exceptions
XWT -- The XML Windowing Toolkit (58)
xwt.io.encoding Error translating between character encodings.
XWT -- The XML Windowing Toolkit (59)
xwt.io.zip Attempted to access a corrupt zip archive.
XWT -- The XML Windowing Toolkit (60)
xwt.io.eof End of file encountered unexpectedly
XWT -- The XML Windowing Toolkit (61)
xwt.net.security.prohibitedHost A piece of untrusted XWT code attempted to contact a restricted host. See Appendix A for details.
XWT -- The XML Windowing Toolkit (62)
xwt.net.dns.temporaryFailure An attempt to resolve a hostname failed but it is not known for certain that the hostname is invalid.
XWT -- The XML Windowing Toolkit (63)
xwt.net.dns.unknownHost An attempt to resolve a hostname failed because the hostname was invalid.
XWT -- The XML Windowing Toolkit (64)
xwt.net.socket.closed A socket was closed unexpectedly.
XWT -- The XML Windowing Toolkit (65)
xwt.net.socket.connectionFailed A connection could not be made to the remote host.
XWT -- The XML Windowing Toolkit (66)
xwt.net.url.malformed Tried to parse a malformed URL.
XWT -- The XML Windowing Toolkit (67)
xwt.net.ssl General SSL protocol errors.
XWT -- The XML Windowing Toolkit (68)
xwt.net.ssl.untrustedCertificate The server's certificate was not signed by a CA trusted by XWT.
XWT -- The XML Windowing Toolkit (69)
xwt.net.http.xyz Thrown when an HTTP error code is returned during an operation. The three characters xyz will be the three-digit HTTP status code.
XWT -- The XML Windowing Toolkit (70)
xwt.net.xmlrpc.null The caller attempted to transmit the null value via XML-RPC.
XWT -- The XML Windowing Toolkit (71)
xwt.net.xmlrpc.circular The caller attempted to transmit a circular data structure via XML-RPC.
XWT -- The XML Windowing Toolkit (72)
xwt.net.xmlrpc.specialObject The caller attempted to transmit a "special" object via XML-RPC (for example, a Box or the XWT object).
XWT -- The XML Windowing Toolkit (73)
xwt.null.put A JavaScript attempted to put to a property on the null value
XWT -- The XML Windowing Toolkit (74)
xwt.null.get A JavaScript attempted to get from a property on the null value
XWT -- The XML Windowing Toolkit (75)
xwt.null.call A JavaScript attempted to call the null value

If an exception is thrown inside a trap, the exception will propagateto the script that triggered the trap.

If an uncaught exception is thrown while applying a template, or therequested template could not be found, an error will be logged and thebox to which the template was being applied will be made invisible(visible = false). This ensures that half-applied widgets arenever shown to the user.

Appendices

Appendix A: Security Architecture and Considerations

Due to the expense and hassle imposed by the commercial PKI codesigning architecture, and the fact that it doesn't reallyprovide any security anyways, XWT user interfaces are distributedas unsigned, untrusted code. As such, they are handled very carefullyby the XWT Core, and assumed to be potentially malicious.

XWT's security architecture is divided into defenses against fourmajor classes of attacks:

Malicious UI attempts to acquire or alter data on the client

XWT user interfaces are run in an extremely restrictive sandbox. Theenvironment does not provide primitives for accessing any data outsidethe XWT core except via XML-RPC and SOAP calls. There are nofacilities to allow XWT user interfaces to access the client'soperating system or to interact with other applications on the samehost (unless they provide a public XML-RPC or SOAP interface).

An XWT script may only access a file on the user's hard disk if theuser explicitly chooses that file from an "open file" or "save file"dialog. There is one exception to this rule: if all templatescurrently loaded in the XWT core originated from the localfilesystem, those templates can load additional xwars from the localfilesystem.

The XWT Core is written in Java, so it is not possible forscripts to perform buffer overflow attacks against the coreitself.

XWT applications may only read from the clipboard when the usermiddle-clicks (X11 paste), presses control-V (Windows paste), orpresses alt-V (Macintosh paste; the command key is mapped to XWT"alt"). This ensures that XWT applications are only granted access todata that other applications have placed on the clipboard when the userspecifically indicates that that information should be made availableto the XWT application.

Malicious UI attempts to use client to circumvent firewalls

XWT user interfaces may only make XML-RPC or SOAP calls and load xwararchives via HTTP; they cannot execute arbitrary HTTP GET's or openregular TCP sockets.

XWT will not allow a script to connect to a non-public IP address(10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in RFC1918). There is one exception -- if all templates currently loadedin the core originated from the same IP address, those scripts maymake calls to that IP address regardless of whether or not it isfirewalled. If XWT does not have access to a DNS resolver (because itis using a proxy which performs DNS lookups), XWT will provide theproxy with the appropriate X-RequestOriginheader that the proxy needs in order to maintain security.

The only remaining possible attack is against a XML-RPC or SOAPservice running on a firewalled host with a public address. Assigningsuch machines public IP addresses is a poor network security policy,and doing so squanders scarce public IPv4 addresses. As such, the onusis on the administrators of such machines to explicitly block accessto clients reporting a User-Agent: header beginning with thethree characters "XWT".

Malicious UI attempts to trick user into divulging secret information

All top-level windows created by XWT are scarred -- a stripeand a lock is drawn across the corner of the window. There is no wayfor a user interface to remove this scar. XWT user interfaces may notcreate windows smaller than the size of the scar.

Malicious network attempts to snoop or man-in-the-middle transactions

XWT user interfaces may transmit network data using HTTPS (SSL 3.0)for encryption. XWT will attempt 128-bit encryption, but willnegotiate down to 40-bit if the server does not support strongcrypto. XWT's SSL implementation is currently provided by TinySSL and The Legion of the Bouncy Castle.

All HTTPS connections must be authenticated by the server using acertificate whose name matches the domain name of the HTTPS URL. Thecertificate must be signed by a trusted root CA. XWT trusts the same93 root CAs whose certificates are included as "trusted" in MicrosoftInternet Explorer 5.5 SP2. This provides a minimal level of protectionagainst man-in-the-middle attacks; you should not trust thisconnection with any data you would not normally trust an SSL-enabledweb browser with.

Appendix B: ECMAscript compliance

XWT's scripts are written in a modified subset of ECMA-262, revision 3(aka JavaScript 1.5). The interpreter strays from the spec in a fewways.

Omissions

The following ECMA features are not supported:

  • The undefined value, ===, and !==
  • The new keyword (and ECMAScript object inheritance)
  • eval
  • getter and setter
  • The ECMA this keyword.
  • The String, Number, and Boolean classes. Note that string, number, and boolean values are supported, however.
  • You may not throw the null value.

Additionally, you must declare all root-scope variables (withvar) before using them; failure to do so will result in anexception. Box properties are pre-defined in the scope that scriptsare executed in.

Extensions

  • The token .. is equivalent to [""].
  • Trapping
  • Cloning
  • Extended catch syntax. The following code:
    } catch(e propname "foo.bar.baz") { // ...}
    Is equivalent to:
    } catch(e) { if (e.propname != null && e.propname >= "foo.bar.baz" && e.propname < "foo.bar.baz/") { // ... }}
    Multiple extended-catch blocks can appear at the end of a single tryblock. However, at most one non-extended catch block may appear, andif it does appear, it must be the last one.
  • Since XWT ECMAscripts are wrapped in XML, the lexical token"lt" is be interpreted as <, the lexical token"gt" is be interpreted as >, and the token"and" is interpreted as &&. Thus thesetokens cannot be used as variable names.
  • The identifier static is a reserved word in ECMAScript,but not in XWT.
  • XWT defines an additional reserved word, "assert", which willevaluate the expression which follows it, throwing axwt.assertion.failed exception if the expression evaluates tofalse.
  • To ensure that XWT files appear the same in all text editors, tabcharacters are not allowed in XWT files.

Appendix C: Logging and Command Line Invocation

Very early in the loading process, XWT begins logging messages aboutwhat it is doing. Where this output is logged to differs by platform;currently it goes to standard output when running inside a JVM, and to$TMPDIR\xwt-log.txt on Win32 (where $TMPDIR is thevalue returned by GetTempPath()). The logs contain a lot ofvaluable debugging information and performance hints; if you arehaving trouble developing an XWT application, be sure to check thelogs.

If XWT encounters a serious problem before it starts logginginformation, or if it is unable to open the log file, it will abortimmediately with a critical abort, which will be displayed on theconsole for POSIX-native cores and in a dialog box for JVM-based andWin32-native cores.

You can invoke XWT directly from the command line duringdevelopment. When using a JVM, the invocation format is:

java -jar path-to-xwt-jar [-sv] source-location [initial-template]

Where path-to-xwt-jar is the path to xwt.jar,which can be downloaded here.

On Win32, the invocation format is:

xwt.exe [-v] source-location [initial-template]

The file xwt.exe is placed in Windows' ActiveX cachedirectory the first time XWT is used on the machine. The ActiveX cachelocation depends on what version of Windows you are using; on newerversions of Windows it is C:\WINDOWS\DOWNLOADED PROGRAMFILES\. You can also extract xwt.exe fromxwt.cab, which is available here.

The source-location parameter can be either the pathto an xwar archive, the http url of an xwar archive, or the path to adirectory comprising an unpacked xwar archive.

The initial-template parameter is the stream name ofa template to be used as the initial template. If ommitted, itdefaults to main.

The -v option causes XWT to enable verbose logging; this willcause it to log lots of information to the log file. Thisoption will also substantially decrease XWT's performance.

Appendix D: ECMAscript and JavaScript tutorials

XWT implements a subset of ECMAscript revision 3, which isequivalent to JavaScript 1.5. For information on the differences,please see Appendix C.Some useful tutorials include:

  • Netscape's JavaScript 1.2 Reference. Although this document is out of date, it is arguably the best guide available for free on the Internet. The changes from JavaScript 1.2 (aka ECMA-262 r1) to 1.5 were minimal, and many of them were omitted from XWT.
  • O'Reilly's JavaScript: The Definitive Guide, by David Flanagan and Paula Ferguson. The latest edition of this book covers JavaScript 1.5 (ECMA-262 r3).
  • The official ECMA-262 specification. This is an extremely technical document.

Appendix E: Grammars

Grammar support is experimental in this releaseand may not work properly. It may change in incompatible ways ordisappear completely from future releases

Grammars are defined with a statement in the following form:

 a ::= b { c }

A grammar is really just another function; once defined you can't tellit apart from an ordinary function. A grammar takes one argument,which can be a string or stream. The argument is parsed and theresult of executing the code block 'c' is returned.

The property 'a' is read; if the value is a grammar, a new productionrule (ie a new alternative, as with '|') is added to that grammar(this is a destructive update). This allows you to add productions topre-existing grammars (for example, adding a new type of expression toa programming language by extending the 'expr' grammar). If the oldvalue is not a grammar, the value is discarded and a new grammarobject is created.

The value 'b' is a pattern, which may consist of seven simpleprimitives:

  • string literals
  • grouping parens ()
  • combinators: | + * ?
  • references to other grammars

The value 'c' and the braces surrounding it are an *optional* codeblock, in which the following identifiers are bound:

  • The identifier 'whole' is bound to the string matched by the entire expression. If the code block is omitted it behaves as if it were "{ return whole; }".
  • For every reference to another grammar which was matched in the pattern, the *name used to reference that other grammar* will be bound to the value returned by its code block. Here's an example of this important distinction:
     var foo ::= 'a' | 'b'; var bar ::= foo; var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };

    On the last line, the identifier 'bar' serves two purposes: it pulls in the definition of the pattern *and* acts as a binder within the scope of the braces.

    If a reference is matched multiple times (either because it appears multiple times in the pattern or because the * or + operator was applied to it) then its name will be bound to an array containing the matches.

Here is the metacircular definition of the grammar facility:

 grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?) identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')* char ::= '\0x0000'..'\0xffff' literal ::= '\'' char+ '\'' | '\'' char '\'' '..' '\'' char '\'' pattern ::= identifier | literal | '(' pattern ')' | pattern '+' | pattern '?' | pattern '*' | pattern pattern | pattern '|' pattern

Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
XWT is a trademark of Adam Megacz

XWT -- The XML Windowing Toolkit (2024)
Top Articles
Latest Posts
Article information

Author: Laurine Ryan

Last Updated:

Views: 5567

Rating: 4.7 / 5 (77 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Laurine Ryan

Birthday: 1994-12-23

Address: Suite 751 871 Lissette Throughway, West Kittie, NH 41603

Phone: +2366831109631

Job: Sales Producer

Hobby: Creative writing, Motor sports, Do it yourself, Skateboarding, Coffee roasting, Calligraphy, Stand-up comedy

Introduction: My name is Laurine Ryan, I am a adorable, fair, graceful, spotless, gorgeous, homely, cooperative person who loves writing and wants to share my knowledge and understanding with you.