VMS DECwindows Guide to Xlib (Release 4) Programming: MIT C Binding

VMS DECwindows Guide to Xlib (Release 4) Programming: MIT C Binding

Order Number: AA--PGZCA--TE


August 1991

This manual is a guide to programming Xlib routines.

Revision/Update Information: This is a new manual.

Operating System: VMS Version 5.4

Software Version: VMS DECwindows Motif Version 1.0

Digital Equipment Corporation
Maynard, Massachusetts


August 1991

The information in this document is subject to change without notice and should not be construed as a commitment by Compaq Computer Corporation. Compaq Computer Corporation assumes no responsibility for any errors that may appear in this document.

The software described in this document is furnished under a license and may be used or copied only in accordance with the terms of such license.

No responsibility is assumed for the use or reliability of software on equipment that is not supplied by Compaq Computer Corporation or its affiliated companies.

Restricted Rights: Use, duplication, or disclosure by the U.S. Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of the Rights in Technical Data and Computer Software clause at DFARS 252.227-7013.

Copyright ©1991

The following are trademarks of Compaq Computer Corporation: Bookreader, CDA, DEC, DECnet, DECwindows, DECwrite, Digital, LinkWorks, LiveLink, LN03, MicroVAX, PrintServer, ReGIS, ULTRIX, VAX, VAXcluster, VAXserver, VAXstation, VMS, VT, XUI, and the DIGITAL logo.

Adobe is a registered trademark of Adobe Systems Incorporated.

BITSTREAM is a registered trademark of Bitstream, Inc.

Helvetica is a trademark of Linotype AG or its subsidiaries, or both.

ITC Avant Garde Gothic is a registered trademark of International Typeface Corporation.

Motif is a trademark of the Open Software Foundation, Inc.

Open Software Foundation, OSF, OSF/Motif, and Motif are trademarks of the Open Software Foundation, Inc.

PostScript is a registered trademark of Adobe Systems Incorporated.

Sony is a registered trademark of Sony Corporation.

Times is a trademark of Linotype AG or its subsidiaries, or both.

ZK5642

This document was prepared using DECdocument, Version V3.3-1e.

Contents Index


Preface

This manual describes how to program Xlib routines using the MIT C binding. VMS DECwindows includes the MIT binding for Xlib programmers using the C programming language and other languages that support pointers.

The manual includes an overview of Xlib and tutorials that show how to use Xlib routines.

Note

This manual uses a generic format when referring to Xlib routine names in text. Routine names are represented in all uppercase letters with separating spaces. In addition, the X prefix has been omitted. For example, in text the routine name is written as OPEN DISPLAY; however, the MIT C binding format of the same routine is XOpenDisplay.

See the X Window System for a complete reference and description of all MIT C Binding Xlib routines.

Intended Audience

This manual is intended for experienced programmers who need to learn graphics programming using Xlib routines. Readers should be familiar with a high-level language. The manual requires minimal knowledge of graphics programming.

Document Structure

This manual is organized as follows:

This manual also includes the following appendixes:

Associated Documents

The following documents contain additional information:

Conventions

The following conventions are used in this manual:
mouse The term mouse is used to refer to any pointing device, such as a mouse, a puck, or a stylus.
MB1 (Select)
MB2 (Drag)
MB3 (Menu)
MB1 indicates the left mouse button, MB2 indicates the middle mouse button, and MB3 indicates the right mouse button. (The buttons can be redefined by the user.)
Ctrl+x A sequence such as Ctrl+x (or Ctrl/x) indicates that you must hold down the key labeled Ctrl while you press another key or a pointing device button.
.
.
.
A vertical ellipsis indicates the omission of items from a code example or command format; the items are omitted because they are not important to the topic being discussed.
[ ] In format descriptions, brackets indicate that whatever is enclosed within the brackets is optional; you can select none, one, or all of the choices. (Brackets are not, however, optional in the syntax of a directory name in a file specification or in the syntax of a substring specification in an assignment statement.)
boldface text Boldface text represents the introduction of a new term or the name of an argument, an attribute, or a reason.

Boldface text is also used to show user input in online versions of the book.

italic text Italic text represents information that can vary in system messages (for example, Internal error number).
UPPERCASE TEXT Uppercase letters indicate that you must enter a command (for example, enter OPEN/READ), or they indicate the name of a routine, the name of a file, the name of a file protection code, or the abbreviation for a system privilege.
- Hyphens in coding examples indicate that additional arguments to the request are provided on the line that follows.
numbers Unless otherwise noted, all numbers in the text are assumed to be decimal. Nondecimal radixes---binary, octal, or hexadecimal---are explicitly indicated.


Chapter 1
Programming Overview of Xlib

The VMS DECwindows programming environment includes Xlib, a library of low-level routines that enable the VMS DECwindows programmer to perform windowing and graphics operations.

This chapter provides the following:

Additionally, the chapter includes an introductory Xlib program. The program includes annotations that are explained more completely in the programming descriptions in later chapters of this guide.

1.1 Overview of Xlib

The VMS DECwindows programming environment enables application programs, called clients, to interact with workstations using the X Window System, Version 11 protocol software. The program that controls workstation devices such as screens and pointing devices is the server. Xlib is a library of routines that enables a client to communicate with the server to create and manage the following:

Xlib processes some client requests, such as requests to measure the width of a character string, within the Xlib library. It sends other client requests, such as those pertaining to putting graphics on a screen or receiving device input, to the server.

The server returns information to clients through either replies or events. Replies and events both return information to clients; the server returns replies synchronously and events asynchronously.

See the X Window System for a list of routines that cause Xlib to send requests to the server.

Figure 1-1 illustrates the relationships among client, Xlib, and server. The client calls Xlib routines, which always reside on the client system. If possible, Xlib processes calls internally and returns information to the client when appropriate. When an Xlib routine requires server intervention, Xlib generates a request and sends the request to the server.

The server may or may not reside on the same system as the client and Xlib. In either case, Xlib communicates with the server through a transport protocol, which can be either local shared memory or DECnet networking software.

Figure 1-1 Client, Xlib, and Server


1.2 Sample Xlib Program

The introductory Xlib program described in Example 1-1 illustrates the structure of a typical client program that uses Xlib windowing and graphic operations. The program creates two windows, draws text into one of them, and exits if the user clicks any mouse button while the cursor is in the window containing text.

The main loop of the program comprises two client-defined routines: doInitialize and doHandleEvents.

This section describes these routines and introduces fundamental concepts about Xlib resources, windowing, and event-handling.

1.2.1 Sample Initialization Routine

The sample program begins by calling a client-defined routine, doInitialize. The routine creates the resources the client needs to perform tasks. Xlib resources include windows, fonts, pixmaps, cursors, color maps, and data structures that define the characteristics of graphics objects. The sample program uses a default font, default cursor, default color map, client-defined windows, and a client-defined data structure that specifies the characteristics of the text displayed.

The doInitialize routine makes a connection between the client and the server. The client-server connection is called the display. After making the connection, or opening the display, the client can get display information from the server. For example, immediately after opening the display, the program calls the DEFAULT SCREEN OF DISPLAY routine to get the identifier of the default screen. The program uses the identifier as an argument in a variety of routines it calls later.

1.2.1.1 Creating Windows

A window is an area of the screen that either receives input or both receives input and displays graphics.

Windows in the X Window System are hierarchically related. At the base of the hierarchy is the root window. All windows that a client creates after opening a display are inferiors of the root window. The sample program includes two inferiors of the root window. First generation inferiors of a window are its children. The root window has one child, identified in the sample as window1. The window named window2 is an inferior of the root window and a child of window1.

To complete the window genealogy, all windows created before a specified window and hierarchically related to it are its ancestors. In the sample program, window1 has one ancestor (the root window); window2 has two ancestors (the root window and window1).

1.2.1.2 Defining Colors

Defining background and foreground colors is part of the process of creating windows in the sample program. The doDefineColor routine allocates named VMS DECwindows colors for client use in a way that permits other clients to share the same color resource. For example, the routine specifies the VMS DECwindows color named "light grey" as the background color of window2. If other clients were using VMS DECwindows color resources, they too could access the VMS DECwindows data structure that defines "light grey." Sharing enables clients to use color resources efficiently.

The sample program calls the doDefineColor routine again in the next step of initialization, creating the graphics context that defines the characteristics of a graphics object. In this case, the program defines foreground and background colors used when writing text.

1.2.1.3 Working with the Window Manager

Most clients run on systems that have a window manager, which is an Xlib application that controls conflicts between clients. Clients provide the window manager with information about how it should treat client resources, although the manager can ignore the information. The sample program provides the window manager with information about the size and placement of window1. Additionally, the program assigns a name that the window manager displays in the title bar of window1.

1.2.1.4 Making Windows Visible on the Screen

Creating windows does not make them visible on the screen. To make its windows visible, a client must map them, painting the windows on a specified screen. The last step of initializing the sample program is to map window1 and window2.

1.2.2 Sample Event-Handling Routine

The core of an Xlib program is a loop in which the client waits for the server to notify it of an event, which is a report of either a change in the state of a device or the execution of a routine call by another client. The server can report 30 types of events associated with the following occurrences:

When an event occurs, the server sends information about the event to Xlib. Xlib stores the information in a data structure. If the client has specified an interest in that kind of event, Xlib puts the data structure on an event queue. The doHandleEvents routine polls the event queue to determine if it contains an event of interest to the client. When the routine finds an event that is of interest to the client, the doHandleEvents routine calls one or more other routines.

Because Xlib clients do their essential work in response to events, they are considered event driven.

The sample program continually checks its event queue to determine if a window has been made visible or a button has been clicked. When the server informs it of either kind of event, the program performs its real work, as follows.

If the event is a window exposure, the program calls the doExpose routine. This routine determines whether the window exposed is window2 and if the event is the first instance of the exposure. If both conditions are true, the program writes a message into the window.

If the event is a button press, the program calls the doButtonPress routine. This routine checks to make certain the cursor is in window2 when the user clicks the mouse button. If the user clicks the mouse button when the cursor is in window1, the program reminds the user to click on window2. Otherwise, the program initiates a series of shutdown routines.

The shutdown routines unmap window1 and window2, free resources allocated for the windows, break the connection between the sample program and its server, and exit the system. On the VMS operating system, clients only need to call SYS$EXIT. Exiting the system causes the other shutdown operations to occur. The call to SYS$EXIT breaks the connection between client and server, which frees resources allocated for client windows, and so forth.

See Example 1-1 for the sample Xlib program.

Note that using the #include directives in the sample program requires that the .h files were extracted during VAX C installation. In addition, note that the .h files reside in the SYS$COMMON:DECW$INCLUDE directory. For programs that use the X11 logical in include directives, users can redefine the logical X11 to DECW$INCLUDE with the following format:

DEFINE X11 DECW$INCLUDE

Example 1-1 Sample Xlib Program

#include <decw$include/Xlib.h> 
#include <decw$include/Xutil.h> 
 
#define FontName\ 
    "-Adobe-New Century Schoolbook-Medium-R-Normal--*-140-*-*-P-*-ISO8859-1" 
#define WindowName "Sample Xlib Program" 
 
Display *dpy; 
Window window1,window2; 
GC gc; 
Screen *screen; 
int n, state = 0; 
char *message[]= { 
    "Click here to exit", 
    "Click HERE to exit!" 
    }; 
 
static void doInitialize( ); 
static int doDefineColor( ); 
static void doCreateWindows( ); 
static void doCreateGraphicsContext( ); 
static void doLoadFont( ); 
static void doExpose( ); 
static void doMapWindows( ); 
static void doHandleEvents( ); 
static void doButtonPress( ); 
 
/***** The main program *****/ 
 
static int main() 
{          
    doInitialize( ); 
    doHandleEvents( ); 
}                                        
 
/***** doInitialize *****/ 
static void doInitialize( ) 
{ 
 
(1)  dpy = XOpenDisplay(0);        
    if (!dpy){ 
        printf("Display not opened!\n"); 
        exit(-1); 
    } 
    screen = XDefaultScreenOfDisplay(dpy); 
 
(2)  XSynchronize(dpy,1); 
             
    doCreateWindows( ); 
 
    doCreateGraphicsContext( ); 
 
    doLoadFont( ); 
 
    doMapWindows( );  
} 
 
/***** Create the windows *****/ 
(3)static void doCreateWindows( ) 
{   
    int window1W = 400; 
    int window1H = 300; 
    int window1X = (XWidthOfScreen(screen)-window1W)>>1; 
    int window1Y = (XHeightOfScreen(screen)-window1H)>>1; 
    int window2X = 50; 
    int window2Y = 75; 
    int window2W = 300; 
    int window2H = 150; 
    XSetWindowAttributes xswa; 
    
    /* Create the window1 window */ 
 
    xswa.event_mask = ExposureMask | ButtonPressMask; 
    xswa.background_pixel = doDefineColor(1); 
 
    window1 = XCreateWindow(dpy, XRootWindowOfScreen(screen), 
        window1X, window1Y, window1W, window1H, 0, 
        XDefaultDepthOfScreen(screen), InputOutput, 
        XDefaultVisualOfScreen(screen), CWEventMask | CWBackPixel, &xswa); 
 
    /* Create the window2 window */                 
 
    xswa.event_mask = ExposureMask | ButtonPressMask; 
    xswa.background_pixel = doDefineColor(2); 
 
    window2 = XCreateWindow(dpy, window1, window2X, window2Y, window2W, 
        window2H, 4, XDefaultDepthOfScreen(screen), InputOutput, 
        XDefaultVisualOfScreen(screen), CWEventMask | CWBackPixel, &xswa); 
 
    XStoreName(dpy, window1, WindowName); 
} 
    
/***** Create the graphics context *****/    
(4)static void doCreateGraphicsContext( ) 
{                                                
    XGCValues xgcv; 
    
    /* Create graphics context. */ 
 
    xgcv.foreground = doDefineColor(3); 
    xgcv.background = doDefineColor(2); 
 
    gc = XCreateGC(dpy, window2, GCForeground | GCBackground, &xgcv);   
}   
 
/***** Load the font for text writing *****/ 
(5)static void doLoadFont( ) 
{ 
    Font font; 
 
    font = XLoadFont(dpy, FontName); 
    XSetFont(dpy, gc, font); 
} 
    
 
/***** Create color *****/ 
 
(6)static int doDefineColor(n) 
{ 
    int pixel; 
    XColor exact_color,screen_color; 
    char *colors[] = { 
        "dark slate blue", 
        "light grey", 
        "firebrick" 
        }; 
 
    if ((XDefaultVisualOfScreen(screen))->class == TrueColor 
        || (XDefaultVisualOfScreen(screen))->class == PseudoColor 
        || (XDefaultVisualOfScreen(screen))->class == DirectColor 
        || (XDefaultVisualOfScreen(screen))->class == StaticColor) 
 
        if (XAllocNamedColor(dpy, XDefaultColormapOfScreen(screen), 
           colors[n-1], &screen_color, &exact_color)) 
               return screen_color.pixel; 
           else 
               printf("Color not allocated!"); 
     else 
        switch (n) { 
            case 1:             return XBlackPixelOfScreen(screen); break; 
            case 2:             return XWhitePixelOfScreen(screen); break; 
            case 3:             return XBlackPixelOfScreen(screen); break; 
        }                                 
}   
 
/***** Map the windows *****/ 
(7)static void doMapWindows( )                                           
{ 
    XMapWindow(dpy, window1); 
    XMapWindow(dpy, window2);        
} 
                                      
/***** Handle the events *****/ 
(8)static void doHandleEvents( ) 
{ 
    XEvent event;         
    for ( ; ; ) {                         
        XNextEvent(dpy, &event); 
        switch (event.type) { 
            case Expose:                doExpose(&event); break; 
            case ButtonPress:           doButtonPress(&event); break; 
        } 
    }                                           
} 
 
/***** Write the message in the window *****/ 
static void doExpose(eventP) 
XEvent *eventP; 
{                                     
    /* If this is an expose event on our child window, then write the text. */ 
 
    if (eventP->xexpose.window != window2) return; 
    XClearWindow(dpy, window2);                                            
    XDrawImageString(dpy, window2, gc, 75, 75, message[state], 
        strlen(message[state])); 
} 
 
 
/***** Shutdown *****/ 
static void doButtonPress(eventP) 
XEvent *eventP; 
{                               
    if (eventP->xexpose.window != window2) { 
        state = 1; 
        XDrawImageString(dpy, window2, gc, 75, 75, message[state], 
            strlen(message[state])); 
        return; 
    } 
 
    /* Destroy the windows */ 
 
(9)  XDestroyWindow(dpy, window1); 
    XCloseDisplay(dpy);    
    sys$exit (1); 
}                          


Next Contents Index