src/video/x11/SDL_x11video.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 08 Jan 2012 02:23:37 -0500
changeset 6188 e82023802002
parent 6167 c071e1372341
child 6311 4e5e46f43438
permissions -rwxr-xr-x
Fixed bug 1242 - PATCH: Improve support for OpenGL ES under X11

Scott Percival 2011-07-03 06:41:51 PDT

This submission is aimed at making life easier for OpenGL ES capable devices
running a X11 stack (e.g. Maemo, Meego, TrimSlice, other ARM SoC boards not
running Android). SDL's Pandora support already has the neccesary GLES-to-X11
glue code, however it's all ghetto'd off in Makefile.pandora and not very
flexible.

The patch:
- adds an awesome --enable-video-opengles option to configure
- re-modifies the opengles and opengles2 SDL_renderers to use function pointers
- no idea why this was removed?
- for SDL_Renderers, links in libGLESv1_CM, libGLES_CM (for PowerVR fans) or
libGLESv2 at runtime
- links in libEGL.so at runtime - the old code made an assumption that
eglFunctions could be pulled from the active GLES library, PowerVR for one
doesn't let you do that with their libGLESv2
- allows you to pick which of GLES v1 or v2 to load via
SDL_GL_CONTEXT_MAJOR_VERSION

So far I've tested this on a Nokia N900 (OMAP 3430/SGX 530 running Maemo 5) and
a Toshiba AC100 (Tegra 2 running Ubuntu 10.10). I haven't tested it on... well,
everything that isn't those two, such as a Pandora, iOS or Android device. The
Pandora specific code should be kept intact (fingers crossed), and nothing
painfully drastic has been added to the SDL_renderers. The library loading
sequence in SDL_x11opengles has been updated to accomodate both NVIDIA's
propensity to let developers get away with murder and PowerVR's alternative of
punishing every missed step.

The test apps work okay with GLES or GLES2 as the renderer. For some reason
alpha blending doesn't seem to work on the Tegra 2; last week NVIDIA pushed out
a new set of X11 GLES drivers, so I'll try and investigate once I upgrade
those. Also, this patch adds things to configure.in, include/SDL_config.h.in
and test/configure.in. I didn't know what the policy was re. committing
generated spaghetti from autotools, so ./autogen.sh has to be run again. Sorry.

I think that's about everything, let me know if there's anything I've
overlooked.
slouken@1950
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@1950
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@1950
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@1950
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@1950
    20
*/
slouken@1950
    21
#include "SDL_config.h"
slouken@1950
    22
slouken@5481
    23
#if SDL_VIDEO_DRIVER_X11
slouken@5481
    24
slouken@4508
    25
#include <unistd.h> /* For getpid() and readlink() */
slouken@4508
    26
slouken@1950
    27
#include "SDL_video.h"
slouken@1950
    28
#include "SDL_mouse.h"
slouken@1950
    29
#include "../SDL_sysvideo.h"
slouken@1950
    30
#include "../SDL_pixels_c.h"
slouken@1950
    31
slouken@1950
    32
#include "SDL_x11video.h"
slouken@5182
    33
#include "SDL_x11framebuffer.h"
eligottlieb@4782
    34
#include "SDL_x11shape.h"
slouken@4923
    35
#include "SDL_x11touch.h" 
slouken@2710
    36
slouken@6188
    37
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@3218
    38
#include "SDL_x11opengles.h"
slouken@3218
    39
#endif
slouken@1950
    40
slouken@1950
    41
/* Initialization/Query functions */
slouken@1950
    42
static int X11_VideoInit(_THIS);
slouken@1950
    43
static void X11_VideoQuit(_THIS);
slouken@1950
    44
slouken@1951
    45
/* Find out what class name we should use */
slouken@1951
    46
static char *
slouken@1951
    47
get_classname()
slouken@1951
    48
{
slouken@1951
    49
    char *spot;
slouken@1951
    50
#if defined(__LINUX__) || defined(__FREEBSD__)
slouken@1951
    51
    char procfile[1024];
slouken@1951
    52
    char linkfile[1024];
slouken@1951
    53
    int linksize;
slouken@1951
    54
#endif
slouken@1951
    55
slouken@1951
    56
    /* First allow environment variable override */
slouken@1951
    57
    spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS");
slouken@1951
    58
    if (spot) {
slouken@1951
    59
        return SDL_strdup(spot);
slouken@1951
    60
    }
slouken@1951
    61
slouken@1951
    62
    /* Next look at the application's executable name */
slouken@1951
    63
#if defined(__LINUX__) || defined(__FREEBSD__)
slouken@1951
    64
#if defined(__LINUX__)
slouken@1951
    65
    SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid());
slouken@1951
    66
#elif defined(__FREEBSD__)
slouken@1951
    67
    SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file",
slouken@1951
    68
                 getpid());
slouken@1951
    69
#else
slouken@1951
    70
#error Where can we find the executable name?
slouken@1951
    71
#endif
slouken@1951
    72
    linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
slouken@1951
    73
    if (linksize > 0) {
slouken@1951
    74
        linkfile[linksize] = '\0';
slouken@1951
    75
        spot = SDL_strrchr(linkfile, '/');
slouken@1951
    76
        if (spot) {
slouken@1951
    77
            return SDL_strdup(spot + 1);
slouken@1951
    78
        } else {
slouken@1951
    79
            return SDL_strdup(linkfile);
slouken@1951
    80
        }
slouken@1951
    81
    }
slouken@1951
    82
#endif /* __LINUX__ || __FREEBSD__ */
slouken@1951
    83
slouken@1951
    84
    /* Finally use the default we've used forever */
slouken@1951
    85
    return SDL_strdup("SDL_App");
slouken@1951
    86
}
slouken@1951
    87
slouken@1950
    88
/* X11 driver bootstrap functions */
slouken@1950
    89
slouken@1950
    90
static int
slouken@1950
    91
X11_Available(void)
slouken@1950
    92
{
slouken@1950
    93
    Display *display = NULL;
slouken@1950
    94
    if (SDL_X11_LoadSymbols()) {
slouken@1950
    95
        display = XOpenDisplay(NULL);
slouken@1950
    96
        if (display != NULL) {
slouken@1950
    97
            XCloseDisplay(display);
slouken@1950
    98
        }
slouken@1950
    99
        SDL_X11_UnloadSymbols();
slouken@1950
   100
    }
slouken@1950
   101
    return (display != NULL);
slouken@1950
   102
}
slouken@1950
   103
slouken@1950
   104
static void
slouken@1950
   105
X11_DeleteDevice(SDL_VideoDevice * device)
slouken@1950
   106
{
slouken@1950
   107
    SDL_VideoData *data = (SDL_VideoData *) device->driverdata;
slouken@1950
   108
    if (data->display) {
slouken@1950
   109
        XCloseDisplay(data->display);
slouken@1950
   110
    }
bob@2324
   111
    SDL_free(data->windowlist);
slouken@1950
   112
    SDL_free(device->driverdata);
slouken@6188
   113
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@3218
   114
    SDL_free(device->gles_data);
slouken@3218
   115
#endif
slouken@1950
   116
    SDL_free(device);
slouken@1950
   117
slouken@1950
   118
    SDL_X11_UnloadSymbols();
slouken@1950
   119
}
slouken@1950
   120
slouken@1950
   121
static SDL_VideoDevice *
slouken@1950
   122
X11_CreateDevice(int devindex)
slouken@1950
   123
{
slouken@1950
   124
    SDL_VideoDevice *device;
slouken@1950
   125
    SDL_VideoData *data;
slouken@1950
   126
    const char *display = NULL; /* Use the DISPLAY environment variable */
slouken@1950
   127
slouken@1950
   128
    if (!SDL_X11_LoadSymbols()) {
slouken@1950
   129
        return NULL;
slouken@1950
   130
    }
slouken@1950
   131
slouken@1950
   132
    /* Initialize all variables that we clean on shutdown */
slouken@1950
   133
    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
bob@2323
   134
    if (!device) {
bob@2323
   135
        SDL_OutOfMemory();
bob@2323
   136
        return NULL;
slouken@1950
   137
    }
bob@2323
   138
    data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
bob@2323
   139
    if (!data) {
slouken@1950
   140
        SDL_OutOfMemory();
bob@2323
   141
        SDL_free(device);
slouken@1950
   142
        return NULL;
slouken@1950
   143
    }
slouken@1950
   144
    device->driverdata = data;
slouken@1950
   145
slouken@6188
   146
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@3218
   147
    device->gles_data = (struct SDL_PrivateGLESData *) SDL_calloc(1, sizeof(SDL_PrivateGLESData));
slouken@3218
   148
    if (!device->gles_data) {
slouken@3218
   149
        SDL_OutOfMemory();
slouken@3218
   150
        return NULL;
slouken@3218
   151
    }
slouken@3218
   152
#endif
slouken@3218
   153
slouken@1950
   154
    /* FIXME: Do we need this?
slouken@1950
   155
       if ( (SDL_strncmp(XDisplayName(display), ":", 1) == 0) ||
slouken@1950
   156
       (SDL_strncmp(XDisplayName(display), "unix:", 5) == 0) ) {
slouken@1950
   157
       local_X11 = 1;
slouken@1950
   158
       } else {
slouken@1950
   159
       local_X11 = 0;
slouken@1950
   160
       }
slouken@1950
   161
     */
slouken@1950
   162
    data->display = XOpenDisplay(display);
slouken@1950
   163
#if defined(__osf__) && defined(SDL_VIDEO_DRIVER_X11_DYNAMIC)
slouken@1950
   164
    /* On Tru64 if linking without -lX11, it fails and you get following message.
slouken@1950
   165
     * Xlib: connection to ":0.0" refused by server
slouken@1950
   166
     * Xlib: XDM authorization key matches an existing client!
slouken@1950
   167
     *
slouken@1950
   168
     * It succeeds if retrying 1 second later
slouken@1950
   169
     * or if running xhost +localhost on shell.
slouken@1950
   170
     */
slouken@1950
   171
    if (data->display == NULL) {
slouken@1950
   172
        SDL_Delay(1000);
slouken@1950
   173
        data->display = XOpenDisplay(display);
slouken@1950
   174
    }
slouken@1950
   175
#endif
slouken@1950
   176
    if (data->display == NULL) {
slouken@1950
   177
        SDL_free(device);
slouken@1950
   178
        SDL_SetError("Couldn't open X11 display");
slouken@1950
   179
        return NULL;
slouken@1950
   180
    }
slouken@1950
   181
#ifdef X11_DEBUG
slouken@1950
   182
    XSynchronize(data->display, True);
slouken@1950
   183
#endif
slouken@1950
   184
slouken@1950
   185
    /* Set the function pointers */
slouken@1950
   186
    device->VideoInit = X11_VideoInit;
slouken@1950
   187
    device->VideoQuit = X11_VideoQuit;
slouken@1950
   188
    device->GetDisplayModes = X11_GetDisplayModes;
slouken@1950
   189
    device->SetDisplayMode = X11_SetDisplayMode;
slouken@3025
   190
    device->SuspendScreenSaver = X11_SuspendScreenSaver;
slouken@1951
   191
    device->PumpEvents = X11_PumpEvents;
slouken@1950
   192
slouken@1950
   193
    device->CreateWindow = X11_CreateWindow;
slouken@1950
   194
    device->CreateWindowFrom = X11_CreateWindowFrom;
slouken@1950
   195
    device->SetWindowTitle = X11_SetWindowTitle;
slouken@2967
   196
    device->SetWindowIcon = X11_SetWindowIcon;
slouken@1950
   197
    device->SetWindowPosition = X11_SetWindowPosition;
slouken@1950
   198
    device->SetWindowSize = X11_SetWindowSize;
slouken@1950
   199
    device->ShowWindow = X11_ShowWindow;
slouken@1950
   200
    device->HideWindow = X11_HideWindow;
slouken@1950
   201
    device->RaiseWindow = X11_RaiseWindow;
slouken@1950
   202
    device->MaximizeWindow = X11_MaximizeWindow;
slouken@1950
   203
    device->MinimizeWindow = X11_MinimizeWindow;
slouken@1950
   204
    device->RestoreWindow = X11_RestoreWindow;
slouken@5302
   205
    device->SetWindowFullscreen = X11_SetWindowFullscreen;
slouken@5466
   206
    device->SetWindowGammaRamp = X11_SetWindowGammaRamp;
slouken@1950
   207
    device->SetWindowGrab = X11_SetWindowGrab;
slouken@1950
   208
    device->DestroyWindow = X11_DestroyWindow;
slouken@5182
   209
    device->CreateWindowFramebuffer = X11_CreateWindowFramebuffer;
slouken@5182
   210
    device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer;
slouken@5182
   211
    device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer;
slouken@1950
   212
    device->GetWindowWMInfo = X11_GetWindowWMInfo;
slouken@5182
   213
eligottlieb@4782
   214
    device->shape_driver.CreateShaper = X11_CreateShaper;
eligottlieb@4782
   215
    device->shape_driver.SetWindowShape = X11_SetWindowShape;
eligottlieb@4782
   216
    device->shape_driver.ResizeWindowShape = X11_ResizeWindowShape;
slouken@5182
   217
slouken@5088
   218
#if SDL_VIDEO_OPENGL_GLX
slouken@1950
   219
    device->GL_LoadLibrary = X11_GL_LoadLibrary;
slouken@1950
   220
    device->GL_GetProcAddress = X11_GL_GetProcAddress;
slouken@3057
   221
    device->GL_UnloadLibrary = X11_GL_UnloadLibrary;
slouken@1950
   222
    device->GL_CreateContext = X11_GL_CreateContext;
slouken@1950
   223
    device->GL_MakeCurrent = X11_GL_MakeCurrent;
slouken@1950
   224
    device->GL_SetSwapInterval = X11_GL_SetSwapInterval;
slouken@1950
   225
    device->GL_GetSwapInterval = X11_GL_GetSwapInterval;
slouken@1950
   226
    device->GL_SwapWindow = X11_GL_SwapWindow;
slouken@1950
   227
    device->GL_DeleteContext = X11_GL_DeleteContext;
slouken@1950
   228
#endif
slouken@6188
   229
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@3218
   230
    device->GL_LoadLibrary = X11_GLES_LoadLibrary;
slouken@3218
   231
    device->GL_GetProcAddress = X11_GLES_GetProcAddress;
slouken@3218
   232
    device->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
slouken@3218
   233
    device->GL_CreateContext = X11_GLES_CreateContext;
slouken@3218
   234
    device->GL_MakeCurrent = X11_GLES_MakeCurrent;
slouken@3218
   235
    device->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
slouken@3218
   236
    device->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
slouken@3218
   237
    device->GL_SwapWindow = X11_GLES_SwapWindow;
slouken@3218
   238
    device->GL_DeleteContext = X11_GLES_DeleteContext;
slouken@3218
   239
#endif
slouken@1950
   240
slouken@4508
   241
    device->SetClipboardText = X11_SetClipboardText;
slouken@4508
   242
    device->GetClipboardText = X11_GetClipboardText;
slouken@4508
   243
    device->HasClipboardText = X11_HasClipboardText;
slouken@4508
   244
slouken@1950
   245
    device->free = X11_DeleteDevice;
slouken@1950
   246
slouken@1950
   247
    return device;
slouken@1950
   248
}
slouken@1950
   249
slouken@1950
   250
VideoBootStrap X11_bootstrap = {
slouken@1950
   251
    "x11", "SDL X11 video driver",
slouken@1950
   252
    X11_Available, X11_CreateDevice
slouken@1950
   253
};
slouken@1950
   254
slouken@4559
   255
static int (*handler) (Display *, XErrorEvent *) = NULL;
slouken@4559
   256
static int
slouken@4559
   257
X11_CheckWindowManagerErrorHandler(Display * d, XErrorEvent * e)
slouken@4559
   258
{
slouken@4559
   259
    if (e->error_code == BadWindow) {
slouken@4559
   260
        return (0);
slouken@4559
   261
    } else {
slouken@4559
   262
        return (handler(d, e));
slouken@4559
   263
    }
slouken@4559
   264
}
slouken@4508
   265
slouken@4518
   266
static void
slouken@4518
   267
X11_CheckWindowManager(_THIS)
slouken@4518
   268
{
slouken@4518
   269
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@4518
   270
    Display *display = data->display;
slouken@4518
   271
    Atom _NET_SUPPORTING_WM_CHECK;
slouken@4518
   272
    int status, real_format;
slouken@4518
   273
    Atom real_type;
slouken@4518
   274
    unsigned long items_read, items_left;
slouken@4518
   275
    unsigned char *propdata;
slouken@4518
   276
    Window wm_window = 0;
slouken@4518
   277
#ifdef DEBUG_WINDOW_MANAGER
slouken@4518
   278
    char *wm_name;
slouken@4518
   279
#endif
slouken@4518
   280
slouken@4559
   281
    /* Set up a handler to gracefully catch errors */
slouken@4559
   282
    XSync(display, False);
slouken@4559
   283
    handler = XSetErrorHandler(X11_CheckWindowManagerErrorHandler);
slouken@4559
   284
slouken@4518
   285
    _NET_SUPPORTING_WM_CHECK = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
slouken@4518
   286
    status = XGetWindowProperty(display, DefaultRootWindow(display), _NET_SUPPORTING_WM_CHECK, 0L, 1L, False, XA_WINDOW, &real_type, &real_format, &items_read, &items_left, &propdata);
slouken@4518
   287
    if (status == Success && items_read) {
slouken@4518
   288
        wm_window = ((Window*)propdata)[0];
slouken@4518
   289
    }
slouken@4559
   290
    if (propdata) {
slouken@4559
   291
        XFree(propdata);
slouken@4559
   292
    }
slouken@4559
   293
slouken@4559
   294
    if (wm_window) {
slouken@4559
   295
        status = XGetWindowProperty(display, wm_window, _NET_SUPPORTING_WM_CHECK, 0L, 1L, False, XA_WINDOW, &real_type, &real_format, &items_read, &items_left, &propdata);
slouken@4559
   296
        if (status != Success || !items_read || wm_window != ((Window*)propdata)[0]) {
slouken@4559
   297
            wm_window = None;
slouken@4559
   298
        }
slouken@4559
   299
        if (propdata) {
slouken@4559
   300
            XFree(propdata);
slouken@4559
   301
        }
slouken@4559
   302
    }
slouken@4559
   303
slouken@4559
   304
    /* Reset the error handler, we're done checking */
slouken@4559
   305
    XSync(display, False);
slouken@4559
   306
    XSetErrorHandler(handler);
slouken@4518
   307
slouken@4518
   308
    if (!wm_window) {
slouken@4518
   309
#ifdef DEBUG_WINDOW_MANAGER
slouken@4518
   310
        printf("Couldn't get _NET_SUPPORTING_WM_CHECK property\n");
slouken@4518
   311
#endif
slouken@4518
   312
        return;
slouken@4518
   313
    }
slouken@4518
   314
    data->net_wm = SDL_TRUE;
slouken@4518
   315
slouken@4518
   316
#ifdef DEBUG_WINDOW_MANAGER
slouken@4518
   317
    wm_name = X11_GetWindowTitle(_this, wm_window);
slouken@4518
   318
    printf("Window manager: %s\n", wm_name);
slouken@4518
   319
    SDL_free(wm_name);
slouken@4518
   320
#endif
slouken@4518
   321
}
slouken@1950
   322
slouken@1950
   323
int
slouken@1950
   324
X11_VideoInit(_THIS)
slouken@1950
   325
{
slouken@1951
   326
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@1951
   327
slouken@1951
   328
    /* Get the window class name, usually the name of the application */
slouken@1951
   329
    data->classname = get_classname();
slouken@1951
   330
mail@6167
   331
    /* Get the process PID to be associated to the window */
mail@6167
   332
    data->pid = getpid();
mail@6167
   333
slouken@1951
   334
    /* Open a connection to the X input manager */
slouken@1951
   335
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   336
    if (SDL_X11_HAVE_UTF8) {
slouken@1951
   337
        data->im =
slouken@1951
   338
            XOpenIM(data->display, NULL, data->classname, data->classname);
slouken@1951
   339
    }
slouken@1951
   340
#endif
slouken@1951
   341
slouken@1951
   342
    /* Look up some useful Atoms */
slouken@4518
   343
#define GET_ATOM(X) data->X = XInternAtom(data->display, #X, False)
slouken@4518
   344
    GET_ATOM(WM_DELETE_WINDOW);
slouken@4518
   345
    GET_ATOM(_NET_WM_STATE);
slouken@4518
   346
    GET_ATOM(_NET_WM_STATE_HIDDEN);
slouken@4518
   347
    GET_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
slouken@4518
   348
    GET_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
slouken@4518
   349
    GET_ATOM(_NET_WM_STATE_FULLSCREEN);
slouken@4518
   350
    GET_ATOM(_NET_WM_NAME);
slouken@4518
   351
    GET_ATOM(_NET_WM_ICON_NAME);
slouken@4518
   352
    GET_ATOM(_NET_WM_ICON);
slouken@4518
   353
    GET_ATOM(UTF8_STRING);
slouken@4518
   354
slouken@4518
   355
    /* Detect the window manager */
slouken@4518
   356
    X11_CheckWindowManager(_this);
slouken@1951
   357
slouken@3521
   358
    if (X11_InitModes(_this) < 0) {
slouken@3521
   359
        return -1;
slouken@3521
   360
    }
slouken@1950
   361
bob@2295
   362
    if (X11_InitKeyboard(_this) != 0) {
bob@2295
   363
        return -1;
bob@2295
   364
    }
slouken@1950
   365
    X11_InitMouse(_this);
slouken@1950
   366
jim@4645
   367
    X11_InitTouch(_this);
slouken@1950
   368
    return 0;
slouken@1950
   369
}
slouken@1950
   370
slouken@1950
   371
void
slouken@1950
   372
X11_VideoQuit(_THIS)
slouken@1950
   373
{
slouken@1951
   374
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@1951
   375
slouken@1951
   376
    if (data->classname) {
slouken@1951
   377
        SDL_free(data->classname);
slouken@1951
   378
    }
slouken@1951
   379
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   380
    if (data->im) {
slouken@1951
   381
        XCloseIM(data->im);
slouken@1951
   382
    }
slouken@1951
   383
#endif
slouken@1951
   384
slouken@1950
   385
    X11_QuitModes(_this);
slouken@1950
   386
    X11_QuitKeyboard(_this);
slouken@1950
   387
    X11_QuitMouse(_this);
jim@4645
   388
    X11_QuitTouch(_this);
slouken@1950
   389
}
slouken@1950
   390
slouken@5466
   391
SDL_bool
slouken@5466
   392
X11_UseDirectColorVisuals(void)
slouken@5466
   393
{
slouken@5466
   394
    return SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ? SDL_FALSE : SDL_TRUE;
slouken@5466
   395
}
slouken@5466
   396
slouken@5481
   397
#endif /* SDL_VIDEO_DRIVER_X11 */
slouken@5481
   398
slouken@1950
   399
/* vim: set ts=4 sw=4 expandtab: */