Cairo support works, both to draw in the window and to write as a png image in a...
[universe.git] / simple_window.cc
index 449ca36..ae981ed 100644 (file)
@@ -1,25 +1,15 @@
 
-////////////////////////////////////////////////////////////////////////////////
-// This program is free software; you can redistribute it and/or              //
-// modify it under the terms of the GNU General Public License                //
-// version 2 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.                                   //
-//                                                                            //
-// Written and (C) by François Fleuret                                        //
-// Contact <francois.fleuret@epfl.ch> for comments & bug reports              //
-////////////////////////////////////////////////////////////////////////////////
-
-// $Id: simple_window.cc,v 1.2 2007-04-24 21:22:52 fleuret Exp $
+// Written and (C) by Francois Fleuret
+// Contact <francois.fleuret@idiap.ch> for comments & bug reports
+
+#include <string.h>
+#include <stdlib.h>
 
 #include "simple_window.h"
 
 SimpleEvent::SimpleEvent() : type(UNDEFINED) {}
 
-SimpleWindow::SimpleWindow(char *name, int x, int y, int w, int h) {
+SimpleWindow::SimpleWindow(const char *name, int x, int y, int w, int h) {
 
   _width = w; _height = h;
 
@@ -27,66 +17,67 @@ SimpleWindow::SimpleWindow(char *name, int x, int y, int w, int h) {
 
   if (_display) {
 
-      Visual *v = XDefaultVisual(_display, DefaultScreen(_display));
+    _screen = DefaultScreen(_display);
+    _visual = XDefaultVisual(_display, _screen);
 
-      _blue_mask = v->blue_mask;
-      _green_mask = v->green_mask;
-      _red_mask = v->red_mask;
+    _blue_mask = _visual->blue_mask;
+    _green_mask = _visual->green_mask;
+    _red_mask = _visual->red_mask;
 
-      if(_blue_mask == 0 || _green_mask == 0 || _red_mask == 0) {
-        cerr << "Can not deal with the colors on that display.\n";
-      }
+    if(_blue_mask == 0 || _green_mask == 0 || _red_mask == 0) {
+      cerr << "Can not deal with the colors on that display.\n";
+    }
 
-      _red_shift = 1;
-      while(!(_red_mask & 1)) {
-        _red_mask = _red_mask >> 1;
-        _red_shift = _red_shift << 1;
-      }
+    _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;
-      }
+    _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;
-      }
+    _blue_shift = 1;
+    while(!(_blue_mask & 1)) {
+      _blue_mask = _blue_mask >> 1;
+      _blue_shift = _blue_shift << 1;
+    }
 
-      _gc = DefaultGC(_display, DefaultScreen(_display));
+    _gc = DefaultGC(_display, DefaultScreen(_display));
 
-      XSetWindowAttributes xswa;
+    XSetWindowAttributes xswa;
 
-      _pixmap = XCreatePixmap(_display, DefaultRootWindow(_display),
-                              _width, _height, DisplayPlanes(_display, DefaultScreen(_display)));
+    _pixmap = XCreatePixmap(_display, DefaultRootWindow(_display),
+                            _width, _height, DisplayPlanes(_display, DefaultScreen(_display)));
 
-      xswa.background_pixmap = _pixmap;
-      xswa.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | KeyReleaseMask;
-      xswa.backing_store = Always;
+    xswa.background_pixmap = _pixmap;
+    xswa.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | KeyReleaseMask;
+    xswa.backing_store = Always;
 
-      _window = XCreateWindow(_display, DefaultRootWindow(_display), x, y, _width, _height,
-                              0, 0, InputOutput, CopyFromParent,
-                              CWBackPixmap | CWEventMask | CWBackingStore,
-                              &xswa);
+    _window = XCreateWindow(_display, DefaultRootWindow(_display), x, y, _width, _height,
+                            0, 0, InputOutput, CopyFromParent,
+                            CWBackPixmap | CWEventMask | CWBackingStore,
+                            &xswa);
 
-      XSizeHints size_hints;
-      size_hints.flags = PMinSize | PMaxSize | USPosition;
-      size_hints.x = x; // These two lines do not seem to be required
-      size_hints.y = y; // ...
-      size_hints.min_width = _width;
-      size_hints.min_height = _height;
-      size_hints.max_width = _width;
-      size_hints.max_height = _height;
-      XSetNormalHints(_display, _window, &size_hints);
+    XSizeHints size_hints;
+    size_hints.flags = PMinSize | PMaxSize | USPosition;
+    size_hints.x = x; // These two lines do not seem to be required
+    size_hints.y = y; // ...
+    size_hints.min_width = _width;
+    size_hints.min_height = _height;
+    size_hints.max_width = _width;
+    size_hints.max_height = _height;
+    XSetNormalHints(_display, _window, &size_hints);
 
-      XStoreName(_display, _window, name);
+    XStoreName(_display, _window, name);
 
-      XSetState(_display, _gc, 0, 0, GXcopy, AllPlanes);
-      XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height);
-      XFlush(_display);
-    } else abort();
+    XSetState(_display, _gc, 0, 0, GXcopy, AllPlanes);
+    XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height);
+    XFlush(_display);
+  } else abort();
 }
 
 
@@ -134,7 +125,7 @@ void SimpleWindow::draw_circle(int x, int y, int r) {
   XDrawArc(_display, _pixmap, _gc, x-r, y-r, 2*r, 2*r, 0, 360*64);
 }
 
-void SimpleWindow::draw_text(char *s, int x, int y) {
+void SimpleWindow::draw_text(const char *s, int x, int y) {
   XDrawString(_display, _pixmap, _gc, x, y, s, strlen(s));
 }
 
@@ -166,6 +157,7 @@ int  SimpleWindow::file_descriptor() {
 
 SimpleEvent SimpleWindow::event() {
   SimpleEvent se;
+  KeySym mykey;
 
   if(XPending(_display) > 0) {
 
@@ -197,22 +189,37 @@ SimpleEvent SimpleWindow::event() {
 
     case KeyPress:
       se.type = SimpleEvent::KEY_PRESS;
-      strncpy(se.key,
-              XKeysymToString(XKeycodeToKeysym(_display, event.xkey.keycode, 0)),
-              (sizeof(se.key)/sizeof(char) - 1));
+      mykey = XkbKeycodeToKeysym(_display,
+                                 event.xkey.keycode, 0,
+                                 event.xkey.state & ShiftMask ? 1 : 0);
+      strncpy(se.key, XKeysymToString(mykey), (sizeof(se.key)/sizeof(char) - 1));
       break;
 
     case KeyRelease:
       se.type = SimpleEvent::KEY_RELEASE;
-      strncpy(se.key,
-              XKeysymToString(XKeycodeToKeysym(_display, event.xkey.keycode, 0)),
-              (sizeof(se.key)/sizeof(char) - 1));
+      mykey = XkbKeycodeToKeysym(_display,
+                                 event.xkey.keycode, 0,
+                                 event.xkey.state & ShiftMask ? 1 : 0);
+      strncpy(se.key, XKeysymToString(mykey), (sizeof(se.key)/sizeof(char) - 1));
       break;
 
     default:
       se.type = SimpleEvent::UNDEFINED;
       break;
+
     }
   } else se.type = SimpleEvent::NO_EVENT;
   return se;
 }
+
+#ifdef CAIRO_SUPPORT
+cairo_t *SimpleWindow::get_cairo_context_resource() {
+  cairo_surface_t *surface;
+
+  surface = cairo_xlib_surface_create(_display, _pixmap, _visual, _width, _height);
+
+  cairo_xlib_surface_set_size(surface, _width, _height);
+
+  return cairo_create(surface);
+}
+#endif