[Subject Prev][Subject Next][Thread Prev][Thread Next][Subject Index][Thread Index]

Re: x-windows programing



Dear Vivek
Sorry for the late response.I was very busy the last fortnight.
Here is a tutorial I wrote some 2 months back for LG.They didn't like it.The tutorial describes Xlib(pronounced X-libe) which is a library of routines(in C) that interface with the X server.
I 've made a few modifications.Hope you like it.
Xlib is like Assembly language;you can do anything but you have to do a lot of coding.I suggest GTK(Gimp Tool Kit) and QT as the alternatives.GTK comes in various flavours(C,C++,Perl,Ada etc) whereas QT is purely object oriented based on C++.Check out the respective sites viz www.gtk.org and www.trolltech.com .If you still want to persist with X, download XFree docs from their site(I've forgotten the name probably www.x.org or any variation of the same).These manuals cover each and every function.I will be more than willing to help in case of any glitches.
Manu

        X Programming using C
Hi
I was just browsing' past the gazette #57 and I came across a request for an
article on Xlib. This was exactly what I wanted a few months back and there was
nobody to help me either around my place,college or the internet. It left me
wondering that have all the Xlib programmers disappeared from the face of
earth.
To cut the long story short I began by looking at the documentation,getting
frustrated and then looking at the documentation again and feeling more
frustrated until I got this brilliant book "X Window Application Programming"
by Eric F. Johnson and Kevin Reichard.It started me on the X and I would like to
hand over the legacy to all the readers of lg.

################The X Factor#####################
The X Window System is a network oriented,device dependent system. It
basically consists of client programs making call to an X server. Xlib maps
requests to X server or provide utility functions. Actually X converts
calls to C language functions to the X server requests which actually
implements that request.
        To run an X program you need to have the requisitive header files and
libraries in /usr/X11R6/include and /usr/X11R6/lib respectively. The
following program is the most basic of all Xlib programs. It simply makes
a connection to the X server,prints some info and quits.

/*connect.c -Program to connect to the X Server
On Linux compile with gcc connect.c -L/usr/X11R6/lib -lX11
*/

#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include<stdio.h>

int main(){
        Display *display_name;
        int depth,screen,connection;

        /*Opening display and setting defaults*/
        display_name = XOpenDisplay(NULL);
        screen = DefaultScreen(display_name);
        depth = DefaultDepth(display_name,screen);
        connection = ConnectionNumber(display_name);

        /*Displaying the info gathered*/
        printf("The display is::%s\n",XDisplayName((char*)display_name));
        printf("Width::%d\tHeight::%d\n",
                                DisplayWidth(display_name,screen),
                                DisplayHeight(display_name,screen));
        printf("Connection number is %d\n",connection);

        if(depth == 1)
                printf("You live in prehistoric times\n");
        else
                printf("You've got a coloured monitor with depth of %d\n",
                        depth);

        /*Closing the display*/
        XCloseDisplay(display_name);
}

The first and foremost step, in case of all X programs is a request for
establishing a connection to the X server. This is accompolished by the
XOpenDisplay function call.We pass a NULL as the parameter to indicate that
our client and server are on the same machine. After establishing a connection
we seek a little info in form of the screen we are connected to(remember each
display may have multiple screens),the depth of the screen(colors/bit For ex
16bit screen screen will return 16).Finally we close the connection by
using XCloseDisplay().

        After this introduction we move on to more serious stuff ie opening a
window on the display. The following program attempts to open a window
on the screen.This window automatically terminates after 10 seconds.

/* window.c --This program opens a window on the display
* Use "gcc -o window window.c -L/usr/X11R6/lib -lX11
* to compile this code.
*/

#include <X11/X.h>
#include <X11/Xlib.h>

int main(void)
{
Display *display;
Window window, rootwindow;
int screen;

display = XOpenDisplay(NULL);
screen = DefaultScreen(display);
rootwindow = RootWindow(display,screen);
window = XCreateSimpleWindow(display, rootwindow,
                0, 0, 100, 100, 1, 0, 0);
XMapWindow(display, window);
XFlush(display);

sleep(10);
XCloseDisplay(display);
return (0);
}

The RootWindow macro returns the root window.RootWindow returns essentially
the background of the screen which is the parent window for all windows on
the display.The next important point of action is the XCreateSimpleWindow()
function.This function effectively creates a window on the display.
Officially the parameters of this function are:-

XCreateSimpleWindow(
        Display *display,                       /*Our display*/
        Window rootwindow,              /*parent Window*/
int x, /*Starting x coordinate*/ int y, /*Starting y coordinate*/
        unsigned int width,             /*Width of the window*/
        unsigned int height,            /*Height of the Window*/
        unsigned int border_width,              /*Width of the border*/
        unsigned long border,           /*Specify border pixel value*/
        unsigned long bkground          /*Color of the background*/
)

XMapWindow() call actually maps the window onto the screen. This is analogous
to ShowWindow() function in the Windoze API.A similar function is
XMapRaised() which accepts same parameters but raises the window over all
existing windows on the display.Xlib maintains a queue of output requests to
the X server.XFlush() call basically flushes out this request by sending
all requests to the X Srever as part of one communication.Ideally this call
should be given after all output calls.Finally sleep(10) waits for 10 seconds
before closing the display.
This was probably the easiest way to draw a window.Now we discuss a more
involved way to make a window appear on the screen.


/*window2.c --Program to display a window on the screen.
 * compile as gcc window2.c -L/usr/X11R6/lib -lX11
 */


#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include<stdio.h>

#define BORDER_WIDTH 2

/* Program wide globals */
Display *theDisplay;
int theScreen;
int theDepth;

Window OpenWindow(int x, int y, int width, int height, int flag){
        XSetWindowAttributes theWindowAttributes;
        unsigned long theWindowMask;
        XSizeHints theSizeHints;
        Window theNewWindow;

        /*Setting the attributes*/
        theWindowAttributes.border_pixel
                =BlackPixel(theDisplay,theScreen);
        theWindowAttributes.background_pixel
                = WhitePixel(theDisplay,theScreen);
        theWindowAttributes.override_redirect = True;


        theWindowMask = CWBackPixel|CWBorderPixel|CWOverrideRedirect;

        theNewWindow = XCreateWindow( theDisplay,
                        RootWindow(theDisplay,theScreen),
                        x,y,width,height,
                        BORDER_WIDTH,theDepth,
                        InputOutput,
                        CopyFromParent,
                        theWindowMask,
                        &theWindowAttributes);

        theSizeHints.flags = PPosition | PSize;
        theSizeHints.x = x;
        theSizeHints.y = y;
        theSizeHints.width = width;
        theSizeHints.height = height;

        XSetNormalHints(theDisplay,theNewWindow,&theSizeHints);

        XMapWindow(theDisplay,theNewWindow);
        XFlush(theDisplay);

        return theNewWindow;
}

void main(void){
        Window theWindow;

        theDisplay = XOpenDisplay(NULL);
        if(theDisplay == NULL){
                fprintf(stderr,"Error::Given display cannot be opened");
                return;
        }
        theScreen = DefaultScreen(theDisplay);
        theDepth = DefaultDepth(theDisplay,theScreen);
        theWindow = OpenWindow(100,100,200,200,0);

        sleep(10);
        XCloseDisplay(theDisplay);
}

This program is more robust as all the code of drawing the window is moved
to another procedure.Moreover window attributes as well as hints to the
window manager are also involved.So let us begin stepping through the
program.
        After establishing a connection to the X server,there is an error
detection routine which checks if the connection was successful.A
successful connection results in a call to OpenWindow() which opens
a window on the display.The two new chaps in OpenWindow() are
XSetWindowAttributes and XSizeHints. Both of these are structures.
While XSetWindowAttributes is needed to set various attributes of the
window, XSizeHints is needed to set information to be used by window
manager.
         Two other functions that need to be explained are XCreateWindow()
and XSetNormalHints().XCreateWindow() has all the ingrediants of our
XCreateSimpleWindow() function and more.A bare bone display is as follows:-

XCreateWindow(
        Display *display,                               /*Our display screen*/
        Window parent,                                  /*The parent window*/
int x,int y, /*Starting coordinates*/
        unsigned int width,unsigned int height, /*Proportions of the window*/
unsigned int border_width, /*Width of the border*/ int depth, /*Depth of the screen*/
        unsigned int Class,                     /*Type of window*/
        Visual *visual,                         /*visual of the window*/
        unsigned long attributemask,    /*Mask of the attributes*/
        XSetWindowAttibutes windowsattrib); /*Structure of window attribs*/
)

        XSetNormalHints() simply sends hints to the window manager informing
it about position,size and dimensions.The flags field has been set to
PPosition|PSize which effectively translates that the program chooses
the position and size.
After understanding the process of opening a window we are all set to learn about drawing in a window. X provides calls for drawing points,lines and
arcs. Circles and ellipses are thought of as an extension of arc function.
In accordance with the GUI packages all these functions have descriptive names
like XDrawPoint(),XDrawLine(),XDrawRectangle(),XDrawArc() etc. We present a
program which draws standard shapes into the present window.


/*Program to draw lines and rectangles--draw.c
*On Linux compile as gcc draw.c -L /usr/X11R6/lib -lX11
*/

#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include<stdio.h>
#define BORDER_WIDTH 2

/* Program wide globals */
Display *theDisplay;
int theScreen;
int theDepth;
unsigned long theBlackPixel;
unsigned long theWhitePixel;

void initX(void){
}

void drawLine(Window theWindow,GC theGC,int x1,int y1,int x2,int y2){
        XDrawLine(theDisplay,theWindow,theGC,x1,y1,x2,y2);

}

void drawRectangle(Window theWindow,GC theGC,int x,int y,int width,int height){
        XDrawRectangle(theDisplay,theWindow,theGC,x,y,width,height);
}

int createGC(Window theNewWindow,GC *theNewGC){
        XGCValues theGCValues;

*theNewGC = XCreateGC(theDisplay,theNewWindow,(unsigned long) 0,&theGCValues);
        if(*theNewGC == 0)
                return 0;
        else{
                XSetForeground(theDisplay,*theNewGC,theWhitePixel);
                XSetBackground(theDisplay,*theNewGC,theBlackPixel);
                return 1;
        }
}

Window OpenWindow(int x, int y, int width, int height, int flag,GC *theNewGC){
        XSetWindowAttributes theWindowAttributes;
        unsigned long theWindowMask;
        XSizeHints theSizeHints;
        XWMHints theWMHints;
        Window theNewWindow;

        /*Setting the attributes*/
        theWindowAttributes.border_pixel
                =BlackPixel(theDisplay,theScreen);
        theWindowAttributes.background_pixel
                = WhitePixel(theDisplay,theScreen);
        theWindowAttributes.override_redirect = False;


        theWindowMask = CWBackPixel|CWBorderPixel|CWOverrideRedirect;

        theNewWindow = XCreateWindow( theDisplay,
                        RootWindow(theDisplay,theScreen),
                        x,y,width,height,
                        BORDER_WIDTH,theDepth,
                        InputOutput,
                        CopyFromParent,
                        theWindowMask,
                        &theWindowAttributes);

        theWMHints.initial_state = NormalState;
        theWMHints.flags = StateHint;

        XSetWMHints(theDisplay,theNewWindow,&theWMHints);

        theSizeHints.flags = PPosition | PSize;
        theSizeHints.x = x;
        theSizeHints.y = y;
        theSizeHints.width = width;
        theSizeHints.height = height;

        XSetNormalHints(theDisplay,theNewWindow,&theSizeHints);

        if( createGC(theNewWindow,theNewGC) == 0){
                XDestroyWindow(theDisplay,theNewWindow);
                return( (Window) 0);
                }

        XMapWindow(theDisplay,theNewWindow);
        XFlush(theDisplay);

        return theNewWindow;
}

void main(void){
        Window theWindow;
        GC theGC;

        theDisplay = XOpenDisplay(NULL);

        theScreen = DefaultScreen(theDisplay);
        theDepth = DefaultDepth(theDisplay,theScreen);
        theBlackPixel = WhitePixel(theDisplay,theScreen);
        theWhitePixel = BlackPixel(theDisplay,theScreen);

        theWindow = OpenWindow(100,100,300,300,0,&theGC);
        drawLine(theWindow,theGC,10,10,100,100);
   drawRectangle(theWindow,theGC,100,100,100,100);
        XFlush(theDisplay);

        sleep(10);
        XDestroyWindow(theDisplay,theWindow);
}

This program displays a rectangle and a line connected to one of the edges.
To draw anything on the screen we need assistance from a GC. A GC is a
reservoir of default values for background,foreground,brush,pen etc. A
GC is needed because without its presence we would have to specify each
and every trivial aspect to the X server. A GC is obtained by a call to
XCreateGC() function.This GC can then be passed to all drawing functions.
Wrapper functions are defined for both line as well as rectangle drawing.
Local variables are defined for BlackPixel() and WhitePixel() macros.
This basically eases the burden on the X server.
As an aside there are functions which draw filled counterparts of the
functions described above.These are aptly called XFillRectangle() and
XFillArc().Moreover there are also functions which draw multiple points,
lines and arcs like XDrawPoints(),XDrawLines() and XDrawRectangles(). Be sure
to check the man pages for details.




_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com