This report is a programmer's reference manual for Trestle, a Modula-3 window system toolkit.
Trestle has been implemented over two underlying window systems: X [XSpec] and the native Firefly [Firefly] window system developed at SRC. Other implementations are possible, but at present the only widely available implementation is Trestle-on-X.
To use Trestle-on-X, you need a Modula-3 compiler and an X server for your system. The Trestle code is an application library layered on top of Xlib, the standard X client library. Trestle applications obey X's ICCCM protocol for cooperating with the window manager and other applications, so you can use your favorite window manager and mix Trestle applications freely with other X applications.
The reference manual is self-contained but non-tutorial; you would do well to read the Trestle Tutorial first [TTut] (Chapter 7). We assume you are familiar with Modula-3 [M3a] [M3b] [M3c] .
The Trestle abstraction. A Trestle.T is a connection to a window system. The window system is assumed to have a keyboard, a pointing device, and one or more display screens. For example, in Trestle-on-X, a Trestle.T is implemented by a connection to an X server.
Each screen is a raster display, whose image is stored in a frame buffer containing a rectangular array of pixels. Changing the contents of a frame buffer is called painting , since it changes the image displayed to the user. The different screens can be of different types (e.g., color or black and white).
Trestle imposes an hv-coordinate system on each display screen, in which the h coordinate increases from left to right and the v coordinate increases from top to bottom. The Trestle interface allows you to determine the number of screens and also their types, dimensions, and the positions of their coordinate origins.
We will call the pointing device the mouse, although it might be a stylus or other instrument. The mouse generally has one or more buttons that the user can click down and up.
The system displays a cursor , a small arrow or other image that points at some pixel of some screen. By moving the mouse the user can move the cursor around the screen or from one screen to another. Applications can change the shape of the cursor to convey information to the user.
The complete Trestle interface is described in Section 3.
The VBT abstraction. The key abstraction in Trestle is the "virtual bitmap terminal" or VBT. A VBT represents a share of the keyboard, mouse, and displays. VBTs are comparable to the windows, widgets, and viewers of other systems.
An application is generally organized as a tree of VBTs, with the root VBT representing the top-level application window. The internal nodes are called split VBTs or parent VBTs: they divide their screens between one or more child VBTs according to some layout depending on the class of split. At the leaves of the tree are VBTs that contain no subwindows.
A typical application consists of a number of leaf VBTs whose behavior is specific to that application, together with some more leaf VBTs that provide buttons, scrollbars, and other "interactors", all held together by a tree of splits that define the geometric layout. A split with only one child is called a filter . For example, a BorderedVBT is a filter that adds a border around the child's screen. A split that can have more than one child is called a proper split. For example, an HVSplit is a split in which the children are laid out horizontally or vertically.
Sections 4, 5, and 6 describe Trestle's built-in proper splits, filters, and leaves.
To obtain a share of a Trestle display, an application creates a VBT and "installs" it with the procedure Trestle.Install, which allocates some portion of some display to the VBT, within which the application can paint. The VBT is said to be installed and is called a top-level window. The size and position of top-level windows depends on the arguments to Trestle.Install and on the whim of the window manager.
A VBT imposes an hv-coordinate system on its screen. A top-level VBT's coordinate system need not be the same as the coordinate system of the screen on which it is installed. The translation between the two coordinate systems can be determined through the Trestle.ScreenOf procedure.
In a split VBT, the translation between the parent and child coordinate systems depends on the class of the split. Trestle provides one filter (TranslateVBT) whose sole purpose is to position the child coordinate system origin at the northwest corner of the child's domain, since this is convenient for some applications. All the other built-in splits make the child coordinate system agree with the parent coordinate system, since this is usually the most convenient.
Information flows through a VBT in two directions. Painting commands travel from the leaves of the tree towards the root. Events like mouse clicks and cursor positions travel from the root towards the leaves. A VBT is an object with methods for handling events; to deliver an event to a VBT, the system invokes the appropriate method. The VBT interface in Section 2 specifies the event-handling methods and the painting procedures.
The screen of a VBT is forgetful; that is, its contents can be lost at any time, at which point the system activates its repaint method, which is expected to repaint what has been lost. Similarly, the height, width, and coordinate origin of a VBT's screen can change at any time, in which case the system activates its reshape method. Finally, the type of the pixels in a VBT's screen can change (e.g., from color to monochrome), in which case the system activates its rescreen method. These events reflect the fact that the user of the window system can expose portions of a top-level window, reshape top-level windows, and move top-level windows from one display to another.
Selections and event-time. From the user's point of view, a selection is a highlighted occurrence of text or other data that can be made in a window via some gesture, such as sweeping with the mouse. Selections are supported to make it easy for users to cut and paste text and other data between windows. A particular selection is always in at most one window at a time, namely the "owner" of the selection. If a selection is in no window at all, its owner is NIL.
From the programmer's point of view, the selection owner is a VBT-valued variable shared between all applications. The procedure VBT.Acquire is used to acquire a selection. Whenever a VBT acquires a selection, the previous owner is notified, so that it can take down any highlighting or other feedback. Any VBT can own a selection, not just a top-level window.
The procedures VBT.Read and VBT.Write are used to read or write the value of the selection. Calls to Read and Write are implemented by locating the selection owner (which could be in the same address space as the caller to Read or Write, or in a different address space) and activating its read or write method, which is responsible for doing the work. The selection values communicated by Read and Write can be of any type that can be pickled (see Section 3.6 of Systems Programming with Modula-3 [SPwM3] ); in particular, they can be of type TEXT.
The VBT to which user keystrokes are directed is called the keyboard focus. Some window managers define the focus to be the window containing the cursor; other window managers move the focus in response to mouse clicks. Trestle applications work with either kind of window manager.
Trestle classifies the keyboard focus as a selection, since it is a global VBT-valued variable that can be acquired and released. If you want to receive keystrokes, you must acquire the focus. If this succeeds, you should provide some feedback to the user, for example by displaying a blinking caret. (Even if the window manager is identifying the top-level window containing the focus, you should still let the user know which subwindow contains the focus.) When you are notified that you have lost the focus, you should take down the feedback.
It is also possible to send any selection owner a "miscellaneous code", which will be delivered by activating the misc method in the owner. For example, the way that Trestle notifies a window that it no longer owns a selection is by sending it a miscellaneous code of type Lost. Miscellaneous codes are also used for other purposes; for example, to notify windows that they have been deleted.
The event-time protocol. There are many potential race conditions involving selec- tions. For example, suppose that the user clicks in window A , expecting it to acquire the keyboard focus. But window A is slow; perhaps it is paging or blocked in a call to a server that is being debugged; and does not respond. So the user clicks in another window B , which acquires the keyboard focus, and types away. A few minutes later, window A comes to life and grabs the keyboard focus. Suddenly and unexpectedly the user's typing is redirected to A instead of B . Similar race conditions can occur with selections other than the keyboard focus; for example, you select a file name, then activate a delete command by clicking, then wonder how long you must wait before it is safe to make another selection.
Trestle uses the event-time protocol to deal with these race conditions. This means that Trestle keeps track of the current event time, which is the timestamp of the last keystroke, mouseclick, or miscellaneous code that has been delivered to any VBT. Attempts to read, write, or acquire a selection must be accompanied by a timestamp, and if this timestamp does not agree with the current event time, the attempt fails. This guarantees that only VBTs that are responding to the user's latest action can access the selections.
When Trestle activates a window's method to deliver it an event, it generally waits for the method to return before it delivers any events to any other windows. This gives the window a fair chance to use the time stamp in the event to access the selections. However, if the method takes an unreasonably long time; more than a few seconds; Trestle may give up on the window and start delivering events to other windows anyway.
As a consequence, if you must do a long-running computation in response to a user event, then you should fork the computation in a separate thread and return from the method promptly, to avoid delaying the user, who may want to click in another window. You should also do any operations that require accessing the selections from the main thread before the method returns, since an event-time operation in the forked thread will fail if the user has continued typing or clicking during the forked computation.
The geometry interfaces. The interfaces Axis, Point, Rect, Region, Trapezoid, and Path are explained in Section 8. In brief, Axis.T.Hor and Axis.T.Ver name the horizontal and vertical coordinate axes; a Point.T (or simply a point ) is a pair of integers representing a point in the plane; a Rect.T is a rectangle of points whose sides are parallel to the coordinate axes; a Region.T is an arbitrary set of points represented as a sorted array of rectangles; a Trapezoid.T is a set of points bounded by two horizontal lines and two lines with arbitrary slopes; and a Path.T is a path in the plane represented by a sequence of straight and curved segments.
Resources. A pixmap is a rectangular array of pixels. A bitmap is a pixmap in which the pixels are one bit deep. For example, a large pixmap could represent a photographic image; a small bitmap could represent a cursor shape. Trestle also uses a pixmap to represent the infinite texture that results from tiling the plane with translations of the pixmap. Thus whether a pixmap represents an infinite texture or a bounded image depends only on the context in which it is used.
A font is a typeface suitable for painting text.
A painting operation is an operation code for changing the values of pixels in the frame buffer of a display screen.
Pixmaps, cursor shapes, fonts, and painting operations are collectively called resources. Resources come in both screen-independent and screen-dependent forms. A screen-independent resource varies with the screentype to produce a similar effect on all types of screens. For example, two important screen-independent painting operations are PaintOp.Fg and PaintOp.Bg, which set pixels to a screen's foreground and background colors. In contrast, a screen-dependent resource is useful only on a particular screentype. If it is used on a VBT with the wrong type of screen, the system won't crash, but the effect will be non-deterministic; a screen-dependent painting operation that blackens a pixel on a black-and-white screen might set a 24-bit pixel to chartreuse on a true-color screen.
Screen-independent resources are convenient, but screen-dependent resources are sometimes necessary for exploiting the capabilities of specific display hardware.
The screen-independent resource types are called Pixmap.T, Cursor.T, Font.T, and PaintOp.T. The interfaces where these types are defined also provide procedures for generating useful resources. For example, PaintOp.FromRGB will produce a screen-independent painting operation that sets a pixel to a particular color; Font.FromName will produce a screen-independent font given the name of the typeface.
The corresponding screen-dependent resources are ScrnPixmap.T , ScrnCursor.T, ScrnFont.T, and ScrnPaintOp.T. The interfaces where these types are defined also specify the representations of the raw values; the layout of pixmaps in memory, the attributes of fonts, and similar details that all sane people prefer to avoid.
Converting a screen-independent resource into the corresponding screen-dependent resource for a particular type of screen is called resolving the resource. The Palette interface will give you a screen-independent resource if you give it a closure for resolving the resource. You can therefore use the Palette interface to construct your own screen-independent resources. For example, you could produce a (PaintOp.T, Font.T) pair that produces red Times Roman text on a color display and black italic text on a black-and-white display; or a Pixmap.T that selects between a low and a high resolution bitmap depending on the screen resolution.
The closure for resolving the resource will be invoked automatically when a top-level window moves to a new screentype for the first time. The closure will be passed an argument of type ScreenType.T, which represents a type of display screen. A ScreenType.T determines the depth of the screen's pixels (e.g., one or eight), the method for associating a color with a pixel value (e.g., color-mapped or true-color), the set of allowed operations on its pixels, and the repositories for screen-dependent fonts, cursors, and pixmaps that can be used on the screen.
Implementing your own splits. Most applications can be built by using Trestle's built-in splits and leaves, together with one or more leaf VBTs specific to the application. If you are programming a more sophisticated application, you may want to augment the built-in splits with some of your own. Section 9 introduces the interfaces that allow you to do this.
To implement a leaf VBT, you only have to supply methods to handle the events that flow down the tree (from the root to the leaves). To implement a split VBT, you also have to supply methods to handle the information that flows up the tree, such as painting commands or commands to change the cursor shape. The VBTClass interface declares these methods and presents their specifications.
Very few splits override the method for painting, since the default behavior, which is to clip to the child's domain and relay the painting to the parent, is usually what is desired. But some splits do override this method: for example, the ZSplit, whose child windows are allowed to overlap one another, has a paint method that clips its children's painting to the visible parts of their domains. And the top level window has a painting method that translates VBT painting commands into X painting commands and relays them to the X server. The interfaces Batch, BatchUtil, and PaintPrivate reveal the details necessary to override painting methods.
The remainder of the reference manual consists of complete Modula-3 interfaces printed in typewriter font and interspersed with commentary printed in roman font. Some of the commentary is in the form of "pseudo-Modula-3" program fragments, which are also printed in typewriter font.
The Trestle release that accompanies SRC Modula-3 version 2.0 contains several interfaces that are not documented in this reference manual. For example, the VTextVBT interface provides editable text VBTs and the TrestleAux interface allows you to set window manager parameters and do strange things to top-level windows. The specifications for these interfaces are directly in the Modula-3 interface files.