You are on page 1of 8

Chapter 7

Creating and
Managing Windows

The preceding chapters provide an overview of X: how to use it, how an


X application is structured, how Xlib is used to create and manage X re-
sources, and how to handle events. This chapter begins an examination
of individual aspects of X programming, beginning with a description of
the basic concepts of windows in X and then delving into the details of
creating, destroying, and otherwise manipulating windows in X.

Basic Window Concepts


Windows are the reason programmers use the X Window System.
Windows are the mechanism that enables several applications to share
the limited space in a physical display screen."'Each application confines
'its output to its own window-an area of the screen.-and accepts input
from the mouse and the keyboard when the pointer focus is in that win-
dow. By enabling windows to overlap one another, the X Window
System can give each application a reasonable amount of space on screen
without one getting in another's way. The user can interact with a
specific application by adjusting the view of that application's window
so that the entire window is visible. You can think of each window as a
small virtual display screen (virtual because it is not real). Each applica-
tion can use this virtual screen without regard to the other applications
that also are displaying in the same physical screen. The windowing sys-
tem ensures that output meant for a specific window does not affect the
contents of any other windows.
Wi' dow System
--m",ing theX In
ppt TfIIf1: ~.--

. indows (0 organize output is not new. It is widely used for graphics as well as
red wdisplays. For examp Ie, many app I'Icatlons
The idea o.fusIng . ror
C 'MS-DOS systems use ch aracter_ Figure 7.1.
onen . d ows, f,or t h'elr user mtenace. A hierarchy of
ch.aracrer-
d windows, or rext wm . C Th e M'acmtos h user mtenace,
. C
Microsoft
windows inX
on.enl~ws,and X use bitmapped graphics windows. Despite the common goal of organizing outpUt
:::Iogical manner, the window systems have varying terminologies, coordinate systems, and ways
of organizing the windows. For example, each window has a parent in X and Microsoft Windows,
but the Macintosh does not have thar concept. To make effective use of windows, you must learn
the terms and concepts that are unique to the window system you are using.
In X, windows are usually rectangular areas of the screen where applications display their output.
Windows can overlap one another on the screen. Typically, each X application has at least one window B.3.1 B.3.2 8.3.3

on the screen. A special X application, the window manager, enables users to arrange the windows
and shuffle them around as if they were pieces of paper on a desktop. One important aspect ofX's
GjB I Cancel I
model of windows is that they are organized in a strict parent-child hierarchy.

Window Hierarchy
All windows in X are organized in a hierarchy:
.• At the top of the hierarchy is the root window, which occupies the entire screen.
~ Every window, except the root, must have a parent.
.• Each window is the child of some other window.
Slacking order of lop·level windows

The main window of an application is a child of the root window. Many more windows usually - - - - - - •• ~ Top

exist within an application's main window. A window can be of arbitrary size, but the server does
not draw any part of a child window that falls outside the boundaries of its parent.
Think of the hierarchy of windows as a family tree, with the root window at the top. A window may
have one or more children and each child may have more children. Figure 7.1 shows a hypothetical
layout of windows together with their tree structure. Notice how there are several levels in the tree,
and there are one or more windows at each level. You can think of the number oflevels as the depth
of the tree, and the windows at the same level as its breadth. X enables you to have as deep a hier-
archy with as much width at each level as you want. Applications routinely use a large number of
windows to build a user interface.
You are already familiar with the terms parent and child. Additionally, the following terms apply to
the window hierarchy:
Stacking Order
.• Sibling. All children of a parent are called siblings. In Figure 7.1, the windows B.l, B.2,
and 8.3 are siblings. They are also called the subwindows of B. x clips all children against the boundary of their parent. In case of overlap among siblings, how-
~ver, the order determines which windows will be fully visible. This order of displaying the siblings
.• Descendant. The descendants of a window are all windows below it in that branch of the
ISknown as the stacking order. If the siblings do not overlap, the order in which they are displaye
hierarchy. Thus, in Figure 7.1, B has nine descendants-the windows B.l, B.2, B.3, B.2.1, does not matter.
B.2.2, B.2.3, B.3.1, 8.3.2, and B.3.3. None of these windows is a descendant of A.
Descendants are also referred to as inferiors. The stacking order of the root window's children is very important, because these are the top-level
.• Ancestor. The ancestors of a window are all windows above it in that branch of the family windows of applications. For example, in Figtire 7.1, windows A and B are siblings of the root, with
tree. Thus, the root window is the ancestor of all windows. In Figure 7.1, B is the ancestor A at the bottom and B at the top of the stacking order. That is why all of B is visible but portions
of B.l, but A is not, because A is not in the same branch as B.l. of A are obscured by B. By changing the stacking order of the root window's children, the user can
decide which application's window is fully visible on the'screen. The user manipulates the stacking
order through the window manager, which does the job by calling Xlib functions, such as
XCirculateSubWindows, XRaiseWindow, XLowerWindow,andXRest ackWindow.

Coordinate System and Geometry


In X, a window has a width, a height, and a border width. The height and width do not include the
border..,Each window also has a coordinate system with the origin at the upper-left corner just in-
side the border (see Figure 7.2). Additionally, the position of the window is specified by the coor-
dinates of its upper-left corner (outside the border) in its parent's coordinate frame. Collectively,
the position and size of a window is known as its geometry. Applications usually enable the user to
specifYthe geometry of the main window. (See Chapter 3, "Exploring X Applications," for an ex-
ample of how to specifYthe geometry.)

The dimensions of windows and the units of the coordinate systems are specified in pixels, but Xlib
has functions that enable you to get the width and height of the screen in millimeters
(XWidthMMOfScreen and XHeightMMOfScreen) as well as in pixels (XWidthOfScreen and
XHeightOfScreen). Using the information provided by these functions, you can convert back and
forth between pixels and millimeters.

Figure 7.2.
Coordinate system and
geometry of a window in X

Position of this
window in parent's
coordinates = (x.y)

X assumes that the coordinates are discrete and each coordinate lies at the center of a pixel. Thus,
the origin (0,0) is at the center of the pixel at the upper-left corner, inside the border (see
Figure 7.3).
} min_aspect, max_aspect;
int base_width, base_height; /* Window size and gravity */
int win_gravity; /* (see later in this chapter) */
XMapWindow(theDisplay, theMain); XSizeHints;
XFlush(theDisplay);
i1'(XGetWindowAttributes(theDisplay, theMain, &MainXWA) == 0) When setting up an XSizeHints structure, you need not specify all fields of the structure. The x, y,
{ width, height, min_width, and min_height are the most commonly specified fields. You set bits
fprintf (stderr, "Error getting attributes of Main. \n" ); in flags to indicate the fields being specified. You can do this by setting flags to the bitwise-OR
exit (2) ;
of named constants defined in the header file <X11/ Xut il. h>. For example, to set the fields men-
} tioned above, flags is set to the bitwise-OR of the constants PPosition, PSize, and PMinSize.
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . - . - . - - - - - - - - - - - - - -* / Here is how these fields are set in ini tapp:
void usage ()
{
fprintf (stderr, "%s [-display name] [-geometry geom]\n',
theAppName);

/* Fill out an XsizeHints structure to inform the window manager


* of desired size and location of main window.
*/
if«(p_XSH = XAllocSizeHints()) == NULL)
Window Manager Interaction {
fprintf (stderr, "Error allocating size hints! \n") ;
The extra steps in setting up the top-level window of an application involve cooperating with the exit (1);
}
window manager. In addition to maintaining the layout of all top-level window~ of the application, p_XSH->flags = (PPosition : PSize : PMinSize);
it takes care of other important tasks, such as deciding which window gets the keystrokes and when p_XSH->height = height;
to install a new colormap so that applications can disp ay colors properly. For all this to work, the p_XSH->min_height = p_XSH->height;
p_XSH->width = width;
applications must cooperate with the window manager; by design, the window manager is a peer of p_XSH->min_width = p_XSH->width;
the other applications, not a superior. p_XSH->x = x;
p_XSH->y = y;
Cooperation with the window manager takes the form of giving hints to it. You call certain Xlib
functions to notify the window manager of the main window's recommended position and size. The position and size come from the arguments passed to the initapp function. The minimum
The window manager does its best to accommodate the request, but the application should be pre- size is assumed to be the same as the specified size. The window manager will not enable the user to
pared to handle the contingency of having a window smaller than it requests. ..• reduce the window below this minimum size.

The P prefix in the names for the constants used to define the flags means that these are program-
Program-Specified Position and Size specified values.

You can use the convenience function XSetWMProperties to give the window manager several useful
hints and to inform it of the main window's preferred position and size. You specify the position
and size, or geometry, in an XSizeHints structure, which is defined in <X11/ Xutil. h> as the fol-
Xlib has many structures with several data fields for which not all fields need to be specified
lowing:
for a function. In such cases, the structure includes a flags field whose bits are used to
typedef struct indicate which of the other fields are set. You can set the flags field by bitwise-OR of
{
long flags; /* Indicates which fields are defined *(
constants that have been defined in the header file <x 11 / Xut il. h>. Each of these constants
int x, y; /* Suggested position and size */ ipdicate that cert~n fields in the structure have been specified. For example, in setting the
int width, height; /* for old window managers */ XS;i.zeHints structure, setting flags to (PPosi tion : PSize) indicates that values are
int min_width, min_height; /* Minimum width and height */
int max_width, max_height; /* Minimum width and height */
prQyidcd for the location (x, y) and size (width, height) fields.
int width_inc, height_inc; /* Width, height increments */
struct
{
int x; /* Numerator of aspect ratio */
int y; /* Denominator of aspect ratio */
selected font. If you want the user's specifications to remain as is, use 1 for both
arguments.
The user's choice of a window's position and size can come through the -geometry command-line
option or the geometry resource. If neither of these is specified, the program provides a default •. int xadd, yadd;
These are values to be added to the width and heighr, respectively. If you do not want any
geometry. The geometry is specified by a string of the form width x height + x + y, where
width and height are integers specifying size of window in pixels, and x and y indicate the posi- padding, provide 0s for these arguments.
tion in the parent's coordinate frame. (For more information about geometry, see Chapter 3.) The last four arguments are the addresses of the integers where XGeometry returns the
selected x, y, width, and height. In initapp, you accept the values directly in the
The user's specification of the geometry need not be complete; the string can have either the size or
the position alone. The programmer's problem is to have the application figure out what the user appropriate fields of the XSizeHints structure:
specifies and reconcile it with the default geometry. Xlib's XGeometry utiliry function is desigr:ted int bitmask;
to do the job; however, it requires the program's default geometry in a string. Handling user-
specified geometry requires the following steps:
/* Process the geometry specification */
1. Construct a string containing r~e default geometry:
bitmask = XGeometry(theDisplay, DefaultScreen(theDisplay),
char default_geometry[801; theGeom! default_geometry, DEFAULT_BDWIDTH,
1, 1, 0, 0, &(p_XSH->x), &(p_XSH->y),
&(p_XSH->width), &(p_XSH->height));
/* Construct a default geometry string */
sprintf(default_geometry, "%dx%d+%d+%d", p_XSH->width, /* Check bitmask and set flags in XSizeHints structure */
pJSH->height, p_XSH->x, p_XSH->y); if (bitmask & (XValue : YValue)) p_XSH->flags := USPosition;
2. Set the user-specified geometry string, stored in the string theGeom in initapp. "-- if (bitmask & (WidthValue : HeightValue))
3. Check whether the command-line or the resource file (.Xdefaults in the user's home
p_XSH->flags := USSize;

directory) provides a geometry string. If so, set the string theGeom to the user's definition The XGeometry function returns an integer value that should be viewed as a pattern of bits (a
of the geometry, giving precedence to the command-line option over the contents of the bi tmask). The set bits in the returned bi tmask indicate which of the x, y, width, and height vari-
resource file. This enables the user to override specifications in the resource file with ables were altered by XGeomet ry. As the previous code shows, if the position or size was altered
command-line options. The following example shows how initapp sets the user-defined because of a user-specified geometry, the flags field of the XSizeHints structure is modified to
geometry: indicate it. The constants named USPosition and USSize are bit patterns that tell the" window
theGeom = default_geometry; manager that these are user-specified options. Ideally, the window manager should use any user-
specified options as is, without any change. The exact behavior depends on the window manager.
/* Override the geometry, if necessary */
if(theGeom_cline != NULL) theGeom = theGeom_cline;
Standard Properties
else
if(theGeom_rsrc 1= NULL) theGeom = theGeom_rsrc; After you settle on a size for the main window, you can create it using XCreateSimpleWindow. This
4. Call XGeomet ry to get the position and size. The values come from the user-specified simple function requires the following arguments:
geometry, ~xcept where items ate missing in the user's specification. XGeometry takes the •. Display
display and screen as the first fWO arguments. For the screen argument, you can use the
•. Parent window's ID
Defaul tScreen macro. The default screen for the display theDisplay is
DefaultScreen (theDisplay). Next come fWO string arguments: the user-specified •. Window's location
geometry followed by the default geometry. The fifth argument is the border width in •. Window's size
pixels. The next four arguments are the following: •. Border width
•. unsigned int width_factor, height._ factor; •. Border color
The user-specified width and height are multiplied by these fWO factors. If you are
•. Background color
displaying text, these arguments can be the width and height of characters for the
In the case of the main window, the parent is the root window, which is identified by the macro if (XStringListToTextProperty(&theAppName, 1, &WName) == 0)
DefaultRootWindow(theDisplay). {
fprintf(stderr, "Error creating XTextPropertyl\n");
Creating the window does not show anything on the screen. The window appears only when you exit (1) ;
}
.map it-and before you map it, you have to inform the window manager about it. This enables the if(XStringListToTextProperty(&theAppName, 1, &IName) == 0)
window manager to intervene and place the window correctly when it is mapped. {
fprintf(stderr, "Error creating XTextPropertyl\n");
The convenience function, XSetWMProperties, is useful for this. As the name implies, you are set- exit('I);
}
ting the properties of a window (the one you just created). In X, a property is some data stored at the
/* Allocate and set up an XWMHints structure (see next section) */
server and tagged by a window ID. You can store a property in a window and restore it. The inter-
pretation of the data represented by a property depends on the applications that use it. Properties
are used for exchanging information among X applications-an example being the communica-
xSetWMProperties(theDisplay, theMain, &WName, &IName, argv, argc,
tion between your application and the window manager. p_XSH, p_XWMH, p_CH);
The arguments to XSetWMProperties are the following: XSetWMProperties combines the functionality of several Xlib functions. You can set the window's
•. Display in which your application's windows are located name and its icon's name using the functions XSetWMName and XSetWMIconName,respectively. Xlib
provides XSetCommandfor storing the command-lineparamet~rs as a property o~ a window. You
•. Window for which you are setting the properties
can use XSetWMNormalHints to provide the size hints to the wmdow manager. Fmally, you could
•. XTextProperty, representing the window's name (use XStringListToTextProperty use XSetWMHints and XSetClassHint to transmit the information in XWMHintsand ~ClassHint
function to convert a string to XTextProperty) structures to the X server. If you use these functions instead ofXSetWMProperties, this is the equiva-
•. XTextProperty, representing the name to be displayed in the window's icon lent sequence of calls:
•. Command-line arguments used in starting the application xClassHint *p_CH;
XWMHints *p_XWMH;
•. Number of command-line arguments xSizeHints *p_XSH;
•. Pointer to the XSizeHints srructure that holds the preferred geometry of the window XTextProperty 'WName;
XTextProperty IName;
•. Pointer'to the XWMHintsstructure holding additional hints for the window manager /* Allocate and initialize the hint structures */
(explained in the next section)
•. Pointer to the XClassHint structure specifYing the application's name and its class name
xSetWMName(theDisplay, theMain, &WName);
In ini tapp, the following code accomplishes the creation of the main window and the setting of xSetlconName(theDisplay, theMain, &IName);
the window manager properties: xSetCommand(theDisplay, theMain, argv, argc);
XSetWMNormalHints(theDisplay, theMain, p_XSH)j
/* Create the main window using the position and size xSetWMHints(theDisplay, theMain, p_XWMH);
* information derived above. For border color, use the xSetClassHint(theDisplay, theMain, p_CH);
* foreground color.
*/
theMain = xcreateSimpleWindow(theDisplay,
DefaultRootWindow(theDisplay),
p_XSH·>x, p_XSH->y, P_XSH->width, P_XSH->height,
DEFAULT_BDWIDTH, theFGpix, theBGpix)j

/* Set up class hint */


if(p_CH = XAllocClassHint(» == NULL)
{
fprintf(stderr, "Error allocating class hintlln");
exit(1) ;
}
p_CH->res_name = theAppNamej
p_CH->res_class = theAppName;
The window manager needs a few more hints from your application. These hints tell the window A window in X has a number of attributes that control many aspects of its appearance and behav-
manager if you ~ant the main window to appear in a normal form or as an icon. Also, the window ior, and how it is is used in an application. You can set the attributes by calling
manager needs information on your program's model of keyboard input. These hints are provided XChangeWindowAttributes. The values for the attributes are passed to this function via an
in an XWMHintsstructure, defined in <X11/Xutil. h> as the following: XSetWindowAttributes structure, which is defined in <X11/Xlib. h> as the following:

#define Bool int #define Bool int

typedef unsigned long XID; typedef struct


{
typedef struct Pixmap background_pixmap; 1* Background pixmap *1
{ unsigned long background_pixel; 1* Background pixel *1
long flags; 1* Indicates which fields are defined *1 Pixmap border_pixmap; 1* Pixmap for border *1
Bool input; 1* True if window manager's help is unsigned long border_pixel; 1* Border pixel value *1
needed in getting keyboard input *1 int bit_gravity; 1* See description *1
int initial_state; I * Normal size or icon? *I int win_gravity; 1* See description *I
Pixmap icon_pixmap; 1* Pixmap to be used as window's icon *1 int backing_store; 1* Use backing store? *1
Window icon_window; 1* Window to be used to show icon *1 unsigned long backing_planes; 1* If yes, which planes*1
int icon_x, icon_y;l* Initial position of icon window *1 unsigned long backing_pixel; 1* For restoring planes*1
Pixmap icon_mask; 1* Bitmap used as mask for icon *1 Bool save_under; 1* Save bits in window?* I
XIO window_group; 1* IO of window group leader *1 long event_mask; I* Events accepted *I
XWMHints; long do_not_propagate_mask;l* Events not forwarded*1
Bool override_redirect; J* See description *I
SpecifYing hints in this structure is similar to the way fields are set in the XSizeHints structure. Colormap colormap; 1* Colormap for window*1
Cursor cursor; 1* Cursor for window *1
You can provide values for the fields you want and indicate your choices by setting bits in the flags
XSetWindowAttributes;
field. In setting up the main window of a simple application, you are most likely to set the
initial_state of the window and the input parameter. If your window will accept keyboard input, The XSetWindowAttributes structure provides for a large number of attributes. Specifically, the
set lnput to True. The initial_state determines whether the window appears as a full-sized following aspects of a window are controlled by the attributes:
window or as an icon. You usually set this to NormalState. The following code shows how to set • Background. The appearance of the window's background is controlled by the attributes
up the XWMHintsstructure for a typical X application's main window: background_pixmap and background_pixel. If you set the background_pixel to a
XWMHints *p_XWMH; pixel value, you get a solid color (corresponding to that pixel) as the background. On the
other hand, by setting background_pixmap to an 8x8 or 16x16 pixmap, you can have a
repeating pattern as the window's background. If you set background_pixmap to the
symbolic constant None, the window wjll have a transparent background. Set
1* Give other hints to window manager by filling out an background_pixmap to ParentRelative to use the parent's background pixmap in a
XWMHints structure and calling XSetWMProperties()
*1 window. Note that when you set the background pixmap, the X server makes a copy of the
pixmap. Thus, you can destroy your copy of the pixmap after setting the background.
if«p_XWMH = XAllocWMHints()) == NULL) Also, the last setting of background_pix map or background_pixel overrides the previous
{
fprintf(stderr, "Error allocating Window Manager hintsl\n"); background setting.
exit(1) ;
}
• Border. Like the background, the border can be a solid color (border_pixel) or a pattern
p_XWMH->flags = (InputHint:StateHint); (border _pixmap).
p_XWMH->lnput = False; ,
• Colormap. The color_map attribute controls how the pixel values in that window get
p_XWMH->initial_state = NormalState;
translated to actual colors. To set this to the parent window's colormap, use
1* Call XSetWMHints or XSetWMProperties. *1 CopyFromParent as the value.
.•. Cursor. The cursor attribure determines the shape of the mouse cursor. For a new cursor,
Defined Constant
you have to set this attribute to the resource ID returned by a funcrion, such as the
XCreateFontCursor function, which creates a cursor out of a character from a special - SouthEastGravity Placed in lower-right corner of resized window
font. XCreateGlyphCursor is another function for creating a new cursor.
SouthGravity Placed in bottom center of resized window
.•. OjfScreen Memory. The fields backing_store, save_under, backing_planes, and
backing_pixel are for informing the X server whether your window will benefir from SouthWestGravity Placed in lower-left corner of resized window
using off-screen memory (or, "backing store") for saving obscured parts. Note, however, WestGravity Placed in left center of resized window
rhat rhis is only a hint to the server; not all servers have off-screen memOlY. Even when CenterGravity Placed in center of resized window
backing_store is present, the server may not have enough for your window (perhaps it
StaticGravity Resized window retains old contents
already used all memory to service anorher client). Thus, your applicarion is still respon-
sible for the contents of all its windows. If your application maps and unmaps a window
without changing the contents (for example, to display a pop-up menu), you should set
The rest of the attributes in the XSetWindowAttributes structure-event mask,
backing_store to the constant Always. Other values are NotUseful and WhenMapped,
do_not_pr'opagate_mask, and override_redirect-are for setting up event handling. When you
each indicating when backing store is useful. Set the save_under attribute to True for a
call the function XSelectInput, you are, in effect, altering the event_mask attribute. (Event han-
pop-up window. The server will save anything under such a win'dow and restore the area
dling mechanisms are further described in Chapter 8, "Handling Events.")
when the window goes away. The backing_planes attribute indicates which bit planes
are to be saved and backing_pixel proviqes the pixel value used when reconstructing a
saved window (useful when all planes ate not saved) . Attribute Setting
.•. Bit gravity. The bit_gravity attribute determines what happens to the contents of a
As with the XSizeHints and XWMHints structures, in the XSetWindowAttl'ibutes structure, you
window after it is rc';i?:::,l It essentially tells the X server where to place the old contents of
can set only a select few attributes. You have to use a bit flag to indicate which of the fields you are
a window after the window is shrunk or enlarged. It is as if the old bits move by gravita-
specifYing. Unlike XSizeHints and XWMHints structures, however, the bit flag is not a member of
tional attraction to a specific side.or corner of the window. The default setting for
the XSetWindowAttributes structure. Instead, the bit flag is the third argument for the
bit_gravity is the defined constant ForgetGravity which means that the old contents
XChangeWindowAttributes function, which takes four arguments:
of the window are discarded after any resize. Table 7.1 summarizes the disposition of the
old contents of the window when it is resized. When a window is resized by the user, the .•. Display
server generates Expose events to inform your application of the areas that need redraw- .•. Window
ing. The bi t_gravi ty setting determines the areas that need refreshing. .•. Bit flag
.•. Window gravity. Analogous to bit gravity, the window gravity attribute, win_gravity, .•. Pointer to the XSetWindowAttributes structure
determines where the window is positioned when its parent's size changes. The settings of
this attribute are similar to that of bit_gravity. For example, the default win_gravity For example, in initapp, you want to set the colormap and the bit_gravity fields. The flag, in
setting ofNorthWestGravi ty states that when its parent is resized, the window moves to this case, is (CWColormap : CWBitGravity):
the upper-left corner of the parent. Because this corner corresponds to the parent's origin,
the window appears fixed to its parent.

Table 7.1. Bit Gravity Constants


xswa.colormap =
DefaultColormap(theOisplay,
Defined Constant Disposition of Old Contents OefaultScreen(theDisplay»;
xswa.bit_gravity = NorthWestGravity;
ForgetGravity Old contents discarded XChangeWindowAttributes (tneDisplay, theMain, (CWColol'map :
CWBitGravity), &xswa);
NorthWestGravity Placed in upper-left corner of resized window
NorthGravity Placed in top center of resized window
NorthEastGravity Placed in upper-right corner of resized window
EastGravity Placed in right center of resized window