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