X11OpenGLWindow.cpp 32 KB

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