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 */ /* FIND NEAREST POSSIBLE CURSOR SIZE TO REQUESTED 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*/ XSetScreenSaver(display,timeout,interval,prefer_blanking,allow_exposures) 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*/ /* FIND MOUSE COORDINATES AND THE STATE OF ITS BUTTONS */ 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 */ XWarpPointer(display,src_w,dest_w,src_x,src_y,src_width, src_height,dest_x,dest_y) 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 AutoRepeatModeDefault*/ } XKeyboardControl;one can change keyboard settings with
XChangeKeyboardControl(display,value_mask,values); XKeyboardControl *values XAutoRepeatOn(display) /* control keyboard auto repeat */ XAutoRepeatOff(display) /* control keyboard auto repeat */ XBell(display,percent)
Images
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, xpad,bytes_per_line) 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
XPutImage(display,d,gc,image,src_x,src_y,dst_x,dst_y,width,height); 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
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
XDestroyRegion(r)
To clear a region, destroy and recreate it. To find the smallest enclosing rectangle use
XClipBox(r,rect) XRectangle rect /*RETURN*/
To use a region as a GC's mask, use
XSetRegion(display,gc,r)
To move a region use
XOffsetRegion(r,dx,dy)
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:-
XIntersectRegion(sra,srb,dr) Region dr; /*RETURN*/ XUnionRegion(sra,srb,dr) Region dr; /*RETURN*/ XUnionRectWithRegion(rect, src_region, dest_region) Rectangle *rect; XSubtractRegion(sra,srb,dr) Region dr; /*RETURN (union - intersection)*/ XXorRegion(sra,srb,dr) 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*/ XSetAccessControl(display,mode) int mode; XEnableAccessControl(display) XDisableAccessControl(display)
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; XCheckIfEvent(display,event,predicate,args) Display *display; XEvent *event; Bool (*predicate)(); char *args; XPeekIfEvent(display,event,predicate,args) /* conditional Peek */ Display *display; XEvent *event; Bool (*predicate)(); char *args;
Grabbing
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 */ XGetInputFocus(display,focus,revert_to) 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, pointer_mode,keyboard_mode,confine_to,cursor,time) 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 ButtonReleaseMask*/ 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 */ /* GRAB THE MOUSE WHENEVER A PARTICULAR COMBINATION OF */ /* MOUSE BUTTONS AND KEYBOARD KEYS ARE PRESSED */ Status XGrabButton(display,button,modifiers,w,owner_events,event_mask, pointer_mode,keyboard_mode,confine_to,cursor,time) 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 */ XFreeFontInfo(names,info,actual_count) XUnloadFont(display,font) 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*/ XFreeColormap(display,cmap) XSetWindowColormap(display,w,cmap)
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, nreds,ngreens,nblues,rmask,gmask,bmask) 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
XStoreColor(display,cmap,screen_def) XColor *screen_def; XStoreColors(display,cmap,defs,ncolors) XColor defs[ncolors]; XStoreNamedColor(display,cmap,color,pixel,flags); char *color; int flags; /* DoRed, DoGreen,DoBlue */
To free color cells or planes use
XFreeColors(display,cmap,pixels,npixels,planes); 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, &attributes); XSelectInput(display,win,ExposureMask + ButtonPressMask+ KeyPressMask) ; gc=XCreateGC(display,win,NULL,NULL); XMapWindow(display,win); cmap= XDefaultColormap(display,0); stat = XAllocColorCells(display,cmap,FALSE,plane_masks, NUMPLANES, pixar, NUMCOLS); /* claim some colorcells */ do{ XNextEvent(display,&event); switch(event.type){ case Expose: sprintf(str0,"depth is = %d", depth); sprintf(str1,"there are %d colorcells", DisplayCells(display,0)); switch(XDoesBackingStore(display)){ case WhenMapped : sprintf(str2,"when mapped"); break; case NotUseful : sprintf(str2,"not useful"); break; case Always : sprintf(str2,"always"); break; default : sprintf (str2,"error in DoesBackingStore"); } XDrawImageString(display,win,gc,20,15,str0,strlen(str0)); XDrawImageString(display,win,gc,20,30,str1,strlen(str1)); XDrawImageString(display,win,gc,20,45,str2,strlen(str2)); sprintf(str2,"planes = %d, %d, %d", plane_masks[0], plane_masks[1],plane_masks[2]); sprintf(str3,"pixels = %d, %d, %d.", pixar[0], pixar[1], pixar[2]); XDrawImageString(display,win,gc,20,60,str2,strlen(str2)); XDrawImageString(display,win,gc,20,75,str3,strlen(str3)); v=DefaultVisual(display,0); switch(v->class){ 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,250,20,str0,strlen(str0)); XDrawImageString(display,win,gc,400,30,"pix vals used",13); for(which_color = 0, which_cell = 0; which_color < NUMCOLS; which_color++){ 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)); XDrawImageString(display,win,gc,430,30+12*which_cell, str1,strlen(str1)); } } 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); } XFlush(display); printf("now press button: \n"); break; case ButtonPress: printf("closing display\n"); XCloseDisplay(display); exit(0); } }while(1); }
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.