#include "X11OpenGLWindow.h" #include "OpenGLInclude.h" #include #include #include #include #include #include //#include #include GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; struct InternalData2 { Display* m_dpy; Window m_root; XVisualInfo* m_vi; Colormap m_cmap; XSetWindowAttributes m_swa; Window m_win; GLXContext m_glc; XWindowAttributes m_gwa; XEvent m_xev; b3WheelCallback m_wheelCallback; b3MouseMoveCallback m_mouseMoveCallback; b3MouseButtonCallback m_mouseButtonCallback; b3ResizeCallback m_resizeCallback; b3KeyboardCallback m_keyboardCallback; InternalData2() :m_dpy(0), m_vi(0), m_wheelCallback(0), m_mouseMoveCallback(0), m_mouseButtonCallback(0), m_resizeCallback(0), m_keyboardCallback(0) { } }; X11OpenGLWindow::X11OpenGLWindow() :m_OpenGLInitialized(false), m_requestedExit(false) { m_data = new InternalData2; } X11OpenGLWindow::~X11OpenGLWindow() { if (m_OpenGLInitialized) { disableOpenGL(); } delete m_data; } void X11OpenGLWindow::enableOpenGL() { m_data->m_glc = glXCreateContext(m_data->m_dpy, m_data->m_vi, NULL, GL_TRUE); glXMakeCurrent(m_data->m_dpy, m_data->m_win, m_data->m_glc); const GLubyte* ven = glGetString(GL_VENDOR); printf("GL_VENDOR=%s\n", ven); const GLubyte* ren = glGetString(GL_RENDERER); printf("GL_RENDERER=%s\n",ren); const GLubyte* ver = glGetString(GL_VERSION); printf("GL_VERSION=%s\n", ver); const GLubyte* sl = glGetString(GL_SHADING_LANGUAGE_VERSION); printf("GL_SHADING_LANGUAGE_VERSION=%s\n", sl); // const GLubyte* ext = glGetString(GL_EXTENSIONS); // printf("GL_EXTENSIONS=%s\n", ext); } void X11OpenGLWindow::disableOpenGL() { glXMakeCurrent(m_data->m_dpy, None, NULL); glXDestroyContext(m_data->m_dpy, m_data->m_glc); } void X11OpenGLWindow::createWindow(const b3gWindowConstructionInfo& ci) { m_data->m_dpy = XOpenDisplay(NULL); if(m_data->m_dpy == NULL) { printf("\n\tcannot connect to X server\n\n"); exit(0); } m_data->m_root = DefaultRootWindow(m_data->m_dpy); m_data->m_vi = glXChooseVisual(m_data->m_dpy, 0, att); if(m_data->m_vi == NULL) { printf("\n\tno appropriate visual found\n\n"); exit(0); } else { printf("\n\tvisual %p selected\n", (void *)m_data->m_vi->visualid); /* %p creates hexadecimal output like in glxinfo */ } m_data->m_cmap = XCreateColormap(m_data->m_dpy, m_data->m_root, m_data->m_vi->visual, AllocNone); m_data->m_swa.colormap = m_data->m_cmap; m_data->m_swa.event_mask = ExposureMask | KeyReleaseMask | KeyPressMask |ButtonPressMask | ButtonReleaseMask |PointerMotionMask|StructureNotifyMask; m_data->m_win = 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); XMapWindow(m_data->m_dpy, m_data->m_win); XStoreName(m_data->m_dpy, m_data->m_win, "VERY SIMPLE APPLICATION"); enableOpenGL(); } void X11OpenGLWindow::closeWindow() { disableOpenGL(); XDestroyWindow(m_data->m_dpy, m_data->m_win); XCloseDisplay(m_data->m_dpy); } int X11OpenGLWindow::getAsciiCodeFromVirtualKeycode(int keycode) { KeySym key, key_lc, key_uc; key = XKeycodeToKeysym( m_data->m_dpy, keycode, 0 ); switch( key ) { case XK_Escape: return B3G_ESCAPE; case XK_Control_L: case XK_Control_R: { return B3G_CONTROL; } case XK_Alt_L: case XK_Alt_R: { return B3G_ALT; } case XK_Shift_L: case XK_Shift_R: return B3G_SHIFT; case XK_F1: return B3G_F1; case XK_F2: return B3G_F2; case XK_F3: return B3G_F3; case XK_F4: return B3G_F4; case XK_F5: return B3G_F5; case XK_F6: return B3G_F6; case XK_F7: return B3G_F7; case XK_F8: return B3G_F8; case XK_F9: return B3G_F9; case XK_F10: return B3G_F10; case XK_F11: return B3G_F11; case XK_F12: return B3G_F12; case XK_F13: return B3G_F13; case XK_F14: return B3G_F14; case XK_F15: return B3G_F15; default: // Make uppercase XConvertCase( key, &key_lc, &key_uc ); key = key_uc; // Valid ISO 8859-1 character? if( (key >= 32 && key <= 126) ||(key >= 160 && key <= 255) ) { return (int) key; } return -1; } return 0; } void X11OpenGLWindow::pumpMessage() { int buttonState = 1; // Process all pending events while( XPending( m_data->m_dpy ) ) { XNextEvent(m_data->m_dpy, &m_data->m_xev); // printf("#"); // fflush(stdout); switch( m_data->m_xev.type ) { case KeyPress: { if (m_data->m_keyboardCallback) { int keycode = getAsciiCodeFromVirtualKeycode(m_data->m_xev.xkey.keycode); int state = 1; (*m_data->m_keyboardCallback)(keycode,state); // printf("keycode %d",keycode); // fflush(stdout); } break; } case KeyRelease: { // fflush(stdout); if (m_data->m_keyboardCallback) { unsigned short is_retriggered = 0; ///filter out keyboard repeat //see http://stackoverflow.com/questions/2100654/ignore-auto-repeat-in-x11-applications if (XEventsQueued(m_data->m_dpy, QueuedAfterReading)) { XEvent nev; XPeekEvent(m_data->m_dpy, &nev); if (nev.type == KeyPress && nev.xkey.time == m_data->m_xev.xkey.time && nev.xkey.keycode == m_data->m_xev.xkey.keycode) { fprintf (stdout, "key #%ld was retriggered.\n", (long) XLookupKeysym (&nev.xkey, 0)); // delete retriggered KeyPress event XNextEvent (m_data->m_dpy, & m_data->m_xev); is_retriggered = 1; } } int keycode = getAsciiCodeFromVirtualKeycode( m_data->m_xev.xkey.keycode); int state = 0; (*m_data->m_keyboardCallback)(keycode,state); } break; } case ButtonRelease: buttonState = 0; //continue with ButtonPress code case ButtonPress: { // printf("!"); // fflush(stdout); int button=-1; switch (m_data->m_xev.xbutton.button) { case Button1: { button=0; break; } case Button2: { button=1; break; } case Button3: { button=2; break; } case Button4: { if (m_data->m_wheelCallback) { (*m_data->m_wheelCallback)(0,10); } break; } case Button5: { if (m_data->m_wheelCallback) { (*m_data->m_wheelCallback)(0,-10); } break; } } int xpos = m_data->m_xev.xmotion.x; int ypos = m_data->m_xev.xmotion.y; if (button>=0 && m_data->m_mouseButtonCallback) { // printf("xpos = %d, ypos = %d\n",xpos,ypos); (*m_data->m_mouseButtonCallback)(button,buttonState,xpos,ypos); } break; } case MotionNotify: { // printf("!"); // fflush(0); if (m_data->m_mouseMoveCallback) { int xpos = m_data->m_xev.xmotion.x; int ypos = m_data->m_xev.xmotion.y; (*m_data->m_mouseMoveCallback)(xpos,ypos); } break; } case ConfigureNotify: { // printf("@"); // fflush(0); if (m_data->m_resizeCallback) { (*m_data->m_resizeCallback)(m_data->m_xev.xconfigure.width,m_data->m_xev.xconfigure.height); } break; } case ClientMessage: { // printf("?"); // fflush(stdout); break; } case Expose: { break; } case DestroyNotify: { break; } default: { //XRRUpdateConfiguration( &event ); } }; } } void X11OpenGLWindow::startRendering() { pumpMessage(); XGetWindowAttributes(m_data->m_dpy, m_data->m_win, &m_data->m_gwa); glViewport(0, 0, m_data->m_gwa.width, m_data->m_gwa.height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); //clear buffers //glCullFace(GL_BACK); //glFrontFace(GL_CCW); glEnable(GL_DEPTH_TEST); } void X11OpenGLWindow::renderAllObjects() { } void X11OpenGLWindow::endRendering() { glXSwapBuffers(m_data->m_dpy, m_data->m_win); } void X11OpenGLWindow::runMainLoop() { } float X11OpenGLWindow::getTimeInSeconds() { return 0.f; } bool X11OpenGLWindow::requestedExit() const { return m_requestedExit; } void X11OpenGLWindow::setRequestExit() { m_requestedExit=true; } void X11OpenGLWindow::setRenderCallback( b3RenderCallback renderCallback) { } void X11OpenGLWindow::setWindowTitle(const char* title) { XStoreName(m_data->m_dpy, m_data->m_win, title); } void X11OpenGLWindow::setWheelCallback(b3WheelCallback wheelCallback) { m_data->m_wheelCallback = wheelCallback; } void X11OpenGLWindow::setMouseMoveCallback(b3MouseMoveCallback mouseCallback) { m_data->m_mouseMoveCallback = mouseCallback; } void X11OpenGLWindow::setMouseButtonCallback(b3MouseButtonCallback mouseCallback) { m_data->m_mouseButtonCallback = mouseCallback; } void X11OpenGLWindow::setResizeCallback(b3ResizeCallback resizeCallback) { m_data->m_resizeCallback = resizeCallback; } void X11OpenGLWindow::setKeyboardCallback( b3KeyboardCallback keyboardCallback) { m_data->m_keyboardCallback = keyboardCallback; } b3KeyboardCallback X11OpenGLWindow::getKeyboardCallback() { return m_data->m_keyboardCallback; }