1 #include "X11OpenGLWindow.h"
2 #include "OpenGLInclude.h"
3 
4 #include<stdio.h>
5 #include<stdlib.h>
6 #ifdef GLEW_STATIC
7 #include "CustomGL/glew.h"
8 #else
9 #include <GL/glew.h>
10 #endif//GLEW_STATIC
11 
12 #ifdef GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS
13 #include "CustomGL/glxew.h"
14 #else
15 #include<GL/glx.h>
16 #endif // GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS
17 #include <assert.h>
18 
19 //#define DYNAMIC_LOAD_X11_FUNCTIONS
20 #ifdef DYNAMIC_LOAD_X11_FUNCTIONS
21 #include <dlfcn.h>
22 #endif //DYNAMIC_LOAD_X11_FUNCTIONS
23 
24 //#include<X11/X.h>
25 //#include<X11/Xlib.h>
26 //#include<GL/gl.h>
27 
28 //defined in GL/glxew.h
29 //#include<GL/glu.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 
35 #include <pthread.h>
36 
37 GLint                   att[] = { GLX_RGBA,
38 GLX_DEPTH_SIZE, 24,
39 GLX_RED_SIZE        , 8,
40 GLX_GREEN_SIZE      , 8,
41 GLX_BLUE_SIZE       , 8,
42 GLX_ALPHA_SIZE      , 8,
43 GLX_STENCIL_SIZE    , 8,
44 GLX_DOUBLEBUFFER,
45 None };
46 /*
47  static int att[] =
48             {
49                 GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None
50 
51               GLX_X_RENDERABLE    , True,
52               GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,
53               GLX_RENDER_TYPE     , GLX_RGBA_BIT,
54               GLX_X_VISUAL_TYPE   , GLX_TRUE_COLOR,
55               GLX_RED_SIZE        , 8,
56               GLX_GREEN_SIZE      , 8,
57               GLX_BLUE_SIZE       , 8,
58               GLX_ALPHA_SIZE      , 8,
59               GLX_DEPTH_SIZE      , 24,
60               GLX_STENCIL_SIZE    , 8,
61               GLX_DOUBLEBUFFER    , True,
62               None
63             };
64 */
65 static bool forceOpenGL3 = true;
66 
67 
68 
69 #ifdef DYNAMIC_LOAD_X11_FUNCTIONS
70 
71 ///our X11 function typedefs
72 
73 typedef int (*PFNXFREE)(void*);
74 typedef XErrorHandler (* PFNXSETERRORHANDLER) (XErrorHandler);
75 typedef int (* PFNXSYNC) (Display* a,Bool b);
76 typedef Display* (* PFNXOPENDISPLAY) (_Xconst char* a);
77 typedef Colormap (*PFNXCREATECOLORMAP) (Display* a,Window b,Visual* c,int d);
78 typedef Window (*PFNXCREATEWINDOW) (Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,int h,unsigned int i,Visual* j,unsigned long k,XSetWindowAttributes* l);
79 typedef int (*PFNXMAPWINDOW) (Display*, Window);
80 typedef int (*PFNXSTORENAME) (Display* a,Window b,_Xconst char* c);
81 typedef int (*PFNXCLOSEDISPLAY) (Display* a);
82 typedef int (*PFNXDESTROYWINDOW) (Display* a,Window b);
83 typedef int (*PFNXRAISEWINDOW) (Display* a, Window b);
84 
85 #if NeedWidePrototypes
86 	typedef KeySym* (*PFNXGETKEYBOARDMAPPING) (Display*,unsigned int,int,int*);
87 	typedef KeySym (*PFNXKEYCODETOKEYSYM) (Display* a,unsigned int b,int c);
88 #else
89 	typedef KeySym* (*PFNXGETKEYBOARDMAPPING) (Display*,KeyCode,int,int*);
90 	typedef KeySym (*PFNXKEYCODETOKEYSYM) (Display* a,KeyCode b,int c);
91 #endif
92 typedef void	(*PFNXCONVERTCASE) (KeySym /* sym */,KeySym *		/* lower */,KeySym * /* upper */);
93 typedef int (*PFNXPENDING) (Display* a);
94 typedef int (*PFNXNEXTEVENT) (Display* a,XEvent* b);
95 typedef int (*PFNXEVENTSQUEUED) (Display* a,int b);
96 typedef int (*PFNXPEEKEVENT) (Display* a,XEvent* b);
97 typedef KeySym (*PFNXLOOKUPKEYSYM) (XKeyEvent* a,int b);
98 typedef Status (*PFNXGETWINDOWATTRIBUTES) (Display* a,Window b,XWindowAttributes* c);
99 
100 #define X11_LIBRARY "libX11.so.6"
101 
102 #define MyXSync m_data->m_x11_XSync
103 #define MyXGetKeyboardMapping m_data->m_x11_XGetKeyboardMapping
104 #define MyXSetErrorHandler m_data->m_x11_XSetErrorHandler
105 #define MyXOpenDisplay m_data->m_x11_XOpenDisplay
106 #define MyXCreateColormap m_data->m_x11_XCreateColormap
107 #define MyXCreateWindow m_data->m_x11_XCreateWindow
108 #define MyXMapWindow m_data->m_x11_XMapWindow
109 #define MyXStoreName m_data->m_x11_XStoreName
110 #define MyXDestroyWindow m_data->m_x11_XDestroyWindow
111 #define MyXRaiseWindow m_data->m_x11_XRaiseWindow
112 #define MyXCloseDisplay m_data->m_x11_XCloseDisplay
113 #define MyXKeycodeToKeysym m_data->m_x11_XKeycodeToKeysym
114 #define MyXConvertCase m_data->m_x11_XConvertCase
115 #define MyXPending m_data->m_x11_XPending
116 #define MyXNextEvent m_data->m_x11_XNextEvent
117 #define MyXEventsQueued m_data->m_x11_XEventsQueued
118 #define MyXPeekEvent m_data->m_x11_XPeekEvent
119 #define MyXNextEvent m_data->m_x11_XNextEvent
120 #define MyXGetWindowAttributes m_data->m_x11_XGetWindowAttributes
121 #define MyXStoreName m_data->m_x11_XStoreName
122 #define MyXFree m_data->m_x11_XFree
123 #define MyXMapWindow m_data->m_x11_XMapWindow
124 #define MyXStoreName m_data->m_x11_XStoreName
125 #define MyXLookupKeysym m_data->m_x11_XLookupKeysym
126 
127 #else
128 #define MyXSync XSync
129 #define MyXGetKeyboardMapping XGetKeyboardMapping
130 #define MyXSetErrorHandler XSetErrorHandler
131 #define MyXOpenDisplay XOpenDisplay
132 #define MyXCreateColormap XCreateColormap
133 #define MyXCreateWindow XCreateWindow
134 #define MyXMapWindow XMapWindow
135 #define MyXStoreName XStoreName
136 #define MyXDestroyWindow XDestroyWindow
137 #define MyXRaiseWindow XRaiseWindow
138 #define MyXCloseDisplay XCloseDisplay
139 #define MyXKeycodeToKeysym XKeycodeToKeysym
140 #define MyXConvertCase XConvertCase
141 #define MyXPending XPending
142 #define MyXNextEvent XNextEvent
143 #define MyXEventsQueued XEventsQueued
144 #define MyXPeekEvent XPeekEvent
145 #define MyXNextEvent XNextEvent
146 #define MyXGetWindowAttributes XGetWindowAttributes
147 #define MyXStoreName XStoreName
148 #define MyXFree XFree
149 #define MyXMapWindow XMapWindow
150 #define MyXStoreName XStoreName
151 #define MyXLookupKeysym XLookupKeysym
152 
153 #endif//DYNAMIC_LOAD_X11_FUNCTIONS
154 
155 enum
156 {
157 	MY_X11_ALT_KEY = 1,
158 	MY_X11_SHIFT_KEY = 2,
159 	MY_X11_CONTROL_KEY = 4
160 };
161 
162 struct InternalData2
163 {
164     Display*                m_dpy;
165     Window                  m_root;
166     XVisualInfo*            m_vi;
167     Colormap                m_cmap;
168     XSetWindowAttributes    m_swa;
169     Window                  m_win;
170     GLXContext              m_glc;
171     XWindowAttributes       m_gwa;
172     XEvent                  m_xev;
173     GLXFBConfig             m_bestFbc;
174     int			    m_modifierFlags;
175     int			    m_glWidth;
176     int			    m_glHeight;
177 
178 #ifdef DYNAMIC_LOAD_X11_FUNCTIONS
179 	//dynamically load stuff
180 	void*									m_x11_library;
181 	PFNXFREE							m_x11_XFree;
182 	PFNXSETERRORHANDLER		m_x11_XSetErrorHandler;
183 	PFNXSYNC							m_x11_XSync;
184 	PFNXOPENDISPLAY				m_x11_XOpenDisplay;
185 	PFNXCREATECOLORMAP		m_x11_XCreateColormap;
186 	PFNXCREATEWINDOW			m_x11_XCreateWindow;
187 	PFNXMAPWINDOW					m_x11_XMapWindow;
188 	PFNXSTORENAME					m_x11_XStoreName;
189 	PFNXCLOSEDISPLAY			m_x11_XCloseDisplay;
190 	PFNXDESTROYWINDOW			m_x11_XDestroyWindow;
191 	PFNXRAISEWINDOW				m_x11_XRaiseWindow;
192 	PFNXKEYCODETOKEYSYM		m_x11_XKeycodeToKeysym;
193 	PFNXGETKEYBOARDMAPPING m_x11_XGetKeyboardMapping;
194 	PFNXCONVERTCASE				m_x11_XConvertCase;
195 	PFNXPENDING						m_x11_XPending;
196 	PFNXNEXTEVENT					m_x11_XNextEvent;
197 	PFNXEVENTSQUEUED			m_x11_XEventsQueued;
198 	PFNXPEEKEVENT					m_x11_XPeekEvent;
199 	PFNXLOOKUPKEYSYM			m_x11_XLookupKeysym;
200 	PFNXGETWINDOWATTRIBUTES m_x11_XGetWindowAttributes;
201 #endif //DYNAMIC_LOAD_X11_FUNCTIONS
202 
203 	b3WheelCallback m_wheelCallback;
204 	b3MouseMoveCallback	m_mouseMoveCallback;
205 	b3MouseButtonCallback	m_mouseButtonCallback;
206 	b3ResizeCallback		m_resizeCallback;
207 	b3KeyboardCallback	m_keyboardCallback;
208 
InternalData2InternalData2209 	InternalData2()
210 	:m_dpy(0),
211 	m_vi(0),
212 	m_modifierFlags(0),
213 	m_glWidth(-1),
214 	m_glHeight(-1),
215 	m_wheelCallback(0),
216 	m_mouseMoveCallback(0),
217 	m_mouseButtonCallback(0),
218 	m_resizeCallback(0),
219 	m_keyboardCallback(0)
220 	{
221 #ifdef DYNAMIC_LOAD_X11_FUNCTIONS
222 		 m_x11_library = dlopen(X11_LIBRARY, RTLD_LOCAL | RTLD_NOW);
223 		 if (!m_x11_library)
224 		{
225 			printf("Error opening X11 library %s\n", X11_LIBRARY);
226 			exit(0);
227 		}
228 
229 		bool missingFunc = false;
230 
231 		missingFunc = ((m_x11_XFree = (PFNXFREE)  dlsym(m_x11_library, "XFree"))==NULL) | missingFunc;
232 		assert(!missingFunc);
233 		if (missingFunc)		{ printf("Error: missing func XFree in %s, exiting!\n", X11_LIBRARY);	exit(0);}
234 		missingFunc = ((m_x11_XSetErrorHandler = (PFNXSETERRORHANDLER) dlsym(m_x11_library,"XSetErrorHandler"))==NULL) | missingFunc;
235 		if (missingFunc)		{ printf("Error: missing func XSetErrorHandler in %s, exiting!\n", X11_LIBRARY);	exit(0);}
236 		missingFunc = ((m_x11_XSetErrorHandler = (PFNXSETERRORHANDLER) dlsym(m_x11_library,"XSetErrorHandler"))==NULL) | missingFunc;
237 		if (missingFunc)		{ printf("Error: missing func XSetErrorHandler in %s, exiting!\n", X11_LIBRARY);	exit(0);}
238 		missingFunc = ((m_x11_XSync = (PFNXSYNC) dlsym(m_x11_library,"XSync"))==NULL) | missingFunc;
239 		if (missingFunc)		{ printf("Error: missing func XSync in %s, exiting!\n", X11_LIBRARY);	exit(0);}
240 		missingFunc = ((m_x11_XOpenDisplay = (PFNXOPENDISPLAY) dlsym(m_x11_library,"XOpenDisplay"))==NULL) | missingFunc;
241 		if (missingFunc)		{ printf("Error: missing func XOpenDisplay in %s, exiting!\n", X11_LIBRARY);	exit(0);}
242 		missingFunc = ((m_x11_XCreateColormap = (PFNXCREATECOLORMAP) dlsym(m_x11_library,"XCreateColormap"))==NULL) | missingFunc;
243 		if (missingFunc)		{ printf("Error: missing func XCreateColormap in %s, exiting!\n", X11_LIBRARY);	exit(0);}
244 		missingFunc = ((m_x11_XCreateWindow = (PFNXCREATEWINDOW) dlsym(m_x11_library,"XCreateWindow"))==NULL) | missingFunc;
245 		if (missingFunc)		{ printf("Error: missing func XCreateWindow in %s, exiting!\n", X11_LIBRARY);	exit(0);}
246 		missingFunc = ((m_x11_XMapWindow = (PFNXMAPWINDOW) dlsym(m_x11_library,"XMapWindow"))==NULL) | missingFunc;
247 		if (missingFunc)		{ printf("Error: missing func XMapWindow in %s, exiting!\n", X11_LIBRARY);	exit(0);}
248 		missingFunc = ((m_x11_XStoreName = (PFNXSTORENAME) dlsym(m_x11_library,"XStoreName"))==NULL) | missingFunc;
249 		if (missingFunc)		{ printf("Error: missing func XStoreName in %s, exiting!\n", X11_LIBRARY);	exit(0);}
250 		missingFunc = ((m_x11_XCloseDisplay = (PFNXCLOSEDISPLAY) dlsym(m_x11_library,"XCloseDisplay"))==NULL) | missingFunc;
251 		if (missingFunc)		{ printf("Error: missing func XCloseDisplay in %s, exiting!\n", X11_LIBRARY);	exit(0);}
252 		missingFunc = ((m_x11_XDestroyWindow = (PFNXDESTROYWINDOW) dlsym(m_x11_library,"XDestroyWindow"))==NULL) | missingFunc;
253 		if (missingFunc)		{ printf("Error: missing func XDestroyWindow in %s, exiting!\n", X11_LIBRARY);	exit(0);}
254 		missingFunc = ((m_x11_XRaiseWindow = (PFNXRAISEWINDOW) dlsym(m_x11_library,"XRaiseWindow"))==NULL) | missingFunc;
255 		if (missingFunc)		{ printf("Error: missing func XRaiseWindow in %s, exiting!\n", X11_LIBRARY);	exit(0);}
256 
257 		missingFunc = ((m_x11_XGetKeyboardMapping = (PFNXGETKEYBOARDMAPPING) dlsym(m_x11_library,"XGetKeyboardMapping"))==NULL) | missingFunc;
258 		if (missingFunc)		{ printf("Error: missing func XGetKeyboardMapping in %s, exiting!\n", X11_LIBRARY);	exit(0);}
259 		missingFunc = ((m_x11_XKeycodeToKeysym = (PFNXKEYCODETOKEYSYM) dlsym(m_x11_library,"XKeycodeToKeysym"))==NULL) | missingFunc;
260 		if (missingFunc)		{ printf("Error: missing func XKeycodeToKeysym in %s, exiting!\n", X11_LIBRARY);	exit(0);}
261 		missingFunc = ((m_x11_XConvertCase = (PFNXCONVERTCASE) dlsym(m_x11_library,"XConvertCase"))==NULL) | missingFunc;
262 		if (missingFunc)		{ printf("Error: missing func XConvertCase in %s, exiting!\n", X11_LIBRARY);	exit(0);}
263 		missingFunc = ((m_x11_XPending = (PFNXPENDING) dlsym(m_x11_library,"XPending"))==NULL) | missingFunc;
264 		if (missingFunc)		{ printf("Error: missing func XPending in %s, exiting!\n", X11_LIBRARY);	exit(0);}
265 		missingFunc = ((m_x11_XNextEvent = (PFNXNEXTEVENT) dlsym(m_x11_library,"XNextEvent"))==NULL) | missingFunc;
266 		if (missingFunc)		{ printf("Error: missing func XNextEvent in %s, exiting!\n", X11_LIBRARY);	exit(0);}
267 		missingFunc = ((m_x11_XEventsQueued = (PFNXEVENTSQUEUED) dlsym(m_x11_library,"XEventsQueued"))==NULL) | missingFunc;
268 		if (missingFunc)		{ printf("Error: missing func XEventsQueued in %s, exiting!\n", X11_LIBRARY);	exit(0);}
269 		missingFunc = ((m_x11_XPeekEvent = (PFNXPEEKEVENT) dlsym(m_x11_library,"XPeekEvent"))==NULL) | missingFunc;
270 		if (missingFunc)		{ printf("Error: missing func XPeekEvent in %s, exiting!\n", X11_LIBRARY);	exit(0);}
271 		missingFunc = ((m_x11_XLookupKeysym = (PFNXLOOKUPKEYSYM) dlsym(m_x11_library,"XLookupKeysym"))==NULL) | missingFunc;
272 		if (missingFunc)		{ printf("Error: missing func XLookupKeysym in %s, exiting!\n", X11_LIBRARY);	exit(0);}
273 		missingFunc = ((m_x11_XGetWindowAttributes = (PFNXGETWINDOWATTRIBUTES) dlsym(m_x11_library,"XGetWindowAttributes"))==NULL) | missingFunc;
274 		if (missingFunc)		{ printf("Error: missing func XGetWindowAttributes in %s, exiting!\n", X11_LIBRARY);	exit(0);}
275 
276 		if (missingFunc)
277 		{
278 			printf("Error: a missing func in %s, exiting!\n", X11_LIBRARY);
279 			exit(0);
280 		} else
281 		{
282 			printf("X11 functions dynamically loaded using dlopen/dlsym OK!\n");
283 		}
284 #endif //DYNAMIC_LOAD_X11_FUNCTIONS
285 	}
286 };
287 
288 #define GLX_CONTEXT_MAJOR_VERSION_ARB       0x2091
289 #define GLX_CONTEXT_MINOR_VERSION_ARB       0x2092
290 typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
291 
292 // Helper to check for extension string presence.  Adapted from:
293 //   http://www.opengl.org/resources/features/OGLextensions/
isExtensionSupported(const char * extList,const char * extension)294 static bool isExtensionSupported(const char *extList, const char *extension)
295 {
296   const char *start;
297   const char *where, *terminator;
298 
299   /* Extension names should not have spaces. */
300   where = strchr(extension, ' ');
301   if (where || *extension == '\0')
302     return false;
303 
304   /* It takes a bit of care to be fool-proof about parsing the
305      OpenGL extensions string. Don't be fooled by sub-strings,
306      etc. */
307   for (start=extList;;) {
308     where = strstr(start, extension);
309 
310     if (!where)
311       break;
312 
313     terminator = where + strlen(extension);
314 
315     if ( where == start || *(where - 1) == ' ' )
316       if ( *terminator == ' ' || *terminator == '\0' )
317         return true;
318 
319     start = terminator;
320   }
321 
322   return false;
323 }
324 
325 static bool ctxErrorOccurred = false;
ctxErrorHandler(Display * dpy,XErrorEvent * ev)326 static int ctxErrorHandler( Display *dpy, XErrorEvent *ev )
327 {
328     ctxErrorOccurred = true;
329     return 0;
330 }
331 
332 
333 
334 
X11OpenGLWindow()335 X11OpenGLWindow::X11OpenGLWindow()
336 :m_OpenGLInitialized(false),
337 m_requestedExit(false)
338 {
339     m_data = new InternalData2;
340 }
341 
~X11OpenGLWindow()342 X11OpenGLWindow::~X11OpenGLWindow()
343 {
344     if (m_OpenGLInitialized)
345     {
346         disableOpenGL();
347     }
348 
349     delete m_data;
350 }
351 
352 
353 
enableOpenGL()354 void X11OpenGLWindow::enableOpenGL()
355 {
356 
357 
358     if (forceOpenGL3)
359     {
360  // Get the default screen's GLX extension list
361   const char *glxExts = glXQueryExtensionsString( m_data->m_dpy,
362                                                   DefaultScreen( m_data->m_dpy ) );
363 
364   // NOTE: It is not necessary to create or make current to a context before
365   // calling glXGetProcAddressARB, unless we dynamically load OpenGL/GLX/X11
366 
367   glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
368   glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
369            glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
370 
371   GLXContext ctx = 0;
372 
373   // Install an X error handler so the application won't exit if GL 3.0
374   // context allocation fails.
375   //
376   // Note this error handler is global.  All display connections in all threads
377   // of a process use the same error handler, so be sure to guard against other
378   // threads issuing X commands while this code is running.
379   ctxErrorOccurred = false;
380   int (*oldHandler)(Display*, XErrorEvent*) =
381          MyXSetErrorHandler(&ctxErrorHandler);
382 
383   // Check for the GLX_ARB_create_context extension string and the function.
384   // If either is not present, use GLX 1.3 context creation method.
385   if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
386        !glXCreateContextAttribsARB )
387   {
388     printf( "glXCreateContextAttribsARB() not found"
389             " ... using old-style GLX context\n" );
390     ctx = glXCreateNewContext( m_data->m_dpy, m_data->m_bestFbc, GLX_RGBA_TYPE, 0, True );
391   }
392 
393   // If it does, try to get a GL 3.0 context!
394   else
395   {
396 	 int context_attribs[] = {
397           GLX_CONTEXT_MAJOR_VERSION_ARB ,3,
398           GLX_CONTEXT_MINOR_VERSION_ARB, 2,
399           GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
400           GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,None
401      };
402 /*
403     int context_attribs[] =
404       {
405         GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
406         GLX_CONTEXT_MINOR_VERSION_ARB, 2,
407 
408         //GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
409         None
410       };
411 */
412     printf( "Creating context\n" );
413     ctx = glXCreateContextAttribsARB( m_data->m_dpy, m_data->m_bestFbc, 0,
414                                       True, context_attribs );
415 
416     // Sync to ensure any errors generated are processed.
417     MyXSync( m_data->m_dpy, False );
418     if ( !ctxErrorOccurred && ctx )
419       printf( "Created GL 3.0 context\n" );
420     else
421     {
422       // Couldn't create GL 3.0 context.  Fall back to old-style 2.x context.
423       // When a context version below 3.0 is requested, implementations will
424       // return the newest context version compatible with OpenGL versions less
425       // than version 3.0.
426       // GLX_CONTEXT_MAJOR_VERSION_ARB = 1
427       context_attribs[1] = 1;
428       // GLX_CONTEXT_MINOR_VERSION_ARB = 0
429       context_attribs[3] = 0;
430 
431       ctxErrorOccurred = false;
432 
433       printf( "Failed to create GL 3.0 context"
434               " ... using old-style GLX context\n" );
435       ctx = glXCreateContextAttribsARB( m_data->m_dpy, m_data->m_bestFbc, 0,
436                                         True, context_attribs );
437     }
438   }
439 
440   // Sync to ensure any errors generated are processed.
441   MyXSync( m_data->m_dpy, False );
442 
443   // Restore the original error handler
444   MyXSetErrorHandler( oldHandler );
445 
446   if ( ctxErrorOccurred || !ctx )
447   {
448     printf( "Failed to create an OpenGL context\n" );
449     exit(1);
450   }
451 
452   // Verifying that context is a direct context
453   if ( ! glXIsDirect ( m_data->m_dpy, ctx ) )
454   {
455     printf( "Indirect GLX rendering context obtained\n" );
456   }
457   else
458   {
459     printf( "Direct GLX rendering context obtained\n" );
460   }
461 
462   printf( "Making context current\n" );
463   glXMakeCurrent( m_data->m_dpy, m_data->m_win, ctx );
464   m_data->m_glc = ctx;
465 
466     } else
467     {
468         m_data->m_glc = glXCreateContext(m_data->m_dpy, m_data->m_vi, NULL, GL_TRUE);
469         glXMakeCurrent(m_data->m_dpy, m_data->m_win, m_data->m_glc);
470     }
471 
472 #ifdef GLEW_INIT_OPENGL11_FUNCTIONS
473 {
474 	GLboolean res = glewOpenGL11Init();
475 	if (res==0)
476 		{
477 			printf("glewOpenGL11Init OK!\n");
478 		} else
479 			{
480 				printf("ERROR: glewOpenGL11Init failed, exiting!\n");
481 				exit(0);
482 			}
483 }
484 
485 #endif //GLEW_INIT_OPENGL11_FUNCTIONS
486 
487     const GLubyte* ven = glGetString(GL_VENDOR);
488     printf("GL_VENDOR=%s\n", ven);
489 
490     const GLubyte* ren = glGetString(GL_RENDERER);
491     printf("GL_RENDERER=%s\n",ren);
492     const GLubyte* ver = glGetString(GL_VERSION);
493     printf("GL_VERSION=%s\n", ver);
494     const GLubyte* sl = glGetString(GL_SHADING_LANGUAGE_VERSION);
495     printf("GL_SHADING_LANGUAGE_VERSION=%s\n", sl);
496 
497 //Access pthreads as a workaround for a bug in Linux/Ubuntu
498 //See https://bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers-319/+bug/1248642
499 
500 	int i=pthread_getconcurrency();
501         printf("pthread_getconcurrency()=%d\n",i);
502 
503 //    const GLubyte* ext = glGetString(GL_EXTENSIONS);
504 //    printf("GL_EXTENSIONS=%s\n", ext);
505 }
506 
disableOpenGL()507 void X11OpenGLWindow::disableOpenGL()
508 {
509     glXMakeCurrent(m_data->m_dpy, None, NULL);
510  	glXDestroyContext(m_data->m_dpy, m_data->m_glc);
511 }
512 
513 
createWindow(const b3gWindowConstructionInfo & ci)514 void    X11OpenGLWindow::createWindow(const b3gWindowConstructionInfo& ci)
515 {
516 
517     m_data->m_dpy = MyXOpenDisplay(NULL);
518 
519     if(m_data->m_dpy == NULL) {
520         printf("\n\tcannot connect to X server\n\n");
521             exit(0);
522      }
523 
524     m_data->m_root = DefaultRootWindow(m_data->m_dpy);
525 
526 
527 #ifdef GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS
528 GLboolean res = glewXInit();
529 if (res==0)
530 {
531 	printf("glewXInit OK\n");
532 } else
533 {
534 	printf("glewXInit failed, exit\n");
535 	exit(0);
536 }
537 #endif //GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS
538 
539 
540     if (ci.m_openglVersion < 3)
541     {
542         forceOpenGL3 = false;
543     }
544 
545     if (forceOpenGL3)
546     {
547         int glxMinor, glxMajor;
548         if (!glXQueryVersion(m_data->m_dpy,&glxMajor,&glxMinor) || (((glxMajor==1)&&(glxMinor<3)) || (glxMajor<1)))
549         {
550             printf("Invalid GLX version: major %d, minor %d\n",glxMajor,glxMinor);
551             exit(0);
552         }
553 
554         static int visual_attribs[] =
555             {
556               GLX_X_RENDERABLE    , True,
557               GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,
558               GLX_RENDER_TYPE     , GLX_RGBA_BIT,
559               GLX_X_VISUAL_TYPE   , GLX_TRUE_COLOR,
560               GLX_RED_SIZE        , 8,
561               GLX_GREEN_SIZE      , 8,
562               GLX_BLUE_SIZE       , 8,
563               GLX_ALPHA_SIZE      , 8,
564               GLX_DEPTH_SIZE      , 24,
565               GLX_STENCIL_SIZE    , 8,
566               GLX_DOUBLEBUFFER    , True,
567               None
568             };
569             int fbcount;
570             GLXFBConfig* fbc = glXChooseFBConfig(m_data->m_dpy, DefaultScreen(m_data->m_dpy), visual_attribs, &fbcount);
571             if (!fbc)
572             {
573                 printf( "Failed to retrieve a framebuffer config\n" );
574                 exit(1);
575             }
576 ///don't use highest samples, it is really slow on some NVIDIA Quadro cards
577 #ifdef USE_HIGHEST_SAMPLES
578             int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
579 
580             int i;
581             for (i=0; i<fbcount; ++i)
582             {
583 	            XVisualInfo *vi = glXGetVisualFromFBConfig( m_data->m_dpy, fbc[i] );
584 	            if ( vi )
585 	            {
586 	              int samp_buf, samples;
587 	              glXGetFBConfigAttrib( m_data->m_dpy, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
588 	              glXGetFBConfigAttrib( m_data->m_dpy, fbc[i], GLX_SAMPLES       , &samples  );
589 
590 	              //printf( "  Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
591 	               //       " SAMPLES = %d\n",
592 	                //      i, vi -> visualid, samp_buf, samples );
593 
594 	              if ( best_fbc < 0 || (samp_buf && (samples > best_num_samp)) )
595 	                best_fbc = i, best_num_samp = samples;
596 	              if ( worst_fbc < 0 || (!samp_buf || (samples < worst_num_samp)) )
597 	                worst_fbc = i, worst_num_samp = samples;
598 	            }
599 	            MyXFree( vi );
600             }
601 
602             m_data->m_bestFbc = fbc[ best_fbc ];
603 #else
604 	    m_data->m_bestFbc = *fbc;
605 #endif
606             // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
607             MyXFree( fbc );
608 
609             m_data->m_vi = glXGetVisualFromFBConfig( m_data->m_dpy, m_data->m_bestFbc );
610 
611 
612             m_data->m_swa.colormap = m_data->m_cmap = MyXCreateColormap( m_data->m_dpy,
613                                                  RootWindow( m_data->m_dpy, m_data->m_vi->screen ),
614                                                  m_data->m_vi->visual, AllocNone );
615             m_data->m_swa.background_pixmap = None ;
616             m_data->m_swa.border_pixel      = 0;
617             m_data->m_swa.event_mask        = ExposureMask | KeyReleaseMask | KeyPressMask |ButtonPressMask | ButtonReleaseMask |PointerMotionMask|StructureNotifyMask;
618 ;
619             m_data->m_root =  RootWindow( m_data->m_dpy, m_data->m_vi->screen );
620 
621             m_data->m_win = MyXCreateWindow( m_data->m_dpy, m_data->m_root,
622                                       0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput,
623                                       m_data->m_vi->visual,
624                                       CWBorderPixel|CWColormap|CWEventMask, &m_data->m_swa );
625 
626             //m_data->m_win = m_data->m_x11_XCreateWindow(m_data->m_dpy, m_data->m_root, 0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput, m_data->m_vi->visual, CWColormap | CWEventMask, &m_data->m_swa);
627 
628 
629             if (!m_data->m_win)
630             {
631                 printf("Cannot create window\n");
632                 exit(0);
633             }
634 
635             MyXMapWindow(m_data->m_dpy, m_data->m_win);
636             MyXStoreName(m_data->m_dpy, m_data->m_win, "OpenGL3 Window");
637 
638 
639     } else
640     {
641          m_data->m_vi = glXChooseVisual(m_data->m_dpy, 0, att);
642 
643 				printf("4\n");
644 
645          if(m_data->m_vi == NULL) {
646             printf("\n\tno appropriate visual found\n\n");
647                 exit(0);
648          }
649          else {
650             printf("\n\tvisual %p selected\n", (void *)m_data->m_vi->visualid); /* %p creates hexadecimal output like in glxinfo */
651          }
652 
653 
654          m_data->m_cmap = MyXCreateColormap(m_data->m_dpy, m_data->m_root, m_data->m_vi->visual, AllocNone);
655          m_data->m_swa.colormap = m_data->m_cmap;
656          m_data->m_swa.event_mask = ExposureMask | KeyReleaseMask | KeyPressMask |ButtonPressMask | ButtonReleaseMask |PointerMotionMask|StructureNotifyMask;
657          m_data->m_win = MyXCreateWindow(m_data->m_dpy, m_data->m_root, 0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput, m_data->m_vi->visual, CWColormap | CWEventMask, &m_data->m_swa);
658 
659          MyXMapWindow(m_data->m_dpy, m_data->m_win);
660 
661          MyXStoreName(m_data->m_dpy, m_data->m_win, "OpenGL2 Window");
662 
663 
664     }
665 
666     enableOpenGL();
667 }
668 
closeWindow()669 void    X11OpenGLWindow::closeWindow()
670 {
671     disableOpenGL();
672 
673     MyXDestroyWindow(m_data->m_dpy, m_data->m_win);
674     MyXCloseDisplay(m_data->m_dpy);
675 }
676 
getAsciiCodeFromVirtualKeycode(int keycode)677 int X11OpenGLWindow::getAsciiCodeFromVirtualKeycode(int keycode)
678 {
679     int result = 0;
680 
681     KeySym key, key_lc, key_uc;
682 
683     int keysyms_per_keycode_return;
684     KeySym *keysym = MyXGetKeyboardMapping(m_data->m_dpy,
685         keycode,
686         1,
687         &keysyms_per_keycode_return);
688 
689     key = keysym[0];
690 
691 
692     //key = MyXKeycodeToKeysym( m_data->m_dpy, keycode, 0 );
693 
694     switch( key )
695     {
696         case XK_Escape:       return B3G_ESCAPE;
697         case XK_Return:       return B3G_RETURN;
698         case XK_BackSpace:    return B3G_BACKSPACE;
699         case XK_Delete:       return B3G_DELETE;
700         case XK_Tab:       	  return 9;
701 
702 	case XK_Control_L:
703 	case XK_Control_R:     {
704 			return B3G_CONTROL;
705             }
706     case XK_Left: return B3G_LEFT_ARROW;
707     case XK_Right: return B3G_RIGHT_ARROW;
708     case XK_Up: return B3G_UP_ARROW;
709     case XK_Down: return B3G_DOWN_ARROW;
710 
711 	case XK_Alt_L:
712 	case XK_Alt_R:
713 		{
714 		  return B3G_ALT;
715 		}
716 	case XK_Shift_L:
717 	case XK_Shift_R:	      return B3G_SHIFT;
718         case XK_F1:           return B3G_F1;
719         case XK_F2:           return B3G_F2;
720         case XK_F3:           return B3G_F3;
721         case XK_F4:           return B3G_F4;
722         case XK_F5:           return B3G_F5;
723         case XK_F6:           return B3G_F6;
724         case XK_F7:           return B3G_F7;
725         case XK_F8:           return B3G_F8;
726         case XK_F9:           return B3G_F9;
727         case XK_F10:          return B3G_F10;
728         case XK_F11:          return B3G_F11;
729         case XK_F12:          return B3G_F12;
730         case XK_F13:          return B3G_F13;
731         case XK_F14:          return B3G_F14;
732         case XK_F15:          return B3G_F15;
733         default:
734 	// Make lowercase
735             MyXConvertCase( key, &key_lc, &key_uc );
736             key = key_lc;
737             // Valid ISO 8859-1 character?
738             if( (key >=  32 && key <= 126) ||(key >= 160 && key <= 255) )
739             {
740                 return (int) key;
741             }
742             result = -1;
743     }
744 
745     MyXFree(keysym);
746 
747     return result;
748 }
749 
isModifierKeyPressed(int key)750 bool    X11OpenGLWindow::isModifierKeyPressed(int key)
751 {
752         bool isPressed = false;
753 
754         switch (key)
755         {
756                 case B3G_ALT:
757                 {
758                         isPressed = ((m_data->m_modifierFlags & MY_X11_ALT_KEY)!=0);
759                         break;
760                 };
761                 case B3G_SHIFT:
762                 {
763                         isPressed = ((m_data->m_modifierFlags & MY_X11_SHIFT_KEY)!=0);
764                         break;
765                 };
766                 case B3G_CONTROL:
767                 {
768                         isPressed = ((m_data->m_modifierFlags & MY_X11_CONTROL_KEY )!=0);
769                         break;
770                 };
771 
772                 default:
773                 {
774                 }
775         };
776         return isPressed;
777 }
778 
pumpMessage()779 void X11OpenGLWindow::pumpMessage()
780 {
781 
782     int buttonState = 1;
783 
784      // Process all pending events
785     while( MyXPending( m_data->m_dpy ) )
786     {
787         MyXNextEvent(m_data->m_dpy, &m_data->m_xev);
788   //      printf("#");
789   //      fflush(stdout);
790         switch( m_data->m_xev.type )
791         {
792             case KeyPress:
793             {
794                     int keycode = getAsciiCodeFromVirtualKeycode(m_data->m_xev.xkey.keycode);
795 		    switch (keycode)
796 			{
797 			case B3G_ALT:
798 			m_data->m_modifierFlags |= MY_X11_ALT_KEY;
799 			break;
800 			case B3G_SHIFT:
801 			m_data->m_modifierFlags |= MY_X11_SHIFT_KEY;
802 			break;
803 			case B3G_CONTROL:
804 			m_data->m_modifierFlags |= MY_X11_CONTROL_KEY;
805 			break;
806 			default:
807 			{}
808 			};
809 		if (m_data->m_keyboardCallback)
810                 {
811 
812                     int state = 1;
813                     (*m_data->m_keyboardCallback)(keycode,state);
814                 //    printf("keycode %d",keycode);
815                   //  fflush(stdout);
816 
817                 }
818                 break;
819             }
820 
821             case KeyRelease:
822             {
823    //           fflush(stdout);
824  int keycode = getAsciiCodeFromVirtualKeycode( m_data->m_xev.xkey.keycode);
825 		  switch (keycode)
826                         {
827                         case B3G_ALT:
828                         m_data->m_modifierFlags &= ~MY_X11_ALT_KEY;
829                         break;
830                         case B3G_SHIFT:
831                         m_data->m_modifierFlags &= ~MY_X11_SHIFT_KEY;
832                         break;
833                         case B3G_CONTROL:
834                         m_data->m_modifierFlags &= ~MY_X11_CONTROL_KEY;
835                         break;
836                         default:
837                         {}
838                         };
839 
840                 if (m_data->m_keyboardCallback)
841                 {
842 #if 0
843                      unsigned short is_retriggered = 0;
844 ///filter out keyboard repeat
845 //see http://stackoverflow.com/questions/2100654/ignore-auto-repeat-in-x11-applications
846                      if (MyXEventsQueued(m_data->m_dpy, QueuedAfterReading))
847                        {
848                          XEvent nev;
849                          MyXPeekEvent(m_data->m_dpy, &nev);
850 
851                          if (nev.type == KeyPress && nev.xkey.time ==  m_data->m_xev.xkey.time &&
852                              nev.xkey.keycode ==  m_data->m_xev.xkey.keycode)
853                            {
854                              fprintf (stdout, "key #%ld was retriggered.\n",
855                                (long) MyXLookupKeysym(&nev.xkey, 0));
856 
857                              // delete retriggered KeyPress event
858                              MyXNextEvent(m_data->m_dpy, & m_data->m_xev);
859                              is_retriggered = 1;
860                            }
861                        }
862 #endif
863                     int state = 0;
864                     (*m_data->m_keyboardCallback)(keycode,state);
865                     }
866 
867                 break;
868             }
869 
870             case ButtonRelease:
871                 buttonState = 0;
872                 //continue with ButtonPress code
873             case ButtonPress:
874             {
875 //                printf("!");
876 //                fflush(stdout);
877 
878                 int button=-1;
879 
880                 switch (m_data->m_xev.xbutton.button)
881                 {
882                     case Button1:
883                     {
884                     button=0;
885                     break;
886                     }
887                     case Button2:
888                     {
889                         button=1;
890                         break;
891                     }
892                     case Button3:
893                     {
894                         button=2;
895                         break;
896                     }
897                     case Button4:
898                     {
899                         if (m_data->m_wheelCallback)
900                         {
901                             (*m_data->m_wheelCallback)(0,10);
902                         }
903                         break;
904                     }
905                     case Button5:
906                     {
907                         if (m_data->m_wheelCallback)
908                         {
909                             (*m_data->m_wheelCallback)(0,-10);
910                         }
911                         break;
912                     }
913                 }
914                 int xpos = m_data->m_xev.xmotion.x;
915                 int ypos = m_data->m_xev.xmotion.y;
916 
917                 if (button>=0 && m_data->m_mouseButtonCallback)
918                 {
919 //                      printf("xpos = %d, ypos = %d\n",xpos,ypos);
920 
921                     (*m_data->m_mouseButtonCallback)(button,buttonState,xpos,ypos);
922                 }
923                 break;
924             }
925             case MotionNotify:
926             {
927 //                printf("!");
928 //                fflush(0);
929                 if (m_data->m_mouseMoveCallback)
930                 {
931                     int xpos = m_data->m_xev.xmotion.x;
932                     int ypos = m_data->m_xev.xmotion.y;
933                     (*m_data->m_mouseMoveCallback)(xpos,ypos);
934                 }
935                 break;
936             }
937             case ConfigureNotify:
938             {
939   //              printf("@");
940   //              fflush(0);
941 		m_data->m_glWidth = m_data->m_xev.xconfigure.width;
942 		m_data->m_glHeight = m_data->m_xev.xconfigure.height;
943 
944                 if (m_data->m_resizeCallback)
945                 {
946                     (*m_data->m_resizeCallback)(m_data->m_xev.xconfigure.width,m_data->m_xev.xconfigure.height);
947                 }
948                 break;
949             }
950             case ClientMessage:
951             {
952   //              printf("?");
953   //              fflush(stdout);
954                 break;
955             }
956             case Expose:
957             {
958                     break;
959             }
960             case DestroyNotify:
961             {
962                 break;
963             }
964             default:
965             {
966                 //XRRUpdateConfiguration( &event );
967             }
968         };
969     }
970 }
971 
972 
973 
startRendering()974 void    X11OpenGLWindow::startRendering()
975 {
976 	pumpMessage();
977 
978     MyXGetWindowAttributes(m_data->m_dpy, m_data->m_win, &m_data->m_gwa);
979     glViewport(0, 0, m_data->m_gwa.width, m_data->m_gwa.height);
980 
981     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);	//clear buffers
982 
983     //glCullFace(GL_BACK);
984     //glFrontFace(GL_CCW);
985     glEnable(GL_DEPTH_TEST);
986 }
987 
renderAllObjects()988 void    X11OpenGLWindow::renderAllObjects()
989 {
990 
991 }
992 
endRendering()993 void    X11OpenGLWindow::endRendering()
994 {
995     glXSwapBuffers(m_data->m_dpy, m_data->m_win);
996 }
997 
runMainLoop()998 void    X11OpenGLWindow::runMainLoop()
999 {
1000 
1001 }
1002 
getTimeInSeconds()1003 float   X11OpenGLWindow::getTimeInSeconds()
1004 {
1005     return 0.f;
1006 }
1007 
requestedExit() const1008 bool    X11OpenGLWindow::requestedExit() const
1009 {
1010     return m_requestedExit;
1011 }
1012 
setRequestExit()1013 void    X11OpenGLWindow::setRequestExit()
1014 {
1015 	m_requestedExit=true;
1016 }
1017 
setRenderCallback(b3RenderCallback renderCallback)1018 void X11OpenGLWindow::setRenderCallback( b3RenderCallback renderCallback)
1019 {
1020 
1021 }
1022 
setWindowTitle(const char * title)1023 void X11OpenGLWindow::setWindowTitle(const char* title)
1024 {
1025     MyXStoreName(m_data->m_dpy, m_data->m_win, title);
1026 }
1027 
1028 
setWheelCallback(b3WheelCallback wheelCallback)1029 void X11OpenGLWindow::setWheelCallback(b3WheelCallback wheelCallback)
1030 {
1031 	m_data->m_wheelCallback = wheelCallback;
1032 }
1033 
setMouseMoveCallback(b3MouseMoveCallback mouseCallback)1034 void X11OpenGLWindow::setMouseMoveCallback(b3MouseMoveCallback	mouseCallback)
1035 {
1036 	m_data->m_mouseMoveCallback = mouseCallback;
1037 }
1038 
setMouseButtonCallback(b3MouseButtonCallback mouseCallback)1039 void X11OpenGLWindow::setMouseButtonCallback(b3MouseButtonCallback	mouseCallback)
1040 {
1041 	m_data->m_mouseButtonCallback = mouseCallback;
1042 }
1043 
setResizeCallback(b3ResizeCallback resizeCallback)1044 void X11OpenGLWindow::setResizeCallback(b3ResizeCallback	resizeCallback)
1045 {
1046 	if (resizeCallback && m_data->m_glWidth>0 && m_data->m_glHeight > 0)
1047 	{
1048 		resizeCallback(m_data->m_glWidth, m_data->m_glHeight);
1049 	}
1050 	m_data->m_resizeCallback = resizeCallback;
1051 }
1052 
setKeyboardCallback(b3KeyboardCallback keyboardCallback)1053 void X11OpenGLWindow::setKeyboardCallback( b3KeyboardCallback	keyboardCallback)
1054 {
1055 	m_data->m_keyboardCallback = keyboardCallback;
1056 
1057 }
1058 
getMouseMoveCallback()1059 b3MouseMoveCallback X11OpenGLWindow::getMouseMoveCallback()
1060 {
1061 	return m_data->m_mouseMoveCallback;
1062 }
getMouseButtonCallback()1063 b3MouseButtonCallback X11OpenGLWindow::getMouseButtonCallback()
1064 {
1065 	return m_data->m_mouseButtonCallback;
1066 }
getResizeCallback()1067 b3ResizeCallback X11OpenGLWindow::getResizeCallback()
1068 {
1069 	return m_data->m_resizeCallback;
1070 }
getWheelCallback()1071 b3WheelCallback X11OpenGLWindow::getWheelCallback()
1072 {
1073 	return m_data->m_wheelCallback;
1074 }
1075 
1076 
getKeyboardCallback()1077 b3KeyboardCallback      X11OpenGLWindow::getKeyboardCallback()
1078 {
1079 	return m_data->m_keyboardCallback;
1080 }
1081 
getWidth() const1082 int   X11OpenGLWindow::getWidth() const
1083 {
1084     if (m_data)
1085         return m_data->m_glWidth;
1086     return 0;
1087 }
getHeight() const1088 int   X11OpenGLWindow::getHeight() const
1089 {
1090     if (m_data)
1091         return m_data->m_glHeight;
1092     return 0;
1093 }
1094 
1095 
1096 #include <stdio.h>
1097 
fileOpenDialog(char * filename,int maxNameLength)1098 int X11OpenGLWindow::fileOpenDialog(char* filename, int maxNameLength)
1099 {
1100 	int len = 0;
1101 	FILE * output = popen("zenity --file-selection --file-filter=\"*.urdf\" --file-filter=\"*.sdf\"  --file-filter=\"*.obj\"  --file-filter=\"*.*\"","r");
1102 	if (output)
1103 	{
1104 		while( fgets(filename, maxNameLength-1, output) != NULL )
1105 		{
1106 			len=strlen(filename);
1107 			if (len>0)
1108 			{
1109 				filename[len-1]=0;
1110 				printf("file open (length=%d) = %s\n", len,filename);
1111 			}
1112 		}
1113 		pclose(output);
1114 	} else
1115 	{
1116 		printf("Error: fileOpenDialog no popen output, perhaps install zenity?\n");
1117 	}
1118 	MyXRaiseWindow(m_data->m_dpy, m_data->m_win);
1119 	return len;
1120 
1121 }
1122