Department of Engineering

IT Services

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.