// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef toolx_X11_session #define toolx_X11_session #include "base_session" #include namespace toolx { namespace X11 { class session : public base_session { typedef base_session parent; public: session(std::ostream& a_out,unsigned int a_monitor = 0) :parent(a_out,a_monitor) ,m_vinfo(0) ,m_ctx(0) ,m_colormap(0) { if(!m_display) return; {int glxMajor, glxMinor; ::glXQueryVersion(m_display,&glxMajor,&glxMinor); if(glxMajor<=0) { m_out << "toolx::X11::session::session : bad GLX-Version " << glxMajor << "." << glxMinor << std::endl; ::XCloseDisplay(m_display); m_display = 0; m_vinfo = 0; m_ctx = 0; return; }} static const int atbs_alpha[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_ALPHA_SIZE, 1, GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, None}; //NOTE : macOS : glXChooseVisual leaks 640 bytes. m_vinfo = ::glXChooseVisual(m_display,m_monitor,(int*)atbs_alpha); if(!m_vinfo) { static const int atbs[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, None}; m_vinfo = ::glXChooseVisual(m_display,m_monitor,(int*)atbs); if(!m_vinfo) { m_out << "toolx::X11::session::session :" << " can't choose a visual on screen " << m_monitor << "." << std::endl; ::XCloseDisplay(m_display); m_display = 0; m_vinfo = 0; m_ctx = 0; return; } } m_ctx = ::glXCreateContext(m_display,m_vinfo,NULL,GL_TRUE); if(!m_ctx) { m_out << "toolx::X11::session::session :" << " can't create a glX context with direct rendering." << std::endl; m_ctx = ::glXCreateContext(m_display,m_vinfo,NULL,GL_FALSE); if(!m_ctx) { m_out << "toolx::X11::session::session :" << " can't create a glX context." << std::endl; ::XCloseDisplay(m_display); m_display = 0; m_vinfo = 0; m_ctx = 0; return; } } // It is better to create a colormap adapted to the visual. m_colormap = ::XCreateColormap(m_display,::XRootWindow(m_display,m_monitor),m_vinfo->visual,AllocNone); if(m_colormap==0L) { m_out << "toolx::X11::session::session : XCreateColormap failed." << std::endl; ::XCloseDisplay(m_display); m_display = 0; m_vinfo = 0; m_ctx = 0; return; } } virtual ~session() { if(m_display) { if(m_ctx) { ::glXDestroyContext(m_display,m_ctx); m_ctx = 0; } if(m_colormap) { ::XFreeColormap(m_display,m_colormap); m_colormap = 0; } ::XCloseDisplay(m_display); m_display = 0; } if(m_vinfo) { ::XFree(m_vinfo); m_vinfo = 0; } } protected: session(const session& a_from) :parent(a_from) ,m_vinfo(0) ,m_ctx(0) ,m_colormap(0) {} session& operator=(const session& a_from){ if(&a_from==this) return *this; parent::operator=(a_from); return *this; } public: GLXContext context() const {return m_ctx;} Window create_window(const char* a_title,int a_x,int a_y,unsigned int a_width,unsigned int a_height) { if(!m_display) return 0L; XSetWindowAttributes swa; swa.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask | KeyPressMask; swa.colormap = m_colormap; swa.border_pixel = 0L; Window window = ::XCreateWindow(m_display, ::XRootWindow(m_display,m_monitor), a_x,a_y,a_width,a_height, 0, m_vinfo->depth, InputOutput, m_vinfo->visual, CWBorderPixel|CWColormap|CWEventMask,&swa); if(window==0L) { m_out << "toolx::X11::session::create_window :" << " can't create a X11 window." << std::endl; return 0L; } XTextProperty tp; ::XStringListToTextProperty((char**)&a_title,1,&tp); XSizeHints sh; sh.flags = USPosition | USSize; ::XSetWMProperties(m_display,window,&tp,&tp,0,0,&sh,0,0); ::XFree(tp.value); ::XSetWMProtocols(m_display,window,&m_WM_DELETE_WINDOW_atom,1); return window; } protected: XVisualInfo* m_vinfo; GLXContext m_ctx; Colormap m_colormap; }; }} #endif