Refreshed the code to compile without warning.
[universe.git] / simple_window.cc
1
2 // Written and (C) by Francois Fleuret
3 // Contact <francois.fleuret@idiap.ch> for comments & bug reports
4
5 #include <string.h>
6 #include <stdlib.h>
7
8 #include "simple_window.h"
9
10 SimpleEvent::SimpleEvent() : type(UNDEFINED) {}
11
12 SimpleWindow::SimpleWindow(const char *name, int x, int y, int w, int h) {
13
14   _width = w; _height = h;
15
16   _display = XOpenDisplay(0);
17
18   if (_display) {
19
20       Visual *v = XDefaultVisual(_display, DefaultScreen(_display));
21
22       _blue_mask = v->blue_mask;
23       _green_mask = v->green_mask;
24       _red_mask = v->red_mask;
25
26       if(_blue_mask == 0 || _green_mask == 0 || _red_mask == 0) {
27         cerr << "Can not deal with the colors on that display.\n";
28       }
29
30       _red_shift = 1;
31       while(!(_red_mask & 1)) {
32         _red_mask = _red_mask >> 1;
33         _red_shift = _red_shift << 1;
34       }
35
36       _green_shift = 1;
37       while(!(_green_mask & 1)) {
38         _green_mask = _green_mask >> 1;
39         _green_shift = _green_shift << 1;
40       }
41
42       _blue_shift = 1;
43       while(!(_blue_mask & 1)) {
44         _blue_mask = _blue_mask >> 1;
45         _blue_shift = _blue_shift << 1;
46       }
47
48       _gc = DefaultGC(_display, DefaultScreen(_display));
49
50       XSetWindowAttributes xswa;
51
52       _pixmap = XCreatePixmap(_display, DefaultRootWindow(_display),
53                               _width, _height, DisplayPlanes(_display, DefaultScreen(_display)));
54
55       xswa.background_pixmap = _pixmap;
56       xswa.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | KeyReleaseMask;
57       xswa.backing_store = Always;
58
59       _window = XCreateWindow(_display, DefaultRootWindow(_display), x, y, _width, _height,
60                               0, 0, InputOutput, CopyFromParent,
61                               CWBackPixmap | CWEventMask | CWBackingStore,
62                               &xswa);
63
64       XSizeHints size_hints;
65       size_hints.flags = PMinSize | PMaxSize | USPosition;
66       size_hints.x = x; // These two lines do not seem to be required
67       size_hints.y = y; // ...
68       size_hints.min_width = _width;
69       size_hints.min_height = _height;
70       size_hints.max_width = _width;
71       size_hints.max_height = _height;
72       XSetNormalHints(_display, _window, &size_hints);
73
74       XStoreName(_display, _window, name);
75
76       XSetState(_display, _gc, 0, 0, GXcopy, AllPlanes);
77       XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height);
78       XFlush(_display);
79     } else abort();
80 }
81
82
83 SimpleWindow::~SimpleWindow() {
84   XUnmapWindow(_display, _window);
85   XDestroyWindow(_display, _window);
86   XCloseDisplay(_display);
87 }
88
89 int SimpleWindow::width() {
90   return _width;
91 }
92
93 int SimpleWindow::height() {
94   return _height;
95 }
96
97 void SimpleWindow::map() {
98   XMapWindow(_display, _window);
99   XFlush(_display);
100 }
101
102 void SimpleWindow::unmap() {
103   XUnmapWindow(_display, _window);
104   XFlush(_display);
105 }
106
107 void SimpleWindow::color(float red, float green, float blue) {
108   XSetState(_display, _gc,
109               ((unsigned int) (  red *   _red_mask)) *   _red_shift
110             + ((unsigned int) (green * _green_mask)) * _green_shift
111             + ((unsigned int) ( blue *  _blue_mask)) *  _blue_shift,
112             0, GXcopy, AllPlanes);
113 }
114
115 void SimpleWindow::draw_point(int x, int y) {
116   XDrawPoint(_display, _pixmap, _gc, x, y);
117 }
118
119 void SimpleWindow::draw_line(int x1, int y1, int x2, int y2) {
120   XDrawLine(_display, _pixmap, _gc, x1, y1, x2, y2);
121 }
122
123 void SimpleWindow::draw_circle(int x, int y, int r) {
124   XDrawArc(_display, _pixmap, _gc, x-r, y-r, 2*r, 2*r, 0, 360*64);
125 }
126
127 void SimpleWindow::draw_text(const char *s, int x, int y) {
128   XDrawString(_display, _pixmap, _gc, x, y, s, strlen(s));
129 }
130
131 void SimpleWindow::fill_rectangle(int x, int y, int w, int h) {
132   XFillRectangle(_display, _pixmap, _gc, x, y, w, h);
133 }
134
135 void SimpleWindow::fill_polygon(int nb, int *x, int *y) {
136   XPoint points[nb];
137   for(int n = 0; n < nb; n++) {
138     points[n].x = x[n];
139     points[n].y = y[n];
140   }
141   XFillPolygon(_display, _pixmap, _gc, points, nb, Nonconvex, CoordModeOrigin);
142 }
143
144 void SimpleWindow::show() {
145   XCopyArea(_display, _pixmap, _window, _gc, 0, 0, _width, _height, 0, 0);
146   XFlush(_display);
147 }
148
149 void SimpleWindow::fill() {
150   XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height);
151 }
152
153 int  SimpleWindow::file_descriptor() {
154   return XConnectionNumber(_display);
155 }
156
157 SimpleEvent SimpleWindow::event() {
158   SimpleEvent se;
159
160   if(XPending(_display) > 0) {
161
162     XEvent event;
163     XNextEvent(_display, &event);
164
165     switch (event.type) {
166
167     case ButtonPress:
168       se.type = SimpleEvent::MOUSE_CLICK_PRESS;
169       se.button = event.xbutton.button;
170       se.x = event.xbutton.x;
171       se.y = event.xbutton.y;
172       break;
173
174     case ButtonRelease:
175       se.type = SimpleEvent::MOUSE_CLICK_RELEASE;
176       se.button = event.xbutton.button;
177       se.x = event.xbutton.x;
178       se.y = event.xbutton.y;
179       break;
180
181     case MotionNotify:
182       se.type = SimpleEvent::MOUSE_MOTION;
183       se.button = event.xbutton.button;
184       se.x = event.xbutton.x;
185       se.y = event.xbutton.y;
186       break;
187
188     case KeyPress:
189       KeySym mykey;
190       mykey = XkbKeycodeToKeysym(_display,
191                                  event.xkey.keycode, 0,
192                                  event.xkey.state & ShiftMask ? 1 : 0);
193
194       se.type = SimpleEvent::KEY_PRESS;
195       strncpy(se.key, XKeysymToString(mykey), (sizeof(se.key)/sizeof(char) - 1));
196
197       break;
198
199     case KeyRelease:
200       KeySym mykey;
201       mykey = XkbKeycodeToKeysym(_display,
202                                  event.xkey.keycode, 0,
203                                  event.xkey.state & ShiftMask ? 1 : 0);
204
205       se.type = SimpleEvent::KEY_RELEASE;
206       strncpy(se.key, XKeysymToString(mykey), (sizeof(se.key)/sizeof(char) - 1));
207       break;
208
209     default:
210       se.type = SimpleEvent::UNDEFINED;
211       break;
212     }
213   } else se.type = SimpleEvent::NO_EVENT;
214   return se;
215 }