By Mohamad Wael

Posted :

Compiling and running X11 programs under windows

Compiling and running X11 programs under windows , featured image

- The setup? you might ask, is what?
- Well, it is simple enough, what is needed , is to have a C/C++ compiler, and an X11 server installed.
- Hmmm, okay fair enough, but how is this done?
- Well, why not just use Cygwin , to just do all that.
- Any details?
- Well first, you must download Cygwin , and later on, just follow the instructions, shown in the following pictures.

- I have some problems with pictures, any textual details?
- Sure, so what was selected , in these pictures, was:

- That is it?
- Well yes, optionally, if you want like to have an X desktop environment, like kde, or mate or gnome , or xfce, you can also select one of those.

Desktop envrionment installation

- That is it?
- Additionally, you can select emacs, and nano, which are just some , text editors if that suits you.

- Well, yes, it is actually quite simple. So, after that, what is the next step?
- Just run the program , named xwinserver, and launch your Cygwin terminal.

- Done, next?
- Why not write and compile a simple X11 program ?
- Sure, how ?
- open your text editor, for example nano, and paste the following code, and save it, as for example demo_app.c.

/* nano demo_app.c */
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/* Global variables */
Display* display;
int root_window ;
int main_window_id;

XFontStruct* font_9_15;

int color_black = 0x00000000;
int color_gray = 0xff333333;
int color_white = 0xffffffff;

GC gc_white;


void
        get_display_conn
            ( ){
    char* connection_string = NULL;
    if ((display = XOpenDisplay (connection_string  )) == NULL ){
        fprintf (stderr, "Error: XOpenDisplay (%s )\n", connection_string );
        exit (EXIT_FAILURE );}
    root_window = XDefaultRootWindow (display );}


void
        load_font
            ( ){
    char *font_name = "9x15";
    if ((font_9_15 = XLoadQueryFont (display , font_name )) == NULL ){
        fprintf ( stderr, "Cannot load the font %s", font_name );
        exit (EXIT_FAILURE );}}


void
        get_gc_white
            ( ){
    XGCValues values;
    unsigned long valuemask = 0;

    gc_white = XCreateGC (display, root_window, valuemask, &values );
    XSetFont (display, gc_white, font_9_15 -> fid );
    XSetForeground (display, gc_white, color_white ); }


void
        create_main_window
            (int argc, char* argv [ ] ){
    int main_window_x = 0;
    int main_window_y = 0;
    int main_window_width = 300;
    int main_window_height = 300;

    unsigned int main_window_border_width = 0;

    unsigned long main_window_border_pixel_value = color_white;
    unsigned long main_window_background_pixel_value = color_gray;

    main_window_id = XCreateSimpleWindow (
        display ,
        root_window ,
        main_window_x ,
        main_window_y ,
        main_window_width ,
        main_window_height ,
        main_window_border_width,
        main_window_border_pixel_value ,
        main_window_background_pixel_value );

    XSizeHints* size_hints ;
    if (!(size_hints = XAllocSizeHints ( ))){
        fprintf (stderr, "failure to allocate memory to size_hints " );
        exit (EXIT_FAILURE );}

    size_hints -> flags = PWinGravity;
    size_hints -> win_gravity = StaticGravity ;


    XClassHint* class_hints;
    if (!(class_hints = XAllocClassHint ( ))){
        fprintf (stderr, "Failure to allocate memory to class_hints" );
        exit (EXIT_FAILURE );}

    class_hints -> res_name = "demo_app";
    class_hints -> res_class = "demo_class";


    XWMHints* wm_hints ;
    if (!(wm_hints = XAllocWMHints ( ))){
        fprintf (stderr, "Failure to allocate memory to wm_hints" );
        exit (EXIT_FAILURE );}

    wm_hints -> flags = StateHint | InputHint  ;
    wm_hints -> initial_state = NormalState;
    wm_hints -> input = True;

    char *main_window_title = "Demo app";
    XTextProperty x_main_window_title;
    if (XStringListToTextProperty (&main_window_title, 1, &x_main_window_title ) == 0 ){
        fprintf (stderr, "Failure to allocate x_main_window_title " );
        exit (EXIT_FAILURE );}


    char *main_window_icon_name = "Demo app icon";
    XTextProperty x_main_window_icon_name;
    if (XStringListToTextProperty (&main_window_icon_name, 1, &x_main_window_icon_name ) == 0) {
        fprintf (stderr, "Failure to allocate x_main_window_icon_name" );
        exit (EXIT_FAILURE );}


    XSetWMProperties  ( display,
            main_window_id,
            &x_main_window_title,
            &x_main_window_icon_name,
            argv,
            argc,
            size_hints,
            wm_hints,
            class_hints );


    XFree (size_hints );
    XFree (wm_hints );
    XFree (class_hints );}


void
        draw_kudos_text
            ( ){
    char* kudos_text = "Kudos, you have done it :)";
    int count_kudos_text = strlen (kudos_text );
    int width_kudos_text = XTextWidth (font_9_15, kudos_text, count_kudos_text );

    XDrawString (display,
                    main_window_id,
                    gc_white,
                    10 , //x
                    20 , //y
                    kudos_text,
                    count_kudos_text );}


void
        handle_events
            ( ){
    XEvent xevent;

    while (true ){
        XNextEvent (display, &xevent );
        switch (xevent .type ){
            case Expose:
                if (xevent .xexpose .count == 0 ){
                    draw_kudos_text ( );}
        default:
            break; }}

    XCloseDisplay(display);}


int
        main
            (int argc , char *argv [ ] ){
    get_display_conn ( );
    load_font ( );
    get_gc_white ( );
    create_main_window (argc , argv );
    XSelectInput (display, main_window_id,  ExposureMask );
    XMapWindow (display, main_window_id );
    handle_events ( );
    return 0;}

- Done, next?
- Compile it using gcc, as follows,

$ gcc demo_app.c -lX11

- Done, what is next.
- Just run the resultant program, as in ./a.exe, and that is it , you are set for creating and running X11 apps under windows.

Running an X11 program under windows

- What about other apps, or running for example a desktop environment.
- Well, if you have installed a desktop environment, as previously shown, you can just launch its GUI applications from the menu, which you can launch as shown earlier.
- Okay, not bad, what if I want to add, another application?
- Well just search for it, and using the Cygwin installer, install it, and after that, just launch it.

- Can Cygwin commands, be added to the environment?
- Yes, I don't see a problem, just edit your path, and add the following two directories.

- And now you can use Unix commands, such as ls, or git or whatever, from the windows command program, or they are just available and accessible, in your environment.