+
+///////////////////////////////////////////////////////////////////////////
+// This program is free software: you can redistribute it and/or modify  //
+// it under the terms of the version 3 of the GNU General Public License //
+// as published by the Free Software Foundation.                         //
+//                                                                       //
+// This program is distributed in the hope that it will be useful, but   //
+// WITHOUT ANY WARRANTY; without even the implied warranty of            //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      //
+// General Public License for more details.                              //
+//                                                                       //
+// You should have received a copy of the GNU General Public License     //
+// along with this program. If not, see <http://www.gnu.org/licenses/>.  //
+//                                                                       //
+// Written by and Copyright (C) Francois Fleuret                         //
+// Contact <francois.fleuret@idiap.ch> for comments & bug reports        //
+///////////////////////////////////////////////////////////////////////////
+
+#include "simple_window.h"
+
+SimpleWindow::SimpleWindow(const char *name, int w, int h) {
+
+  width = w; height = h;
+
+  dpy = XOpenDisplay(0);
+
+  if (dpy) {
+
+      Visual *v = XDefaultVisual(dpy, DefaultScreen(dpy));
+
+      blue_mask = v->blue_mask;
+      green_mask = v->green_mask;
+      red_mask = v->red_mask;
+
+      if(blue_mask == 0 || green_mask == 0 || red_mask == 0) {
+        std::cerr << "Can not deal with the colors on that display.\n";
+      }
+
+      // We compute how many bits we have for each component, and
+      // compute the corresponding mask
+      red_shift = 1;
+      while(!(red_mask & 1)) {
+        red_mask = red_mask >> 1;
+        red_shift = red_shift << 1;
+      }
+
+      green_shift = 1;
+      while(!(green_mask & 1)) {
+        green_mask = green_mask >> 1;
+        green_shift = green_shift << 1;
+      }
+
+      blue_shift = 1;
+      while(!(blue_mask & 1)) {
+        blue_mask = blue_mask >> 1;
+        blue_shift = blue_shift << 1;
+      }
+
+      gc = DefaultGC(dpy, DefaultScreen(dpy));
+
+      XSetWindowAttributes xswa;
+
+      pixmap = XCreatePixmap(dpy, DefaultRootWindow(dpy),
+                            width, height, DisplayPlanes(dpy, DefaultScreen(dpy)));
+
+      xswa.background_pixmap = pixmap;
+      xswa.event_mask = NoEventMask;
+      xswa.backing_store = Always;
+
+      window = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0, width, height,
+                            0, 0, InputOutput, CopyFromParent,
+                            CWBackPixmap | CWEventMask | CWBackingStore,
+                            &xswa);
+
+      XSizeHints size_hints;
+      size_hints.flags = PMinSize | PMaxSize;
+      size_hints.min_width = width;
+      size_hints.min_height = height;
+      size_hints.max_width = width;
+      size_hints.max_height = height;
+      XSetNormalHints(dpy, window, &size_hints);
+
+      XStoreName(dpy, window, name);
+
+      XSetState(dpy, gc, 0, 0, GXcopy, AllPlanes);
+      XFillRectangle(dpy, pixmap, gc, 0, 0, width, height);
+      XFlush(dpy);
+    } else abort();
+}
+
+SimpleWindow::~SimpleWindow() {
+  XUnmapWindow(dpy, window);
+  XDestroyWindow(dpy, window);
+  XCloseDisplay(dpy);
+}
+
+int SimpleWindow::get_width() {
+  return width;
+}
+
+int SimpleWindow::get_height() {
+  return height;
+}
+
+void SimpleWindow::map() {
+  XMapWindow(dpy, window);
+  XFlush(dpy);
+}
+
+void SimpleWindow::unmap() {
+  XUnmapWindow(dpy, window);
+  XFlush(dpy);
+}
+
+void SimpleWindow::color(float red, float green, float blue) {
+  // We work under the assumption that the bits come in the
+  // red/green/blue order with the corresponding masks
+  XSetState(dpy, gc,
+              ((unsigned int) (  red *   red_mask)) *   red_shift
+           + ((unsigned int) (green * green_mask)) * green_shift
+           + ((unsigned int) ( blue *  blue_mask)) *  blue_shift,
+           0, GXcopy, AllPlanes);
+}
+
+void SimpleWindow::draw_point(int x, int y) {
+  XDrawPoint(dpy, pixmap, gc, x, y);
+}
+
+void SimpleWindow::draw_line(int x1, int y1, int x2, int y2) {
+  XDrawLine(dpy, pixmap, gc, x1, y1, x2, y2);
+}
+
+void SimpleWindow::draw_circle(int x, int y, int r) {
+  XDrawArc(dpy, pixmap, gc, x-r, y-r, 2*r, 2*r, 0, 360*64);
+}
+
+void SimpleWindow::draw_text(char *s, int x, int y) {
+  XDrawString(dpy, pixmap, gc, x, y, s, strlen(s));
+}
+
+void SimpleWindow::fill_rectangle(int x, int y, int w, int h) {
+  XFillRectangle(dpy, pixmap, gc, x, y, w, h);
+}
+
+void SimpleWindow::show() {
+  XCopyArea(dpy, pixmap, window, gc, 0, 0, width, height, 0, 0);
+  XFlush(dpy);
+}
+
+void SimpleWindow::fill() {
+  XFillRectangle(dpy, pixmap, gc, 0, 0, width, height);
+}