Department of Engineering

IT Services

Miscellaneous Routines

Not all of the following routines are very useful; they are included mainly for the sake of completeness. The following routines return the biggest (in the case of cursors), else the fastest size of the required resource.

XQueryBestSize(display,class,d,width, height,rwidth,rheight)
   int class; /* TileShape, CursorShape, StippleShape*/
   unsigned int width, height;       /* requested size                */
   unsigned int *rwidth, *rheight;   /* RETURN of required legal size */

XQueryBestTile(display,d,width, height,rwidth,rheight)
   unsigned int width, height;       /* requested size                */
   unsigned int *rwidth, *rheight;   /* RETURN of required legal size */

XQueryBestStipple(display,d,width, height,rwidth,rheight)
   unsigned int width, height;       /* requested size                */
   unsigned int *rwidth, *rheight;   /* RETURN of required legal size */
XQueryBestCursor(display,d,width, height, rwidth, rheight)
    unsigned int width, height;       /* requested size                  */
    unsigned int *rwidth, *rheight;   /* RETURN possible size            */
int XTranslateCoordinates(display,src_w,dest_w,src_x,src_y,dest_x,dest_y,child)
   int *dest_x, *dest_y; /*RETURN src_x, src_y relative to the dest window*/
   Window *child; /*RETURN a child window of dest_w if the point is within it*/

Status XGetGeometry(display,d,root,x,y,width,height,border_width,depth);
   Drawable *root; /*RETURN the root of d*/
   int *x,*y;   /*RETURN coords if d is a window, else 0 */
   unsigned int *width, *height;  /*RETURN*/
   unsigned int *border_width; /*RETURN border_width if d is a window, else 0*/
   unsigned int *depth; /*RETURN*/

    /* LIST THE PARENT AND CHILDREN OF A WINDOW                 */
Status XQueryTree(display,w, parent, children, nchildren)
   Window *parent;      /* RETURN pointer to parent window id  */
   int *nchildren;      /* RETURN pointer to number of children*/
   Window **children;   /* RETURN pointer to array of child ids*/

    int timeout;     /* blank screen after this many seconds*/
    int interval;  /* interval between screen saver invocations*/
    int prefer_blanking;/*DontPreferBlanking,PreferBlanking,DefaultBlanking*/
    int allowExposures;/*DontAllowExposure, AllowExposures,DefaultExposures*/

Pointer control

See also the chapter on events.

XChangePointerControl(display,do_accel,do_threshold,accel numerator,
		  accel denominator, threshold)/* SET MOUSE ACCELERATION */
    int do_accel;        /*True or False. Do you want to set accel ? */
    int do_threshold;    /*True or False. Do you want to set threshold ? */
    int accel numerator, accel denominator; /* -1 restores default*/
    int threshold;   /* ignore moves up to this number of pixels*/

XGetPointerControl(display,accel numerator,accel denominator, threshold)
    int *accel numerator,   /*RETURN*/
    int *accel denominator; /* RETURN*/
    int *threshold;   /* RETURN*/

Status XQueryPointer(display,w,root,child,root x,root y,win x win y,mask)
    Window w;        /* relative to which window                */
    Window *root, *child;      /*RETURN*/
    int *root x, *root y;      /* RETURN*/
    int *win x,*win y;    /* RETURN*/
    unsigned int *mask;    /* RETURN button states                    */

   Window src_w,dest_w;
   int src_x,src_y;
   unsigned int src_width,src_height;
   int dest_x,dest_y;

Keyboard Control

Using these flags, KBKeyClickPercent, KBBellPercent, KBBellPitch, KBBellDuration, KBLed, KBLedMode, KBKey, KBAutoRepeatMode and this structure

 typedef struct {
        int key_click_percent;
        int bell_percent;/
        int bell_duration;
        int led;
        int led_mode;         /*LedModeOff LedModeOn*/
        int key;
        int auto_repeat_mode; /*AutoRepeatModeOn AutoRepeatModeOff
} XKeyboardControl;
one can change keyboard settings with
   XKeyboardControl *values

XAutoRepeatOn(display)          /* control keyboard auto repeat        */
XAutoRepeatOff(display)         /* control keyboard auto repeat        */


A display may support multiple screens, each having several different visual types supported at different depths. To cope with this, the following routines and structures are used.

typedef struct {                 /*       MASKS                 */
  Visual *visual;                /*    VisualNoMask             */
  VisualID visualid;             /*    VisualIDMask             */
  int screen;                    /*    VisualScreenMask         */
  int depth;                     /*    VisualDepthMask          */
  int class;                     /*    VisualClassMask          */
  int red_mask;                  /*    VisualRedMaskMask        */
  int green_mask;                /*    VisualGreenMaskMask      */
  int blue_mask;                 /*    VisualBlueMaskMask       */
  int colormap_size;             /*    VisualColormapSizeMask   */
  int bits_per_rgb;              /*    VisualBitsPerRGBMask     */
} XVisualInfo;                   /*    VisualAllMask            */

typedef struct _XImage {
    int width, height;          /* size of image */
    int xoffset;                /* number of pixels offset in X direction */
    int format;                 /* Bitmap, XYPixmap, ZPixmap */
    char *data;                 /* pointer to image data */
    int byte_order;             /* data byte order, LSBFirst, MSBFirst */
    int bitmap_unit;            /* quant. of scanline 8, 16, 32 */
    int bitmap_bit_order;       /* LeastSignificant, MostSignificant */
    int bitmap_pad;             /* 8, 16, 32 either XY or ZFormat */
    int depth;                  /* depth of image */
    int bytes_per_line;         /* accelarator to next line */
    int bits_per_pixel;         /* bits per pixel (ZFormat) */
    unsigned long red_mask;     /* bits in Z arrangment */
    unsigned long green_mask;
    unsigned long blue_mask;
    char *obdata;               /* hook for the object routines to hang on */
    struct funcs {              /* image manipulation routines */
        struct _XImage *(*create_image)();
        int (*destroy_image)();        
        unsigned long (*get_pixel)();  
        int (*put_pixel)();            
        struct _XImage *(*sub_image)();
        int (*add_pixel)();
        } f;
} XImage;

Drawables are stored in the server. An image is stored on the client machine. The XImage structure contains all the data corresponding to the drawable. Once you know the format of the data within the image, you can manipulate the data using bit-arithmetic.

There is a standard format for coding bitmap data which is used in some of the routines which follow. The bits are stored in scan-line order starting at the top left hand corner bit which is stored in the least significant position in the first memory word being used. Each line begins on a 16 bit boundary and is padded to a 16 bit boundary at the right hand end. The lines follow each other from top to bottom.

There are two standard formats for pixmaps, XY and Z. In XY format the bitmaps in the pixmap occur one after another with the most significant bit plane first. In Z format the pixels are stored individually and come in the same order as the bits in a bitmap. If the hardware supports 2 to 8 bit planes then each pixel is stored in one byte; if the hardware is 9 to 16 planes the pixels have a 16 bit word each. Z format may not be used with black and white display hardware.

   To create an XImage structure use
XImage *XCreateImage(display,visual,depth,format,offset,data,width,height,
   int xpad; /*8, 16, 32 */
   char * data;
   int bytes_per_line; /* if 0, then data assumed contiguous */

To fill this image with data, use

XImage *XGetImage(display,d,x,y,width,height,plane_mask,format);
   XImage *image;
   int src_x,src_y; /* offset from top-left of image */

To combine an image in memory with a rectangle of a drawable on your display, use

   XImage *image;
   int src_x,src_y; /* offset from top-left of image */

To copy part of an existing image to a new one and create an XImage, use

XImage *XSubImage(ximage,x,y,width,height)

You can manipulate the data directly or use

long XGetPixel(ximage,x,y)
int XPutPixel(ximage,x,y,pixel)
int XAddPixel(ximage, value) /* This adds (int) value to each pixel*/


Regions are sets of pixels. They are held by the client program and are often used to create masks etc. These are created by

Region XCreateRegion();

which creates an empty region. This can be assigned to using

Region XPolygonRegion(points,n,fill_rule)
XPoint points[];
and destroyed by

To clear a region, destroy and recreate it. To find the smallest enclosing rectangle use

XRectangle rect /*RETURN*/

To use a region as a GC's mask, use


To move a region use


To change the size of a region use

XShrinkRegion(r,dx,dy) /* if dx or dy <0 then the shrink becomes expand*/

Other operations are:-

Region dr; /*RETURN*/

Region dr; /*RETURN*/

XUnionRectWithRegion(rect, src_region, dest_region)
Rectangle *rect;

Region dr; /*RETURN (union - intersection)*/

Region dr; /*RETURN*/

int XEmptyRegion(r)   /* is the region null ? */

int XEqualRegion(r1,r2)

int XPointInRegion(r,x,y)

int XRectInRegion(r,x,y,width,height)

Access Control

X is not particularly sophisticated about its access control. Each server program looks in /etc/X?.hosts when it starts up to find a list of machines which it will accept connections from. (? is the display number) The following calls permit the user to modify the situation. From the terminal it is also possible to add and remove hosts using xhost(1).

All the functions use the XHostAddress structure. DECnet nodes must terminate in '::' to distinguish them from internet nodes.

#include <sys/socket.h>
XAddHost (display,host)              /* add a host      */
    XHostAddress *host;    /* network address */

XAddHosts (display,hosts,num_hosts)              /* add hosts      */
    XHostAddress *hosts;    /* network address */
     int num_hosts;

#include <sys/socket.h>
XRemoveHost (display,host)           /* remove a host   */
    XHostAddress *host;    /* network address */

XRemoveHosts (display,hosts,num_hosts)           /* remove a hosts   */
    XHostAddress *host;    /* network address */
     int num_hosts;

#include <sys/socket.h>
struct in_addr *XListHosts (display,nhosts,state)/* RETURN list of hosts */
    int *nhosts;        /* RETURN number of hosts on list */
    Bool *state;        /* RETURN state of connection set up*/

     int mode;



More On Events

Some of the event routines have conditional versions. They take a routine of this form which returns true if the event is wanted, else False.

  Bool (*predicate)(display,event,args)
  Display *display;
  XEvent *event;
  char *args;

XIfEvent(display,event,predicate,args) /* returns an event iff right sort*/
   Display *display;
   XEvent *event;
   Bool (*predicate)();
   char *args;

   Display *display;
   XEvent *event;
   Bool (*predicate)();
   char *args;

XPeekIfEvent(display,event,predicate,args)  /* conditional Peek */
   Display *display;   
   XEvent *event;      
   Bool (*predicate)();
   char *args;


A client can monopolise the keyboard and pointer but if at all possible you should avoid doing this. If you have selected both ButtonPress and ButtonRelease in a window, then X will `grab' the pointer after the ButtonPress event until the button is released.

XGrabServer(display)        /* the server will buffer up requests from  */
                            /* all other client programs                */
XUngrabServer(display)      /* allow execution of other client's requests  */

XSetInputFocus(display,focus,revert_to,time)/* keybd events go to window*/
    Window focus;        /* is in if it is a decendent of the focus  */
    int revert_to;       /*RevertToParent,RevertToPointerRoot,RevertToNone
                           if the window becomes non- viewable. */
    Time time;           /* timestamp  or CurrentTime */
    /* window, otherwise they are sent to the focus window itself*/
    /* the RootWindow is the default focus window                */

    Window *focus;        /* RETURNS ID of focus window  */
    int *revert_to;       /*RevertToParent,RevertToPointerRoot,RevertToNone*/
    /* GRAB ALL MOUSE EVENTS for those of the clients windows   */
Status XGrabPointer(display,w,owner_events,event_mask,
    Window w;       /* SelectInput suitably else send here if   */
                    /* normal window has not called SelectInput */
    Bool owner_events; /*If False then all pointer events selected by
                         the mask are reported with respect to grab_window.
                         If True then pointer events that would normally
                         have been reported are reported as usual,
                         otherwise as in False */
    unsigned int event_mask;/* always augmented with ButtonPressMask and
    int pointer_mode,keyboard_mode;  /*If GrabModeAsync then event
                                       processing continues normally.
                                       If GrabModeSync the pointer/keyboard
                                       appears to freeze until XAllowEvents
                                       is called */                      
    Window confine_to;      /* if pointer isn't initially in this window
                               then it's warped into it */
    Cursor cursor;   /* temporary cursor to use    */
    Time time;       /* either a timestamp or CurrentTime */

XUngrabPointer(display,time)       /* UNDO THE EFFECT OF XGrabPointer */
    Time time;       /* either a timestamp or CurrentTime */

Status XGrabButton(display,button,modifiers,w,owner_events,event_mask,
    unsigned int buttons;
    unsigned int modifiers;
    Window w;   /* window for events which are excluded by      */
       /* SelectInput from the window they would normally go to */
    Bool owner_events;                                            
    unsigned int event_mask;                                      
    int pointer_mode,keyboard_mode;                               
    Window confine_to;                                            
    Cursor cursor;   /* temporary cursor to use                 */

XUngrabButton(display,button,modifiers,w) /* UNDO XGrabButton    */
    unsigned int buttons;                                             
    unsigned int modifiers;                                           
    Window w;   /* window for events which are excluded by      */

More On Fonts

Here are the individual font preparation routines.

Font XLoadFont(display,name)      /* load a font returning the font-id */
    char *name;                   /* null-terminated font name         */

Status XQueryFont(font, info)
    Font font;           /* for the font with this font-id    */
    FontInfo *info;      /* RETURN with FontInfo filled in    */
                         /* except for the font widths array  */


short *XFontWidths(font)
    Font font;           /* fill font widths array for font   */

More On Color

As well as grabbing the keyboard and mouse you can also hog resources. This behaviour is most graphically displayed when clients create colormaps of their own. When the pointer goes into their window, their colormap gets swopped in and the windows of other clients suddenly have their colormap taken from under their feet, resulting in false colors. If you do have to make your own colormap and manipulate it, use

Colormap XCreateColormap(display,w,visual,alloc)           
   Visual *visual; /* GrayScale, Pseudocolor etc */         
   int alloc;      /* AllocAll or AllocNone. 
                      If visual is StaticGray or TrueColor then pick
                      AllocNone, meaning none of colormap cells are writeable*/

Colormap XCopyColormapAndFree(display,cmap)
                   /* This moves all of the client's existing allocations to
                      a new colormap and frees the old ones. This is useful
                      when the old colormap gets filled up*/



Figure 3: Colors and bit planes

Read/Write Color Cells - Using read/write colour cells is more involved than the read-only cells in the earlier chapter. Allocating colorcells and Storing colors in them involve separate commands. N colors and planes can be allocated simultaneously. The idea is that

Status XAllocColorCells(display,cmap,contig,plane_masks,nplanes,pixels,ncolors);
   Bool contig;   /* True if planes must be contiguous, else False */
   unsigned long  plane_masks[nplanes];     /*RETURN*/
   unsigned int   nplanes;         /*supplies number of planes ( >=0 )*/
   unsigned long  pixels[ncolors];          /*RETURN*/
   unsigned int   ncolors;        /*supplies number of colors ( >0 ) */

allocates a number of pixel values to an client program. If nplanes is zero then the pixel array returned will contain the pixel values. Otherwise you will need to OR each element in the masks array with each element in the pixels array to get all the pixel values. No mask will have any bits in common with other masks or pixel values. If you ask for 3 pixel values and 3 bits in the plane mask, your bit plane mask would be 7 containing the bits 1, 2 and 4 and you would be allocated the pixel values 8, 16 and 24. Thus from the pixel value 8 the values from 8 to 15 can be derived by ORing in one or more of these bits. Similarly 16 gives (16 - 23) and 24 gives (24 - 31). Thus we have in fact been allocated all the pixel values from 8 to 31 inclusive.

By ORing together masks and pixels, ncolors*2nplanes distinct pixels can be produced, all of which are writeable.

For GrayScale or PseudoColor each mask will have exactly 1 bit; for DirectColor each mask will have 3 bits. The cells you allocate have no defined colors until set with XLookupColor then XStoreColor(s) or XStoreNamedColor.

If no pixels are asked for then as many bit planes as possible are allocated. Such a request can succeed only once. See the example program at the end of this section for further clarification of read/write colour cells.

If you want to vary the number of bits that correspond to each primary color, use

Status XAllocColorPlanes(display,cmap,contig,pixels,ncolors,
   Bool contig;   /* True if planes must be contiguous, else False */
   unsigned long  pixels[nplanes];     /*RETURN*/
   int   ncolors; /* specifies number of colors needed ( >0 ) */
   int nreds, ngreens, nblues; /* specifies the number of shades you want */
   unsigned long  *rmask, *gmask, *bmask; /*RETURN bit masks for planes*/

No mask will have any bits in common with other masks. By ORing together masks and pixels, ncolors*2nreds+ngreens+nblues) distinct pixels can be produced, but in the colormap there are only ncolors*2nreds) red entries, ncolors*2ngreens) green entries and ncolors*2nblues) blues entries. To set colors, use

   XColor *screen_def;
   XColor defs[ncolors];

   char *color;
   int flags; /* DoRed, DoGreen,DoBlue */

To free color cells or planes use

unsigned long pixels[npixels]; /* pixels you want to free */
unsigned long planes;          /* planes you want to free */

This is an example of using read/write colour cells. It is rather long winded in order to illustrate the way in which the pixel values are allocated. It eventually ends up with 24 different colours which it draws in a technicolor stripe across the screen and prints some detail of the pixels is has been given as it goes along.  

#include  <X11/cursorfont.h> 
#include <stdio.h> 
#include <X11/X.h>
#include <X11/Xlib.h> 
#include <X11/Xutil.h> 
#define TRUE 1 
#define FALSE 0 
#define PLANELIM  65536 
#define NUMPLANES     3             /* number of bit planes asked for */ 
#define NUMCOLS    3                /* number of colours asked for    */ 
#define PLNUM     (1 << NUMPLANES)  /* pixel value factor from planes */ 
#define PIXNUM    NUMCOLS * PLNUM   /* total pixel values obtained    */ 
 main (argc, argv) 
 char   *argv[]; 
 int     argc; 
     XColor   color_cell[PIXNUM];    /* must have room for pixnum */ 
     XSetWindowAttributes attributes; 
     int     Red = 60000; 
     int     Green = 40000; 
     int     Blue = 20000; 
     int     i,j; 
     int     mask; 
     Visual *visual; 
     int depth; 
     int which_color,which_cell,which_plane; 
     Display *display; 
     Visual *v; 
     Window  win; 
     GC gc; 
     Colormap cmap; 
     XEvent event; 
     int     stat; 
     long     plane_masks[NUMPLANES]; 
     long     pixar[NUMCOLS]; 
     char str0[50],str1[50],str2[50],str3[50], str4[50];
     int ret;

     setbuf (stdout, NULL); 
     setbuf (stderr, NULL); 

     display = XOpenDisplay(NULL); 
     visual = DefaultVisual(display,0); 
     depth  = DefaultDepth(display,0); 
     attributes.background_pixel      = XWhitePixel(display,0); 
     attributes.border_pixel          = XBlackPixel(display,0); 
     attributes.override_redirect     = 0; 
     win = XCreateWindow(display,XRootWindow(display,0),0,0,507,426,5, 
        depth,  InputOutput,visual ,CWBackPixel+CWBorderPixel+CWOverrideRedirect,
     XSelectInput(display,win,ExposureMask + ButtonPressMask+ KeyPressMask) ; 
     cmap= XDefaultColormap(display,0); 
     stat = XAllocColorCells(display,cmap,FALSE,plane_masks, NUMPLANES,
            pixar, NUMCOLS); /* claim some colorcells */ 

       case Expose: 
              sprintf(str0,"depth is = %d", depth);
              sprintf(str1,"there are %d colorcells", DisplayCells(display,0));
                case WhenMapped : sprintf(str2,"when mapped");
                case NotUseful :  sprintf(str2,"not useful");
                case Always :     sprintf(str2,"always");
                default :         sprintf (str2,"error in DoesBackingStore");

              sprintf(str2,"planes = %d, %d, %d", plane_masks[0],
              sprintf(str3,"pixels = %d, %d, %d.", 
                          pixar[0], pixar[1], pixar[2]); 

 	        case StaticGray:sprintf(str0,"static gray"); break; 
 	        case GrayScale:sprintf(str0," gray scale"); break; 
                case StaticColor:sprintf(str0,"static color"); break; 
                case PseudoColor:sprintf(str0,"pseudocolor"); break; 
                case TrueColor:sprintf(str0,"true color"); break; 
                case DirectColor:sprintf(str0,"direct color"); break; 
              XDrawImageString(display,win,gc,400,30,"pix vals used",13); 

              for(which_color = 0, which_cell = 0; which_color < NUMCOLS; 
                 color_cell[ which_cell++].pixel = pixar[which_color]; 
                 for(which_plane = 0; which_plane < PLNUM; which_plane++){
                         /* permute the bits to generate all the */ 
 	            mask = 0;      /* possible pixel values */ 
                    for(i = 1, j = 0; i < PLNUM; i <<= 1, j++) 
           	       if(i & which_plane) 
 		          mask |= plane_masks[j]; 
 	            color_cell[ which_cell++].pixel = pixar[which_color] |  mask; 
                    sprintf(str1," %d",(pixar[which_color]  | mask)); 
              for(i = 0; i < PIXNUM; i++){
                 /* generate some arbitrary colours */ 
                 color_cell[i].flags= DoRed | DoGreen | DoBlue; 
                 color_cell[i].red = Red; 
                 color_cell[i].green = Green; 
                 color_cell[i].blue = Blue; 
                 Red = ((Red + 3000) % 65536); 
                 Green = ((Green + 3000) % 65536); 
                 Blue = ((Blue + 3000) % 65536); 
              XStoreColors(display,cmap, color_cell,PIXNUM); 

              for(i = 0; i < PIXNUM; i++){   
                 /* draw a multi-coloured stripe    */ 
                 XSetForeground(display,gc, color_cell[i].pixel); 
                 XFillRectangle(display,win,gc,10 * i, 100, 10, 200); 

              printf("now press button: \n"); 

       case ButtonPress:
              printf("closing display\n"); 

XAllocColorCells allows you to do quick overlays. By drawing into one plane, you can change the displayed output without affecting the other planes and restore the original quickly.