Starting Up
Opening a Display Server
Before any windows can be used it is necessary to establish a connection
with a display server. A server is identified by the name of the machine it is on and
the display number on that machine. If the server name string is NULL then the contents
of the DISPLAY environment variable is substituted to determine
which display to use. The full display name has the form
hostname:display_number.screen
.
Multiple screens/terminals can be controlled by a single X server as long as they are on the same
display; i.e. they are controlled with a single mouse and a single keyboard.
Display *XOpenDisplay(name) /* open a display on the named server. If successful then all the screens on the display may be used . */ char *name; /* e.g. mit-athena:0.0*/ XCloseDisplay(display) /* close a display completely */
When a client's connection to a display is closed, the resources held by the server solely on the client's behalf are freed. When the last connection to the X server is closed, more resources are freed and the server does a reset.
Finding out about the display
Some simple routines can be used to discover general characteristics of the display. These shall be described in some detail as an introduction to some X concepts.
int DefaultScreen(display) /* This returns the default screen number; the only */ /* one you're likely to use */ int ScreenCount(display) /* This returns the number of possible screens */ int DefaultDepth() /* A graphics display can be thought of as overlying bitplanes where only one bit per plane affects the color of a pixel. This routine returns the number of planes used */ unsigned long AllPlanes() /* The bits in the returned long represent the planes used */ int DisplayPlanes(display, screen_number) /* returns the number of possible planes*/ Colormap DefaultColormap(display, screen_number) /* Information on the current colors is stored in a table called a colormap */ int DisplayCells(display, screen_number) /* returns number of entries in the default colormap */ unsigned long BlackPixel(display, screen_number) /* There are permanently */ unsigned long WhitePixel(display, screen_number) /* allocated entries in the default colormap for black and white. These routines return longs that are used to reference these colors */ GC DefaultGC(display, screen_number) /* Graphics commands get details about the current foreground color, etc, from a Graphics Context structure. This routine returns the default one */ Window DefaultRootWindow(display) /* This returns the initial window that covers the screen */ Visual *DefaultVisual(display,screen_number) /* So that various kinds of hardware can be supported `invisibly', some hardware-specific information is stored in the visual structure*/ int DisplayHeight(display,screen_number) /* height of display in pixels */ int DisplayWidth(display,screen_number) /* width of display in pixels */
Creating & Destroying Windows
Before drawing or writing on the screen each program which is using the
server creates one or more windows. The windows exist in a tree structure
growing down from the RootWindow
which covers the whole display.
Many applications only use windows which have root as the parent. If you create a grandchild window you will find that the baby window behaves as if its parent constituted the whole physical display; all output to the baby window is clipped at the boundaries of its parent.
No window appears on the display until it is mapped, all its
ancestors are mapped and an expose event has been received. Furthermore the
mapping command must reach the
server before anything will happen. When you map a window you must
either deliberately flush all buffers (see the section on Events for
details of XFlush
) or draw something on the display to push your mapping
command across the network. The subroutines for mapping windows are given
later in this section.
Creating a window alone is not sufficient to enable you to actually see
anything on the display.
If you don't want to bother setting up too many things, you can create windows that inherit their attributes from their parent.
Window XCreateSimpleWindow (display,parent, x, y, width, height, borderwidth, border,background) Display *display /* The value returned by XOpenDisplay */ Window parent; /* parent window i.d. probably RootWindow */ int x, y; /* specify top LH corner of border */ unsigned int width, height; /* specify internal dimensions */ unsigned int border; /* border pixel */ unsigned long background; /* background pixel */
For more sophisticated windows use,
Window XCreateWindow (display,parent,x,y,width,height,border_width,depth,class,visual,valuemask,attributes) Window parent; /* parent window i.d. probably RootWindow */ int x, y; /* specify top LH corner of border */ unsigned int width, height; /* specify internal dimensions */ unsigned int borderwidth; /* border width */ int depth; unsigned int class; /*InputOutput,InputOnly,CopyFromParent*/ /*(InputOnly windows are transparent)*/ Visual *visual; /*CopyFromParent, etc */ unsigned long valuemask; /* selects attribute fields */ XSetWindowAttributes *attributes; /* contains the attributes */
The following structure is used when initialising windows.
typedef struct { /* DEFAULT MASK */ Pixmap background_pixmap; /* None CWBackPixmap */ unsigned long background_pixel; /* - CWBackPixel */ Pixmap border_pixmap; /* CopyFromParent CWBorderPixmap */ unsigned long border_pixel; /* - CWBorderPixel */ int bit_gravity; /* ForgetGravity CWBitGravity */ int win_gravity; /* NorthWestGravity CWWinGravity */ int backing_store; /* NotUseful CWBackingStore */ unsigned long backing_planes; /* ~0 CWBackingPlanes */ unsigned long backing_pixel; /* 0 CWBackingPixel */ Bool save_under; /* False CWSaveUnder */ long event_mask; /* 0 CWEventMask */ long do_not_propagate_mask; /* 0 CWDontPropagate */ Bool override_redirect; /* False CWOverrideRedirect */ Colormap colormap; /* CopyFromParent CWColormap */ Cursor cursor; /* None CWCursor */ } XSetWindowAttributes;
background_pixmap
:- This lets you have a patterned background. It must have
the same root and depth as the window.
If None
then there's no background. If ParentRelative
,
the parent's background is used but
the parent and child must have the same depth.
border_pixmap
:- This and the window must have the same root and depth
(else a BadMatch
error).
If CopyFromParent
the parent's pixmap is copied
bit_gravity
:- Defines which region is retained should the window be
resized.
win_gravity
:- Defines how the window is re-positioned should its
parent be resized.
backing_store
:- WhenMapped
advises the server to save the
contents of the window if it's unmapped or obscured. Always
advises the
server that saving the contents even when unmapped would be useful. Not
all servers support backing store. Use DoesBackingStore() to find out.
backing_planes
:- Defines which planes will be saved.
backing_pixel
:- Defines what value to put in planes not saved.
save_under
:- True
advises the server to save regions obscured
by the window.
do_not_propagate_mask
:- Defines which events should not be propagated to
ancestors.
override_redirect
:- If True
then the window manager won't know about
the window.
colormap
:- This must have the same visual type as the window.
If CopyFromParent
the parent's colormap is copied
There are a couple of calls which can be used to destroy windows. Windows are unmapped automatically before they are destroyed.
XDestroyWindow(display,w) /* destroy the window with the given i.d. */| XDestroySubwindows(display,w) Window w; /* destroys all the subwindows of the specified window */ /* the window itself is not destroyed */
Attributes of a window are returned using the following call and structure :-
Status XGetWindowAttributes(display,w,window_attributes) XWindowAttributes *window_attributes; /* RETURN completed structure*/ typedef struct { int x, y; /* location of window */ int width, height; /* width and height of window */ int border_width; /* border width of window */ int depth; /* depth of window */ Visual *visual; /* the associated visual structure */ Window root; /* root of screen containing window */ int class; /* InputOutput, InputOnly*/ int bit_gravity; /* one of bit gravity values */ int win_gravity; /* one of the window gravity values */ int backing_store; /* NotUseful, WhenMapped, Always */ unsigned long backing_planes;/* planes to be preserved if possible */ unsigned long backing_pixel;/* value to be used when restoring planes */ Bool save_under; /* should bits under be saved? */ Colormap colormap; /* color map associated with window */ Bool map_installed; /* is color map currently installed*/ int map_state; /* IsUnmapped, IsUnviewable, IsViewable */ long all_event_masks; /* events that interest all people */ long your_event_mask; /* my event mask */ long do_not_propagate_mask; /* events that should not propagate */ Bool override_redirect; /* boolean value for override-redirect */ } XWindowAttributes;
Mapping, Moving & Uncovering Windows
Map windows using
XMapWindow(display,w) XMapSubwindows(display,w) XUnmapWindow(display,w) XUnmapSubwindows(display,w)
There are also a few fairly self-explanatory calls which can be used to move the windows around and shuffle them to the top and bottom of the pile like papers on a desk. The window manager may well interfere with your intentions, though - it's up to the user where top-level windows are, and which is on top.
XChangeWindowAttributes(display,w,valuemask,attributes) XSetWindowAttributes *attributes; XConfigureWindow(display,w, x, y, valuemask, values) unsigned int valuemask /* to select relevant fields of value */ XWindowChanges *values; /* contains new details */ XResizeWindow(display,w,width,height); XMoveResizeWindow(display,w,x,y,width,height); XSetWindowBorderWidth(display,w,width); XRaiseWindow(display,w) /* raise the window to the front */ XLowerWindow(display,w) /* lower window to the back */ XMoveWindow(display,w, x, y) /* move and raise w */ XCirculateSubwindows(display,w,direction); /* direction is RaiseLowest or LowerHighest*/ XCirculateSubwindowsUp(display,w) /* raises the lowest mapped child */ XCirculateSubwindowsDown(display,w) /* lowers the highest mapped child*/
Defining Bitmaps and Pixmaps
Off screen memory (a pixmap) is often used to define images for later use in graphics operations. Pixmaps are also used to define tiles, or patterns, for use as window backgrounds, borders, or cursors. A single bit plane pixmap is sometimes referred to as a bitmap.
To create a Pixmap, use
Pixmap XCreatePixmap(display,d,width,height,depth) unsigned int width, height, depth;
To read a bitmap from a file (created by the bitmap
program, perhaps), use
int XReadBitmapFile(display,d,filename,width,height,bitmap,x_hot,y_hot) /* possible return values are BitmapOpenFailed, BitmapFileInvalid BitmapNoMemory, BitmapSuccess */ int *width, *height; /*RETURN*/ Pixmap *bitmap; /*RETURN*/ int *x_hot,*y_hot; /*RETURN*/
To write a bitmap to a file, use
int XWriteBitmapFile(display,filename,bitmap,width,height,x_hot,y_hot) /* possible return values are BitmapOpenFailed, BitmapNoMemory BitmapSuccess */ int width, height; Pixmap bitmap; int x_hot,y_hot;
If you #include
a bitmap file in your program you can use
Pixmap XCreateBitmapFromData(display,d,data,width,height) char *data
Pixmaps consume a lot of memory. Use
XFreePixmap(display,pixmap)
as soon as possible to release memory.