2 ////////////////////////////////////////////////////////////////////////////////
3 // This program is free software; you can redistribute it and/or //
4 // modify it under the terms of the GNU General Public License //
5 // version 2 as published by the Free Software Foundation. //
7 // This program is distributed in the hope that it will be useful, but //
8 // WITHOUT ANY WARRANTY; without even the implied warranty of //
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
10 // General Public License for more details. //
12 // Written and (C) by François Fleuret //
13 // Contact <francois.fleuret@epfl.ch> for comments & bug reports //
14 ////////////////////////////////////////////////////////////////////////////////
16 #include "simple_window.h"
18 SimpleEvent::SimpleEvent() : type(UNDEFINED) {}
20 SimpleWindow::SimpleWindow(char *name, int x, int y, int w, int h) {
22 _width = w; _height = h;
24 _display = XOpenDisplay(0);
28 Visual *v = XDefaultVisual(_display, DefaultScreen(_display));
30 _blue_mask = v->blue_mask;
31 _green_mask = v->green_mask;
32 _red_mask = v->red_mask;
34 if(_blue_mask == 0 || _green_mask == 0 || _red_mask == 0) {
35 cerr << "Can not deal with the colors on that display.\n";
39 while(!(_red_mask & 1)) {
40 _red_mask = _red_mask >> 1;
41 _red_shift = _red_shift << 1;
45 while(!(_green_mask & 1)) {
46 _green_mask = _green_mask >> 1;
47 _green_shift = _green_shift << 1;
51 while(!(_blue_mask & 1)) {
52 _blue_mask = _blue_mask >> 1;
53 _blue_shift = _blue_shift << 1;
56 _gc = DefaultGC(_display, DefaultScreen(_display));
58 XSetWindowAttributes xswa;
60 _pixmap = XCreatePixmap(_display, DefaultRootWindow(_display),
61 _width, _height, DisplayPlanes(_display, DefaultScreen(_display)));
63 xswa.background_pixmap = _pixmap;
64 xswa.event_mask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyPressMask | KeyReleaseMask;
65 xswa.backing_store = Always;
67 _window = XCreateWindow(_display, DefaultRootWindow(_display), x, y, _width, _height,
68 0, 0, InputOutput, CopyFromParent,
69 CWBackPixmap | CWEventMask | CWBackingStore,
72 XSizeHints size_hints;
73 size_hints.flags = PMinSize | PMaxSize | USPosition;
74 size_hints.x = x; // These two lines do not seem to be required
75 size_hints.y = y; // ...
76 size_hints.min_width = _width;
77 size_hints.min_height = _height;
78 size_hints.max_width = _width;
79 size_hints.max_height = _height;
80 XSetNormalHints(_display, _window, &size_hints);
82 XStoreName(_display, _window, name);
84 XSetState(_display, _gc, 0, 0, GXcopy, AllPlanes);
85 XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height);
91 SimpleWindow::~SimpleWindow() {
92 XUnmapWindow(_display, _window);
93 XDestroyWindow(_display, _window);
94 XCloseDisplay(_display);
97 int SimpleWindow::width() {
101 int SimpleWindow::height() {
105 void SimpleWindow::map() {
106 XMapWindow(_display, _window);
110 void SimpleWindow::unmap() {
111 XUnmapWindow(_display, _window);
115 void SimpleWindow::color(float red, float green, float blue) {
116 XSetState(_display, _gc,
117 ((unsigned int) ( red * _red_mask)) * _red_shift
118 + ((unsigned int) (green * _green_mask)) * _green_shift
119 + ((unsigned int) ( blue * _blue_mask)) * _blue_shift,
120 0, GXcopy, AllPlanes);
123 void SimpleWindow::draw_point(int x, int y) {
124 XDrawPoint(_display, _pixmap, _gc, x, y);
127 void SimpleWindow::draw_line(int x1, int y1, int x2, int y2) {
128 XDrawLine(_display, _pixmap, _gc, x1, y1, x2, y2);
131 void SimpleWindow::draw_circle(int x, int y, int r) {
132 XDrawArc(_display, _pixmap, _gc, x-r, y-r, 2*r, 2*r, 0, 360*64);
135 void SimpleWindow::draw_text(char *s, int x, int y) {
136 XDrawString(_display, _pixmap, _gc, x, y, s, strlen(s));
139 void SimpleWindow::fill_rectangle(int x, int y, int w, int h) {
140 XFillRectangle(_display, _pixmap, _gc, x, y, w, h);
143 void SimpleWindow::fill_polygon(int nb, int *x, int *y) {
145 for(int n = 0; n < nb; n++) {
149 XFillPolygon(_display, _pixmap, _gc, points, nb, Nonconvex, CoordModeOrigin);
152 void SimpleWindow::show() {
153 XCopyArea(_display, _pixmap, _window, _gc, 0, 0, _width, _height, 0, 0);
157 void SimpleWindow::fill() {
158 XFillRectangle(_display, _pixmap, _gc, 0, 0, _width, _height);
161 int SimpleWindow::file_descriptor() {
162 return XConnectionNumber(_display);
165 SimpleEvent SimpleWindow::event() {
168 if(XPending(_display) > 0) {
171 XNextEvent(_display, &event);
173 switch (event.type) {
176 se.type = SimpleEvent::MOUSE_CLICK_PRESS;
177 se.button = event.xbutton.button;
178 se.x = event.xbutton.x;
179 se.y = event.xbutton.y;
183 se.type = SimpleEvent::MOUSE_CLICK_RELEASE;
184 se.button = event.xbutton.button;
185 se.x = event.xbutton.x;
186 se.y = event.xbutton.y;
190 se.type = SimpleEvent::MOUSE_MOTION;
191 se.button = event.xbutton.button;
192 se.x = event.xbutton.x;
193 se.y = event.xbutton.y;
197 se.type = SimpleEvent::KEY_PRESS;
199 XKeysymToString(XKeycodeToKeysym(_display, event.xkey.keycode, 0)),
200 (sizeof(se.key)/sizeof(char) - 1));
204 se.type = SimpleEvent::KEY_RELEASE;
206 XKeysymToString(XKeycodeToKeysym(_display, event.xkey.keycode, 0)),
207 (sizeof(se.key)/sizeof(char) - 1));
211 se.type = SimpleEvent::UNDEFINED;
214 } else se.type = SimpleEvent::NO_EVENT;