Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
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;
    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;
}
Пример #5
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;
}