Chapter X7. An Introduction to X-Window Programming
 
Goals for this chapter: rpm packages covered in this chapter: 
  • XFree86 (X)
  • qt-2.3-0
  • gtk
 
 
Despite their well earned reputation as a source of confusion,
standards are one of the enabling factors behind the sucess of Linux.
If it weren't for the adoption of the right standards by Linux Torvalds
and other developers,
Linux would likely be a small footnote in history of Operating Systems
 - Dan Quinlan - Free Standards Group Chairmain.

Programming X Window System


Programming in X Window means write programs that run on the X Window graphical enviroment. From the first days when X Window appears on the UNIX scene, differents and important enhancements become more and more available to get more wonderfull and sophisticated results.

The first concept to fix in the mind is the Client-Server X Window philosophy. This means that the applications or xclients need a server, an X Window Server to run that may be in local computer with a single display or with more display, or far miles away from your location; also in this case is possible that the remote system haves multiple displays. In X Window is elementary send an application in the local enviroment to another display.

As we introduce before, this is possible running the commands:

[root@www root]# !ex
export DISPLAY=ftosx1:0.0
[root@www root]#mozilla

or

[root@www root]#mozilla -display ftosx1:0.0

Is necessary that the remote system accept clients (run: "xhost +" on the remote), and that both systems are listed in "/etc/hosts".

Note for example the following panorama. We can send any X Application (called xclient) to any display running commands like previous.

Now, that we know the target we will start introducing the Libraries that we need to know to create graphical applications.

Basically X Programming is a question of C (or C++) and the relative library.

We have the following libraries, each one have a specific use:

Using these libraries we can get graphical applications with the following look:


Note here that there are no depth in the buttons. Buttons are flat. These was the result available basically, from 1974 when X Windows become available ... and also up to 1989, when enter in serious competition with MS Windows. After those days, MS Windows release 3.0 ... basically for the mass and UNIX and X Windows remains like a closed group of expert.

Thanks to Linux, UNIX back to the masses and X was re-introduced however generally users and companies does not know X Window programming like Microsoft C++, Borland C++ or other similar enviroments.

Take for example, Adobe Inc, that release its Framemaker for Linux under beta. They use Motif, (we will describe in this chapter, and more in full along the rest of the course), but where they can get programmers that know X Window?

X Window programming is more "pure" in the sense of C Language (than MS Windows).

Levels of X-Window programming


How we can get these results ? The X Window System, is a clear and sophisticated development and user system that may offers incredible results; niether MS Windows or Mac OS X, are near to these results. However, X, programming is not real elementary because there are different functions with thousands of API.

We present here the X Window programming levels, that offers you an idea about the complexity. Basically C Language is only a first step in the know-how. Then is necessary to know XLib and then Xt more near to user. The OSF/Motif, now OpenMotif or other Toolkits (in the past we had, XView), and others are other little Universes. Motif, itself is a Universe. All these topics are covered here.
 

Some "great" semplications had been reached using C++ and "incredible" toolkits, like Troll Qt.
 

The Toolkit: Xt Intrinsics


In Chapter 3 we cover for example the Resources available in X Window System. Do you remember ? These resources offers you the possibility to change for example the colors.

We can launch, for example, "xclock" and then using the resource "fg" or "bg" to setup the foreground to cyan or red. But, how is possible to do that ?

This is possible using the "libXt.a".

We present here a small part of code that solve this problem.

...
static XrmOptionDescRec options [] = {
  { "-foreground",    "*Foreground",                   XrmoptionSepArg, 0 },
  { "-background",    "*Background",                   XrmoptionSepArg, 0 },
  { "-fg",            "*Foreground",                   XrmoptionSepArg, 0 },
  { "-bg",            "*Background",                   XrmoptionSepArg, 0 },
  { "-gutterwidth",   "*Keyboard.Key.gutterWidth",     XrmoptionSepArg, 0 },
  { "-gw",            "*Keyboard.Key.gutterWidth",     XrmoptionSepArg, 0 },
  { "-font",          "*Keyboard.Key.keycapFont",      XrmoptionSepArg, 0 },
  { "-geometry",      "*Keyboard.Key.geometry",        XrmoptionSepArg, 0 },
  { "-fn",            "*Keyboard.Key.keycapFont",      XrmoptionSepArg, 0 },
#ifdef HAVE_XTRAP
  { "-xtrap",         "*useXTrap",                     XrmoptionNoArg, "on" },
  { "-use-xtrap",     "*useXTrap",                     XrmoptionNoArg, "on" },
  { "-use_xtrap",     "*useXTrap",                     XrmoptionNoArg, "on" },
  { "-no-xtrap",      "*useXTrap",                     XrmoptionNoArg,"off" },
  { "-no_xtrap",      "*useXTrap",                     XrmoptionNoArg,"off" },
#endif
  { "-keyboard",      "*Keyboard.keyboard",            XrmoptionSepArg, 0 },
  { "-kbd",           "*Keyboard.keyboard",            XrmoptionSepArg, 0 }
};
...

int main (int argc, char **argv)
{
  char *class = "XKeyCaps";
  XtAppContext app;
  Widget toplevel, box, box2, buttons;
  struct info_labels *info;
  KeyboardWidget keyboard = 0;
  Arg av [20];
  int ac = 0;
  char version_buf [255];

  toplevel = XtAppInitialize (&app,
                              class,
                      options,
                              XtNumber (options),
                              &argc,
                              argv,
                              xkeycapsDefaults,
                              NULL,
                              0);

...

Therefore, resources like color,font are implicit in the level of the Xt library.

Of course we can also write an application and handle a particular resource.
 

OSF/Motif


OSF stand for the Open Software Foundation, formed in Boston Massachusetts, and join in 1996 to the X/Open to form the actual OpenGroup. OSF born like a consortium to define a Graphical standard for UNIX systems.

Between 1989 and 1991, Motif was (after some little war with OpenLook) the standard.

Motif, in those days was really excellent and advanced in Comparasion to MS Windows 2.X or 3.0.

For example, look the depth on the button.

MS Windows offers this feel only from MS Windows 95 (about four years later), in true was like a Motif reproduction on MS Windows 95 tools.

The complete source for this button is the following:

[root@ftosx1 chapter-25]# more multi_font
multi_font    multi_font.c  multi_font.o
[root@ftosx1 chapter-25]# more multi_font.c
/* multi_font.c -- create three compound strings using 12, 14 and 18
** point fonts. The user can specify resources so that each of the strings
** use different fonts by setting resources similar to that shown
** by the fallback resources.
*/

#include <Xm/Label.h>
#include <Xm/PushB.h>

String fallbacks[] =
{
        "*.renderTable: TAG1, TAG2, TAG3",
        "*.fontType: FONT_IS_FONT",
        "*TAG1.fontName: -*-helvetica-*-r-*--*-120-*",
        "*TAG2.fontName: -*-helvetica-bold-o-*--*-140-*",
        "*TAG3.fontName: -*-helvetica-bold-r-*--*-180-*",
        NULL
};

main (int argc, char *argv[])
{
        Widget       toplevel, button;
        XtAppContext app;
        XmString     s1, s2, s3, text, tmp;
        Arg          args[2];
        String string1 = "Next",
               string2 = "-",
               string3 = ">";

        XtSetLanguageProc (NULL, NULL, NULL);
        toplevel = XtVaOpenApplication (&app, "Demo", NULL, 0, &argc, argv, fallbacks,
                                        sessionShellWidgetClass, NULL);

        s1 = XmStringGenerate ((XtPointer) string1, NULL, XmCHARSET_TEXT, "TAG1");
        s2 = XmStringGenerate ((XtPointer) string2, NULL, XmCHARSET_TEXT, "TAG2");
        s3 = XmStringGenerate ((XtPointer) string3, NULL, XmCHARSET_TEXT, "TAG3");

        /* concatenate the 3 strings on top of each other, but we can only
        ** do two at a time. So do s1 and s2 onto tmp and then do s3.
        */
        tmp = XmStringConcatAndFree (s1, s2);
        text = XmStringConcatAndFree (tmp, s3);
        XtSetArg (args[0], XmNlabelString, text);
        //label = XmCreateLabel (toplevel, "widget_name", args, 1);
        button = XmCreatePushButton (toplevel, "button", args, 1);
        XtManageChild (button);

        XmStringFree (text);
        XtRealizeWidget (toplevel);
        XtAppMainLoop (app);
}

In some sense this code is a modified version (in about five minutes) from an original example available in Chapter 25 - Volume 6A "Motif Programming Manual".

  • Motif 2.1 - Programmer's Guide
  • Motif 2.1 - Programmer's Reference, Volume 1
  • Motif 2.1 - Programmer's Reference, Volume 2
  • Motif 2.1 - Programmer's Reference, Volume 3
  • Motif 2.1 - Widget Writer's Guide
  • Motif 2.1 - Style Guide and Glossary
  • Motif 2.1 - Style Guide Certification Check List
  • Motif 2.1 - Style Guide Reference
Is very important to note the Motif Style Guide that defines how must be writen an application to be Motif complaint.
 

Developing CDE Applications

After the release of Motif, slowly the OpenGroup start to work to define a standard for the UNIX GUI. Standard means that all OpenGroup vendors, that are the UNIX vendors will use this GUI, and no others.  The CDE as we introduce before is basically:

To develop CDE complain applications , the Opengroup formerly  (IBM, HP, Sun, Novell (UnixLabs)), develop a builder.

Basically, CDE is Motif in C language, but there are some minor changes and graphical concepts fixed on CDE that does not are included in Motif.
 

The CDE development is a "interesting" Software engineer development. Any CDE developer (and real any Linux X Windows developers, must read this guides):

 
  • M021 
  • CDE 2.1/Motif 2.1 User's Guide 
  • M022 
  • CDE 2.1 - System Manager's Guide 
  • M023 
  • CDE 2.1 - Programmer's Overview and Guide 
  • M024A 
  • CDE 2.1 - Programmer's Reference, Volume 1 
  • M024B 
  • CDE 2.1 - Programmer's Reference, Volume 2 
  • M024C 
  • CDE 2.1 - Programmer's Reference, Volume 3 
  • M026 
  • CDE 2.1 - Application Developer's Guide 
  • M027 
  • CDE 2.1/Motif 2.1 - Style Guide and Glossary 
  • M028 
  • CDE 2.1/Motif 2.1 - Style Guide Certification Check List 
  • M029 
  • CDE 2.1/Motif 2.1 - Style Guide Reference 
  • M213 
  • Motif 2.1 - Programmer's Guide 
  • M214A 
  • Motif 2.1 - Programmer's Reference, Volume 1 
  • M214B 
  • Motif 2.1 - Programmer's Reference, Volume 2 
  • M214C 
  • Motif 2.1 - Programmer's Reference, Volume 3 
  • M216 
  • Motif 2.1 - Widget Writer's Guide 
  • CAE Specifications
    • C320  Motif Toolkit API
    • C321  Calendaring and Scheduling API (XCS)
    • C323  XCDE Services and Applications
    • C324 XCDE Definitions and Infrastructure

    Programming X in C++


    After Motif, start get attention from the entire IT comunity, different and important enhancements become available. Basically, C++ classes, and inherance offers some facilities that may facilitate Widget development, but is necessary to consider two things:

    Actually (May 2002) ABI does not have a good support on C++:

    Check the info on LSB (Linux Standard):






    The GNU GCC 3.1, will be the compiler solution implementing the necessary mapping.
     

    An Introduction to the Troll's Qt toolkit.

    Troll Qt is the library, originally invented to solve a GUI problem: "Same source, muliptle GUI". In fact, Troll Qt is available for "any" UNIX flavor, including Linux as well MS Windows.

    From the same source, Qt offers binaries for multiple GUI, like MS Windows and/or Linux.

    Actually Qt offers support also for Mac OS X, in Qt 3.0.

    In Qt 3.0 is also supported for the first time the support for DataBase, like MySQL, OBDC and others.

    These "drivers" are located in the "sqldrivers" directory in the Qt library release.

    [root@ftosx1 sqldrivers]# pwd
    /usr/lib/qt-3.0.3/plugins/sqldrivers
    [root@ftosx1 sqldrivers]# ls -al
    total 221
    drwxr-xr-x    2 root     root          144 Apr 22 15:48 .
    drwxr-xr-x    4 root     root          104 Apr 22 15:48 ..
    -rwxr-xr-x    1 root     root        50515 Mar 28 07:43 libqsqlmysql.so
    -rwxr-xr-x    1 root     root       104459 Mar 28 07:43 libqsqlodbc.so
    -rwxr-xr-x    1 root     root        61789 Mar 28 07:43 libqsqlpsql.so
    [root@ftosx1 sqldrivers]#

    The great QT efforts to simply under a complete toolkit, and its use on KDE efforts, allows to everyone to have ... almost any Graphical behaviour included like: OpenLook, CDE, NeXT, and others.




    Note for example, the CDE and OpenLook, included here as a simple Windows decoration with the same results ... without to learn Motif or XView the OpenLook Toolkit!

    Programming X with Tcl/Tk

    Tcl/Tk that will be covered in Chapter X14. Developing applications with Tcl/Tk is the scripting mode (Develop Graphical Application from scripts, without compiler), that offers the same look without any compiler. I, in 1998, develop a multiple platform applications that runs on
     
     

    The same Tcl/Tk on MS Window 95 runs ... ... also on Linux !

    The Tcl/Tk code, uses a Graphical Shell, called "wish".

    In fact, in the same mode shell scripts starts with the line:

    [root@ftosx1 Tcl_Tk]# more !$
    more ./hello.ui.tcl
    #! /bin/sh
    # the next line restarts using wish \
    exec wish "$0" "$@"

    # interface generated by SpecTcl version 1.1 from /root/FTLC/FTContribs/Files/Tcl_Tk/hello.ui
    #   root     is the parent window for this user interface

    proc hello_ui {root args} {

            # this treats "." as a special case

        global base
            if {$root == "."} {
                set base ""
            } else {
                set base $root
            }

            label $base.label#1 \
                    -text {Tcl/Tk s great!} \
                    -textvariable date
     

            # Geometry management

            grid $base.label#1 -in $root    -row 1 -column 1  \
                    -sticky nesw

            # Resize behavior management

            grid rowconfigure $root 1 -weight 0 -minsize 30
            grid columnconfigure $root 1 -weight 0 -minsize 30
    # additional interface code

    # end additional interface code

    }
     

    # Allow interface to be run "stand-alone" for testing

    catch {
        if [info exists embed_args] {
            # we are running in the plugin
            hello_ui .
        } else {
            # we are running in stand-alone mode
            if {$argv0 == [info script]} {
                wm title . "Testing hello_ui"
                hello_ui .
            }
        }
    }
    [root@ftosx1 Tcl_Tk]#

    Note the "wish" program.
     

    Graphical scripts programming languages


    Tcl/Tk is a Graphical Scripting language. However, there are other modes and programming langauges.

    For example, the RedHat installer called "anaconda" uses Python and the Tkinker, that using Tk (The Tcl toolkit) generate graphics. Also, the "netcfg" uses this system.





    In the same mode is also possible to develop Qt application using PERL or Python. Python is a long better than PERL, because uses classes and inherence concepts. PERL, generally is more indicated to CGI script and other similar tasks, however both lnaguages will mix to create Parrot. (also called PERL 6).

    We present here the code for themes.py, that present the Qt themes using, PyQt that is a toolkit to develop Qt applications with Python.

    Programming X with JAVA


    Java is a complete and definitive solution to the problem: "same source, multiple binaries". Tcl/Tk hold some years at Sun Labs, when was developed "SpecTcl" a builder capable to generate both Tcl/Tk and Java code.

    Java needs a compiler to generate the

    [root@ftosx1 JAVA]# more hello.java
    // SpecTcl generated class hello, version 1.1

    import java.awt.*;

    public class hello extends java.applet.Applet {

    // a slot to hold an arbitrary object pointer that can
    // be filled in by the app. and referenced in actions
    public Object arg;

    public Button button_1;

    //methods to support form introspection
    public static String names[] = {
            "button_1",
    };
    public String[] getNames() {
            return names;
    }

    //There should be an easier way to do this
    public Object[] getWidgets() {
            Object[] list = new Object[1];
            list[0] = button_1;
            return list;
    }

    public void init() {

            // main panel
            GridBagLayout grid = new GridBagLayout();
            int rowHeights[] = {0,30};
            int columnWidths[] = {0,30};
            double rowWeights[] = {0.0,0.0};
            double columnWeights[] = {0.0,0.0};
            grid.rowHeights = rowHeights;
            grid.columnWidths = columnWidths;
            grid.rowWeights = rowWeights;
            grid.columnWeights = columnWeights;

            button_1 = new Button();
            button_1.setLabel("hello World");
            this.add(button_1);

            // Geometry management
            GridBagConstraints con = new GridBagConstraints();
            reset(con);
            con.gridx = 1;
            con.gridy = 1;
            con.anchor = GridBagConstraints.CENTER;
            con.fill = GridBagConstraints.NONE;
            grid.setConstraints(button_1, con);
     

            // Resize behavior management and parent heirarchy
            setLayout(grid);

            // Give the application a chance to do its initialization

    }
     

    public boolean handleEvent(Event event) {
            if (event.id==event.KEY_ACTION && event.key==event.F4 && event.modifiers==event.ALT_MASK) {  // Alt-F4 always
     exits
                    System.exit(3);
            } else
                    return super.handleEvent(event);
            return true;
    }

    public static void main(String[] args) {
        Frame f = new Frame("hello Test");
        hello win = new hello();
        win.init();
        f.add("Center", win);
        f.pack();
        f.show();
    }

    private void reset(GridBagConstraints con) {
        con.gridx = GridBagConstraints.RELATIVE;
        con.gridy = GridBagConstraints.RELATIVE;
        con.gridwidth = 1;
        con.gridheight = 1;

        con.weightx = 0;
        con.weighty = 0;
        con.anchor = GridBagConstraints.CENTER;
        con.fill = GridBagConstraints.NONE;

        con.insets = new Insets(0, 0, 0, 0);
        con.ipadx = 0;
        con.ipady = 0;
    }

    }

    [root@ftosx1 JAVA]# pwd
    /root/FTLinuxCourse_Complete-2002/FTContribs/Files/JAVA
    [root@ftosx1 JAVA]#

    Now, we compile and generate the code.

    [root@ftosx1 JAVA]# javac hello.java
    [root@ftosx1 JAVA]# java hello

    ... and we will get:

    We can also get all the actual enviroments running Java.

    Visit xwt.org for additional info.
     
     
     
     
     

    Compiling an X program: xkmf


    The program" "xkmf", means "make the Makefile", or create the Makefile.

    Generally, X Window applications, or xclients are available on the Web and in FTP sites, compress with the "compress" format.

    These files generally have a ".Z" extension. This type was the UNIX compressed mode available from those days.

    You can consult the compress manual file.
     

    COMPRESS(1)                                           COMPRESS(1)

    NAME
           compress, uncompress, zcat - compress and expand data (version 4.1)

    SYNOPSIS
           compress [ -f ] [ -v ] [ -c ] [ -V ] [ -r ] [ -b bits ] [ name ...  ]
           uncompress [ -f ] [ -v ] [ -c ] [ -V ] [ name ...  ]
           zcat [ -V ] [ name ...  ]

    DESCRIPTION
           Compress  reduces  the  size  of the named files using adaptive Lempel-Ziv coding.  Whenever possible, each
           file is replaced by one with the extension .Z, while keeping the same ownership modes, access and modifica­
           tion  times.  If no files are specified, the standard input is compressed to the standard output.  Compress
           will only attempt to compress regular files.  In particular, it will ignore symbolic links. If a  file  has
           multiple hard links, compress will refuse to compress it unless the -f flag is given.
    ...

    To uncompress these files we can run the command: uncompress.

    For example if we want to uncompress and compile this program we need to run the following commands:

    [root@ftosx1 FTKDE]# ls -al xkeycaps-2.46.tar.Z
    -rw-r--r--    1 root     root       489439 Oct 17 17:22 xkeycaps-2.46.tar.Z

    Then uncompress it!

    [root@ftosx1 FTKDE]# uncompress xkeycaps-2.46.tar.Z
    [root@ftosx1 FTKDE]#

    Then expand the tarball.

    [root@ftosx1 FTKDE]# tar xvf xkeycaps-2.46.tar

    Now, to compile the program we need to create the Makefile.

    In fact, there are no makefile inside the source, but a special file called: Imakefile

    [root@ftosx1 xkeycaps-2.46]# ls -al *ake*
    -rw-r--r--    1 220      tony        22705 Dec 13  1999 Imakefile
    [root@ftosx1 xkeycaps-2.46]#

    Now we create the Makefile running

    [root@ftosx1 xkeycaps-2.46]# xmkmf
    imake -DUseInstalled -I/usr/X11R6/lib/X11/config
    [root@ftosx1 xkeycaps-2.46]#

    ... and now to compile we simply run:
    [root@ftosx1 xkeycaps-2.46]# make

    The previous source includes XLib functions to handle the keyboard.

    Future Technologies modify the source to create the "FT Advanced Keyboard", available in FTGUIX and LinuxUtilities.

    The original "Imakefile" , may be very small and concise:

    [root@ftosx1 Source]# more Imakefile
    # Type "xmkmf" to turn this Imakefile into a Makefile.  Then type
    # "make Makefiles" to turn all the subdirectories' Imakefiles into
    # Makefiles... then type "make" and each subdir will get "made".

    #define IHaveSubdirs
    #define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)'

    SUBDIRS = chapter-2 chapter-4 chapter-5 chapter-6 chapter-7 chapter-8 chapter-9 chapter-10 chapter-11 chapter-12 chapter-13 chapter-14 chapter-15
    chapter-16 chapter-17 chapter-18 chapter-19 chapter-20 chapter-21 chapter-22 chapter-23 chapter-24 chapter-25 chapter-26 chapter-27 AppendixA

    MakeSubdirs($(SUBDIRS))
    DependSubdirs($(SUBDIRS))
    CleanSubdirs($(SUBDIRS))
    [root@ftosx1 Source]#

    But, the Makefile generated from it may up to 1000 lines long.

    [root@ftosx1 Source]# ls -al Makefile
    -rw-r--r--    1 root     root        26515 Apr 19 12:01 Makefile
    [root@ftosx1 Source]# wc -l Makefile
       1021 Makefile
    [root@ftosx1 Source]#
     

    Exercises

    1. Read carefull this chapter to take full confidence on your system.


    Test

    1. List the three most important X11 Libraries
    2. Where are located these libraries ?
    3. Why are called X11 libraries? In other words what means 11 in X11?
    4. List three UNIX vendors that adopt CDE
    5. When was formed the OpenGroup ?
    6. What's OSF ? What did ?
    7. Is possible using Qt and KDE, get CDE look and feel ?
    8. What is a graphical Scripting languages ?
    9. What is the name of the Tcl/Tk Graphical shell ?
    10. Is possible to use Tcl/Tk to write applications that runs in MS Windows and Linux ?
    11. What programming languages uses "anaconda" the RedHat installer ?
    12. Is possible to get Qt Themes if we develop applications using scripting languages ?
    13. Is possible to write Graphical programs using PERL language ?
    14. Is possible to write Graphical programs that uses Qt Toolkit using PERL ? ... and using Python ?
    15. Are there some mode to know what is the X Window Server version ?
    16. In what language was developed X11 ?
    17. In what language is developed Motif ?
    18. Is possible to compile Motif programs in C++ ?
    19. What was the language used in Qt ?
    20. Is possible to write X programs in Java ?
    21. What is XWT ?
    22. What is the program to create Makefile enviroment on X11 Source ?
    23. What does the program "xmkmf" ?
    24. It is possible to create Makefiles, using "xmk" that compile an entire hierarchy of directories creating the relative Makefile, inside any directory ?
    25. Generally, the Makefile generated by "xmkmf" will be short or long ?
    Consult the answers

    Check the Interactive Exam Cram X Window: Try the interactive cram ...

    Internet Resources for this Chapter.