4.1 Fundamental classes
In GWindows, you define a user interface as a tree of objects. gwincls.h provides the following fundamental classes:
WindowPair - This is the class that represents a pair window in the window tree. Generally, you won't want to change any of the properties on a WindowPair. Window pairs provide a checkredraw method, which will redraw the window tree from this point, as needed. Redrawing a window pair redraws its children, and likewise, updating a WindowPair updates its children.
It is important that every WindowPair has exactly two children.
GWindow - This class represents concrete, visible screen
windows. The properties split and
used to determine the stated size of the window. GWindow
class objects may provide methods to redraw and update
the window, and may specify
stylehints it wishes to
use. The attribute
abssplit is used to determine the kind
of split. If it's set, the window's
size is "absolute" -- the window is that many lines (for text
windows) or that many pixels (for graphics windows). If not, the size
is a percentage. Remember from chapter 2, however, that a window's
size metrics may not refer to the window itself, but to a window pair
somewhere further up the tree.
is further separated into three classes reflecting the basic window types under Glk.
TextBuffer- This is a scrolling window of text. You can print to it, or draw graphics in it, but you can't reposition the cursor. Many Glk implementations allow
TextBufferwindows to be scrolled. In a
TextBuffer, the text may be displayed in a proportional font, depending on the implementation and user preferences. Generally, the main output window will be a
TextBuffers support single-character and line input, as well as hyperlinks if available, but do not support mouse input (except in the form of hyperlinks ** Note: Hyperlinks aren't really mouse input; in GlkDOS, for example, you select hyperlinks by picking the link you wish to activate from a list at the bottom of the screen. However, most interpreters use the mouse to select hyperlinks. A hyperlink is a region of text which, when selected, generates a hyperlink event. The system is similar to links in a web page.)
TextGrid- This is a non-scrolling window which displays fixed-width text arranged on a grid. You can position the cursor within the window.
TextGridssupport character, line, and mouse input. Some Glk implementations also support hyperlinks in grid windows. The status line and menus are usually
GraphWin- This is a window which exists purely for graphics. Text cannot be printed in a
GraphWin, and they support neither keyboard input nor hyperlinks. They do support mouse input, however. Output in a
GraphWinis, obviously, graphical. You can draw blorb images in a
GraphWin, or draw manually using Glk's drawing primitives (which, at this time, consist of drawing and erasing colored rectangles). Because graphics are an optional capability, GWindows will replace
GraphWinwindows with blank windows if the system detects that graphics are not available.
WindowPairobjects provide a
winidproperty, which contains the Glk opaque reference for the window. If you wish to use a Glk function on a window, you pass this
winidproperty to Glk:
GWindows also provide a way for determining their actual
size on the screen. The properties
contain the actual size of the window, in whatever units are
appropriate (characters or pixels). These values are updated whenever
the window is redrawn, so that they will be correct even if the user
maliciously changes his screen size.
Some techniques are common enough that GWindows provides predefined classes for a special-purpose window.
A widget is a
GWindow which has special code to
make the window do a certain task. GWindows ships with a large
number of widgets to provide common tasks. Some examples of widgets
GStatusLine (a widget which emulates the standard
GPopupWin (a widget which provides a window
which changes its size when activated), and
widget which generates a menu of options). Though new widgets are
being created all the time, the ones which existed when this manual
was written are documented in section 7.
Because you may not want all of the widgets, and because you may want to add new widgets later, each widget is kept in a separate file. Some widgets are based on other widgets. A well-written widget file will include its required widgets for you.
There are two fundamental types of widget:
An abstract widget encapsulates a single specific
kind of behavior. An abstract widget isn't a complete
GWindow on its own; it has to be combined with another
widget. For example,
GPopupWin is a widget for any kind
of window that pops up. It is not a window on it's own though; a
GPopupWin has to be combined with a
(or with another widget) to specify what sort of window should
actually pop up.
There is a special abstract widget called
GCombiner. This widget doesn't do anything on its own;
its purpose is to combine two widgets which offer overlapping
properties into a single widget. For example, a
changes its size when it is "activated". A
loads a new menu when it is "activated". To have both happen,
the classes have to be combined using a
connects the "activate" methods.
gpopmen.h shows the
GPopupMenu class, which does exactly this. Because
GCombiner is such a powerful widget, it's recommended
that you steer clear of it until you're very comfortable with GWindows
A concrete widget is a widget which is a complete GWindow in
and of itself.
GMenu, for example, is a concrete
widget. You can create a
GMenu, and insert it directly in
your user interface as you would a
This document will use the term printable for any value
which can be output by the
function. GWindows often uses printables to generate its output.
4.5 Event Handlers
An event handler is a function which is run in response
to some event in the outside world. Examples of user events include
character events (the player just typed a character), mouse
events (The player just clicked with the mouse), and timer
events (The computer's clock just went "tick"). Glk offers a wide
variety of events. Line input events (The event caused when the
player types out a whole command and presses enter) are handled by the
standard library. GWindows offers event handlers for mouse and
character events, and takes care of redraw events (The
interpreter has lost track of the screen, and needs to have it
redrawn) and arrange events (Something has caused some windows
to change their sizes, so they should be updated to fit the new
size). Other events are handled by your
4.6 GWindows Installation
Like Inform's standard library, GWindows consists of three
gwindows.h. To use GWindows in a program, you must
Any configuration constants you wish to use should go before the
gwindefs.h. Any entry points you wish
to use should go before the inclusion of
Any GWindows widgets you wish to use should be included after
GWindows requires L. Ross Raszewski's
(version 4.0 or greater) and John Cater's
will be automatically included by GWindows.
GWindows uses the following global variables to monitor the state of the interface:
The first group of variables help GWindows interact with the standard library. You can read them whenever you like, but if you change them, you should re-start the window system to make the changes take effect. Failure to do this might confuse GWindows.
GWindowwhich serves as the main output window. It is always the case that the library variable
gg_mainwinwill contain the same value as
Main_GWindow, as it does in the standard library. However, you might prefer input to come from a separate window (The way that input into, say, a mud client might occur in a separate window at the bottom of the screen). If you set the
Input_GWindowto another window, input will come from that window instead.
The next group of variables communicate information to GWindows. You can set them at any time.
cmd_overrideis set to some printable, this will happen. Generally, you will want to do this only within an event handler.
The final global variables are read-only.
GW_Abilities & Xis nonzero, where
Xis one of the following:
: Graphics windows are available
: Image drawing in graphics windows is available
: Mouse input is available in
: Mouse input is available in
@throw GW_Massive_Error errtype;, where errtype is some value identifying the error (Preferably a constant string describing the problem.)
To be nice to players, you might want to check
GW_Abilities when setting up your interface; if you're
using a graphical interface like the one above, you should also create
a textual version, and use that if
4.8 GWindows configuration constants
Main_GWindowis not equal to
4.9 GWindows Entry Points
GWindows installs itself using the Glk entry points of the standard library. As such, it offers its own entry points to replace them:
GWindows also uses the
entrypoint. It provides the entrypoint
(which takes no parameters), which is equivalent to
InitGlkWindow(0), and is called whenever the user
interface is being created fresh. You are required to provide
this function. It should, at the very least, do the following things:
Active_UI is set correctly.
Main_GWindow is set correctly.
If you're using a separate input window, make sure
Input_GWindow is set correctly.
By "correctly", we mean that the variables have the proper
values for this point in the game. If you use more than one user
InitGWindows should set the
variables to their initial states if they are zero -- if they are
nonzero, you can assume that the interface is being recreated (say,
after a restore), and the values are already set correctly.
GWindowsHandleError(x) is called whenever an
otherwise-irrecoverable error occurs (That is, it will only be called for errors
so heinous that the system cannot continue) . Return 2 from this function
to indicate that the problem has been dealt with -- though it's usually
far too late by then. The parameter describes the error. GWindows itself uses
the following error codes:
GW_ERR_ABS_GRAPH"Attempt to coerce a window of absolute size into a blank window." -- GWindows will automatically replace graphics windows with blank windows if graphics are not available, but if the graphics window has an absolute size, this is not possible. This error will generally be raised if you attempt to use a graphical UI on an interpreter not supporting graphics.
GW_ERR_NO_OPEN"Attempt to open a window failed." This is raised if glk refused to open a requested window.
GW_ERR_RED_NO_WIN"Attempt to redraw a window which is not open." This is raised if a window which is not part of the current active interface receives a redraw message (for example, because you called GW_ForceRedraw on the wrong UI)