Programming: Simple X11 Code Sample for Linux and Mac OS X

X Window System, Mac OS X



X Window (or X11) is the low level windowing system (the equivalent of the Win32 API under Windows) available with Unix / Linux and Mac OS X. According to this page, X11 is an option under Mac OS X (on my Lion-based system, X11 is available by default). Desktop environments like KDE or Gnome are built on top of X11. Then using X11 API can be an interesting solution if you need to quickly test an piece of code under Linux and Max OS X (it’s my case…).

And nice news, the compilation has the same syntax under both operating systems.

Here is the full source code of a simple X11 app that creates a X window and displays some basic information about the system. To quit the app, two ways are available:

  • 1 – ESC key. This is the simplest way to stop the app. Just catch the KeyPress event and test the presence of the XK_Escape code.
  • 2 – Window close button (the cross). Don’t know why, but it’s not obvious to manage the close button. Once you have found that the WM_DELETE_WINDOW
    message is the key of all your troubles, you can easily code the management of the close button.



To compile and link the code sample, just open a terminal in the folder of your source code (too easy under Linux, a bit less easy under Mac ;) ) and type:

$ g++ xl01.cpp -o xl01 -I/usr/X11R6/include -I/usr/X11R6/include/X11 -L/usr/X11R6/lib 
-L/usr/X11R6/lib/X11 -lX11



Now to execute the demo:

$ ./xl01

X Window X11 app demo under Linux
Terminal, Linux Mint 10



Under Linux, you should see something like this:

X Window X11 app demo under Linux
X11 demo under Linux Mint 10



And under Mac OS X, you should see something like this:

X Window X11 app demo under Mac OS X
X11 demo under Mac OS X Lion



And now the full cross-platform source code that all of you are waiting for:

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <sys/utsname.h>
 
int main(int argc, char** argv)
{
  Display* dpy = XOpenDisplay(NULL);
  if (dpy == NULL) 
  {
    fprintf(stderr, "Cannot open display\n");
    exit(1);
  }
 
  int s = DefaultScreen(dpy);
  Window win = XCreateSimpleWindow(dpy, RootWindow(dpy, s), 10, 10, 660, 200, 1,
                                   BlackPixel(dpy, s), WhitePixel(dpy, s));
  XSelectInput(dpy, win, ExposureMask | KeyPressMask);
  XMapWindow(dpy, win);
 
#if defined(__APPLE_CC__)  
  XStoreName(dpy, win, "Geeks3D.com - X11 window under Mac OS X (Lion)");
#else
  XStoreName(dpy, win, "Geeks3D.com - X11 window under Linux (Mint 10)");
#endif  
 
  Atom WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 
  XSetWMProtocols(dpy, win, &WM_DELETE_WINDOW, 1);  
 
  bool uname_ok = false;
  struct utsname sname;  
  int ret = uname(&sname);
  if (ret != -1)
  {
    uname_ok = true;
  }
 
  XEvent e;
  while (1) 
  {
    XNextEvent(dpy, &e);
    if (e.type == Expose) 
    {
      int y_offset = 20;
 
#if defined(__APPLE_CC__)  
      const char* s1 = "X11 test app under Mac OS X Lion";
#else      
      const char* s1 = "X11 test app under Linux";
#endif      
 
      const char* s2 = "(C)2012 Geeks3D.com"; 
      XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, s1, strlen(s1));
      y_offset += 20;
      XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, s2, strlen(s2));
      y_offset += 20;
 
      if (uname_ok)
      {
        char buf[256] = {0};
 
        sprintf(buf, "System information:");
        XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
        y_offset += 15;
 
        sprintf(buf, "- System: %s", sname.sysname);
        XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
        y_offset += 15;
 
        sprintf(buf, "- Release: %s", sname.release);
        XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
        y_offset += 15;
 
        sprintf(buf, "- Version: %s", sname.version);
        XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
        y_offset += 15;
 
        sprintf(buf, "- Machine: %s", sname.machine);
        XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
        y_offset += 20;
      }
 
 
      XWindowAttributes  wa;
      XGetWindowAttributes(dpy, win, &wa);
      int width = wa.width;
      int height = wa.height;
      char buf[128]={0};
      sprintf(buf, "Current window size: %dx%d", width, height);
      XDrawString(dpy, win, DefaultGC(dpy, s), 10, y_offset, buf, strlen(buf));
      y_offset += 20;
    }
 
    if (e.type == KeyPress)
    {
      char buf[128] = {0};
      KeySym keysym;
      int len = XLookupString(&e.xkey, buf, sizeof buf, &keysym, NULL);
      if (keysym == XK_Escape)
        break;
    }
 
    if ((e.type == ClientMessage) && 
        (static_cast<unsigned int>(e.xclient.data.l[0]) == WM_DELETE_WINDOW))
    {
      break;
    }
  }
 
  XDestroyWindow(dpy, win);
  XCloseDisplay(dpy);
  return 0;
}



Some references:





[ Subscribe to Geeks3D latest news by email ]

Geeks3D.com

↑ Grab this Headline Animator