Create a simple X11 application, using an X11 protocol library such as Xlib, that draws a box and "Hello World" in a window

Task
Window creation/X11
You are encouraged to solve this task according to the task description, using any language you may know.

ALGOL 68

Works with: ALGOL 68G version tested with release mk15-0.8b.fc9.i386

Using the X11 & plotutil libraries is not part of any of the original UNESCO/IFIP ALGOL 68 reports. As at December 2008 only ALGOL 68G comes with these built in.

FILE window;
draw device (window, "X", "600x400");
open (window, "Hello, World!", stand draw channel);
  draw erase (window);
  draw move (window, 0.25, 0.5);
  draw colour (window, 1, 0, 0);
  draw text (window, "c", "c", "hello world");
  draw show (window);
  VOID (read char); 
close (window)

C

Library: Xlib

Compile with:

  • gcc -L/usr/X11R6/lib -lX11 hello-x.c -o hello-x

<lang c>#include <X11/Xlib.h>

  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <string.h>

int main(void) {

  Display *d;
  Window w;
  XEvent e;
  char *msg = "Hello, World!";
  int s;
  d = XOpenDisplay(NULL);
  if (d == NULL) {
     fprintf(stderr, "Cannot open display\n");
     exit(1);
  }
  s = DefaultScreen(d);
  w = XCreateSimpleWindow(d, RootWindow(d, s), 10, 10, 100, 100, 1,
                          BlackPixel(d, s), WhitePixel(d, s));
  XSelectInput(d, w, ExposureMask | KeyPressMask);
  XMapWindow(d, w);
  while (1) {
     XNextEvent(d, &e);
     if (e.type == Expose) {
        XFillRectangle(d, w, DefaultGC(d, s), 20, 20, 10, 10);
        XDrawString(d, w, DefaultGC(d, s), 10, 50, msg, strlen(msg));
     }
     if (e.type == KeyPress)
        break;
  }
  XCloseDisplay(d);
  return 0;

} </lang>

Common Lisp

This example needs review by someone who knows about: X11
This example was written in near-total ignorance of X11 by consulting the CLX manual to find equivalents for the parts of the C example. It was also only tested with Mac OS X X11, which is not exactly normal.

If you know X11, please review this example and, as necessary, improve it or describe what should be done for someone who knows the language.

Translation of: C
Library: CLX

This example uses CLX, which is the de facto standard X11 library for Common Lisp. CLX is not a binding to Xlib; it is a Lisp library implementing the X11 protocol.

<lang lisp>;;; Single-file/interactive setup; large applications should define an ASDF system instead (cl:require :asdf) (asdf:operate 'asdf:load-op :clx) (cl:defpackage #:rc-xlib-window

 (:use #:cl #:xlib))

(cl:in-package #:rc-xlib-window)

(let ((display (open-default-display)))

 (unwind-protect
     (let* ((window (create-window :parent (screen-root (display-default-screen display))
                                   :x 10
                                   :y 10
                                   :width 100
                                   :height 100
                                   :event-mask '(:exposure :key-press)))
            (gc (create-gcontext :drawable window)))
       (map-window window)
       (event-case (display :discard-p t)
         (exposure ()
           (draw-rectangle window gc 20 20 10 10 t)
           (draw-glyphs window gc 10 40 "Hello, World!")
           nil #| continue receiving events |#)
         (key-press ()
           t #| non-nil result signals event-case to exit |#))))
   (close-display display))</lang>

OCaml

Library: OCaml-Xlib

execute as a script with:

ocaml -I +Xlib Xlib.cma script.ml

or compile to native code:

ocamlopt -I +Xlib Xlib.cmxa prog.ml -o prog

or to make a standalone script add these lines at the beginning of the file:

#!/usr/bin/env ocaml
#directory "+Xlib"
#load "Xlib.cma"

<lang ocaml>open Xlib

let () =

 let d = xOpenDisplay "" in
 let s = xDefaultScreen d in
 let w = xCreateSimpleWindow d (xRootWindow d s) 10 10 100 100 1
                               (xBlackPixel d s) (xWhitePixel d s) in
 xSelectInput d w [ExposureMask; KeyPressMask];
 xMapWindow d w;
 let msg = "Hello, World!" in
 let rec main_loop() =
   match xEventType(xNextEventFun d) with
   | Expose ->
       xFillRectangle d w (xDefaultGC d s) 20 20 10 10;
       xDrawString d w (xDefaultGC d s) 10 50 msg;
       main_loop()
   | KeyPress -> ()  (* exit main loop *)
   | _ -> main_loop()
 in
 main_loop();
 xCloseDisplay d;
</lang>

Python

This example needs review by someone who knows about: X11
Note (stolen from CLX example): This example was written in near-total ignorance of X11 by consulting the python-xlib's examples (included in its distribution) to find equivalents for the parts of the C example.

If you know X11, please review this example and, as necessary, improve it or describe what should be done for someone who knows the language.

Translation of: C
Library: python-Xlib

Download Python X library from http://sourceforge.net/projects/python-xlib/ . python-xlib is a pure python library therefore the example should work anywhere where python does. Run:

  • python xlib_hello_world.py

<lang python>from Xlib import X, display

class Window:

   def __init__(self, display, msg):
       self.display = display
       self.msg = msg
       
       self.screen = self.display.screen()
       self.window = self.screen.root.create_window(
           10, 10, 100, 100, 1,
           self.screen.root_depth,
           background_pixel=self.screen.white_pixel,
           event_mask=X.ExposureMask | X.KeyPressMask,
           )
       self.gc = self.window.create_gc(
           foreground = self.screen.black_pixel,
           background = self.screen.white_pixel,
           )
       self.window.map()
   def loop(self):
       while True:
           e = self.display.next_event()
               
           if e.type == X.Expose:
               self.window.fill_rectangle(self.gc, 20, 20, 10, 10)
               self.window.draw_text(self.gc, 10, 50, self.msg)
           elif e.type == X.KeyPress:
               raise SystemExit


if __name__ == "__main__":

   Window(display.Display(), "Hello, World!").loop()

</lang>

Tcl

Tcl does not come with a low-level connection to the X protocol, as it has long been distributed with Tk which offers a much higher-level interface (and which is portable to other platforms too). This means that the interface has to be crafted directly. This can be done with either SWIG or critcl. This example shows how to do it the latter way:

Low level interface package

Library: critcl

<lang tcl>package provide xlib 1 package require critcl

critcl::clibraries -L/usr/X11/lib -lX11 critcl::ccode {

   #include <X11/Xlib.h>
   Display *d;
   GC gc;

}

critcl::cproc XOpenDisplay {Tcl_Interp* interp char* name} ok {

   d = XOpenDisplay(name[0] ? name : NULL);
   if (d == NULL) {

Tcl_AppendResult(interp, "cannot open display", NULL); return TCL_ERROR;

   }
   gc = DefaultGC(d, DefaultScreen(d));
   return TCL_OK;

}

critcl::cproc XCloseDisplay {} void {

   XCloseDisplay(d);

}

critcl::cproc XCreateSimpleWindow {

   int x  int y  int width  int height  int events

} int {

   int s = DefaultScreen(d);
   Window w = XCreateSimpleWindow(d, RootWindow(d,s), x, y, width, height, 0,

BlackPixel(d,s), WhitePixel(d,s));

   XSelectInput(d, w, ExposureMask | events);
   return (int) w;

}

critcl::cproc XMapWindow {int w} void {

   XMapWindow(d, (Window) w);

} critcl::cproc XUnmapWindow {int w} void {

   XUnmapWindow(d, (Window) w);

}

critcl::cproc XNextEvent {Tcl_Interp* interp} char* {

   XEvent e;
   XNextEvent(d, &e);
   switch (e.type) {

case Expose: return "expose"; case KeyPress: return "key"; /* etc. This is a cheap hack version. */ default: return "?";

   }

}

critcl::cproc XFillRectangle {int w int x int y int width int height} void {

   XFillRectangle(d, (Window)w, gc, x, y, width, height);

}

critcl::cproc XDrawString {int w int x int y Tcl_Obj* msg} void {

   int len;
   const char *str = Tcl_GetStringFromObj(msg, &len);
   XDrawString(d, (Window)w, gc, x, y, str, len);

}</lang> Note that this only does enough for this demo. A full adaptation is too long for RosettaCode...

High level interface package

Just because there is a low level package does not mean that it is pleasant to use from Tcl code. Therefore it is wrapped up inside a higher-level package that provides a more natural way of interacting. <lang tcl>package require Tcl 8.5 package provide x 11

namespace eval ::x {

   namespace export {[a-z]*}
   namespace ensemble create
   variable mask
   array set mask {

KeyPress 1 KeyRelease 2 ButtonPress 4 ButtonRelease 8

   }
   proc display {script} {

OpenDisplay {} catch {uplevel 1 $script} msg opts CloseDisplay return -options $opts $msg

   }
   proc eventloop {var handlers} {

upvar 1 $var v while 1 { set v [WaitForEvent] uplevel 1 [list switch $v $handlers] }

   }
   proc window {x y width height events} {

set m 0 variable mask foreach e $events {catch {incr m $mask($e)}} Window $x $y $width $height $m

   }

}

package require xlib rename ::XOpenDisplay ::x::OpenDisplay rename ::XCloseDisplay ::x::CloseDisplay rename ::XCreateSimpleWindow ::x::Window rename ::XMapWindow ::x::map rename ::XUnmapWindow ::x::unmap rename ::XNextEvent ::x::WaitForEvent rename ::XFillRectangle ::x::fillrect rename ::XDrawString ::x::text</lang>

Demonstration script

This script puts the pieces together to carry out the details of the task. <lang tcl>lappend auto_path lib . package require x

  1. With a display connection open, create and map a window

x display {

   set w [x window 10 10 100 100 KeyPress]
   x map $w
   x eventloop e {

expose { # Paint the window x fillrect $w 20 20 10 10 x text $w 10 50 "Hello, World!" } key { # Quit the event loop break }

   }

}</lang>