X Windows Programming in C++: Part II

Continuing with our task of creating a C++ version of basicwin.c, we next look at XOpenDisplay / XCloseDisplay. Here’s some code snippets from basicwin.c showing the use of these functions:


/* basicwin.c */

#include <X11/Xlib.h>

/*
 .
 .
 .
 */

Display *display;
int screen_num;

/*
 .
 .
 .
 */

void main(argc, argv)
int argc;
char **argv;
{
/*
 .
 .
 .
 */
  char *display_name = NULL;

/* connect to X server */
  if ( (display=XOpenDisplay(display_name)) == NULL )
  {
    (void) fprintf( stderr, "%s: cannot connect to X server %s\n", 
                    progname, XDisplayName(display_name));
    exit( -1 );
  }

  /* get screen size from display structure macro */
  screen_num = DefaultScreen(display);
  display_width = DisplayWidth(display, screen_num);
  display_height = DisplayHeight(display, screen_num);
/*
 .
 .
 .
 */
    XCloseDisplay(display);
    exit(1);
/*
 .
 .
 .
 */
}

C++ allows us to do something like this:


/* basicwin.cpp */
 
#include "xdisplay.h"

/*
 .
 .
 .
 */

int main(int argc, char **argv)
{
/*
 .
 .
 .
 */

  try
  {
    CXDisplayPtr display(CXDisplay::OpenDisplay()) ;

    /*
     * get screen size -- one could pass the screen num if
     * a screen other then the default screen is used
     */
    display_width = display->GetDisplayWidth();
    display_height = display->GetDisplayHeight();
/*
 .
 .
 .
 */
    /* Get available icon sizes from Window manager */
    // Dereferencing a CXDisplayPtr returns a Display *
    if (!XGetIconSizes(*display, display->GetRootWindow(), 
                       &size_list, &count))

  }
  catch(bad_CXDisplay& e)
  {
    cerr << e.what() << endl ;
  }

  /*
   * XCloseDisplay gets called automatically 
   */
  return -1 ;
}

CXDisplayPtr is defined in xdisplay.h. Connecting to an X server is handled by the constructor for the class CXDisplay. Disconnecting from an X server is handled by CXDisplay’s destructor. CXDisplayPtr wraps CXDisplay in a boost::shared_ptr. The static member function, CXDisplay::OpenDisplay connects to an X server (by calling CXDisplay’s constructor) and returns a CXDisplayPtr which can be used as a pointer to a Display by dereferencing it. CXDisplay’s destructor is called when the CXDisplayPtr goes out of scope and all references to it are released.

— start —


/*******************************************************************
 *
 * xdisplay.h -- Wrap Display with a boost::shared_ptr
 *
 *  Copyright (C) 2006 by James A. Chappell (rlrrlrll@gmail.com)
 *
 *  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 __xdisplay_h__
#define __xdisplay_h__

#include <X11/Xlib.h>

#include <exception>

#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>

#define USE_DEFAULT_SCREEN -1

class bad_CXDisplay : public std::exception
{
public:
  virtual const char* what() const throw()
  {
    return "bad_CXDisplay" ; // for now
  }
} ;

class CXDisplay ;

typedef boost::shared_ptr<CXDisplay> CXDisplayPtr ;

class CXDisplay : private boost::noncopyable
{
public:
  static CXDisplayPtr OpenDisplay(const char *display_name = NULL) ;

  ~CXDisplay() ;

  Display* operator->() { return display_ ; }
  operator Display* const () { return display_ ; }

  int GetScreenCount() const { return ScreenCount(display_) ; }
  int GetDefaultScreen() const { return DefaultScreen(display_) ; }
  Window GetRootWindow(int screen_num = USE_DEFAULT_SCREEN) const ;
  int GetDisplayWidth(int screen_num = USE_DEFAULT_SCREEN) const ;
  int GetDisplayHeight(int screen_num = USE_DEFAULT_SCREEN) const ;
  int GetDefaultDepth(int screen_num = USE_DEFAULT_SCREEN) const ;
  unsigned long GetBlackPixel(int screen_num = USE_DEFAULT_SCREEN) const ;
  unsigned long GetWhitePixel(int screen_num = USE_DEFAULT_SCREEN) const ;

private:
  Display *display_ ;
  //
  // Only call via static member function OpenDisplay
  //
  CXDisplay(const char *display_name) ;
 
  //
  // see if s indicates using the default screen, otherwise
  // return s
  int screen(int s) const
  {
    return (s == USE_DEFAULT_SCREEN) ? GetDefaultScreen() : s ;
  }

  // no default constructor
  CXDisplay() {}
} ;


inline CXDisplayPtr CXDisplay::OpenDisplay(const char *display_name)
{
  return CXDisplayPtr(new CXDisplay(display_name)) ;
}


inline CXDisplay::CXDisplay(const char *display_name)
{
  display_ = XOpenDisplay(display_name) ;
  if (!display_)
  {
    throw bad_CXDisplay() ;
  }
}


inline CXDisplay::~CXDisplay()
{
  XCloseDisplay(display_);
}


inline Window CXDisplay::GetRootWindow(int screen_num) const
{
  return RootWindow(display_, screen(screen_num)) ;
}


inline int CXDisplay::GetDisplayWidth(int screen_num) const
{
  return DisplayWidth(display_, screen(screen_num)) ;
}


inline int CXDisplay::GetDisplayHeight(int screen_num) const
{
  return DisplayHeight(display_, screen(screen_num)) ;
}


inline int CXDisplay::GetDefaultDepth(int screen_num) const 
{
  return DefaultDepth(display_, screen(screen_num)) ;
}


inline unsigned long CXDisplay::GetBlackPixel(int screen_num) const
{
  return BlackPixel(display_, screen(screen_num)) ;
}


inline unsigned long CXDisplay::GetWhitePixel(int screen_num) const
{
  return WhitePixel(display_, screen(screen_num)) ;
}

#endif

— end —

Leave a Reply

Your email address will not be published. Required fields are marked *

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

All trademarks and copyrights on this page are owned by their respective owners. Quotes from linked articles are probably the property of the publications linked or the property of the person(s) quoted. The rest © 2001- 2025 by James A. Chappell