static Uint32 X11_GetGlobalMouseState(int *x, int *y) { Display *display = GetDisplay(); const int num_screens = SDL_GetNumVideoDisplays(); int i; /* !!! FIXME: should we XSync() here first? */ for (i = 0; i < num_screens; i++) { SDL_DisplayData *data = (SDL_DisplayData *) SDL_GetDisplayDriverData(i); if (data != NULL) { Window root, child; int rootx, rooty, winx, winy; unsigned int mask; if (X11_XQueryPointer(display, RootWindow(display, data->screen), &root, &child, &rootx, &rooty, &winx, &winy, &mask)) { XWindowAttributes root_attrs; Uint32 retval = 0; retval |= (mask & Button1Mask) ? SDL_BUTTON_LMASK : 0; retval |= (mask & Button2Mask) ? SDL_BUTTON_MMASK : 0; retval |= (mask & Button3Mask) ? SDL_BUTTON_RMASK : 0; /* SDL_DisplayData->x,y point to screen origin, and adding them to mouse coordinates relative to root window doesn't do the right thing * (observed on dual monitor setup with primary display being the rightmost one - mouse was offset to the right). * * Adding root position to root-relative coordinates seems to be a better way to get absolute position. */ X11_XGetWindowAttributes(display, root, &root_attrs); *x = root_attrs.x + rootx; *y = root_attrs.y + rooty; return retval; } } } SDL_assert(0 && "The pointer wasn't on any X11 screen?!"); return 0; }
/* Create and set up our X11 dialog box indow. */ static int X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data ) { int x, y; XSizeHints *sizehints; XSetWindowAttributes wnd_attr; Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG, _NET_WM_NAME, UTF8_STRING; Display *display = data->display; SDL_WindowData *windowdata = NULL; const SDL_MessageBoxData *messageboxdata = data->messageboxdata; if ( messageboxdata->window ) { SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(messageboxdata->window)->driverdata; windowdata = (SDL_WindowData *)messageboxdata->window->driverdata; data->screen = displaydata->screen; } else { data->screen = DefaultScreen( display ); } data->event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | FocusChangeMask | PointerMotionMask; wnd_attr.event_mask = data->event_mask; data->window = X11_XCreateWindow( display, RootWindow(display, data->screen), 0, 0, data->dialog_width, data->dialog_height, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &wnd_attr ); if ( data->window == None ) { return SDL_SetError("Couldn't create X window"); } if ( windowdata ) { /* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */ X11_XSetTransientForHint( display, data->window, windowdata->xwindow ); } X11_XStoreName( display, data->window, messageboxdata->title ); _NET_WM_NAME = X11_XInternAtom(display, "_NET_WM_NAME", False); UTF8_STRING = X11_XInternAtom(display, "UTF8_STRING", False); X11_XChangeProperty(display, data->window, _NET_WM_NAME, UTF8_STRING, 8, PropModeReplace, (unsigned char *) messageboxdata->title, strlen(messageboxdata->title) + 1 ); /* Let the window manager know this is a dialog box */ _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); _NET_WM_WINDOW_TYPE_DIALOG = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False); X11_XChangeProperty(display, data->window, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&_NET_WM_WINDOW_TYPE_DIALOG, 1); /* Allow the window to be deleted by the window manager */ data->wm_protocols = X11_XInternAtom( display, "WM_PROTOCOLS", False ); data->wm_delete_message = X11_XInternAtom( display, "WM_DELETE_WINDOW", False ); X11_XSetWMProtocols( display, data->window, &data->wm_delete_message, 1 ); if ( windowdata ) { XWindowAttributes attrib; Window dummy; X11_XGetWindowAttributes(display, windowdata->xwindow, &attrib); x = attrib.x + ( attrib.width - data->dialog_width ) / 2; y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ; X11_XTranslateCoordinates(display, windowdata->xwindow, RootWindow(display, data->screen), x, y, &x, &y, &dummy); } else { const SDL_VideoDevice *dev = SDL_GetVideoDevice(); if ((dev) && (dev->displays) && (dev->num_displays > 0)) { const SDL_VideoDisplay *dpy = &dev->displays[0]; const SDL_DisplayData *dpydata = (SDL_DisplayData *) dpy->driverdata; x = dpydata->x + (( dpy->current_mode.w - data->dialog_width ) / 2); y = dpydata->y + (( dpy->current_mode.h - data->dialog_height ) / 3); } else { /* oh well. This will misposition on a multi-head setup. Init first next time. */ x = ( DisplayWidth( display, data->screen ) - data->dialog_width ) / 2; y = ( DisplayHeight( display, data->screen ) - data->dialog_height ) / 3 ; } } X11_XMoveWindow( display, data->window, x, y ); sizehints = X11_XAllocSizeHints(); if ( sizehints ) { sizehints->flags = USPosition | USSize | PMaxSize | PMinSize; sizehints->x = x; sizehints->y = y; sizehints->width = data->dialog_width; sizehints->height = data->dialog_height; sizehints->min_width = sizehints->max_width = data->dialog_width; sizehints->min_height = sizehints->max_height = data->dialog_height; X11_XSetWMNormalHints( display, data->window, sizehints ); X11_XFree( sizehints ); } X11_XMapRaised( display, data->window ); #if SDL_VIDEO_DRIVER_X11_XDBE /* Initialise a back buffer for double buffering */ if (SDL_X11_HAVE_XDBE) { int xdbe_major, xdbe_minor; if (X11_XdbeQueryExtension(display, &xdbe_major, &xdbe_minor) != 0) { data->xdbe = SDL_TRUE; data->buf = X11_XdbeAllocateBackBufferName(display, data->window, XdbeUndefined); } else { data->xdbe = SDL_FALSE; } } #endif return 0; }
SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window * window) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; int screen = ((SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata)->screen; XWindowAttributes xattr; XVisualInfo v, *vinfo; int n; GLXContext context = NULL, share_context; if (_this->gl_config.share_with_current_context) { share_context = (GLXContext)SDL_GL_GetCurrentContext(); } else { share_context = NULL; } /* We do this to create a clean separation between X and GLX errors. */ X11_XSync(display, False); errorHandlerOperation = "create GL context"; errorBase = _this->gl_data->errorBase; errorCode = Success; handler = X11_XSetErrorHandler(X11_GL_ErrorHandler); X11_XGetWindowAttributes(display, data->xwindow, &xattr); v.screen = screen; v.visualid = X11_XVisualIDFromVisual(xattr.visual); vinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n); if (vinfo) { if (_this->gl_config.major_version < 3 && _this->gl_config.profile_mask == 0 && _this->gl_config.flags == 0) { /* Create legacy context */ context = _this->gl_data->glXCreateContext(display, vinfo, share_context, True); } else { /* max 10 attributes plus terminator */ int attribs[11] = { GLX_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, GLX_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, 0 }; int iattr = 4; /* SDL profile bits match GLX profile bits */ if( _this->gl_config.profile_mask != 0 ) { attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB; attribs[iattr++] = _this->gl_config.profile_mask; } /* SDL flags match GLX flags */ if( _this->gl_config.flags != 0 ) { attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB; attribs[iattr++] = _this->gl_config.flags; } /* only set if glx extension is available */ if( _this->gl_data->HAS_GLX_ARB_context_flush_control ) { attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB; attribs[iattr++] = _this->gl_config.release_behavior ? GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB : GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB; } attribs[iattr++] = 0; /* Get a pointer to the context creation function for GL 3.0 */ if (!_this->gl_data->glXCreateContextAttribsARB) { SDL_SetError("OpenGL 3.0 and later are not supported by this system"); } else { int glxAttribs[64]; /* Create a GL 3.x context */ GLXFBConfig *framebuffer_config = NULL; int fbcount = 0; X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE); if (!_this->gl_data->glXChooseFBConfig || !(framebuffer_config = _this->gl_data->glXChooseFBConfig(display, DefaultScreen(display), glxAttribs, &fbcount))) { SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable"); } else { context = _this->gl_data->glXCreateContextAttribsARB(display, framebuffer_config[0], share_context, True, attribs); X11_XFree(framebuffer_config); } } } X11_XFree(vinfo); } X11_XSync(display, False); X11_XSetErrorHandler(handler); if (!context) { if (errorCode == Success) { SDL_SetError("Could not create GL context"); } return NULL; } if (X11_GL_MakeCurrent(_this, window, context) < 0) { X11_GL_DeleteContext(_this, context); return NULL; } return context; }
/* Create and set up our X11 dialog box indow. */ static int X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data ) { int x, y; XSizeHints *sizehints; XSetWindowAttributes wnd_attr; Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG; Display *display = data->display; SDL_WindowData *windowdata = NULL; const SDL_MessageBoxData *messageboxdata = data->messageboxdata; if ( messageboxdata->window ) { SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(messageboxdata->window)->driverdata; windowdata = (SDL_WindowData *)messageboxdata->window->driverdata; data->screen = displaydata->screen; } else { data->screen = DefaultScreen( display ); } data->event_mask = ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | FocusChangeMask | PointerMotionMask; wnd_attr.event_mask = data->event_mask; data->window = X11_XCreateWindow( display, RootWindow(display, data->screen), 0, 0, data->dialog_width, data->dialog_height, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask, &wnd_attr ); if ( data->window == None ) { return SDL_SetError("Couldn't create X window"); } if ( windowdata ) { /* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */ X11_XSetTransientForHint( display, data->window, windowdata->xwindow ); } X11_XStoreName( display, data->window, messageboxdata->title ); /* Let the window manager know this is a dialog box */ _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); _NET_WM_WINDOW_TYPE_DIALOG = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False); X11_XChangeProperty(display, data->window, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&_NET_WM_WINDOW_TYPE_DIALOG, 1); /* Allow the window to be deleted by the window manager */ data->wm_protocols = X11_XInternAtom( display, "WM_PROTOCOLS", False ); data->wm_delete_message = X11_XInternAtom( display, "WM_DELETE_WINDOW", False ); X11_XSetWMProtocols( display, data->window, &data->wm_delete_message, 1 ); if ( windowdata ) { XWindowAttributes attrib; Window dummy; X11_XGetWindowAttributes(display, windowdata->xwindow, &attrib); x = attrib.x + ( attrib.width - data->dialog_width ) / 2; y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ; X11_XTranslateCoordinates(display, windowdata->xwindow, RootWindow(display, data->screen), x, y, &x, &y, &dummy); } else { x = ( DisplayWidth( display, data->screen ) - data->dialog_width ) / 2; y = ( DisplayHeight( display, data->screen ) - data->dialog_height ) / 3 ; } X11_XMoveWindow( display, data->window, x, y ); sizehints = X11_XAllocSizeHints(); if ( sizehints ) { sizehints->flags = USPosition | USSize | PMaxSize | PMinSize; sizehints->x = x; sizehints->y = y; sizehints->width = data->dialog_width; sizehints->height = data->dialog_height; sizehints->min_width = sizehints->max_width = data->dialog_width; sizehints->min_height = sizehints->max_height = data->dialog_height; X11_XSetWMNormalHints( display, data->window, sizehints ); X11_XFree( sizehints ); } X11_XMapRaised( display, data->window ); return 0; }
SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window * window) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; int screen = ((SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata)->screen; XWindowAttributes xattr; XVisualInfo v, *vinfo; int n; GLXContext context = NULL, share_context; PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = NULL; if (_this->gl_config.share_with_current_context) { share_context = (GLXContext)SDL_GL_GetCurrentContext(); } else { share_context = NULL; } /* We do this to create a clean separation between X and GLX errors. */ X11_XSync(display, False); errorBase = _this->gl_data->errorBase; handler = X11_XSetErrorHandler(X11_GL_CreateContextErrorHandler); X11_XGetWindowAttributes(display, data->xwindow, &xattr); v.screen = screen; v.visualid = X11_XVisualIDFromVisual(xattr.visual); vinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n); if (vinfo) { if (_this->gl_config.major_version < 3 && _this->gl_config.profile_mask == 0 && _this->gl_config.flags == 0) { /* Create legacy context */ context = _this->gl_data->glXCreateContext(display, vinfo, share_context, True); } else { /* If we want a GL 3.0 context or later we need to get a temporary context to grab the new context creation function */ GLXContext temp_context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True); if (temp_context) { /* max 8 attributes plus terminator */ int attribs[9] = { GLX_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, GLX_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, 0 }; int iattr = 4; /* SDL profile bits match GLX profile bits */ if( _this->gl_config.profile_mask != 0 ) { attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB; attribs[iattr++] = _this->gl_config.profile_mask; } /* SDL flags match GLX flags */ if( _this->gl_config.flags != 0 ) { attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB; attribs[iattr++] = _this->gl_config.flags; } attribs[iattr++] = 0; /* Get a pointer to the context creation function for GL 3.0 */ glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data-> glXGetProcAddress((GLubyte *) "glXCreateContextAttribsARB"); if (!glXCreateContextAttribs) { SDL_SetError("GL 3.x is not supported"); context = temp_context; } else { int glxAttribs[64]; /* Create a GL 3.x context */ GLXFBConfig *framebuffer_config = NULL; int fbcount = 0; GLXFBConfig *(*glXChooseFBConfig) (Display * disp, int screen, const int *attrib_list, int *nelements); glXChooseFBConfig = (GLXFBConfig * (*)(Display *, int, const int *, int *)) _this->gl_data-> glXGetProcAddress((GLubyte *) "glXChooseFBConfig"); X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE); if (!glXChooseFBConfig || !(framebuffer_config = glXChooseFBConfig(display, DefaultScreen(display), glxAttribs, &fbcount))) { SDL_SetError ("No good framebuffers found. GL 3.x disabled"); context = temp_context; } else { context = glXCreateContextAttribs(display, framebuffer_config[0], share_context, True, attribs); _this->gl_data->glXDestroyContext(display, temp_context); } } } } X11_XFree(vinfo); } X11_XSync(display, False); X11_XSetErrorHandler(handler); if (!context) { SDL_SetError("Could not create GL context"); return NULL; } if (X11_GL_MakeCurrent(_this, window, context) < 0) { X11_GL_DeleteContext(_this, context); return NULL; } return context; }