changeset 9:8769ee69bd05

Simple X11App class is done.
author Eris Caffee <discordia@eldalin.com>
date Sun, 22 Apr 2012 01:25:33 -0500
parents c5c33bf5f1fb
children 60f59a6159ed
files include/App.h include/X11App.h include/xlib_App.xbm src/App.cpp src/X11App.cpp src/main.cpp
diffstat 6 files changed, 303 insertions(+), 498 deletions(-) [+]
line diff
     1.1 --- a/include/App.h	Sat Apr 21 03:40:26 2012 -0500
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,94 +0,0 @@
     1.4 -#include <map>
     1.5 -#include <string>
     1.6 -
     1.7 -#include <X11/Xlib.h>
     1.8 -
     1.9 -////////////////////////////////////////////////////////////////////////////////
    1.10 -class App
    1.11 -   {
    1.12 -   public:
    1.13 -
    1.14 -   /////////////////////////////////////
    1.15 -   class BitMap
    1.16 -      {
    1.17 -      public:
    1.18 -      BitMap(const std::string & file);
    1.19 -      ~BitMap();
    1.20 -
    1.21 -      void make_pixmap(Display * dpy, Drawable d);
    1.22 -
    1.23 -      // Yeah, it's all public here.  Keeping it simple.
    1.24 -      std::string name;
    1.25 -      unsigned int width;
    1.26 -      unsigned int height;
    1.27 -      unsigned char * data;
    1.28 -      Pixmap pixmap;
    1.29 -
    1.30 -      private:
    1.31 -      BitMap(const App::BitMap & b);
    1.32 -
    1.33 -      int read_from_file(const std::string & file);
    1.34 -      };
    1.35 -
    1.36 -   /////////////////////////////////////
    1.37 -   // TODO: Need to be able to support child windows.
    1.38 -   // Thus, I need a tree and this class should be a node of the tree.
    1.39 -   // I could use an STL multimap container that maps child nodes onto parent nodes
    1.40 -   // The root node would need to be a bit special.  Perhaps it would map to itself.
    1.41 -   // Use the equal_range() method to get the children of the specified node.
    1.42 -   // I would still need to implement my own tree walking methods: get root node,
    1.43 -   // for each child (get children and recurse).
    1.44 -   //
    1.45 -   // It may be more efficient to implement the tree directly instead of using
    1.46 -   // std::map as an intermediary.
    1.47 -
    1.48 -   class WindowData
    1.49 -      {
    1.50 -      public:
    1.51 -      WindowData(const std::string & n, Window w, App::BitMap * i) :
    1.52 -	 name(n), win(w), icon(i) {};
    1.53 -      ~WindowData()
    1.54 -	 {
    1.55 -	 if (icon) { delete icon; icon = NULL; }
    1.56 -	 }
    1.57 -
    1.58 -
    1.59 -      std::string name;
    1.60 -      Window win;
    1.61 -      App::BitMap * icon;
    1.62 -      };
    1.63 -
    1.64 -   /////////////////////////////////////
    1.65 -
    1.66 -   typedef std::pair<std::string, App::WindowData *> win_pair;
    1.67 -   typedef std::map<std::string, App::WindowData *> WindowMap;
    1.68 -
    1.69 -   App(const std::string & appname);
    1.70 -   ~App();
    1.71 -
    1.72 -   static int x_error_handler(Display * dpy, XErrorEvent *err);
    1.73 -
    1.74 -   void create_window(const std::string& win_name,
    1.75 -		      int x, int y,
    1.76 -		      unsigned int width, unsigned int height,
    1.77 -		      App::BitMap * icon);
    1.78 -
    1.79 -   inline int display_height(void) const
    1.80 -      { return DisplayHeight(dpy, DefaultScreen(dpy)); };
    1.81 -
    1.82 -   inline int display_width(void) const
    1.83 -      { return DisplayWidth(dpy, DefaultScreen(dpy)); };
    1.84 -
    1.85 -   void run(void);
    1.86 -
    1.87 -   private:
    1.88 -   App();
    1.89 -   App(const App & a);
    1.90 -
    1.91 -   Display * dpy;
    1.92 -   WindowMap windows;
    1.93 -   long event_mask;
    1.94 -   Atom wm_delete_window;  // Need this in contructor and run().
    1.95 -
    1.96 -   std::string button_state_string(unsigned int state) const;
    1.97 -   };
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/include/X11App.h	Sun Apr 22 01:25:33 2012 -0500
     2.3 @@ -0,0 +1,43 @@
     2.4 +#ifndef APP_H
     2.5 +#define X11APP_H
     2.6 +
     2.7 +#include <string>
     2.8 +
     2.9 +#include <X11/Xlib.h>
    2.10 +
    2.11 +class X11Window
    2.12 +   {
    2.13 +   public:
    2.14 +   X11Window(Display * dpy,
    2.15 +	     const std::string& win_name,
    2.16 +	     int x, int y,
    2.17 +	     unsigned int width, unsigned int height);
    2.18 +
    2.19 +   std::string name;
    2.20 +   Window win;
    2.21 +   };
    2.22 +
    2.23 +class X11App
    2.24 +   {
    2.25 +   public:
    2.26 +
    2.27 +   X11App(const std::string & appname);
    2.28 +   ~X11App();
    2.29 +
    2.30 +   void run(void);
    2.31 +
    2.32 +   private:
    2.33 +   X11App();
    2.34 +   X11App(const X11App & a);
    2.35 +   X11App operator=(const X11App&);
    2.36 +
    2.37 +   std::string button_state_string(unsigned int state);
    2.38 +
    2.39 +   X11Window * main_win;
    2.40 +   Display * dpy;
    2.41 +   long event_mask;
    2.42 +   Atom wm_delete_window;
    2.43 +
    2.44 +   };
    2.45 +
    2.46 +#endif
     3.1 --- a/include/xlib_App.xbm	Sat Apr 21 03:40:26 2012 -0500
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,46 +0,0 @@
     3.4 -#define xlib_App_width 64
     3.5 -#define xlib_App_height 64
     3.6 -static unsigned char xlib_App_bits[] = {
     3.7 -   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     3.8 -   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     3.9 -   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    3.10 -   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    3.11 -   0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00,
    3.12 -   0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
    3.13 -   0x80, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc0, 0xff, 0x3f, 0x00,
    3.14 -   0x00, 0x00, 0x3c, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x3e, 0x00,
    3.15 -   0xf0, 0xff, 0x7f, 0x00, 0x00, 0x80, 0x1f, 0x00, 0xf0, 0xff, 0x7f, 0x00,
    3.16 -   0x00, 0x80, 0x0f, 0x00, 0xf8, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x07, 0x00,
    3.17 -   0xfc, 0xff, 0xff, 0x01, 0x00, 0xe0, 0x03, 0x00, 0xfc, 0xf8, 0xff, 0x01,
    3.18 -   0x00, 0xf0, 0x01, 0x00, 0x38, 0xf0, 0xff, 0x03, 0x00, 0xf8, 0x01, 0x00,
    3.19 -   0x00, 0xe0, 0xff, 0x03, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07,
    3.20 -   0x00, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x3f, 0x00, 0x00,
    3.21 -   0x00, 0x80, 0xff, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f,
    3.22 -   0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xc0, 0x03, 0x00, 0x00,
    3.23 -   0x00, 0x00, 0xff, 0x3f, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x3f,
    3.24 -   0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0xf8, 0x00, 0x00, 0x00,
    3.25 -   0x00, 0x00, 0xfc, 0xff, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff,
    3.26 -   0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00,
    3.27 -   0x00, 0x00, 0xf0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
    3.28 -   0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x07, 0x00, 0x00, 0x00,
    3.29 -   0x00, 0x00, 0xe0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
    3.30 -   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00,
    3.31 -   0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
    3.32 -   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x01, 0x00, 0x00, 0x00,
    3.33 -   0x00, 0x00, 0xe0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
    3.34 -   0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00,
    3.35 -   0x00, 0x00, 0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
    3.36 -   0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xcf, 0xff, 0x7f, 0x00, 0x00, 0x00,
    3.37 -   0x00, 0xe0, 0x87, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf0, 0x03, 0xff,
    3.38 -   0xff, 0x07, 0xe0, 0x00, 0x00, 0xfc, 0x00, 0xfe, 0xff, 0x1f, 0xf0, 0x00,
    3.39 -   0x00, 0xfe, 0x00, 0xfc, 0xff, 0xff, 0x7c, 0x00, 0x00, 0x3f, 0x00, 0xf8,
    3.40 -   0xff, 0xff, 0x7f, 0x00, 0x80, 0x1f, 0x00, 0xf8, 0xff, 0xff, 0x3f, 0x00,
    3.41 -   0xc0, 0x0f, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0x00, 0xe0, 0x03, 0x00, 0xe0,
    3.42 -   0xff, 0xff, 0x0f, 0x00, 0xf0, 0x01, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00,
    3.43 -   0xf0, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x03, 0x00, 0x40, 0x00, 0x00, 0xc0,
    3.44 -   0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00,
    3.45 -   0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    3.46 -   0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    3.47 -   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    3.48 -   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    3.49 -   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
     4.1 --- a/src/App.cpp	Sat Apr 21 03:40:26 2012 -0500
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,356 +0,0 @@
     4.4 -#include "App.h"
     4.5 -
     4.6 -#include <cstdlib>
     4.7 -#include <iostream>
     4.8 -#include <typeinfo>
     4.9 -#include <X11/Xutil.h>
    4.10 -
    4.11 -
    4.12 -////////////////////////////////////////////////////////////////////////////////
    4.13 -App::App(const std::string & appname)
    4.14 -   {
    4.15 -   XSetErrorHandler(&App::x_error_handler);
    4.16 -
    4.17 -   if ((dpy = XOpenDisplay(NULL)) == NULL) 
    4.18 -      {
    4.19 -      std::cerr << "Unable to connect to display " << XDisplayName(NULL) << std::endl;
    4.20 -      exit(1);
    4.21 -      }
    4.22 -   std::cout << "Display name     : " << XDisplayName(NULL) << std::endl
    4.23 -	     << "Number of screens: " << ScreenCount(dpy) << std::endl
    4.24 -	     << "Default screen   : " << DefaultScreen(dpy) << std::endl
    4.25 -	     << "Protocol Version : " << ProtocolVersion(dpy) << std::endl
    4.26 -	     << "Protocol Revision: " << ProtocolRevision(dpy) << std::endl
    4.27 -	     << "Server Vendor    : " << ServerVendor(dpy) << std::endl
    4.28 -	     << "Vendor Release   : " << VendorRelease(dpy) << std::endl
    4.29 -	     << std::endl
    4.30 -	     << "Display width    : " << this->display_width() << std::endl
    4.31 -	     << "Display height   : " << this->display_height() << std::endl
    4.32 -	 ;
    4.33 -
    4.34 -   App::BitMap * icon = new App::BitMap("xlib_App.xbm");
    4.35 -
    4.36 -   // Create the main window
    4.37 -   create_window("main", 
    4.38 -		 0, 0 , 
    4.39 -		 this->display_width()/2, this->display_height()/2, 
    4.40 -		 icon);
    4.41 -
    4.42 -   // Get a reference to our WindowData structure.  We need the Window handle from it for a few things.
    4.43 -   App::WindowData * wd = windows["main"];
    4.44 -
    4.45 -
    4.46 -
    4.47 -
    4.48 -   // We need to set the window manager hints, size hints, window name, and icon name
    4.49 -
    4.50 -   // Even though we are not passing any actual size_hints, the Xlib programming manual says to pass the flags below anyway.
    4.51 -   XSizeHints *size_hints;
    4.52 -   if (!(size_hints = XAllocSizeHints())) 
    4.53 -      {
    4.54 -      std::cerr << "XAllocSizeHints: memory allocation failure" << std::endl;
    4.55 -      exit(1);
    4.56 -      }
    4.57 -   size_hints->flags = PPosition | PSize;
    4.58 -
    4.59 -   // Get X Properties for the window and icon names.
    4.60 -   XTextProperty windowName, iconName;
    4.61 -   const char * ptr = appname.c_str();
    4.62 -   if (XStringListToTextProperty(const_cast<char **>(&ptr), 1, &windowName) == 0) 
    4.63 -      {
    4.64 -      std::cerr << "XStringListToTextProperty: structure allocation for windowName failed." << std::endl;;
    4.65 -      exit(1);
    4.66 -   }
    4.67 -   ptr = icon->name.c_str();
    4.68 -   if (XStringListToTextProperty(const_cast<char **>(&ptr), 1, &iconName) == 0) 
    4.69 -      {
    4.70 -      std::cerr << "XStringListToTextProperty: structure allocation for iconName failed." << std::endl;;
    4.71 -      exit(1);
    4.72 -   }
    4.73 -
    4.74 -   XWMHints *wm_hints;
    4.75 -   if (!(wm_hints = XAllocWMHints()))
    4.76 -      {
    4.77 -      std::cerr << "XAllocWMHints: memory allocation failure" << std::endl;
    4.78 -      exit(0);
    4.79 -      }
    4.80 -   wm_hints->initial_state = NormalState;
    4.81 -   wm_hints->input = True;
    4.82 -   wm_hints->icon_pixmap = icon->pixmap;
    4.83 -   wm_hints->flags = StateHint | IconPixmapHint | InputHint;
    4.84 -
    4.85 -   XSetWMProperties(dpy, wd->win, &windowName, &iconName,
    4.86 -    		    NULL, 0, size_hints, wm_hints,
    4.87 -		    NULL);
    4.88 -
    4.89 -
    4.90 -
    4.91 -   // Select the event types we want to receive.
    4.92 -   //Other interesting events include KeyReleaseMask and ButtonReleaseMask
    4.93 -   event_mask = 
    4.94 -	 ExposureMask | StructureNotifyMask |
    4.95 -	 KeyPressMask | KeyReleaseMask | 
    4.96 -	 FocusChangeMask |
    4.97 -	 PointerMotionMask |
    4.98 -	 EnterWindowMask | LeaveWindowMask |
    4.99 -	 ButtonPressMask | ButtonReleaseMask ;
   4.100 -   XSelectInput(dpy, wd->win, event_mask);
   4.101 -
   4.102 -
   4.103 -
   4.104 -   // Make sure we get delete events from the window manager.
   4.105 -   // "wm_delete_window" is the Atom which corresponds to the delete
   4.106 -   //  window message sent by the window manager. 
   4.107 -
   4.108 -   wm_delete_window = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
   4.109 -   XSetWMProtocols(dpy, wd->win, &wm_delete_window, 1);
   4.110 -
   4.111 -
   4.112 -   // This give BadMatch and I don't know why.
   4.113 -   // XSetWindowAttributes setwinattr;
   4.114 -   // setwinattr.background_pixmap = bg_pixmap->pixmap;
   4.115 -   // XChangeWindowAttributes(dpy, wd->win, CWBackPixmap, &setwinattr);
   4.116 -
   4.117 -   // Also BadMatch
   4.118 -   // XSetWindowBackgroundPixmap(dpy, wd->win, icon->pixmap);
   4.119 -
   4.120 -
   4.121 -   //   XSetWindowBackgroundPixmap(dpy, wd->win, None);
   4.122 -
   4.123 -
   4.124 -   // Map the window.  Remember: this does not display the window immediately.
   4.125 -   // The request is queued until events are read, or we call XFlush or XSync.
   4.126 -   XMapWindow(dpy, wd->win);
   4.127 -   }
   4.128 -
   4.129 -////////////////////////////////////////////////////////////////////////////////
   4.130 -App::~App()
   4.131 -   {
   4.132 -   // Ugh.  I really wish I could figure out why I can't make a map of string 
   4.133 -   // to WindowData instead of having ton use WindowData *
   4.134 -   // I'd like to eliminate this next loop.
   4.135 -   for( WindowMap::iterator i = windows.begin(); i != windows.end(); ++i)
   4.136 -      {
   4.137 -      App::WindowData * wp = (*i).second;
   4.138 -      windows.erase(i);
   4.139 -      delete wp;
   4.140 -      }
   4.141 -
   4.142 -   if (dpy)
   4.143 -      {
   4.144 -      XCloseDisplay(dpy);
   4.145 -      }
   4.146 -   }
   4.147 -
   4.148 -////////////////////////////////////////////////////////////////////////////////
   4.149 -int App::x_error_handler(Display * dpy, XErrorEvent *err)
   4.150 -   {
   4.151 -   char err_msg[1024];
   4.152 -   err_msg[0] = 0;
   4.153 -   XGetErrorText(dpy, err->error_code, err_msg, 1024);
   4.154 -   std::cerr << "X11 Error"<< std::endl
   4.155 -	     << "    display     : " << DisplayString(dpy) << std::endl
   4.156 -	     << "    serial      : " << err->serial << std::endl
   4.157 -	     << "    error_code  : " << (int) err->error_code << std::endl
   4.158 -	     << "    request_code: " << (int) err->request_code << std::endl
   4.159 -	     << "    minor_code  : " << (int) err->minor_code << std::endl
   4.160 -	     << err_msg << std::endl;
   4.161 -   return 0;
   4.162 -   }
   4.163 -
   4.164 -////////////////////////////////////////////////////////////////////////////////
   4.165 -void App::create_window(const std::string & win_name,
   4.166 -			int x, int y,
   4.167 -			unsigned int width, unsigned int height,
   4.168 -			App::BitMap * icon)
   4.169 -   {
   4.170 -   Window win;
   4.171 -   int border_width = 4;           /* Border four pixels wide */
   4.172 -
   4.173 -   int screen_num = DefaultScreen(dpy);
   4.174 -
   4.175 -   /* Create opaque window */
   4.176 -   win = XCreateSimpleWindow(dpy, 
   4.177 -			     RootWindow(dpy, screen_num),
   4.178 -			     x, y, 
   4.179 -			     width, height, 
   4.180 -			     border_width, 
   4.181 -			     None, None);
   4.182 -   //			     BlackPixel(dpy, screen_num),
   4.183 -   //			     WhitePixel(dpy, screen_num));
   4.184 -
   4.185 -   icon->make_pixmap(dpy, win);
   4.186 -
   4.187 -   // Add it to the window list
   4.188 -   App::WindowData * win_data = new App::WindowData(win_name, win, icon);
   4.189 -   windows.insert(win_pair(win_name, win_data));
   4.190 -   }
   4.191 -
   4.192 -////////////////////////////////////////////////////////////////////////////////
   4.193 -void App::run(void)
   4.194 -   {
   4.195 -   XEvent e;
   4.196 -   KeySym k;
   4.197 -   char key_buffer[8];
   4.198 -   key_buffer[7] = 0;
   4.199 -   XComposeStatus compose_status;
   4.200 -
   4.201 -   int done = 0;
   4.202 -
   4.203 -   while (!done)
   4.204 -      {
   4.205 -      while (XCheckIfEvent(dpy, &e, 
   4.206 -      			   // *sniff*  My very first lambda function in C++
   4.207 -      			   [&](Display * d, XEvent * e, XPointer a)->Bool { return True; }, 
   4.208 -      			   NULL))
   4.209 -	 {
   4.210 -	 switch (e.type)
   4.211 -	    {
   4.212 -
   4.213 -	    ////////////////////////
   4.214 -	    // General window events
   4.215 -	    case Expose:
   4.216 -	       // We'll only redraw the entire window at a time, so unless this is 
   4.217 -	       // the last contiguous expose, don't draw the window.
   4.218 -	       if (e.xexpose.count != 0)
   4.219 -		  break;
   4.220 -	       // Draw the window contents here
   4.221 -	       break;
   4.222 -	    case ClientMessage:
   4.223 -	       if ((Atom)e.xclient.data.l[0] == wm_delete_window)
   4.224 -		  done = 1;
   4.225 -	       break;
   4.226 -
   4.227 -	    ///////////////////////
   4.228 -	    // Mouse events
   4.229 -	    case MotionNotify:
   4.230 -	       std::cout << "Mouse at (" << e.xmotion.x << "," << e.xmotion.y << ")" << std::endl;
   4.231 -	       break;
   4.232 -	    case ButtonPress:
   4.233 -	       std::cout << "You pressed button " << e.xbutton.button << 
   4.234 -		     " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << 
   4.235 -		     " state " << button_state_string(e.xbutton.state ) << std::endl;
   4.236 -	       break;
   4.237 -	    case ButtonRelease:
   4.238 -	       std::cout << "You released button " << e.xbutton.button <<
   4.239 -		     " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << 
   4.240 -		     " state " << button_state_string(e.xbutton.state ) << std::endl;
   4.241 -	       break;
   4.242 -	    case EnterNotify:
   4.243 -	       std::cout << "Mouse has entered the window" <<
   4.244 -		     " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << 
   4.245 -		     " state " << button_state_string(e.xbutton.state ) << std::endl;
   4.246 -	       break;
   4.247 -	    case LeaveNotify:
   4.248 -	       std::cout << "Mouse has left the window" << 
   4.249 -		     " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << 
   4.250 -		     " state " << button_state_string(e.xbutton.state ) << std::endl;
   4.251 -	       break;
   4.252 -
   4.253 -	    //////////////////
   4.254 -	    // Keyboard Events
   4.255 -	    case FocusIn:
   4.256 -	       // Interesting note: When we regain focus due to a mouse click in the window, 
   4.257 -	       // we first get a LeaveNotify, then the FocusIn, then an EnterNotify, and then
   4.258 -	       // the ButtonPress and ButtonRelease.  So in a real app we might want to have
   4.259 -	       // the FocusIn handler read ahead and handle (discard) the next ButtonPress,
   4.260 -	       // and ButtonRelease so that the click does not have a real effect on the application.
   4.261 -	       std::cout << "Got keyboard focus" << std::endl;
   4.262 -	       break;
   4.263 -	    case FocusOut:
   4.264 -	       std::cout << "Lost keyboard focus" << std::endl;
   4.265 -	       break;
   4.266 -	    case KeyPress:
   4.267 -	       // Doing the lookup like this, using XLookupString, means I get the modified
   4.268 -	       // character back.  Thus type shift+a gives me XK_A instead of XK_a
   4.269 -	       // If I used XKeySym I'd instead get a sequence such as this:
   4.270 -	       // XK_Shift_L followed by XK_a
   4.271 -	       //
   4.272 -	       // In the end, that might be a more useful way to go, but for now I'll keep
   4.273 -	       // things simple.
   4.274 -	       XLookupString(&(e.xkey), key_buffer, 7, &k, &compose_status);
   4.275 -	       switch (k)
   4.276 -		  {
   4.277 -		  case XK_Escape:
   4.278 -		  case XK_q:
   4.279 -		     std::cout << "Goodbye!" << std::endl;
   4.280 -		     done = 1;
   4.281 -		     break;
   4.282 -		  default:
   4.283 -		     std::cout << "You typed " << key_buffer << std::endl;
   4.284 -		     break;
   4.285 -		  }
   4.286 -	    case MappingNotify:
   4.287 -	       // While it is uncommon for the user to change the keyboard mapping while
   4.288 -	       // a program is running, handling this case is so trivial that there is 
   4.289 -	       // simply no excuse to leave it out.
   4.290 -	       XRefreshKeyboardMapping((XMappingEvent *)&e);
   4.291 -	       break;
   4.292 -
   4.293 -	    default:
   4.294 -	       break;
   4.295 -	    }
   4.296 -	 }
   4.297 -
   4.298 -      // Do idle time things here
   4.299 -
   4.300 -      }
   4.301 -   }
   4.302 -
   4.303 -////////////////////////////////////////////////////////////////////////////////
   4.304 -std::string App::button_state_string(unsigned int state) const
   4.305 -   {
   4.306 -   std::string str = "";
   4.307 -   if (state & Button1Mask) { str.append("Button1 "); }
   4.308 -   if (state & Button2Mask) { str.append("Button2 "); }
   4.309 -   if (state & Button3Mask) { str.append("Button3 "); }
   4.310 -   if (state & Button4Mask) { str.append("Button4 "); }
   4.311 -   if (state & Button5Mask) { str.append("Button5 "); }
   4.312 -   if (state & ShiftMask)   { str.append("Shift "); }
   4.313 -   if (state & LockMask)    { str.append("Lock "); }
   4.314 -   if (state & ControlMask) { str.append("Control "); }
   4.315 -   if (state & Mod1Mask)    { str.append("Mod1 "); }
   4.316 -   if (state & Mod2Mask)    { str.append("Mod2 "); }
   4.317 -   if (state & Mod3Mask)    { str.append("Mod3 "); }
   4.318 -   if (state & Mod4Mask)    { str.append("Mod4 "); }
   4.319 -   if (state & Mod5Mask)    { str.append("Mod5 "); }
   4.320 -   return str;
   4.321 -   }
   4.322 -
   4.323 -////////////////////////////////////////////////////////////////////////////////
   4.324 -// App::BitMap
   4.325 -////////////////////////////////////////////////////////////////////////////////
   4.326 -App::BitMap::BitMap(const std::string & file)
   4.327 -   {
   4.328 -   read_from_file(file);
   4.329 -   }
   4.330 -
   4.331 -////////////////////////////////////////////////////////////////////////////////
   4.332 -App::BitMap::~BitMap() 
   4.333 -   {
   4.334 -   if (data) { XFree(data); data = NULL; }
   4.335 -   }
   4.336 -
   4.337 -////////////////////////////////////////////////////////////////////////////////
   4.338 -void App::BitMap::make_pixmap(Display * dpy, Drawable d)
   4.339 -   {
   4.340 -   pixmap = XCreateBitmapFromData(dpy, d, (char *) data, width, height);
   4.341 -   }
   4.342 -
   4.343 -////////////////////////////////////////////////////////////////////////////////
   4.344 -int App::BitMap::read_from_file(const std::string & file)
   4.345 -   {
   4.346 -   if (BitmapSuccess != XReadBitmapFileData(file.c_str(), &width, &height, &data, NULL, NULL))
   4.347 -      {
   4.348 -      return 0;
   4.349 -      }
   4.350 -
   4.351 -   name = file;
   4.352 -   size_t p = name.rfind("/");
   4.353 -   if (p != std::string::npos)
   4.354 -      {
   4.355 -      name.replace(0, p+1, "");
   4.356 -      }
   4.357 -   return 1;
   4.358 -   }
   4.359 -
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/X11App.cpp	Sun Apr 22 01:25:33 2012 -0500
     5.3 @@ -0,0 +1,258 @@
     5.4 +#include "X11App.h"
     5.5 +
     5.6 +#include <cstdlib>
     5.7 +#include <iostream>
     5.8 +#include <typeinfo>
     5.9 +#include <X11/Xutil.h>
    5.10 +
    5.11 +////////////////////////////////////////////////////////////////////////////////
    5.12 +// X11Window
    5.13 +////////////////////////////////////////////////////////////////////////////////
    5.14 +X11Window::X11Window(Display * dpy,
    5.15 +		     const std::string & win_name,
    5.16 +		     int x, int y,
    5.17 +		     unsigned int width, unsigned int height) :
    5.18 +   name (win_name),
    5.19 +   win (0)
    5.20 +   {
    5.21 +   int screen_num = DefaultScreen(dpy);
    5.22 +
    5.23 +   win = XCreateSimpleWindow(dpy, 
    5.24 +			     RootWindow(dpy, screen_num),
    5.25 +			     x, y, 
    5.26 +			     width, height, 
    5.27 +			     1, 
    5.28 +			     None, None);
    5.29 +
    5.30 +   }
    5.31 +
    5.32 +////////////////////////////////////////////////////////////////////////////////
    5.33 +// X11App
    5.34 +////////////////////////////////////////////////////////////////////////////////
    5.35 +X11App::X11App(const std::string & appname) :
    5.36 +   main_win (NULL), dpy (NULL), event_mask (0), wm_delete_window (0)
    5.37 +   {
    5.38 +
    5.39 +   if ((dpy = XOpenDisplay(NULL)) == NULL) 
    5.40 +      {
    5.41 +      std::cerr << "Unable to connect to display " << XDisplayName(NULL) << std::endl;
    5.42 +      exit(1);
    5.43 +      }
    5.44 +   std::cout << "Display name     : " << XDisplayName(NULL) << std::endl
    5.45 +	     << "Number of screens: " << ScreenCount(dpy) << std::endl
    5.46 +	     << "Default screen   : " << DefaultScreen(dpy) << std::endl
    5.47 +	     << "Protocol Version : " << ProtocolVersion(dpy) << std::endl
    5.48 +	     << "Protocol Revision: " << ProtocolRevision(dpy) << std::endl
    5.49 +	     << "Server Vendor    : " << ServerVendor(dpy) << std::endl
    5.50 +	     << "Vendor Release   : " << VendorRelease(dpy) << std::endl
    5.51 +	     << std::endl
    5.52 +	     << "Display width    : " << DisplayWidth(dpy, DefaultScreen(dpy)) << std::endl
    5.53 +	     << "Display height   : " << DisplayHeight(dpy, DefaultScreen(dpy)) << std::endl
    5.54 +	 ;
    5.55 +
    5.56 +   // Create the main window
    5.57 +   main_win = new X11Window(dpy, "main", 0, 0, 
    5.58 +			    DisplayWidth(dpy, DefaultScreen(dpy)) / 2,
    5.59 +			    DisplayHeight(dpy, DefaultScreen(dpy)) / 2);
    5.60 +
    5.61 +
    5.62 +   // We need to set the window manager hints, size hints, and window name.
    5.63 +
    5.64 +   // Even though we are not passing any actual size_hints, the Xlib programming manual says to pass the flags below anyway.
    5.65 +   XSizeHints *size_hints;
    5.66 +   if (!(size_hints = XAllocSizeHints())) 
    5.67 +      {
    5.68 +      std::cerr << "XAllocSizeHints: memory allocation failure" << std::endl;
    5.69 +      exit(1);
    5.70 +      }
    5.71 +   size_hints->flags = PPosition | PSize;
    5.72 +
    5.73 +
    5.74 +   // Get X Properties for the window name.
    5.75 +   XTextProperty windowName;
    5.76 +   const char * ptr = appname.c_str();
    5.77 +   if (XStringListToTextProperty(const_cast<char **>(&ptr), 1, &windowName) == 0) 
    5.78 +      {
    5.79 +      std::cerr << "XStringListToTextProperty: structure allocation for windowName failed." << std::endl;;
    5.80 +      exit(1);
    5.81 +      }
    5.82 +
    5.83 +   XWMHints *wm_hints;
    5.84 +   if (!(wm_hints = XAllocWMHints()))
    5.85 +      {
    5.86 +      std::cerr << "XAllocWMHints: memory allocation failure" << std::endl;
    5.87 +      exit(0);
    5.88 +      }
    5.89 +   wm_hints->initial_state = NormalState;
    5.90 +   wm_hints->input = True;
    5.91 +   wm_hints->flags = StateHint | InputHint;
    5.92 +
    5.93 +   XSetWMProperties(dpy, main_win->win, &windowName, NULL, 
    5.94 +    		    NULL, 0, size_hints, wm_hints,
    5.95 +		    NULL);
    5.96 +
    5.97 +
    5.98 +   // Select the event types we want to receive.
    5.99 +   event_mask = 
   5.100 +	 ExposureMask | StructureNotifyMask |
   5.101 +	 KeyPressMask | KeyReleaseMask | 
   5.102 +	 FocusChangeMask |
   5.103 +	 PointerMotionMask |
   5.104 +	 EnterWindowMask | LeaveWindowMask |
   5.105 +	 ButtonPressMask | ButtonReleaseMask ;
   5.106 +   XSelectInput(dpy, main_win->win, event_mask);
   5.107 +
   5.108 +
   5.109 +   // Make sure we get delete events from the window manager.
   5.110 +   // "wm_delete_window" is the Atom which corresponds to the delete
   5.111 +   //  window message sent by the window manager. 
   5.112 +
   5.113 +   wm_delete_window = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
   5.114 +   XSetWMProtocols(dpy, main_win->win, &wm_delete_window, 1);
   5.115 +
   5.116 +
   5.117 +   // Map the window.  Remember: this does not display the window immediately.
   5.118 +   // The request is queued until events are read, or we call XFlush or XSync.
   5.119 +   XMapWindow(dpy, main_win->win);
   5.120 +   }
   5.121 +
   5.122 +////////////////////////////////////////////////////////////////////////////////
   5.123 +X11App::~X11App()
   5.124 +   {
   5.125 +   if (main_win) { delete main_win; }
   5.126 +   if (dpy) { XCloseDisplay(dpy); }
   5.127 +   }
   5.128 +
   5.129 +////////////////////////////////////////////////////////////////////////////////
   5.130 +void X11App::run(void)
   5.131 +   {
   5.132 +   XEvent e;
   5.133 +   KeySym k;
   5.134 +   char key_buffer[8];
   5.135 +   key_buffer[7] = 0;
   5.136 +   XComposeStatus compose_status;
   5.137 +
   5.138 +   int done = 0;
   5.139 +
   5.140 +   while (!done)
   5.141 +      {
   5.142 +      while (XCheckIfEvent(dpy, &e, 
   5.143 +      			   // *sniff*  My very first lambda function in C++
   5.144 +      			   [&](Display * d, XEvent * e, XPointer a)->Bool { return True; }, 
   5.145 +      			   NULL))
   5.146 +	 {
   5.147 +	 switch (e.type)
   5.148 +	    {
   5.149 +
   5.150 +	    ////////////////////////
   5.151 +	    // General window events
   5.152 +	    case Expose:
   5.153 +	       // We'll only redraw the entire window at a time, so unless this is 
   5.154 +	       // the last contiguous expose, don't draw the window.
   5.155 +	       if (e.xexpose.count != 0)
   5.156 +		  break;
   5.157 +	       // Draw the window contents here
   5.158 +	       break;
   5.159 +	    case ClientMessage:
   5.160 +	       if ((Atom)e.xclient.data.l[0] == wm_delete_window)
   5.161 +		  done = 1;
   5.162 +	       break;
   5.163 +
   5.164 +	       ///////////////////////
   5.165 +	       // Mouse events
   5.166 +	    case MotionNotify:
   5.167 +	       std::cout << "Mouse at (" << e.xmotion.x << "," << e.xmotion.y << ")" << std::endl;
   5.168 +	       break;
   5.169 +	    case ButtonPress:
   5.170 +	       std::cout << "You pressed button " << e.xbutton.button << 
   5.171 +		     " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << 
   5.172 +		     " state " << button_state_string(e.xbutton.state ) << std::endl;
   5.173 +	       break;
   5.174 +	    case ButtonRelease:
   5.175 +	       std::cout << "You released button " << e.xbutton.button <<
   5.176 +		     " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << 
   5.177 +		     " state " << button_state_string(e.xbutton.state ) << std::endl;
   5.178 +	       break;
   5.179 +	    case EnterNotify:
   5.180 +	       std::cout << "Mouse has entered the window" <<
   5.181 +		     " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << 
   5.182 +		     " state " << button_state_string(e.xbutton.state ) << std::endl;
   5.183 +	       break;
   5.184 +	    case LeaveNotify:
   5.185 +	       std::cout << "Mouse has left the window" << 
   5.186 +		     " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << 
   5.187 +		     " state " << button_state_string(e.xbutton.state ) << std::endl;
   5.188 +	       break;
   5.189 +
   5.190 +	       //////////////////
   5.191 +	       // Keyboard Events
   5.192 +	    case FocusIn:
   5.193 +	       // Interesting note: When we regain focus due to a mouse click in the window, 
   5.194 +	       // we first get a LeaveNotify, then the FocusIn, then an EnterNotify, and then
   5.195 +	       // the ButtonPress and ButtonRelease.  So in a real app we might want to have
   5.196 +	       // the FocusIn handler read ahead and handle (discard) the next ButtonPress,
   5.197 +	       // and ButtonRelease so that the click does not have a real effect on the application.
   5.198 +	       std::cout << "Got keyboard focus" << std::endl;
   5.199 +	       break;
   5.200 +	    case FocusOut:
   5.201 +	       std::cout << "Lost keyboard focus" << std::endl;
   5.202 +	       break;
   5.203 +	    case KeyPress:
   5.204 +	       // Doing the lookup like this, using XLookupString, means I get the modified
   5.205 +	       // character back.  Thus type shift+a gives me XK_A instead of XK_a
   5.206 +	       // If I used XKeySym I'd instead get a sequence such as this:
   5.207 +	       // XK_Shift_L followed by XK_a
   5.208 +	       //
   5.209 +	       // In the end, that might be a more useful way to go, but for now I'll keep
   5.210 +	       // things simple.
   5.211 +	       XLookupString(&(e.xkey), key_buffer, 7, &k, &compose_status);
   5.212 +	       switch (k)
   5.213 +		  {
   5.214 +		  case XK_Escape:
   5.215 +		  case XK_q:
   5.216 +		     std::cout << "Goodbye!" << std::endl;
   5.217 +		     done = 1;
   5.218 +		     break;
   5.219 +		  default:
   5.220 +		     std::cout << "You typed " << key_buffer << std::endl;
   5.221 +		     break;
   5.222 +		  }
   5.223 +	    case MappingNotify:
   5.224 +	       // While it is uncommon for the user to change the keyboard mapping while
   5.225 +	       // a program is running, handling this case is so trivial that there is 
   5.226 +	       // simply no excuse to leave it out.
   5.227 +	       XRefreshKeyboardMapping((XMappingEvent *)&e);
   5.228 +	       break;
   5.229 +
   5.230 +	    default:
   5.231 +	       break;
   5.232 +	    }
   5.233 +	 }
   5.234 +
   5.235 +      // Do idle time things here
   5.236 +
   5.237 +      }
   5.238 +   }
   5.239 +
   5.240 +////////////////////////////////////////////////////////////////////////////////
   5.241 +std::string X11App::button_state_string(unsigned int state)
   5.242 +   {
   5.243 +   std::string str = "";
   5.244 +   if (state & Button1Mask) { str.append("Button1 "); }
   5.245 +   if (state & Button2Mask) { str.append("Button2 "); }
   5.246 +   if (state & Button3Mask) { str.append("Button3 "); }
   5.247 +   if (state & Button4Mask) { str.append("Button4 "); }
   5.248 +   if (state & Button5Mask) { str.append("Button5 "); }
   5.249 +   if (state & ShiftMask)   { str.append("Shift "); }
   5.250 +   if (state & LockMask)    { str.append("Lock "); }
   5.251 +   if (state & ControlMask) { str.append("Control "); }
   5.252 +   if (state & Mod1Mask)    { str.append("Mod1 "); }
   5.253 +   if (state & Mod2Mask)    { str.append("Mod2 "); }
   5.254 +   if (state & Mod3Mask)    { str.append("Mod3 "); }
   5.255 +   if (state & Mod4Mask)    { str.append("Mod4 "); }
   5.256 +   if (state & Mod5Mask)    { str.append("Mod5 "); }
   5.257 +   size_t i = str.rfind(' '); 
   5.258 +   if (i != str.npos) { str.erase(i, 1); }
   5.259 +   return str;
   5.260 +   }
   5.261 +
     6.1 --- a/src/main.cpp	Sat Apr 21 03:40:26 2012 -0500
     6.2 +++ b/src/main.cpp	Sun Apr 22 01:25:33 2012 -0500
     6.3 @@ -2,11 +2,11 @@
     6.4  
     6.5  #include <unistd.h>
     6.6  
     6.7 -#include "App.h"
     6.8 +#include "X11App.h"
     6.9  
    6.10  int main(void)
    6.11     {
    6.12 -   App * app = new App("xlib_App");
    6.13 +   X11App * app = new X11App("xlib_App");
    6.14     app->run();
    6.15     exit(0);
    6.16     }