X Windows Programming in C++: Part I

Years ago, I did quite a bit X Windows programming. When I started developing X Windows software, I was also learning C++ (this was a long time ago). Unfortunately , the X Windows system I was developing software for did not have a C++ compiler. This led to some frustration since using C++ would have made some of my tasks easier.

A fews years later, I worked on another project using X and Motif. It was mandated that this software be written in C leading to same frustration I experience when I first started learning X (by this time I was a seasoned C++ developer, so writing anything in C seemed like a step backward).

I’ve decided to revisit X Windows programming on my own for a few reasons:

  • I’m a little rusty when it comes to X Windows programming.

  • I want to use X in a project I’ve been contemplating for the past few years.

  • I’m currently working on Microsoft Windows C++/C# project at work and I want to do some non-Microsoft programming on my own.

My first step in getting back into X Windows programming was to revist the book, Xlib Programming Manual, Rel. 5. The examples in this book are written in C (Kerninghan and Ritchie C, no less). One of these examples, basicwin.c, demonstrates the fundementals of programming with the X library. I figure coming up with a C++ version of basicwin.c would be a useful learning experience for myself and possibly others.

I’ll start out by taking pieces of basicwin.c and converting them to C++. I’ll start with following code fragments showing the use of the structures: XSizeHints, XWMHints, and XClassHint.


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

/*
 .
 .
 .
 */

void main(argc, argv)
int argc;
char **argv;
{
  XSizeHints *size_hints;
  XWMHints *wm_hints;
  XClassHint *class_hints;
  Display *display;
  Window win;
  
  char *window_name = "Basic Window Program";
  char *icon_name = "basicwin";

  if (!(size_hints = XAllocSizeHints())) {
    fprintf(stderr, "%s: failure allocating memory\n", argv[0]);
    exit(0);
  }
  if (!(wm_hints = XAllocWMHints())) {
    fprintf(stderr, "%s: failure allocating memory\n", argv[0]);
    exit(0);
  }
  if (!(class_hints = XAllocClassHint())) {
    fprintf(stderr, "%s: failure allocating memory\n", argv[0]);
    exit(0);
  }

/*
 .
 .
 .
 */

  size_hints->flags = PPosition | PSize | PMinSize;
  size_hints->min_width = 300;
  size_hints->min_height = 200;

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

  class_hints->res_name = progname;
  class_hints->res_class = "Basicwin";

  XSetWMProperties(display, win, &windowName, &iconName,
      argv, argc, size_hints, wm_hints,
      class_hints);

/*
 .
 .
 .
 */

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

/*
 .
 .
 .
 */
}

C++ allows us to do something like this:


#include "xalloc.h"

/*
 .
 .
 .
 */

int main(int argc, char **argv)
{
  CXSizeHints size_hints;
  CXClassHint class_hints;
  CXWMHints wm_hints;

  Window win;
  Display *display;

/*
 .
 .
 .
 */

  size_hints->flags = PPosition | PSize | PMinSize;
  size_hints->min_width = 300;
  size_hints->min_height = 200;

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

  class_hints->res_name = progname;
  class_hints->res_class = "Basicwin";

  XSetWMProperties(display, win, &windowName, &iconName, 
                   argv, argc, size_hints, wm_hints, 
                   class_hints);
/*
 .
 .
 .
 */

  return 0 ;
}

CXSizeHints, CXClassHint and CXWMHints are defined in xalloc.h, along with CXIconSize which isn’t shown in the above example. The allocation is taken care of in the constructors and XFree is called from the destructors. Check out xalloc.h to see how this all works.

— start —


/*******************************************************************
 *
 * xlloc.h - Define wrappers around pointers to ClassHint, IconSize, 
 *           SizeHints, and WMHints
 *
 *  Copyright (C) 2006 by James A. Chappell
 *
 *  Permission is hereby granted, free of charge, to any person
 *  obtaining a copy of this software and associated documentation
 *  files (the "Software"), to deal in the Software without
 *  restriction, including without limitation the rights to use,
 *  copy, modify, merge, publish, distribute, sublicense, and/or
 *  sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following
 *  condition:
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *  OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef __xalloc_h__
#define __xalloc_h__

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

#include <exception>

//
// Exception, thrown if alloc fails
//
class bad_XAlloc : public std::exception
{
public:
  virtual const char* what() const throw()
  {
    return "bad_XAlloc" ; // for now
  }
} ;


template<class T, T (*alloc())> class _XAlloc 
{
public:
//
// Default Constructor
//
  _XAlloc()
  {
    allocator() ;
  }
//
// Copy Constructor
//
  _XAlloc(const _XAlloc& a)
  {
    allocator() ;
    copy(a.p_) ;
  }
//
// More Constructors
//
  _XAlloc(const T *a)
  {
    allocator() ;
    copy(a) ;
  }

  _XAlloc(const T& a)
  {
    allocator() ;
    copy(&a) ;
  }
//
// Destructor
//
  ~_XAlloc()
  {
    XFree(p_) ; 
  }
//
// Assignment operators
//
  _XAlloc& operator= (const _XAlloc& a)
  {
    if (p_ != a.p_)
    {
      copy(a.p_) ;
    }
   
    return *this ;
  }

  _XAlloc& operator= (const T *a)
  {
    if (p_ != a)
    {
      copy(a) ;
    }
   
    return *this ;
  }

  _XAlloc& operator= (const T& a)
  {
    if (p_ != &a)
    {
      copy(&a) ;
    }
   
    return *this ;
  }
//
// More operators
//
  T* operator->() { return p_ ; }
  operator T* const () { return p_ ; }

private:

  void allocator()
  {
    p_ = alloc() ;
    if (!p_)
    {
      throw bad_XAlloc() ;
    }
  }

  void copy (const T *p)
  {
    *p_ = *p ;
  }
  
  T *p_ ;
} ;

//
// Hide some of the nastiness above with typedefs...
//
typedef _XAlloc<XClassHint, &XAllocClassHint> CXClassHint ;
typedef _XAlloc<XIconSize, &XAllocIconSize> CXIconSize ;
typedef _XAlloc<XSizeHints, &XAllocSizeHints> CXSizeHints ;
typedef _XAlloc<XWMHints, &XAllocWMHints> CXWMHints ;

#endif

— end —

One thought on “X Windows Programming in C++: Part I”

  1. Pingback: More Boat Blogging

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.