src/video/x11/SDL_x11window.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 08 Jan 2012 02:23:37 -0500
changeset 6188 e82023802002
parent 6167 c071e1372341
child 6275 963497e37d34
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@1951
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@1951
     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@1951
     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@1951
    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@1951
    20
*/
slouken@1951
    21
#include "SDL_config.h"
slouken@1951
    22
slouken@5481
    23
#if SDL_VIDEO_DRIVER_X11
slouken@5481
    24
slouken@1951
    25
#include "../SDL_sysvideo.h"
slouken@4465
    26
#include "../SDL_pixels_c.h"
slouken@1951
    27
#include "../../events/SDL_keyboard_c.h"
slouken@2940
    28
#include "../../events/SDL_mouse_c.h"
slouken@1951
    29
slouken@1951
    30
#include "SDL_x11video.h"
slouken@2940
    31
#include "SDL_x11mouse.h"
eligottlieb@4782
    32
#include "SDL_x11shape.h"
slouken@1951
    33
slouken@6188
    34
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@3161
    35
#include "SDL_x11opengles.h"
slouken@3161
    36
#endif
slouken@3161
    37
slouken@4465
    38
#include "SDL_timer.h"
slouken@3241
    39
#include "SDL_syswm.h"
slouken@3241
    40
slouken@3077
    41
#define _NET_WM_STATE_REMOVE    0l
slouken@3077
    42
#define _NET_WM_STATE_ADD       1l
slouken@3077
    43
#define _NET_WM_STATE_TOGGLE    2l
slouken@3077
    44
slouken@4518
    45
static SDL_bool
slouken@4522
    46
X11_IsWindowOldFullscreen(_THIS, SDL_Window * window)
slouken@4518
    47
{
slouken@4522
    48
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@4518
    49
slouken@4518
    50
    /* ICCCM2.0-compliant window managers can handle fullscreen windows */
slouken@4518
    51
    if ((window->flags & SDL_WINDOW_FULLSCREEN) && !videodata->net_wm) {
slouken@4518
    52
        return SDL_TRUE;
slouken@4518
    53
    } else {
slouken@4518
    54
        return SDL_FALSE;
slouken@4518
    55
    }
slouken@4518
    56
}
slouken@4518
    57
slouken@4522
    58
static SDL_bool
slouken@4522
    59
X11_IsWindowMapped(_THIS, SDL_Window * window)
slouken@4522
    60
{
slouken@4522
    61
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@4522
    62
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@4522
    63
    XWindowAttributes attr;
slouken@4522
    64
slouken@4522
    65
    XGetWindowAttributes(videodata->display, data->xwindow, &attr);
slouken@4522
    66
    if (attr.map_state != IsUnmapped) {
slouken@4522
    67
        return SDL_TRUE;
slouken@4522
    68
    } else {
slouken@4522
    69
        return SDL_FALSE;
slouken@4522
    70
    }
slouken@4522
    71
}
slouken@4522
    72
slouken@4522
    73
static int
slouken@4522
    74
X11_GetWMStateProperty(_THIS, SDL_Window * window, Atom atoms[3])
slouken@4522
    75
{
slouken@4522
    76
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@4522
    77
    int count = 0;
slouken@4522
    78
slouken@4522
    79
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@4522
    80
        atoms[count++] = data->_NET_WM_STATE_FULLSCREEN;
slouken@4522
    81
    }
slouken@4522
    82
    if (window->flags & SDL_WINDOW_MAXIMIZED) {
slouken@4522
    83
        atoms[count++] = data->_NET_WM_STATE_MAXIMIZED_VERT;
slouken@4522
    84
        atoms[count++] = data->_NET_WM_STATE_MAXIMIZED_HORZ;
slouken@4522
    85
    }
slouken@4522
    86
    return count;
slouken@4522
    87
}
slouken@4522
    88
slouken@1951
    89
static int
slouken@1951
    90
SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
slouken@1951
    91
{
slouken@1951
    92
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@1951
    93
    SDL_WindowData *data;
slouken@1951
    94
    int numwindows = videodata->numwindows;
bob@2324
    95
    int windowlistlength = videodata->windowlistlength;
slouken@1951
    96
    SDL_WindowData **windowlist = videodata->windowlist;
slouken@1951
    97
slouken@1951
    98
    /* Allocate the window data */
bob@2323
    99
    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
slouken@1951
   100
    if (!data) {
slouken@1951
   101
        SDL_OutOfMemory();
slouken@1951
   102
        return -1;
slouken@1951
   103
    }
slouken@3685
   104
    data->window = window;
slouken@3685
   105
    data->xwindow = w;
slouken@1951
   106
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   107
    if (SDL_X11_HAVE_UTF8) {
slouken@1951
   108
        data->ic =
slouken@1951
   109
            pXCreateIC(videodata->im, XNClientWindow, w, XNFocusWindow, w,
slouken@1951
   110
                       XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
slouken@1951
   111
                       XNResourceName, videodata->classname, XNResourceClass,
slouken@1951
   112
                       videodata->classname, NULL);
slouken@1951
   113
    }
slouken@1951
   114
#endif
slouken@1951
   115
    data->created = created;
slouken@1951
   116
    data->videodata = videodata;
slouken@1951
   117
bob@2323
   118
    /* Associate the data with the window */
bob@2324
   119
bob@2324
   120
    if (numwindows < windowlistlength) {
bob@2324
   121
        windowlist[numwindows] = data;
bob@2324
   122
        videodata->numwindows++;
bob@2324
   123
    } else {
bob@2324
   124
        windowlist =
bob@2324
   125
            (SDL_WindowData **) SDL_realloc(windowlist,
bob@2324
   126
                                            (numwindows +
bob@2324
   127
                                             1) * sizeof(*windowlist));
bob@2324
   128
        if (!windowlist) {
bob@2324
   129
            SDL_OutOfMemory();
bob@2324
   130
            SDL_free(data);
bob@2324
   131
            return -1;
bob@2323
   132
        }
bob@2324
   133
        windowlist[numwindows] = data;
bob@2324
   134
        videodata->numwindows++;
bob@2324
   135
        videodata->windowlistlength++;
bob@2324
   136
        videodata->windowlist = windowlist;
bob@2323
   137
    }
bob@2323
   138
slouken@1951
   139
    /* Fill in the SDL window with the window data */
slouken@1951
   140
    {
slouken@1951
   141
        XWindowAttributes attrib;
slouken@1951
   142
slouken@1951
   143
        XGetWindowAttributes(data->videodata->display, w, &attrib);
slouken@1951
   144
        window->x = attrib.x;
slouken@1951
   145
        window->y = attrib.y;
slouken@1951
   146
        window->w = attrib.width;
slouken@1951
   147
        window->h = attrib.height;
slouken@1951
   148
        if (attrib.map_state != IsUnmapped) {
slouken@1951
   149
            window->flags |= SDL_WINDOW_SHOWN;
slouken@1951
   150
        } else {
slouken@1951
   151
            window->flags &= ~SDL_WINDOW_SHOWN;
slouken@1951
   152
        }
slouken@5182
   153
        data->visual = attrib.visual;
slouken@5466
   154
        data->colormap = attrib.colormap;
slouken@1951
   155
    }
slouken@3077
   156
slouken@3077
   157
    {
slouken@4518
   158
        Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
slouken@4518
   159
        Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
slouken@4518
   160
        Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
slouken@4518
   161
        Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
slouken@3077
   162
        Atom actualType;
slouken@3077
   163
        int actualFormat;
slouken@3077
   164
        unsigned long i, numItems, bytesAfter;
slouken@3077
   165
        unsigned char *propertyValue = NULL;
slouken@3077
   166
        long maxLength = 1024;
slouken@3077
   167
slouken@3077
   168
        if (XGetWindowProperty(data->videodata->display, w, _NET_WM_STATE,
slouken@3078
   169
                               0l, maxLength, False, XA_ATOM, &actualType,
slouken@3078
   170
                               &actualFormat, &numItems, &bytesAfter,
slouken@3078
   171
                               &propertyValue) == Success) {
slouken@3078
   172
            Atom *atoms = (Atom *) propertyValue;
slouken@3077
   173
            int maximized = 0;
slouken@4518
   174
            int fullscreen = 0;
slouken@3077
   175
slouken@3077
   176
            for (i = 0; i < numItems; ++i) {
slouken@3077
   177
                if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) {
slouken@3077
   178
                    maximized |= 1;
slouken@3077
   179
                } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
slouken@3077
   180
                    maximized |= 2;
slouken@4518
   181
                } else if ( atoms[i] == _NET_WM_STATE_FULLSCREEN) {
slouken@4518
   182
                    fullscreen = 1;
slouken@3077
   183
                }
slouken@3077
   184
            }
slouken@3077
   185
            if (maximized == 3) {
slouken@3077
   186
                window->flags |= SDL_WINDOW_MAXIMIZED;
slouken@4518
   187
            }  else if (fullscreen == 1) {
slouken@4518
   188
                window->flags |= SDL_WINDOW_FULLSCREEN;
slouken@3077
   189
            }
slouken@3077
   190
            XFree(propertyValue);
slouken@3077
   191
        }
slouken@3077
   192
    }
slouken@3077
   193
icculus@6024
   194
    {
icculus@6024
   195
        Window FocalWindow;
icculus@6024
   196
        int RevertTo=0;
icculus@6024
   197
        XGetInputFocus(data->videodata->display, &FocalWindow, &RevertTo);
icculus@6024
   198
        if (FocalWindow==w)
icculus@6024
   199
        {
icculus@6024
   200
            window->flags |= SDL_WINDOW_INPUT_FOCUS;
icculus@6024
   201
            SDL_SetKeyboardFocus(data->window);
icculus@6024
   202
        }
icculus@6024
   203
icculus@6024
   204
        if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
icculus@6024
   205
            /* Tell x11 to clip mouse */
icculus@6024
   206
        }
icculus@6024
   207
    }
icculus@6024
   208
slouken@1951
   209
    /* FIXME: How can I tell?
slouken@1951
   210
       {
slouken@1951
   211
       DWORD style = GetWindowLong(hwnd, GWL_STYLE);
slouken@1951
   212
       if (style & WS_VISIBLE) {
slouken@1951
   213
       if (style & (WS_BORDER | WS_THICKFRAME)) {
slouken@1951
   214
       window->flags &= ~SDL_WINDOW_BORDERLESS;
slouken@1951
   215
       } else {
slouken@1951
   216
       window->flags |= SDL_WINDOW_BORDERLESS;
slouken@1951
   217
       }
slouken@1951
   218
       if (style & WS_THICKFRAME) {
slouken@1951
   219
       window->flags |= SDL_WINDOW_RESIZABLE;
slouken@1951
   220
       } else {
slouken@1951
   221
       window->flags &= ~SDL_WINDOW_RESIZABLE;
slouken@1951
   222
       }
slouken@1951
   223
       if (style & WS_MINIMIZE) {
slouken@1951
   224
       window->flags |= SDL_WINDOW_MINIMIZED;
slouken@1951
   225
       } else {
slouken@1951
   226
       window->flags &= ~SDL_WINDOW_MINIMIZED;
slouken@1951
   227
       }
slouken@1951
   228
       }
slouken@1951
   229
       if (GetFocus() == hwnd) {
slouken@1951
   230
       int index = data->videodata->keyboard;
slouken@1951
   231
       window->flags |= SDL_WINDOW_INPUT_FOCUS;
slouken@3685
   232
       SDL_SetKeyboardFocus(index, data->window);
slouken@1951
   233
slouken@1951
   234
       if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@1951
   235
       RECT rect;
slouken@1951
   236
       GetClientRect(hwnd, &rect);
slouken@1951
   237
       ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1951
   238
       ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1951
   239
       ClipCursor(&rect);
slouken@1951
   240
       }
slouken@1951
   241
       }
slouken@1951
   242
     */
slouken@1951
   243
slouken@1951
   244
    /* All done! */
slouken@1951
   245
    window->driverdata = data;
slouken@1951
   246
    return 0;
slouken@1951
   247
}
slouken@1951
   248
slouken@1951
   249
int
slouken@1951
   250
X11_CreateWindow(_THIS, SDL_Window * window)
slouken@1951
   251
{
slouken@1951
   252
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@1951
   253
    SDL_DisplayData *displaydata =
slouken@5246
   254
        (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
slouken@4521
   255
    Display *display = data->display;
slouken@4521
   256
    int screen = displaydata->screen;
slouken@1951
   257
    Visual *visual;
slouken@1951
   258
    int depth;
slouken@1951
   259
    XSetWindowAttributes xattr;
slouken@1951
   260
    Window w;
mail@6167
   261
    XSizeHints sizehints;
mail@6167
   262
    XWMHints wmhints;
mail@6167
   263
    XClassHint classhints;
slouken@4521
   264
    Atom _NET_WM_WINDOW_TYPE;
slouken@4521
   265
    Atom _NET_WM_WINDOW_TYPE_NORMAL;
mail@6167
   266
    Atom _NET_WM_PID;
slouken@4522
   267
    int wmstate_count;
slouken@4522
   268
    Atom wmstate_atoms[3];
icculus@6045
   269
    Uint32 fevent = 0;
slouken@4518
   270
slouken@1951
   271
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@1951
   272
/* FIXME
slouken@1951
   273
    if ( use_xinerama ) {
slouken@1951
   274
        x = xinerama_info.x_org;
slouken@1951
   275
        y = xinerama_info.y_org;
slouken@1951
   276
    }
slouken@1951
   277
*/
slouken@1951
   278
#endif
slouken@5088
   279
#if SDL_VIDEO_OPENGL_GLX
slouken@1951
   280
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1952
   281
        XVisualInfo *vinfo;
slouken@1952
   282
slouken@4521
   283
        vinfo = X11_GL_GetVisual(_this, display, screen);
slouken@1952
   284
        if (!vinfo) {
slouken@1952
   285
            return -1;
slouken@1952
   286
        }
slouken@1952
   287
        visual = vinfo->visual;
slouken@1952
   288
        depth = vinfo->depth;
slouken@1952
   289
        XFree(vinfo);
slouken@1952
   290
    } else
slouken@1952
   291
#endif
slouken@6188
   292
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@3161
   293
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@3161
   294
        XVisualInfo *vinfo;
slouken@3161
   295
slouken@4521
   296
        vinfo = X11_GLES_GetVisual(_this, display, screen);
slouken@3161
   297
        if (!vinfo) {
slouken@3161
   298
            return -1;
slouken@3161
   299
        }
slouken@3161
   300
        visual = vinfo->visual;
slouken@3161
   301
        depth = vinfo->depth;
slouken@3161
   302
        XFree(vinfo);
slouken@3161
   303
    } else
slouken@3161
   304
#endif
slouken@1952
   305
    {
slouken@1951
   306
        visual = displaydata->visual;
slouken@1951
   307
        depth = displaydata->depth;
slouken@1951
   308
    }
slouken@1951
   309
slouken@5386
   310
    xattr.override_redirect = False;
slouken@1951
   311
    xattr.background_pixel = 0;
slouken@1951
   312
    xattr.border_pixel = 0;
slouken@5466
   313
slouken@5466
   314
    if (visual->class == DirectColor) {
slouken@5466
   315
        XColor *colorcells;
slouken@5466
   316
        int i;
slouken@5466
   317
        int ncolors;
slouken@5466
   318
        int rmax, gmax, bmax;
slouken@5466
   319
        int rmask, gmask, bmask;
slouken@5466
   320
        int rshift, gshift, bshift;
slouken@5466
   321
slouken@5466
   322
        xattr.colormap =
slouken@5466
   323
            XCreateColormap(display, RootWindow(display, screen),
slouken@5466
   324
                            visual, AllocAll);
slouken@5466
   325
slouken@5466
   326
        /* If we can't create a colormap, then we must die */
slouken@5466
   327
        if (!xattr.colormap) {
slouken@5466
   328
            SDL_SetError("Could not create writable colormap");
slouken@5466
   329
            return -1;
slouken@5466
   330
        }
slouken@5466
   331
slouken@5466
   332
        /* OK, we got a colormap, now fill it in as best as we can */
slouken@5466
   333
        colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
slouken@5466
   334
        if (!colorcells) {
slouken@5466
   335
            SDL_OutOfMemory();
slouken@5466
   336
            return -1;
slouken@5466
   337
        }
slouken@5466
   338
        ncolors = visual->map_entries;
slouken@5466
   339
        rmax = 0xffff;
slouken@5466
   340
        gmax = 0xffff;
slouken@5466
   341
        bmax = 0xffff;
slouken@5466
   342
slouken@5466
   343
        rshift = 0;
slouken@5466
   344
        rmask = visual->red_mask;
slouken@5466
   345
        while (0 == (rmask & 1)) {
slouken@5466
   346
            rshift++;
slouken@5466
   347
            rmask >>= 1;
slouken@5466
   348
        }
slouken@5466
   349
slouken@5466
   350
        gshift = 0;
slouken@5466
   351
        gmask = visual->green_mask;
slouken@5466
   352
        while (0 == (gmask & 1)) {
slouken@5466
   353
            gshift++;
slouken@5466
   354
            gmask >>= 1;
slouken@5466
   355
        }
slouken@5466
   356
slouken@5466
   357
        bshift = 0;
slouken@5466
   358
        bmask = visual->blue_mask;
slouken@5466
   359
        while (0 == (bmask & 1)) {
slouken@5466
   360
            bshift++;
slouken@5466
   361
            bmask >>= 1;
slouken@5466
   362
        }
slouken@5466
   363
slouken@5466
   364
        /* build the color table pixel values */
slouken@5466
   365
        for (i = 0; i < ncolors; i++) {
slouken@5466
   366
            Uint32 red = (rmax * i) / (ncolors - 1);
slouken@5466
   367
            Uint32 green = (gmax * i) / (ncolors - 1);
slouken@5466
   368
            Uint32 blue = (bmax * i) / (ncolors - 1);
slouken@5466
   369
slouken@5466
   370
            Uint32 rbits = (rmask * i) / (ncolors - 1);
slouken@5466
   371
            Uint32 gbits = (gmask * i) / (ncolors - 1);
slouken@5466
   372
            Uint32 bbits = (bmask * i) / (ncolors - 1);
slouken@5466
   373
slouken@5466
   374
            Uint32 pix =
slouken@5466
   375
                (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
slouken@5466
   376
slouken@5466
   377
            colorcells[i].pixel = pix;
slouken@5466
   378
slouken@5466
   379
            colorcells[i].red = red;
slouken@5466
   380
            colorcells[i].green = green;
slouken@5466
   381
            colorcells[i].blue = blue;
slouken@5466
   382
slouken@5466
   383
            colorcells[i].flags = DoRed | DoGreen | DoBlue;
slouken@5466
   384
        }
slouken@5466
   385
slouken@5466
   386
        XStoreColors(display, xattr.colormap, colorcells, ncolors);
slouken@5466
   387
slouken@5466
   388
        SDL_free(colorcells);
slouken@5466
   389
    } else {
slouken@5466
   390
        xattr.colormap =
slouken@5466
   391
            XCreateColormap(display, RootWindow(display, screen),
slouken@5466
   392
                            visual, AllocNone);
slouken@5466
   393
    }
slouken@1951
   394
slouken@5386
   395
    w = XCreateWindow(display, RootWindow(display, screen),
slouken@5386
   396
                      window->x, window->y, window->w, window->h,
slouken@5386
   397
                      0, depth, InputOutput, visual,
slouken@1951
   398
                      (CWOverrideRedirect | CWBackPixel | CWBorderPixel |
slouken@1951
   399
                       CWColormap), &xattr);
slouken@1952
   400
    if (!w) {
slouken@1952
   401
        SDL_SetError("Couldn't create window");
slouken@1952
   402
        return -1;
slouken@1952
   403
    }
slouken@6188
   404
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@6188
   405
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@6188
   406
        /* Create the GLES window surface */
slouken@6188
   407
        _this->gles_data->egl_surface =
slouken@6188
   408
            _this->gles_data->eglCreateWindowSurface(_this->gles_data->
slouken@3161
   409
                                                 egl_display,
slouken@3161
   410
                                                 _this->gles_data->egl_config,
slouken@3161
   411
                                                 (NativeWindowType) w, NULL);
slouken@3161
   412
slouken@6188
   413
        if (_this->gles_data->egl_surface == EGL_NO_SURFACE) {
slouken@6188
   414
            SDL_SetError("Could not create GLES window surface");
slouken@6188
   415
            return -1;
slouken@6188
   416
        }
slouken@3161
   417
    }
slouken@3161
   418
#endif
slouken@1951
   419
slouken@5386
   420
    if (window->flags & SDL_WINDOW_BORDERLESS) {
slouken@1951
   421
        SDL_bool set;
slouken@1951
   422
        Atom WM_HINTS;
slouken@1951
   423
slouken@1951
   424
        /* We haven't modified the window manager hints yet */
slouken@1951
   425
        set = SDL_FALSE;
slouken@1951
   426
slouken@1951
   427
        /* First try to set MWM hints */
slouken@4521
   428
        WM_HINTS = XInternAtom(display, "_MOTIF_WM_HINTS", True);
slouken@1951
   429
        if (WM_HINTS != None) {
slouken@1951
   430
            /* Hints used by Motif compliant window managers */
slouken@1951
   431
            struct
slouken@1951
   432
            {
slouken@1951
   433
                unsigned long flags;
slouken@1951
   434
                unsigned long functions;
slouken@1951
   435
                unsigned long decorations;
slouken@1951
   436
                long input_mode;
slouken@1951
   437
                unsigned long status;
slouken@1951
   438
            } MWMHints = {
slouken@1951
   439
            (1L << 1), 0, 0, 0, 0};
slouken@1951
   440
slouken@4521
   441
            XChangeProperty(display, w, WM_HINTS, WM_HINTS, 32,
slouken@1951
   442
                            PropModeReplace, (unsigned char *) &MWMHints,
slouken@4521
   443
                            sizeof(MWMHints) / 4);
slouken@1951
   444
            set = SDL_TRUE;
slouken@1951
   445
        }
slouken@1951
   446
        /* Now try to set KWM hints */
slouken@4521
   447
        WM_HINTS = XInternAtom(display, "KWM_WIN_DECORATION", True);
slouken@1951
   448
        if (WM_HINTS != None) {
slouken@1951
   449
            long KWMHints = 0;
slouken@1951
   450
slouken@4521
   451
            XChangeProperty(display, w, WM_HINTS, WM_HINTS, 32,
slouken@1951
   452
                            PropModeReplace,
slouken@1951
   453
                            (unsigned char *) &KWMHints,
slouken@4521
   454
                            sizeof(KWMHints) / 4);
slouken@1951
   455
            set = SDL_TRUE;
slouken@1951
   456
        }
slouken@1951
   457
        /* Now try to set GNOME hints */
slouken@4521
   458
        WM_HINTS = XInternAtom(display, "_WIN_HINTS", True);
slouken@1951
   459
        if (WM_HINTS != None) {
slouken@1951
   460
            long GNOMEHints = 0;
slouken@1951
   461
slouken@4521
   462
            XChangeProperty(display, w, WM_HINTS, WM_HINTS, 32,
slouken@1951
   463
                            PropModeReplace,
slouken@1951
   464
                            (unsigned char *) &GNOMEHints,
slouken@4521
   465
                            sizeof(GNOMEHints) / 4);
slouken@1951
   466
            set = SDL_TRUE;
slouken@1951
   467
        }
slouken@1951
   468
        /* Finally set the transient hints if necessary */
slouken@1951
   469
        if (!set) {
slouken@4521
   470
            XSetTransientForHint(display, w, RootWindow(display, screen));
slouken@1951
   471
        }
slouken@1951
   472
    } else {
slouken@1951
   473
        SDL_bool set;
slouken@1951
   474
        Atom WM_HINTS;
slouken@1951
   475
slouken@1951
   476
        /* We haven't modified the window manager hints yet */
slouken@1951
   477
        set = SDL_FALSE;
slouken@1951
   478
slouken@1951
   479
        /* First try to unset MWM hints */
slouken@4521
   480
        WM_HINTS = XInternAtom(display, "_MOTIF_WM_HINTS", True);
slouken@1951
   481
        if (WM_HINTS != None) {
slouken@4521
   482
            XDeleteProperty(display, w, WM_HINTS);
slouken@1951
   483
            set = SDL_TRUE;
slouken@1951
   484
        }
slouken@1951
   485
        /* Now try to unset KWM hints */
slouken@4521
   486
        WM_HINTS = XInternAtom(display, "KWM_WIN_DECORATION", True);
slouken@1951
   487
        if (WM_HINTS != None) {
slouken@4521
   488
            XDeleteProperty(display, w, WM_HINTS);
slouken@1951
   489
            set = SDL_TRUE;
slouken@1951
   490
        }
slouken@1951
   491
        /* Now try to unset GNOME hints */
slouken@4521
   492
        WM_HINTS = XInternAtom(display, "_WIN_HINTS", True);
slouken@1951
   493
        if (WM_HINTS != None) {
slouken@4521
   494
            XDeleteProperty(display, w, WM_HINTS);
slouken@1951
   495
            set = SDL_TRUE;
slouken@1951
   496
        }
slouken@1951
   497
        /* Finally unset the transient hints if necessary */
slouken@1951
   498
        if (!set) {
slouken@4555
   499
            XDeleteProperty(display, w, XA_WM_TRANSIENT_FOR);
slouken@1951
   500
        }
slouken@1951
   501
    }
slouken@1951
   502
mail@6167
   503
    /* Setup the normal size hints */
mail@6167
   504
    if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
mail@6167
   505
        sizehints.min_width = sizehints.max_width = window->w;
mail@6167
   506
        sizehints.min_height = sizehints.max_height = window->h;
mail@6167
   507
        sizehints.flags = PMaxSize | PMinSize;
slouken@1951
   508
    }
mail@6167
   509
    sizehints.x = window->x;
mail@6167
   510
    sizehints.y = window->y;
mail@6167
   511
    sizehints.flags |= USPosition;
slouken@1951
   512
mail@6167
   513
    /* Setup the input hints so we get keyboard input */
mail@6167
   514
    wmhints.input = True;
mail@6167
   515
    wmhints.flags = InputHint;
mail@6167
   516
mail@6167
   517
    /* Setup the class hints so we can get an icon (AfterStep) */
mail@6167
   518
    classhints.res_name = data->classname;
mail@6167
   519
    classhints.res_class = data->classname;
mail@6167
   520
mail@6167
   521
    /* Set the size, input and class hints, and define WM_CLIENT_MACHINE and WM_LOCALE_NAME */
mail@6167
   522
    XSetWMProperties(display, w, NULL, NULL, NULL, 0, &sizehints, &wmhints, &classhints);
mail@6167
   523
mail@6167
   524
    /* Set the PID related to the window for the given hostname, if possible */
mail@6167
   525
    if (data->pid > 0) {
mail@6167
   526
        _NET_WM_PID = XInternAtom(display, "_NET_WM_PID", False);
mail@6167
   527
        XChangeProperty(display, w, _NET_WM_PID, XA_CARDINAL, 32, PropModeReplace,
mail@6167
   528
                        (unsigned char *)&data->pid, 1);
slouken@1951
   529
    }
slouken@1951
   530
slouken@4522
   531
    /* Set the window manager state */
slouken@4522
   532
    wmstate_count = X11_GetWMStateProperty(_this, window, wmstate_atoms);
slouken@4522
   533
    if (wmstate_count > 0) {
slouken@4522
   534
        XChangeProperty(display, w, data->_NET_WM_STATE, XA_ATOM, 32,
slouken@4522
   535
                        PropModeReplace,
slouken@4522
   536
                        (unsigned char *)wmstate_atoms, wmstate_count);
slouken@4522
   537
    } else {
slouken@4522
   538
        XDeleteProperty(display, w, data->_NET_WM_STATE);
slouken@4518
   539
    }
slouken@4518
   540
slouken@4521
   541
    /* Let the window manager know we're a "normal" window */
slouken@4521
   542
    _NET_WM_WINDOW_TYPE = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
slouken@4521
   543
    _NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
slouken@4521
   544
    XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
slouken@4521
   545
                    PropModeReplace,
slouken@4521
   546
                    (unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1);
slouken@4521
   547
slouken@1951
   548
    /* Allow the window to be deleted by the window manager */
slouken@4521
   549
    XSetWMProtocols(display, w, &data->WM_DELETE_WINDOW, 1);
slouken@1951
   550
slouken@1951
   551
    if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
slouken@4521
   552
        XDestroyWindow(display, w);
slouken@1951
   553
        return -1;
slouken@1951
   554
    }
slouken@5386
   555
bob@2325
   556
#ifdef X_HAVE_UTF8_STRING
icculus@6045
   557
    if (SDL_X11_HAVE_UTF8) {
bob@2325
   558
        pXGetICValues(((SDL_WindowData *) window->driverdata)->ic,
bob@2325
   559
                      XNFilterEvents, &fevent, NULL);
kazeuser@2718
   560
    }
bob@2325
   561
#endif
bob@2325
   562
icculus@6045
   563
    XSelectInput(display, w,
icculus@6045
   564
                 (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
icculus@6045
   565
                 ExposureMask | ButtonPressMask | ButtonReleaseMask |
icculus@6045
   566
                 PointerMotionMask | KeyPressMask | KeyReleaseMask |
icculus@6045
   567
                 PropertyChangeMask | StructureNotifyMask |
icculus@6045
   568
                 KeymapStateMask | fevent));
icculus@6045
   569
slouken@5031
   570
    XFlush(display);
slouken@5031
   571
slouken@1951
   572
    return 0;
slouken@1951
   573
}
slouken@1951
   574
slouken@1951
   575
int
bob@2324
   576
X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@1951
   577
{
slouken@1951
   578
    Window w = (Window) data;
slouken@1951
   579
slouken@4518
   580
    window->title = X11_GetWindowTitle(_this, w);
slouken@1951
   581
slouken@1951
   582
    if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
slouken@1951
   583
        return -1;
slouken@1951
   584
    }
slouken@1951
   585
    return 0;
slouken@1951
   586
}
slouken@1951
   587
slouken@4518
   588
char *
slouken@4518
   589
X11_GetWindowTitle(_THIS, Window xwindow)
slouken@4518
   590
{
slouken@4518
   591
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@4518
   592
    Display *display = data->display;
slouken@4518
   593
    int status, real_format;
slouken@4518
   594
    Atom real_type;
slouken@4518
   595
    unsigned long items_read, items_left;
slouken@4518
   596
    unsigned char *propdata;
slouken@4518
   597
    char *title = NULL;
slouken@4518
   598
slouken@4518
   599
    status = XGetWindowProperty(display, xwindow, data->_NET_WM_NAME,
slouken@4518
   600
                0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
slouken@4518
   601
                &items_read, &items_left, &propdata);
icculus@6023
   602
    if (status == Success && propdata) {
slouken@4518
   603
        title = SDL_strdup(SDL_static_cast(char*, propdata));
slouken@4518
   604
        XFree(propdata);
slouken@4518
   605
    } else {
slouken@4518
   606
        status = XGetWindowProperty(display, xwindow, XA_WM_NAME,
slouken@4518
   607
                    0L, 8192L, False, XA_STRING, &real_type, &real_format,
slouken@4518
   608
                    &items_read, &items_left, &propdata);
icculus@6023
   609
        if (status == Success && propdata) {
slouken@4518
   610
            title = SDL_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1);
slouken@4518
   611
        } else {
slouken@4518
   612
            title = SDL_strdup("");
slouken@4518
   613
        }
slouken@4518
   614
    }
slouken@4518
   615
    return title;
slouken@4518
   616
}
slouken@4518
   617
slouken@1951
   618
void
slouken@1951
   619
X11_SetWindowTitle(_THIS, SDL_Window * window)
slouken@1951
   620
{
slouken@1951
   621
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   622
    Display *display = data->videodata->display;
slouken@1951
   623
    XTextProperty titleprop, iconprop;
slouken@1951
   624
    Status status;
slouken@1951
   625
    const char *title = window->title;
slouken@1951
   626
    const char *icon = NULL;
slouken@1951
   627
slouken@1951
   628
#ifdef X_HAVE_UTF8_STRING
slouken@4518
   629
    Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
slouken@4518
   630
    Atom _NET_WM_ICON_NAME = data->videodata->_NET_WM_ICON_NAME;
slouken@1951
   631
#endif
slouken@1951
   632
slouken@1951
   633
    if (title != NULL) {
slouken@2143
   634
        char *title_locale = SDL_iconv_utf8_locale(title);
slouken@2143
   635
        if (!title_locale) {
slouken@1951
   636
            SDL_OutOfMemory();
slouken@1951
   637
            return;
slouken@1951
   638
        }
slouken@2143
   639
        status = XStringListToTextProperty(&title_locale, 1, &titleprop);
slouken@2143
   640
        SDL_free(title_locale);
slouken@1951
   641
        if (status) {
slouken@3685
   642
            XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME);
slouken@1951
   643
            XFree(titleprop.value);
slouken@1951
   644
        }
slouken@1951
   645
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   646
        if (SDL_X11_HAVE_UTF8) {
slouken@1951
   647
            status =
slouken@1951
   648
                Xutf8TextListToTextProperty(display, (char **) &title, 1,
slouken@1951
   649
                                            XUTF8StringStyle, &titleprop);
slouken@1951
   650
            if (status == Success) {
slouken@3685
   651
                XSetTextProperty(display, data->xwindow, &titleprop,
slouken@1951
   652
                                 _NET_WM_NAME);
slouken@1951
   653
                XFree(titleprop.value);
slouken@1951
   654
            }
slouken@1951
   655
        }
slouken@1951
   656
#endif
slouken@1951
   657
    }
slouken@1951
   658
    if (icon != NULL) {
slouken@2143
   659
        char *icon_locale = SDL_iconv_utf8_locale(icon);
slouken@2143
   660
        if (!icon_locale) {
slouken@1951
   661
            SDL_OutOfMemory();
slouken@1951
   662
            return;
slouken@1951
   663
        }
slouken@2143
   664
        status = XStringListToTextProperty(&icon_locale, 1, &iconprop);
slouken@2143
   665
        SDL_free(icon_locale);
slouken@1951
   666
        if (status) {
slouken@3685
   667
            XSetTextProperty(display, data->xwindow, &iconprop,
slouken@1951
   668
                             XA_WM_ICON_NAME);
slouken@1951
   669
            XFree(iconprop.value);
slouken@1951
   670
        }
slouken@1951
   671
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   672
        if (SDL_X11_HAVE_UTF8) {
slouken@1951
   673
            status =
slouken@1951
   674
                Xutf8TextListToTextProperty(display, (char **) &icon, 1,
slouken@1951
   675
                                            XUTF8StringStyle, &iconprop);
slouken@1951
   676
            if (status == Success) {
slouken@3685
   677
                XSetTextProperty(display, data->xwindow, &iconprop,
slouken@1951
   678
                                 _NET_WM_ICON_NAME);
slouken@1951
   679
                XFree(iconprop.value);
slouken@1951
   680
            }
slouken@1951
   681
        }
slouken@1951
   682
#endif
slouken@1951
   683
    }
slouken@5031
   684
    XFlush(display);
slouken@1951
   685
}
slouken@1951
   686
slouken@1951
   687
void
slouken@2967
   688
X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
slouken@2967
   689
{
slouken@2967
   690
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@2967
   691
    Display *display = data->videodata->display;
slouken@4518
   692
    Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON;
slouken@2967
   693
slouken@2967
   694
    if (icon) {
slouken@2967
   695
        SDL_PixelFormat format;
slouken@2967
   696
        SDL_Surface *surface;
slouken@2967
   697
        int propsize;
slouken@4528
   698
        long *propdata;
slouken@2967
   699
slouken@2967
   700
        /* Convert the icon to ARGB for modern window managers */
slouken@5288
   701
        SDL_InitFormat(&format, SDL_PIXELFORMAT_ARGB8888);
slouken@2967
   702
        surface = SDL_ConvertSurface(icon, &format, 0);
slouken@2967
   703
        if (!surface) {
slouken@2967
   704
            return;
slouken@2967
   705
        }
slouken@2967
   706
slouken@2967
   707
        /* Set the _NET_WM_ICON property */
slouken@2990
   708
        propsize = 2 + (icon->w * icon->h);
slouken@4566
   709
        propdata = SDL_malloc(propsize * sizeof(long));
slouken@2967
   710
        if (propdata) {
slouken@4528
   711
            int x, y;
slouken@4528
   712
            Uint32 *src;
slouken@4528
   713
            long *dst;
slouken@4528
   714
slouken@2967
   715
            propdata[0] = icon->w;
slouken@2967
   716
            propdata[1] = icon->h;
slouken@4528
   717
            dst = &propdata[2];
slouken@4528
   718
            for (y = 0; y < icon->h; ++y) {
slouken@4528
   719
                src = (Uint32*)((Uint8*)surface->pixels + y * surface->pitch);
slouken@4528
   720
                for (x = 0; x < icon->w; ++x) {
slouken@4528
   721
                    *dst++ = *src++;
slouken@4528
   722
                }
slouken@4528
   723
            }
slouken@3685
   724
            XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL,
slouken@2990
   725
                            32, PropModeReplace, (unsigned char *) propdata,
slouken@2990
   726
                            propsize);
slouken@2967
   727
        }
slouken@2967
   728
        SDL_FreeSurface(surface);
slouken@2967
   729
    } else {
slouken@3685
   730
        XDeleteProperty(display, data->xwindow, _NET_WM_ICON);
slouken@2967
   731
    }
slouken@5031
   732
    XFlush(display);
slouken@2967
   733
}
slouken@2967
   734
slouken@2967
   735
void
slouken@1951
   736
X11_SetWindowPosition(_THIS, SDL_Window * window)
slouken@1951
   737
{
slouken@1951
   738
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   739
    Display *display = data->videodata->display;
slouken@1951
   740
slouken@5478
   741
    XMoveWindow(display, data->xwindow, window->x, window->y);
slouken@5031
   742
    XFlush(display);
slouken@1951
   743
}
slouken@1951
   744
slouken@1951
   745
void
slouken@1951
   746
X11_SetWindowSize(_THIS, SDL_Window * window)
slouken@1951
   747
{
slouken@1951
   748
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   749
    Display *display = data->videodata->display;
slouken@1951
   750
slouken@4937
   751
    if (SDL_IsShapedWindow(window))
eligottlieb@4782
   752
        X11_ResizeWindowShape(window);
slouken@5531
   753
    if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
slouken@5531
   754
         /* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the XResizeWindow, thus
slouken@5531
   755
            we must set the size hints to adjust the window size.*/
slouken@5531
   756
         XSizeHints *sizehints = XAllocSizeHints();
slouken@5531
   757
         long userhints;
slouken@5531
   758
slouken@5531
   759
         XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
slouken@5531
   760
slouken@5531
   761
         sizehints->min_width = sizehints->max_height = window->w;
slouken@5531
   762
         sizehints->min_height = sizehints->max_height = window->h;
slouken@5531
   763
slouken@5531
   764
         XSetWMNormalHints(display, data->xwindow, sizehints);
slouken@5531
   765
slouken@5531
   766
         XFree(sizehints);
slouken@5531
   767
    } else
slouken@5531
   768
        XResizeWindow(display, data->xwindow, window->w, window->h);
slouken@5031
   769
    XFlush(display);
slouken@1951
   770
}
slouken@1951
   771
slouken@1951
   772
void
slouken@1951
   773
X11_ShowWindow(_THIS, SDL_Window * window)
slouken@1951
   774
{
slouken@1951
   775
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   776
    Display *display = data->videodata->display;
slouken@1951
   777
slouken@3685
   778
    XMapRaised(display, data->xwindow);
slouken@5031
   779
    XFlush(display);
slouken@1951
   780
}
slouken@1951
   781
slouken@1951
   782
void
slouken@1951
   783
X11_HideWindow(_THIS, SDL_Window * window)
slouken@1951
   784
{
slouken@1951
   785
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   786
    Display *display = data->videodata->display;
slouken@1951
   787
slouken@3685
   788
    XUnmapWindow(display, data->xwindow);
slouken@5031
   789
    XFlush(display);
slouken@1951
   790
}
slouken@1951
   791
slouken@1951
   792
void
slouken@1951
   793
X11_RaiseWindow(_THIS, SDL_Window * window)
slouken@1951
   794
{
slouken@1951
   795
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   796
    Display *display = data->videodata->display;
slouken@1951
   797
slouken@3685
   798
    XRaiseWindow(display, data->xwindow);
slouken@5031
   799
    XFlush(display);
slouken@1951
   800
}
slouken@1951
   801
slouken@3077
   802
static void
slouken@5302
   803
SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized)
slouken@3077
   804
{
slouken@3077
   805
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@3077
   806
    SDL_DisplayData *displaydata =
slouken@5246
   807
        (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
slouken@3077
   808
    Display *display = data->videodata->display;
slouken@4518
   809
    Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
slouken@4518
   810
    Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
slouken@4518
   811
    Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
slouken@4522
   812
    Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
slouken@3077
   813
slouken@4522
   814
    if (X11_IsWindowMapped(_this, window)) {
slouken@4522
   815
        XEvent e;
slouken@3077
   816
slouken@4524
   817
        SDL_zero(e);
slouken@4522
   818
        e.xany.type = ClientMessage;
slouken@4522
   819
        e.xclient.message_type = _NET_WM_STATE;
slouken@4522
   820
        e.xclient.format = 32;
slouken@4522
   821
        e.xclient.window = data->xwindow;
slouken@4522
   822
        e.xclient.data.l[0] =
slouken@4522
   823
            maximized ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
slouken@4522
   824
        e.xclient.data.l[1] = _NET_WM_STATE_MAXIMIZED_VERT;
slouken@4522
   825
        e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ;
slouken@4522
   826
        e.xclient.data.l[3] = 0l;
slouken@4522
   827
slouken@4522
   828
        XSendEvent(display, RootWindow(display, displaydata->screen), 0,
slouken@4522
   829
                   SubstructureNotifyMask | SubstructureRedirectMask, &e);
slouken@4522
   830
    } else {
slouken@4522
   831
        int count = 0;
slouken@4522
   832
        Atom atoms[3];
slouken@4522
   833
slouken@4522
   834
        if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@4522
   835
            atoms[count++] = _NET_WM_STATE_FULLSCREEN;
slouken@4522
   836
        }
slouken@4522
   837
        if (maximized) {
slouken@4522
   838
            atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
slouken@4522
   839
            atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
slouken@4522
   840
        }
slouken@4522
   841
        if (count > 0) {
slouken@4522
   842
            XChangeProperty(display, data->xwindow, _NET_WM_STATE, XA_ATOM, 32,
slouken@4522
   843
                            PropModeReplace, (unsigned char *)atoms, count);
slouken@4522
   844
        } else {
slouken@4522
   845
            XDeleteProperty(display, data->xwindow, _NET_WM_STATE);
slouken@4522
   846
        }
slouken@4522
   847
    }
slouken@5031
   848
    XFlush(display);
slouken@3077
   849
}
slouken@3077
   850
slouken@1951
   851
void
slouken@1951
   852
X11_MaximizeWindow(_THIS, SDL_Window * window)
slouken@1951
   853
{
slouken@5302
   854
    SetWindowMaximized(_this, window, SDL_TRUE);
slouken@1951
   855
}
slouken@1951
   856
slouken@1951
   857
void
slouken@1951
   858
X11_MinimizeWindow(_THIS, SDL_Window * window)
slouken@1951
   859
{
slouken@4518
   860
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@4518
   861
    SDL_DisplayData *displaydata =
slouken@5246
   862
        (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
slouken@4518
   863
    Display *display = data->videodata->display;
slouken@4518
   864
 
slouken@4518
   865
    XIconifyWindow(display, data->xwindow, displaydata->screen);
slouken@5031
   866
    XFlush(display);
slouken@1951
   867
}
slouken@1951
   868
slouken@1951
   869
void
slouken@1951
   870
X11_RestoreWindow(_THIS, SDL_Window * window)
slouken@1951
   871
{
slouken@5302
   872
    SetWindowMaximized(_this, window, SDL_FALSE);
slouken@1951
   873
    X11_ShowWindow(_this, window);
slouken@1951
   874
}
slouken@1951
   875
slouken@5305
   876
void
slouken@5305
   877
X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
slouken@5302
   878
{
slouken@5302
   879
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5305
   880
    SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
slouken@5302
   881
    Display *display = data->videodata->display;
slouken@5302
   882
    Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
slouken@5302
   883
    Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
slouken@5302
   884
    Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
slouken@5302
   885
    Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
slouken@5302
   886
slouken@5302
   887
    if (X11_IsWindowMapped(_this, window)) {
slouken@5302
   888
        XEvent e;
slouken@5302
   889
slouken@5302
   890
        SDL_zero(e);
slouken@5302
   891
        e.xany.type = ClientMessage;
slouken@5302
   892
        e.xclient.message_type = _NET_WM_STATE;
slouken@5302
   893
        e.xclient.format = 32;
slouken@5302
   894
        e.xclient.window = data->xwindow;
slouken@5302
   895
        e.xclient.data.l[0] =
slouken@5302
   896
            fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
slouken@5302
   897
        e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
slouken@5302
   898
        e.xclient.data.l[3] = 0l;
slouken@5302
   899
slouken@5302
   900
        XSendEvent(display, RootWindow(display, displaydata->screen), 0,
slouken@5302
   901
                   SubstructureNotifyMask | SubstructureRedirectMask, &e);
slouken@5302
   902
    } else {
slouken@5302
   903
        int count = 0;
slouken@5302
   904
        Atom atoms[3];
slouken@5302
   905
slouken@5302
   906
        if (fullscreen) {
slouken@5302
   907
            atoms[count++] = _NET_WM_STATE_FULLSCREEN;
slouken@5302
   908
        }
slouken@5302
   909
        if (window->flags & SDL_WINDOW_MAXIMIZED) {
slouken@5302
   910
            atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
slouken@5302
   911
            atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
slouken@5302
   912
        }
slouken@5302
   913
        if (count > 0) {
slouken@5302
   914
            XChangeProperty(display, data->xwindow, _NET_WM_STATE, XA_ATOM, 32,
slouken@5302
   915
                            PropModeReplace, (unsigned char *)atoms, count);
slouken@5302
   916
        } else {
slouken@5302
   917
            XDeleteProperty(display, data->xwindow, _NET_WM_STATE);
slouken@5302
   918
        }
slouken@5302
   919
    }
slouken@5302
   920
    XFlush(display);
slouken@5302
   921
}
slouken@5302
   922
slouken@5466
   923
int
slouken@5466
   924
X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
slouken@5466
   925
{
slouken@5466
   926
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5466
   927
    Display *display = data->videodata->display;
slouken@5466
   928
    Visual *visual = data->visual;
slouken@5466
   929
    Colormap colormap = data->colormap;
slouken@5466
   930
    XColor *colorcells;
slouken@5466
   931
    int ncolors;
slouken@5466
   932
    int rmask, gmask, bmask;
slouken@5466
   933
    int rshift, gshift, bshift;
icculus@5981
   934
    int i;
slouken@5466
   935
slouken@5466
   936
    if (visual->class != DirectColor) {
slouken@5466
   937
        SDL_SetError("Window doesn't have DirectColor visual");
slouken@5466
   938
        return -1;
slouken@5466
   939
    }
slouken@5466
   940
slouken@5466
   941
    ncolors = visual->map_entries;
slouken@5466
   942
    colorcells = SDL_malloc(ncolors * sizeof(XColor));
slouken@5466
   943
    if (!colorcells) {
slouken@5466
   944
        SDL_OutOfMemory();
slouken@5466
   945
        return -1;
slouken@5466
   946
    }
slouken@5466
   947
slouken@5466
   948
    rshift = 0;
slouken@5466
   949
    rmask = visual->red_mask;
slouken@5466
   950
    while (0 == (rmask & 1)) {
slouken@5466
   951
        rshift++;
slouken@5466
   952
        rmask >>= 1;
slouken@5466
   953
    }
slouken@5466
   954
slouken@5466
   955
    gshift = 0;
slouken@5466
   956
    gmask = visual->green_mask;
slouken@5466
   957
    while (0 == (gmask & 1)) {
slouken@5466
   958
        gshift++;
slouken@5466
   959
        gmask >>= 1;
slouken@5466
   960
    }
slouken@5466
   961
slouken@5466
   962
    bshift = 0;
slouken@5466
   963
    bmask = visual->blue_mask;
slouken@5466
   964
    while (0 == (bmask & 1)) {
slouken@5466
   965
        bshift++;
slouken@5466
   966
        bmask >>= 1;
slouken@5466
   967
    }
slouken@5466
   968
slouken@5466
   969
    /* build the color table pixel values */
slouken@5466
   970
    for (i = 0; i < ncolors; i++) {
slouken@5466
   971
        Uint32 rbits = (rmask * i) / (ncolors - 1);
slouken@5466
   972
        Uint32 gbits = (gmask * i) / (ncolors - 1);
slouken@5466
   973
        Uint32 bbits = (bmask * i) / (ncolors - 1);
slouken@5466
   974
        Uint32 pix = (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
slouken@5466
   975
slouken@5466
   976
        colorcells[i].pixel = pix;
slouken@5466
   977
slouken@5466
   978
        colorcells[i].red = ramp[(0 * 256) + i];
slouken@5466
   979
        colorcells[i].green = ramp[(1 * 256) + i];
slouken@5466
   980
        colorcells[i].blue = ramp[(2 * 256) + i];
slouken@5466
   981
slouken@5466
   982
        colorcells[i].flags = DoRed | DoGreen | DoBlue;
slouken@5466
   983
    }
slouken@5466
   984
slouken@5466
   985
    XStoreColors(display, colormap, colorcells, ncolors);
slouken@5466
   986
    XFlush(display);
slouken@5466
   987
    SDL_free(colorcells);
slouken@5466
   988
slouken@5466
   989
    return 0;
slouken@5466
   990
}
slouken@5466
   991
slouken@5302
   992
void
slouken@1951
   993
X11_SetWindowGrab(_THIS, SDL_Window * window)
slouken@1951
   994
{
slouken@2875
   995
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@2875
   996
    Display *display = data->videodata->display;
slouken@4518
   997
    SDL_bool oldstyle_fullscreen;
slouken@2875
   998
slouken@4518
   999
    /* ICCCM2.0-compliant window managers can handle fullscreen windows */
slouken@4522
  1000
    oldstyle_fullscreen = X11_IsWindowOldFullscreen(_this, window);
slouken@4518
  1001
slouken@4518
  1002
    if (((window->flags & SDL_WINDOW_INPUT_GRABBED) || oldstyle_fullscreen)
slouken@2876
  1003
        && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@2875
  1004
        /* Try to grab the mouse */
slouken@2876
  1005
        for (;;) {
slouken@2876
  1006
            int result =
slouken@3685
  1007
                XGrabPointer(display, data->xwindow, True, 0, GrabModeAsync,
slouken@3685
  1008
                             GrabModeAsync, data->xwindow, None, CurrentTime);
slouken@2876
  1009
            if (result == GrabSuccess) {
slouken@2875
  1010
                break;
slouken@2875
  1011
            }
slouken@2875
  1012
            SDL_Delay(100);
slouken@2875
  1013
        }
slouken@2875
  1014
slouken@2875
  1015
        /* Raise the window if we grab the mouse */
slouken@3685
  1016
        XRaiseWindow(display, data->xwindow);
slouken@2875
  1017
slouken@2875
  1018
        /* Now grab the keyboard */
slouken@3685
  1019
        XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
slouken@2876
  1020
                      GrabModeAsync, CurrentTime);
slouken@2875
  1021
    } else {
slouken@2875
  1022
        XUngrabPointer(display, CurrentTime);
slouken@2875
  1023
        XUngrabKeyboard(display, CurrentTime);
slouken@2875
  1024
    }
slouken@1951
  1025
}
slouken@1951
  1026
slouken@1951
  1027
void
slouken@1951
  1028
X11_DestroyWindow(_THIS, SDL_Window * window)
slouken@1951
  1029
{
slouken@1951
  1030
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
bob@2323
  1031
    window->driverdata = NULL;
slouken@1951
  1032
slouken@1951
  1033
    if (data) {
bob@2323
  1034
        SDL_VideoData *videodata = (SDL_VideoData *) data->videodata;
bob@2323
  1035
        Display *display = videodata->display;
bob@2323
  1036
        int numwindows = videodata->numwindows;
bob@2323
  1037
        SDL_WindowData **windowlist = videodata->windowlist;
bob@2323
  1038
        int i;
bob@2323
  1039
bob@2323
  1040
        if (windowlist) {
bob@2324
  1041
            for (i = 0; i < numwindows; ++i) {
slouken@3685
  1042
                if (windowlist[i] && (windowlist[i]->window == window)) {
bob@2324
  1043
                    windowlist[i] = windowlist[numwindows - 1];
bob@2324
  1044
                    windowlist[numwindows - 1] = NULL;
bob@2324
  1045
                    videodata->numwindows--;
bob@2324
  1046
                    break;
bob@2324
  1047
                }
bob@2323
  1048
            }
bob@2323
  1049
        }
slouken@1951
  1050
#ifdef X_HAVE_UTF8_STRING
slouken@1951
  1051
        if (data->ic) {
slouken@1951
  1052
            XDestroyIC(data->ic);
slouken@1951
  1053
        }
slouken@1951
  1054
#endif
slouken@1951
  1055
        if (data->created) {
slouken@3685
  1056
            XDestroyWindow(display, data->xwindow);
slouken@5031
  1057
            XFlush(display);
slouken@1951
  1058
        }
slouken@1951
  1059
        SDL_free(data);
slouken@1951
  1060
    }
slouken@1951
  1061
}
slouken@1951
  1062
slouken@1951
  1063
SDL_bool
slouken@1951
  1064
X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
slouken@1951
  1065
{
slouken@4510
  1066
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@4510
  1067
    Display *display = data->videodata->display;
slouken@4510
  1068
slouken@4510
  1069
    if (info->version.major == SDL_MAJOR_VERSION &&
slouken@4510
  1070
        info->version.minor == SDL_MINOR_VERSION) {
slouken@4510
  1071
        info->subsystem = SDL_SYSWM_X11;
slouken@5056
  1072
        info->info.x11.display = display;
slouken@5056
  1073
        info->info.x11.window = data->xwindow;
slouken@1951
  1074
        return SDL_TRUE;
slouken@1951
  1075
    } else {
slouken@1951
  1076
        SDL_SetError("Application not compiled with SDL %d.%d\n",
slouken@1951
  1077
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@1951
  1078
        return SDL_FALSE;
slouken@1951
  1079
    }
slouken@1951
  1080
}
slouken@1951
  1081
slouken@5481
  1082
#endif /* SDL_VIDEO_DRIVER_X11 */
slouken@5481
  1083
slouken@1951
  1084
/* vi: set ts=4 sw=4 expandtab: */