1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 // Free Software Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 #ifdef HAVE_CONFIG_H
20 #include "gnashconfig.h"
21 #endif
22
23 #include <iostream>
24 #include <cerrno>
25 #include <exception>
26 #include <sstream>
27
28 #include "log.h"
29 #include "GnashException.h"
30
31 #ifdef HAVE_GTK2
32 #include "gdk/gdkx.h"
33 #endif
34
35 #ifdef HAVE_X11_X_H
36 # include <X11/X.h>
37 # include <X11/Xlib.h>
38 # include <X11/Xutil.h>
39 #include <X11/keysym.h>
40 #else
41 # error "This file needs X11"
42 #endif
43
44 #include "X11Device.h"
45 #include "GnashDevice.h"
46
47 namespace gnash {
48
49 namespace renderer {
50
51 namespace x11 {
52
53 // The debug log used by all the gnash libraries.
54 static LogFile& dbglogfile = LogFile::getDefaultInstance();
55
56 // FIXME: this font name shouldn't be hardcoded!
57 const char *FONT = "/usr/share/fonts/truetype/freefont/FreeSerif.ttf";
58
X11Device()59 X11Device::X11Device()
60 : _display(0),
61 _screennum(0),
62 _root(0),
63 _window(0),
64 _visual(0),
65 _screen(0),
66 _depth(0),
67 _vinfo(0),
68 _vid(0)
69 {
70 GNASH_REPORT_FUNCTION;
71 dbglogfile.setVerbosity();
72 }
73
X11Device(int vid)74 X11Device::X11Device(int vid)
75 : _display(0),
76 _screennum(0),
77 _root(0),
78 _window(0),
79 _visual(0),
80 _screen(0),
81 _depth(0),
82 _vinfo(0),
83 _vid(vid)
84 {
85 GNASH_REPORT_FUNCTION;
86
87 if (!initDevice(0, 0)) {
88 log_error(_("Couldn't initialize X11 device!"));
89 }
90 }
91
X11Device(int argc,char * argv[])92 X11Device::X11Device(int argc, char *argv[])
93 : _display(0),
94 _screennum(0),
95 _root(0),
96 _window(0),
97 _visual(0),
98 _screen(0),
99 _depth(0),
100 _vinfo(0),
101 _vid(0)
102 {
103 GNASH_REPORT_FUNCTION;
104
105 if (!initDevice(argc, argv)) {
106 log_error(_("Couldn't initialize X11 device!"));
107 }
108 }
109
~X11Device()110 X11Device::~X11Device()
111 {
112 GNASH_REPORT_FUNCTION;
113 if (_display) {
114 if (_root) {
115 XDestroyWindow(_display, _root);
116 }
117 if (_window) {
118 XDestroyWindow(_display, _window);
119 }
120 XCloseDisplay(_display);
121 }
122 XFree(_vinfo);
123 }
124
125 bool
initDevice(int argc,char * argv[])126 X11Device::initDevice(int argc, char *argv[])
127 {
128 GNASH_REPORT_FUNCTION;
129
130 char *dpyName = NULL;
131 int num_visuals = 0;
132
133 for (int i = 1; i < argc; i++) {
134 if (strcmp(argv[i], "-display") == 0) {
135 dpyName = argv[i+1];
136 i++;
137 }
138 }
139
140 _display = XOpenDisplay(dpyName);
141 if (!_display) {
142 log_error(_("couldn't open X11 display!"));
143 return false;
144 }
145
146 _root = XDefaultRootWindow(_display);
147 _screennum = XDefaultScreen(_display);
148
149 _depth = DefaultDepth(_display, _screennum);
150 _colormap = DefaultColormap(_display, _screennum);
151 _screen = DefaultScreenOfDisplay(_display);
152
153 XVisualInfo visTemplate;
154 // _vid is from the Mesa EGL. The visual for EGL needs to match
155 // the one for X11.
156 std::cerr << "X11 visual from EGL is: " << _vid << std::endl;
157 visTemplate.visualid = _vid;
158
159 _vinfo = XGetVisualInfo(_display, VisualIDMask, &visTemplate, &num_visuals);
160 std::cerr << "Num Visuals: " << num_visuals << std::endl;
161 if (!_vinfo) {
162 log_error(_("Error: couldn't get X visual\n"));
163 exit(1);
164 }
165 std::cerr << "X11 visual is: " << _vinfo->visual << std::endl;
166
167 XFree(_vinfo);
168
169 // XWindowAttributes gattr;
170 // XGetWindowAttributes(_display, _root, &gattr);
171
172 // std::cerr << "Width: " << gattr.backing_store << std::endl;
173 // std::cerr << "Width: " << gattr.depth << std::endl;
174
175 return true;
176 }
177
178 // Initialize X11 Window layer
179 bool
attachWindow(GnashDevice::native_window_t window)180 X11Device::attachWindow(GnashDevice::native_window_t window)
181 {
182 GNASH_REPORT_FUNCTION;
183
184 _window = static_cast<Window>(window);
185
186 return true;
187 }
188
189
190 // Return a string with the error code as text, instead of a numeric value
191 const char *
getErrorString(int error)192 X11Device::getErrorString(int error)
193 {
194 static char msg[80];
195
196 if (_display) {
197 XGetErrorText(_display, error, msg, 80);
198 } else {
199 log_error(_("The default Display is not set!"));
200 }
201
202 return msg;
203 }
204
205 // Create an X11 window to render in. This is only used by testing
206 void
createWindow(const char * name,int x,int y,int width,int height)207 X11Device::createWindow(const char *name, int x, int y, int width, int height)
208 {
209 GNASH_REPORT_FUNCTION;
210
211 if (!_display) {
212 log_error(_("No Display device set!"));
213 return;
214 }
215
216 if (!_root) {
217 log_error(_("No drawable window set!"));
218 return;
219 }
220
221 XSetWindowAttributes attr;
222 unsigned long mask;
223 // Window root;
224 // XVisualInfo visTemplate;
225 // int num_visuals;
226
227 // window attributes
228 attr.background_pixel = 0;
229 attr.border_pixel = 0;
230 attr.colormap = XCreateColormap(_display, _root, _vinfo->visual, AllocNone);
231 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
232 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
233
234 _window = XCreateWindow(_display, _root, 0, 0, width, height,
235 0, _vinfo->depth, InputOutput,
236 _vinfo->visual, mask, &attr);
237
238 // set hints and properties
239 XSizeHints sizehints;
240 sizehints.x = x;
241 sizehints.y = y;
242 sizehints.width = width;
243 sizehints.height = height;
244 sizehints.flags = USSize | USPosition;
245 XSetNormalHints(_display, _window, &sizehints);
246 XSetStandardProperties(_display, _window, name, name, None, (char **)NULL,
247 0, &sizehints);
248
249 XMapWindow(_display, _window);
250 }
251
252 void
eventLoop(size_t passes)253 X11Device::eventLoop(size_t passes)
254 {
255 std::cerr << "Starting event loop..." << std::endl;
256
257 while (passes--) {
258 int redraw = 0;
259 XEvent event;
260 int width, height;
261
262 reshape_func reshape = 0;
263 key_func keyPress = 0;
264 // draw_func draw = 0;
265
266 XNextEvent(_display, &event);
267
268 switch (event.type) {
269 case Expose:
270 redraw = 1;
271 break;
272 case ConfigureNotify:
273 if (reshape) {
274 width = event.xconfigure.width;
275 height = event.xconfigure.height;
276 reshape(width, height);
277 }
278 break;
279 case KeyPress:
280 {
281 char buffer[10];
282 int code;
283 code = XLookupKeysym(&event.xkey, 0);
284 if (!keyPress || !keyPress(code)) {
285 // int r = XLookupString(&event.xkey, buffer, sizeof(buffer),
286 // NULL, NULL);
287 if (buffer[0] == 27) {
288 // escape
289 return;
290 } else {
291 std::cerr << buffer;
292 }
293 }
294 }
295 redraw = 1;
296 break;
297 default:
298 ; // no-op
299 }
300
301 if (redraw) {
302 // draw();
303 // eglSwapBuffers(egl_dpy, egl_surf);
304 }
305 } // end of while passes
306 }
307
308 } // namespace x11
309 } // namespace renderer
310 } // namespace gnash
311
312 // local Variables:
313 // mode: C++
314 // indent-tabs-mode: nil
315 // End:
316