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