2 // Written and (C) by Francois Fleuret
3 // Contact <francois.fleuret@idiap.ch> for comments & bug reports
8 #include "simple_window.h"
10 SimpleEvent::SimpleEvent() : type(UNDEFINED) {}
12 SimpleWindow::SimpleWindow(const char *name, int x, int y, int w, int h) {
14 _width = w; _height = h;
16 _display = XOpenDisplay(0);
20 _screen = DefaultScreen(_display);
21 _visual = XDefaultVisual(_display, _screen);
23 _blue_mask = _visual->blue_mask;
24 _green_mask = _visual->green_mask;
25 _red_mask = _visual->red_mask;
27 if(_blue_mask == 0 || _green_mask == 0 || _red_mask == 0) {
28 cerr << "Can not deal with the colors on that display.\n";
32 while(!(_red_mask & 1)) {
33 _red_mask = _red_mask >> 1;
34 _red_shift = _red_shift << 1;
38 while(!(_green_mask & 1)) {
39 _green_mask = _green_mask >> 1;
40 _green_shift = _green_shift << 1;
44 while(!(_blue_mask & 1)) {
45 _blue_mask = _blue_mask >> 1;
46 _blue_shift = _blue_shift << 1;
49 _gc = DefaultGC(_display, DefaultScreen(_display));
51 XSetWindowAttributes xswa;
53 _pixmap = XCreatePixmap(_display, DefaultRootWindow(_display),
54 _width, _height, DisplayPlanes(_display, DefaultScreen(_display)));
56 xswa.background_pixmap = _pixmap;
57 xswa.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | KeyReleaseMask;
58 xswa.backing_store = Always;
60 _window = XCreateWindow(_display, DefaultRootWindow(_display), x, y, _width, _height,
61 0, 0, InputOutput, CopyFromParent,
62 CWBackPixmap | CWEventMask | CWBackingStore,
65 XSizeHints size_hints;
66 size_hints.flags = PMinSize | PMaxSize | USPosition;
67 size_hints.x = x; // These two lines do not seem to be required
68 size_hints.y = y; // ...
69 size_hints.min_width = _width;
70 size_hints.min_height = _height;
71 size_hints.max_width = _width;
72 size_hints.max_height = _height;
73 XSetNormalHints(_display, _window, &size_hints);
75 XStoreName(_display, _window, name);
77 XSetState(_display, _gc, 0, 0, GXcopy, AllPlanes);
78 XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height);
82 _cairo_surface = cairo_xlib_surface_create(_display, _pixmap, _visual, _width, _height);
83 cairo_xlib_surface_set_size(_cairo_surface, _width, _height);
84 _cairo_context = cairo_create(_cairo_surface);
91 SimpleWindow::~SimpleWindow() {
92 XUnmapWindow(_display, _window);
93 XDestroyWindow(_display, _window);
94 XCloseDisplay(_display);
96 cairo_destroy(_cairo_context);
97 cairo_surface_destroy(_cairo_surface);
101 int SimpleWindow::width() {
105 int SimpleWindow::height() {
109 void SimpleWindow::map() {
110 XMapWindow(_display, _window);
114 void SimpleWindow::unmap() {
115 XUnmapWindow(_display, _window);
119 void SimpleWindow::color(float red, float green, float blue) {
120 XSetState(_display, _gc,
121 ((unsigned int) ( red * _red_mask)) * _red_shift
122 + ((unsigned int) (green * _green_mask)) * _green_shift
123 + ((unsigned int) ( blue * _blue_mask)) * _blue_shift,
124 0, GXcopy, AllPlanes);
127 void SimpleWindow::draw_point(int x, int y) {
128 XDrawPoint(_display, _pixmap, _gc, x, y);
131 void SimpleWindow::draw_line(int x1, int y1, int x2, int y2) {
132 XDrawLine(_display, _pixmap, _gc, x1, y1, x2, y2);
135 void SimpleWindow::draw_circle(int x, int y, int r) {
136 XDrawArc(_display, _pixmap, _gc, x-r, y-r, 2*r, 2*r, 0, 360*64);
139 void SimpleWindow::draw_text(const char *s, int x, int y) {
140 XDrawString(_display, _pixmap, _gc, x, y, s, strlen(s));
143 void SimpleWindow::fill_rectangle(int x, int y, int w, int h) {
144 XFillRectangle(_display, _pixmap, _gc, x, y, w, h);
147 void SimpleWindow::fill_polygon(int nb, int *x, int *y) {
149 for(int n = 0; n < nb; n++) {
153 XFillPolygon(_display, _pixmap, _gc, points, nb, Nonconvex, CoordModeOrigin);
156 void SimpleWindow::show() {
157 XCopyArea(_display, _pixmap, _window, _gc, 0, 0, _width, _height, 0, 0);
161 void SimpleWindow::fill() {
162 XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height);
165 int SimpleWindow::file_descriptor() {
166 return XConnectionNumber(_display);
169 SimpleEvent SimpleWindow::event() {
173 if(XPending(_display) > 0) {
176 XNextEvent(_display, &event);
178 switch (event.type) {
181 se.type = SimpleEvent::MOUSE_CLICK_PRESS;
182 se.button = event.xbutton.button;
183 se.x = event.xbutton.x;
184 se.y = event.xbutton.y;
188 se.type = SimpleEvent::MOUSE_CLICK_RELEASE;
189 se.button = event.xbutton.button;
190 se.x = event.xbutton.x;
191 se.y = event.xbutton.y;
195 se.type = SimpleEvent::MOUSE_MOTION;
196 se.button = event.xbutton.button;
197 se.x = event.xbutton.x;
198 se.y = event.xbutton.y;
202 se.type = SimpleEvent::KEY_PRESS;
203 mykey = XkbKeycodeToKeysym(_display,
204 event.xkey.keycode, 0,
205 event.xkey.state & ShiftMask ? 1 : 0);
206 strncpy(se.key, XKeysymToString(mykey), (sizeof(se.key)/sizeof(char) - 1));
210 se.type = SimpleEvent::KEY_RELEASE;
211 mykey = XkbKeycodeToKeysym(_display,
212 event.xkey.keycode, 0,
213 event.xkey.state & ShiftMask ? 1 : 0);
214 strncpy(se.key, XKeysymToString(mykey), (sizeof(se.key)/sizeof(char) - 1));
218 se.type = SimpleEvent::UNDEFINED;
222 } else se.type = SimpleEvent::NO_EVENT;
227 cairo_t *SimpleWindow::get_cairo_context_resource() {
228 return _cairo_context;