src/video/x11/SDL_x11window.c
author Michael Sartain <mikesart@valvesoftware.com>
Thu, 11 Oct 2012 09:34:13 -0700
changeset 6568 1a6b0ae81937
parent 6562 c52863165594
child 6575 833a983f218e
permissions -rw-r--r--
Fix Colormap when using X11_SetWindowFullscreenViaWM() path.

This was needed to get X11_SetWindowGammaRamp() working. Sam points out that there is an issue right now where
colormaps will only work with fullscreen windows, and we may want to set this when getting input focus for
windowed apps.
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"
dimitris@6316
    33
#include "SDL_x11xinput2.h"
slouken@1951
    34
slouken@6188
    35
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@3161
    36
#include "SDL_x11opengles.h"
slouken@3161
    37
#endif
slouken@3161
    38
slouken@4465
    39
#include "SDL_timer.h"
slouken@3241
    40
#include "SDL_syswm.h"
icculus@6467
    41
#include "SDL_assert.h"
slouken@3241
    42
slouken@3077
    43
#define _NET_WM_STATE_REMOVE    0l
slouken@3077
    44
#define _NET_WM_STATE_ADD       1l
slouken@3077
    45
#define _NET_WM_STATE_TOGGLE    2l
slouken@3077
    46
icculus@6467
    47
static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win)
icculus@6467
    48
{
icculus@6467
    49
    return ev->type == MapNotify && ev->xmap.window == *((Window*)win);
icculus@6467
    50
}
icculus@6467
    51
static Bool isUnmapNotify(Display *dpy, XEvent *ev, XPointer win)
icculus@6467
    52
{
icculus@6467
    53
    return ev->type == UnmapNotify && ev->xunmap.window == *((Window*)win);
icculus@6467
    54
}
icculus@6467
    55
static Bool isConfigureNotify(Display *dpy, XEvent *ev, XPointer win)
icculus@6467
    56
{
slouken@6480
    57
    return ev->type == ConfigureNotify && ev->xconfigure.window == *((Window*)win);
slouken@6480
    58
}
icculus@6467
    59
slouken@4518
    60
static SDL_bool
icculus@6467
    61
X11_IsWindowLegacyFullscreen(_THIS, SDL_Window * window)
slouken@4518
    62
{
icculus@6467
    63
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
icculus@6467
    64
    return (data->fswindow != 0);
slouken@4518
    65
}
slouken@4518
    66
slouken@4522
    67
static SDL_bool
slouken@4522
    68
X11_IsWindowMapped(_THIS, SDL_Window * window)
slouken@4522
    69
{
slouken@4522
    70
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@4522
    71
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@4522
    72
    XWindowAttributes attr;
slouken@4522
    73
slouken@4522
    74
    XGetWindowAttributes(videodata->display, data->xwindow, &attr);
slouken@4522
    75
    if (attr.map_state != IsUnmapped) {
slouken@4522
    76
        return SDL_TRUE;
slouken@4522
    77
    } else {
slouken@4522
    78
        return SDL_FALSE;
slouken@4522
    79
    }
slouken@4522
    80
}
slouken@4522
    81
slouken@6540
    82
#if 0
slouken@6481
    83
static SDL_bool
slouken@6481
    84
X11_IsActionAllowed(SDL_Window *window, Atom action)
slouken@4522
    85
{
slouken@6481
    86
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@6481
    87
    Atom _NET_WM_ALLOWED_ACTIONS = data->videodata->_NET_WM_ALLOWED_ACTIONS;
slouken@6481
    88
    Atom type;
slouken@6481
    89
    Display *display = data->videodata->display;
slouken@6481
    90
    int form;
slouken@6481
    91
    unsigned long remain;
slouken@6481
    92
    unsigned long len, i;
slouken@6481
    93
    Atom *list;
slouken@6481
    94
    SDL_bool ret = SDL_FALSE;
slouken@6481
    95
slouken@6481
    96
    if (XGetWindowProperty(display, data->xwindow, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, XA_ATOM, &type, &form, &len, &remain, (unsigned char **)&list) == Success)
slouken@6481
    97
    {
slouken@6481
    98
        for (i=0; i<len; ++i)
slouken@6481
    99
        {
slouken@6481
   100
            if (list[i] == action) {
slouken@6481
   101
                ret = SDL_TRUE;
slouken@6481
   102
                break;
slouken@6481
   103
            }
slouken@6481
   104
        }
slouken@6481
   105
        XFree(list);
slouken@6481
   106
    }
slouken@6481
   107
    return ret;
slouken@6481
   108
}
slouken@6540
   109
#endif /* 0 */
slouken@6481
   110
slouken@6487
   111
void
slouken@6487
   112
X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
slouken@6481
   113
{
slouken@6481
   114
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@6487
   115
    Display *display = videodata->display;
slouken@6487
   116
    Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
slouken@6486
   117
    /*Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;*/
slouken@6481
   118
    Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
slouken@6481
   119
    Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
slouken@6481
   120
    Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
slouken@6481
   121
    Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
slouken@6487
   122
    Atom atoms[5];
slouken@4522
   123
    int count = 0;
slouken@4522
   124
slouken@6486
   125
    /* The window manager sets this property, we shouldn't set it.
slouken@6486
   126
       If we did, this would indicate to the window manager that we don't
slouken@6486
   127
       actually want to be mapped during XMapRaised(), which would be bad.
slouken@6486
   128
     *
slouken@6481
   129
    if (flags & SDL_WINDOW_HIDDEN) {
slouken@6481
   130
        atoms[count++] = _NET_WM_STATE_HIDDEN;
slouken@4522
   131
    }
slouken@6486
   132
    */
slouken@6481
   133
    if (flags & SDL_WINDOW_INPUT_FOCUS) {
slouken@6481
   134
        atoms[count++] = _NET_WM_STATE_FOCUSED;
slouken@6481
   135
    }
slouken@6481
   136
    if (flags & SDL_WINDOW_MAXIMIZED) {
slouken@6481
   137
        atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
slouken@6481
   138
        atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
slouken@6481
   139
    }
slouken@6481
   140
    if (flags & SDL_WINDOW_FULLSCREEN) {
slouken@6481
   141
        atoms[count++] = _NET_WM_STATE_FULLSCREEN;
slouken@4522
   142
    }
slouken@6487
   143
    if (count > 0) {
slouken@6487
   144
        XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
slouken@6487
   145
                        PropModeReplace, (unsigned char *)atoms, count);
slouken@6487
   146
    } else {
slouken@6487
   147
        XDeleteProperty(display, xwindow, _NET_WM_STATE);
slouken@6487
   148
    }
slouken@4522
   149
}
slouken@4522
   150
slouken@6481
   151
Uint32
slouken@6487
   152
X11_GetNetWMState(_THIS, Window xwindow)
slouken@6481
   153
{
slouken@6481
   154
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@6487
   155
    Display *display = videodata->display;
slouken@6481
   156
    Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
slouken@6481
   157
    Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;
slouken@6481
   158
    Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
slouken@6481
   159
    Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
slouken@6481
   160
    Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
slouken@6481
   161
    Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
slouken@6481
   162
    Atom actualType;
slouken@6481
   163
    int actualFormat;
slouken@6481
   164
    unsigned long i, numItems, bytesAfter;
slouken@6481
   165
    unsigned char *propertyValue = NULL;
slouken@6481
   166
    long maxLength = 1024;
slouken@6481
   167
    Uint32 flags = 0;
slouken@6481
   168
slouken@6487
   169
    if (XGetWindowProperty(display, xwindow, _NET_WM_STATE,
slouken@6481
   170
                           0l, maxLength, False, XA_ATOM, &actualType,
slouken@6481
   171
                           &actualFormat, &numItems, &bytesAfter,
slouken@6481
   172
                           &propertyValue) == Success) {
slouken@6481
   173
        Atom *atoms = (Atom *) propertyValue;
slouken@6481
   174
        int maximized = 0;
slouken@6481
   175
        int fullscreen = 0;
slouken@6481
   176
slouken@6481
   177
        for (i = 0; i < numItems; ++i) {
slouken@6481
   178
            if (atoms[i] == _NET_WM_STATE_HIDDEN) {
slouken@6486
   179
                flags |= SDL_WINDOW_HIDDEN;
slouken@6481
   180
            } else if (atoms[i] == _NET_WM_STATE_FOCUSED) {
slouken@6481
   181
                flags |= SDL_WINDOW_INPUT_FOCUS;
slouken@6481
   182
            } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) {
slouken@6481
   183
                maximized |= 1;
slouken@6481
   184
            } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
slouken@6481
   185
                maximized |= 2;
slouken@6481
   186
            } else if ( atoms[i] == _NET_WM_STATE_FULLSCREEN) {
slouken@6481
   187
                fullscreen = 1;
slouken@6481
   188
            }
slouken@6481
   189
        }
slouken@6481
   190
        if (maximized == 3) {
slouken@6481
   191
            flags |= SDL_WINDOW_MAXIMIZED;
slouken@6481
   192
        }  else if (fullscreen == 1) {
slouken@6481
   193
            flags |= SDL_WINDOW_FULLSCREEN;
slouken@6481
   194
        }
slouken@6481
   195
        XFree(propertyValue);
slouken@6481
   196
    }
slouken@6481
   197
slouken@6484
   198
    /* FIXME, check the size hints for resizable */
slouken@6484
   199
    /*flags |= SDL_WINDOW_RESIZABLE;*/
slouken@6481
   200
slouken@6481
   201
    return flags;
slouken@6481
   202
}
slouken@6481
   203
slouken@1951
   204
static int
slouken@1951
   205
SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
slouken@1951
   206
{
slouken@1951
   207
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@1951
   208
    SDL_WindowData *data;
slouken@1951
   209
    int numwindows = videodata->numwindows;
bob@2324
   210
    int windowlistlength = videodata->windowlistlength;
slouken@1951
   211
    SDL_WindowData **windowlist = videodata->windowlist;
slouken@1951
   212
slouken@1951
   213
    /* Allocate the window data */
bob@2323
   214
    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
slouken@1951
   215
    if (!data) {
slouken@1951
   216
        SDL_OutOfMemory();
slouken@1951
   217
        return -1;
slouken@1951
   218
    }
slouken@3685
   219
    data->window = window;
slouken@3685
   220
    data->xwindow = w;
slouken@1951
   221
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   222
    if (SDL_X11_HAVE_UTF8) {
slouken@1951
   223
        data->ic =
slouken@1951
   224
            pXCreateIC(videodata->im, XNClientWindow, w, XNFocusWindow, w,
slouken@1951
   225
                       XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
slouken@1951
   226
                       XNResourceName, videodata->classname, XNResourceClass,
slouken@1951
   227
                       videodata->classname, NULL);
slouken@1951
   228
    }
slouken@1951
   229
#endif
slouken@1951
   230
    data->created = created;
slouken@1951
   231
    data->videodata = videodata;
slouken@1951
   232
bob@2323
   233
    /* Associate the data with the window */
bob@2324
   234
bob@2324
   235
    if (numwindows < windowlistlength) {
bob@2324
   236
        windowlist[numwindows] = data;
bob@2324
   237
        videodata->numwindows++;
bob@2324
   238
    } else {
bob@2324
   239
        windowlist =
bob@2324
   240
            (SDL_WindowData **) SDL_realloc(windowlist,
bob@2324
   241
                                            (numwindows +
bob@2324
   242
                                             1) * sizeof(*windowlist));
bob@2324
   243
        if (!windowlist) {
bob@2324
   244
            SDL_OutOfMemory();
bob@2324
   245
            SDL_free(data);
bob@2324
   246
            return -1;
bob@2323
   247
        }
bob@2324
   248
        windowlist[numwindows] = data;
bob@2324
   249
        videodata->numwindows++;
bob@2324
   250
        videodata->windowlistlength++;
bob@2324
   251
        videodata->windowlist = windowlist;
bob@2323
   252
    }
bob@2323
   253
slouken@1951
   254
    /* Fill in the SDL window with the window data */
slouken@1951
   255
    {
slouken@1951
   256
        XWindowAttributes attrib;
slouken@1951
   257
slouken@1951
   258
        XGetWindowAttributes(data->videodata->display, w, &attrib);
slouken@1951
   259
        window->x = attrib.x;
slouken@1951
   260
        window->y = attrib.y;
slouken@1951
   261
        window->w = attrib.width;
slouken@1951
   262
        window->h = attrib.height;
slouken@1951
   263
        if (attrib.map_state != IsUnmapped) {
slouken@1951
   264
            window->flags |= SDL_WINDOW_SHOWN;
slouken@1951
   265
        } else {
slouken@1951
   266
            window->flags &= ~SDL_WINDOW_SHOWN;
slouken@1951
   267
        }
slouken@5182
   268
        data->visual = attrib.visual;
slouken@5466
   269
        data->colormap = attrib.colormap;
slouken@1951
   270
    }
slouken@3077
   271
slouken@6487
   272
    window->flags |= X11_GetNetWMState(_this, w);
slouken@3077
   273
icculus@6024
   274
    {
icculus@6024
   275
        Window FocalWindow;
icculus@6024
   276
        int RevertTo=0;
icculus@6024
   277
        XGetInputFocus(data->videodata->display, &FocalWindow, &RevertTo);
icculus@6024
   278
        if (FocalWindow==w)
icculus@6024
   279
        {
icculus@6024
   280
            window->flags |= SDL_WINDOW_INPUT_FOCUS;
slouken@6481
   281
        }
slouken@6481
   282
slouken@6481
   283
        if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
icculus@6024
   284
            SDL_SetKeyboardFocus(data->window);
icculus@6024
   285
        }
icculus@6024
   286
icculus@6024
   287
        if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
icculus@6024
   288
            /* Tell x11 to clip mouse */
icculus@6024
   289
        }
icculus@6024
   290
    }
icculus@6024
   291
slouken@1951
   292
    /* All done! */
slouken@6487
   293
    window->driverdata = data;
slouken@1951
   294
    return 0;
slouken@1951
   295
}
slouken@1951
   296
icculus@6422
   297
static void
icculus@6422
   298
SetWindowBordered(Display *display, int screen, Window window, SDL_bool border)
icculus@6422
   299
{
icculus@6422
   300
    /*
icculus@6422
   301
     * this code used to check for KWM_WIN_DECORATION, but KDE hasn't
icculus@6422
   302
     *  supported it for years and years. It now respects _MOTIF_WM_HINTS.
icculus@6422
   303
     *  Gnome is similar: just use the Motif atom.
icculus@6422
   304
     */
icculus@6422
   305
icculus@6422
   306
    Atom WM_HINTS = XInternAtom(display, "_MOTIF_WM_HINTS", True);
icculus@6422
   307
    if (WM_HINTS != None) {
icculus@6422
   308
        /* Hints used by Motif compliant window managers */
icculus@6422
   309
        struct
icculus@6422
   310
        {
icculus@6422
   311
            unsigned long flags;
icculus@6422
   312
            unsigned long functions;
icculus@6422
   313
            unsigned long decorations;
icculus@6422
   314
            long input_mode;
icculus@6422
   315
            unsigned long status;
icculus@6422
   316
        } MWMHints = {
icculus@6422
   317
            (1L << 1), 0, border ? 1 : 0, 0, 0
icculus@6422
   318
        };
icculus@6422
   319
icculus@6422
   320
        XChangeProperty(display, window, WM_HINTS, WM_HINTS, 32,
icculus@6422
   321
                        PropModeReplace, (unsigned char *) &MWMHints,
icculus@6422
   322
                        sizeof(MWMHints) / 4);
icculus@6422
   323
    } else {  /* set the transient hints instead, if necessary */
icculus@6422
   324
        XSetTransientForHint(display, window, RootWindow(display, screen));
icculus@6422
   325
    }
icculus@6422
   326
}
icculus@6422
   327
slouken@1951
   328
int
slouken@1951
   329
X11_CreateWindow(_THIS, SDL_Window * window)
slouken@1951
   330
{
slouken@1951
   331
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@1951
   332
    SDL_DisplayData *displaydata =
slouken@5246
   333
        (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
slouken@4521
   334
    Display *display = data->display;
slouken@4521
   335
    int screen = displaydata->screen;
slouken@1951
   336
    Visual *visual;
slouken@1951
   337
    int depth;
slouken@1951
   338
    XSetWindowAttributes xattr;
slouken@1951
   339
    Window w;
urkle@6462
   340
    XSizeHints *sizehints;
urkle@6462
   341
    XWMHints *wmhints;
urkle@6462
   342
    XClassHint *classhints;
slouken@4521
   343
    Atom _NET_WM_WINDOW_TYPE;
slouken@4521
   344
    Atom _NET_WM_WINDOW_TYPE_NORMAL;
mail@6167
   345
    Atom _NET_WM_PID;
icculus@6045
   346
    Uint32 fevent = 0;
slouken@4518
   347
slouken@6369
   348
#if SDL_VIDEO_OPENGL_GLX || SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@1951
   349
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1952
   350
        XVisualInfo *vinfo;
slouken@1952
   351
slouken@6370
   352
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2        
slouken@6370
   353
        if (_this->gl_config.use_egl == 1) {
slouken@6369
   354
            vinfo = X11_GLES_GetVisual(_this, display, screen);
slouken@6369
   355
        } else
slouken@6369
   356
#endif
slouken@6369
   357
        {
slouken@6370
   358
#if SDL_VIDEO_OPENGL_GLX
slouken@6369
   359
            vinfo = X11_GL_GetVisual(_this, display, screen);
slouken@6370
   360
#endif
slouken@1952
   361
        }
slouken@3161
   362
        if (!vinfo) {
slouken@3161
   363
            return -1;
slouken@3161
   364
        }
slouken@3161
   365
        visual = vinfo->visual;
slouken@3161
   366
        depth = vinfo->depth;
slouken@3161
   367
        XFree(vinfo);
slouken@3161
   368
    } else
slouken@3161
   369
#endif
slouken@1952
   370
    {
slouken@1951
   371
        visual = displaydata->visual;
slouken@1951
   372
        depth = displaydata->depth;
slouken@1951
   373
    }
slouken@1951
   374
slouken@5386
   375
    xattr.override_redirect = False;
slouken@1951
   376
    xattr.background_pixel = 0;
slouken@1951
   377
    xattr.border_pixel = 0;
slouken@5466
   378
slouken@5466
   379
    if (visual->class == DirectColor) {
slouken@5466
   380
        XColor *colorcells;
slouken@5466
   381
        int i;
slouken@5466
   382
        int ncolors;
slouken@5466
   383
        int rmax, gmax, bmax;
slouken@5466
   384
        int rmask, gmask, bmask;
slouken@5466
   385
        int rshift, gshift, bshift;
slouken@5466
   386
slouken@5466
   387
        xattr.colormap =
slouken@5466
   388
            XCreateColormap(display, RootWindow(display, screen),
slouken@5466
   389
                            visual, AllocAll);
slouken@5466
   390
slouken@5466
   391
        /* If we can't create a colormap, then we must die */
slouken@5466
   392
        if (!xattr.colormap) {
slouken@5466
   393
            SDL_SetError("Could not create writable colormap");
slouken@5466
   394
            return -1;
slouken@5466
   395
        }
slouken@5466
   396
slouken@5466
   397
        /* OK, we got a colormap, now fill it in as best as we can */
slouken@5466
   398
        colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
slouken@5466
   399
        if (!colorcells) {
slouken@5466
   400
            SDL_OutOfMemory();
slouken@5466
   401
            return -1;
slouken@5466
   402
        }
slouken@5466
   403
        ncolors = visual->map_entries;
slouken@5466
   404
        rmax = 0xffff;
slouken@5466
   405
        gmax = 0xffff;
slouken@5466
   406
        bmax = 0xffff;
slouken@5466
   407
slouken@5466
   408
        rshift = 0;
slouken@5466
   409
        rmask = visual->red_mask;
slouken@5466
   410
        while (0 == (rmask & 1)) {
slouken@5466
   411
            rshift++;
slouken@5466
   412
            rmask >>= 1;
slouken@5466
   413
        }
slouken@5466
   414
slouken@5466
   415
        gshift = 0;
slouken@5466
   416
        gmask = visual->green_mask;
slouken@5466
   417
        while (0 == (gmask & 1)) {
slouken@5466
   418
            gshift++;
slouken@5466
   419
            gmask >>= 1;
slouken@5466
   420
        }
slouken@5466
   421
slouken@5466
   422
        bshift = 0;
slouken@5466
   423
        bmask = visual->blue_mask;
slouken@5466
   424
        while (0 == (bmask & 1)) {
slouken@5466
   425
            bshift++;
slouken@5466
   426
            bmask >>= 1;
slouken@5466
   427
        }
slouken@5466
   428
slouken@5466
   429
        /* build the color table pixel values */
slouken@5466
   430
        for (i = 0; i < ncolors; i++) {
slouken@5466
   431
            Uint32 red = (rmax * i) / (ncolors - 1);
slouken@5466
   432
            Uint32 green = (gmax * i) / (ncolors - 1);
slouken@5466
   433
            Uint32 blue = (bmax * i) / (ncolors - 1);
slouken@5466
   434
slouken@5466
   435
            Uint32 rbits = (rmask * i) / (ncolors - 1);
slouken@5466
   436
            Uint32 gbits = (gmask * i) / (ncolors - 1);
slouken@5466
   437
            Uint32 bbits = (bmask * i) / (ncolors - 1);
slouken@5466
   438
slouken@5466
   439
            Uint32 pix =
slouken@5466
   440
                (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
slouken@5466
   441
slouken@5466
   442
            colorcells[i].pixel = pix;
slouken@5466
   443
slouken@5466
   444
            colorcells[i].red = red;
slouken@5466
   445
            colorcells[i].green = green;
slouken@5466
   446
            colorcells[i].blue = blue;
slouken@5466
   447
slouken@5466
   448
            colorcells[i].flags = DoRed | DoGreen | DoBlue;
slouken@5466
   449
        }
slouken@5466
   450
slouken@5466
   451
        XStoreColors(display, xattr.colormap, colorcells, ncolors);
slouken@5466
   452
slouken@5466
   453
        SDL_free(colorcells);
slouken@5466
   454
    } else {
slouken@5466
   455
        xattr.colormap =
slouken@5466
   456
            XCreateColormap(display, RootWindow(display, screen),
slouken@5466
   457
                            visual, AllocNone);
slouken@5466
   458
    }
slouken@1951
   459
slouken@5386
   460
    w = XCreateWindow(display, RootWindow(display, screen),
slouken@5386
   461
                      window->x, window->y, window->w, window->h,
slouken@5386
   462
                      0, depth, InputOutput, visual,
slouken@1951
   463
                      (CWOverrideRedirect | CWBackPixel | CWBorderPixel |
slouken@1951
   464
                       CWColormap), &xattr);
slouken@1952
   465
    if (!w) {
slouken@1952
   466
        SDL_SetError("Couldn't create window");
slouken@1952
   467
        return -1;
slouken@1952
   468
    }
slouken@6188
   469
#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
slouken@6373
   470
    if ((window->flags & SDL_WINDOW_OPENGL) && (_this->gl_config.use_egl == 1)) {
slouken@6373
   471
        if (!_this->gles_data) {
slouken@6373
   472
            XDestroyWindow(display, w);
slouken@6373
   473
            return -1;
slouken@6373
   474
        }
slouken@6373
   475
slouken@6188
   476
        /* Create the GLES window surface */
slouken@6188
   477
        _this->gles_data->egl_surface =
slouken@6188
   478
            _this->gles_data->eglCreateWindowSurface(_this->gles_data->
slouken@3161
   479
                                                 egl_display,
slouken@3161
   480
                                                 _this->gles_data->egl_config,
slouken@3161
   481
                                                 (NativeWindowType) w, NULL);
slouken@3161
   482
slouken@6188
   483
        if (_this->gles_data->egl_surface == EGL_NO_SURFACE) {
slouken@6188
   484
            SDL_SetError("Could not create GLES window surface");
slouken@6373
   485
            XDestroyWindow(display, w);
slouken@6188
   486
            return -1;
slouken@6188
   487
        }
slouken@3161
   488
    }
slouken@3161
   489
#endif
slouken@1951
   490
icculus@6422
   491
    SetWindowBordered(display, screen, w,
icculus@6422
   492
                      (window->flags & SDL_WINDOW_BORDERLESS) == 0);
slouken@1951
   493
urkle@6462
   494
    sizehints = XAllocSizeHints();
mail@6167
   495
    /* Setup the normal size hints */
urkle@6462
   496
    sizehints->flags = 0;
mail@6167
   497
    if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
urkle@6462
   498
        sizehints->min_width = sizehints->max_width = window->w;
urkle@6462
   499
        sizehints->min_height = sizehints->max_height = window->h;
urkle@6462
   500
        sizehints->flags |= (PMaxSize | PMinSize);
slouken@1951
   501
    }
urkle@6462
   502
    sizehints->x = window->x;
urkle@6462
   503
    sizehints->y = window->y;
urkle@6462
   504
    sizehints->flags |= USPosition;
slouken@1951
   505
mail@6167
   506
    /* Setup the input hints so we get keyboard input */
urkle@6462
   507
    wmhints = XAllocWMHints();
urkle@6462
   508
    wmhints->input = True;
urkle@6462
   509
    wmhints->flags = InputHint;
mail@6167
   510
mail@6167
   511
    /* Setup the class hints so we can get an icon (AfterStep) */
urkle@6462
   512
    classhints = XAllocClassHint();
urkle@6462
   513
    classhints->res_name = data->classname;
urkle@6462
   514
    classhints->res_class = data->classname;
mail@6167
   515
mail@6167
   516
    /* Set the size, input and class hints, and define WM_CLIENT_MACHINE and WM_LOCALE_NAME */
urkle@6462
   517
    XSetWMProperties(display, w, NULL, NULL, NULL, 0, sizehints, wmhints, classhints);
mail@6167
   518
urkle@6462
   519
    XFree(sizehints);
urkle@6462
   520
    XFree(wmhints);
urkle@6462
   521
    XFree(classhints);
mail@6167
   522
    /* Set the PID related to the window for the given hostname, if possible */
mail@6167
   523
    if (data->pid > 0) {
mail@6167
   524
        _NET_WM_PID = XInternAtom(display, "_NET_WM_PID", False);
mail@6167
   525
        XChangeProperty(display, w, _NET_WM_PID, XA_CARDINAL, 32, PropModeReplace,
mail@6167
   526
                        (unsigned char *)&data->pid, 1);
slouken@1951
   527
    }
slouken@1951
   528
slouken@4522
   529
    /* Set the window manager state */
slouken@6487
   530
    X11_SetNetWMState(_this, w, window->flags);
slouken@4518
   531
slouken@4521
   532
    /* Let the window manager know we're a "normal" window */
slouken@4521
   533
    _NET_WM_WINDOW_TYPE = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
slouken@4521
   534
    _NET_WM_WINDOW_TYPE_NORMAL = XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
slouken@4521
   535
    XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
slouken@4521
   536
                    PropModeReplace,
slouken@4521
   537
                    (unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1);
slouken@4521
   538
slouken@1951
   539
    /* Allow the window to be deleted by the window manager */
slouken@4521
   540
    XSetWMProtocols(display, w, &data->WM_DELETE_WINDOW, 1);
slouken@1951
   541
slouken@1951
   542
    if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
slouken@4521
   543
        XDestroyWindow(display, w);
slouken@1951
   544
        return -1;
slouken@1951
   545
    }
slouken@5386
   546
bob@2325
   547
#ifdef X_HAVE_UTF8_STRING
icculus@6045
   548
    if (SDL_X11_HAVE_UTF8) {
bob@2325
   549
        pXGetICValues(((SDL_WindowData *) window->driverdata)->ic,
bob@2325
   550
                      XNFilterEvents, &fevent, NULL);
kazeuser@2718
   551
    }
bob@2325
   552
#endif
bob@2325
   553
dimitris@6316
   554
    X11_Xinput2SelectTouch(_this, window);
dimitris@6316
   555
icculus@6045
   556
    XSelectInput(display, w,
icculus@6045
   557
                 (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
icculus@6045
   558
                 ExposureMask | ButtonPressMask | ButtonReleaseMask |
icculus@6045
   559
                 PointerMotionMask | KeyPressMask | KeyReleaseMask |
icculus@6045
   560
                 PropertyChangeMask | StructureNotifyMask |
icculus@6045
   561
                 KeymapStateMask | fevent));
icculus@6045
   562
slouken@5031
   563
    XFlush(display);
slouken@5031
   564
slouken@1951
   565
    return 0;
slouken@1951
   566
}
slouken@1951
   567
slouken@1951
   568
int
bob@2324
   569
X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@1951
   570
{
slouken@1951
   571
    Window w = (Window) data;
slouken@1951
   572
slouken@4518
   573
    window->title = X11_GetWindowTitle(_this, w);
slouken@1951
   574
slouken@1951
   575
    if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
slouken@1951
   576
        return -1;
slouken@1951
   577
    }
slouken@1951
   578
    return 0;
slouken@1951
   579
}
slouken@1951
   580
slouken@4518
   581
char *
slouken@4518
   582
X11_GetWindowTitle(_THIS, Window xwindow)
slouken@4518
   583
{
slouken@4518
   584
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@4518
   585
    Display *display = data->display;
slouken@4518
   586
    int status, real_format;
slouken@4518
   587
    Atom real_type;
slouken@4518
   588
    unsigned long items_read, items_left;
slouken@4518
   589
    unsigned char *propdata;
slouken@4518
   590
    char *title = NULL;
slouken@4518
   591
slouken@4518
   592
    status = XGetWindowProperty(display, xwindow, data->_NET_WM_NAME,
slouken@4518
   593
                0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
slouken@4518
   594
                &items_read, &items_left, &propdata);
icculus@6023
   595
    if (status == Success && propdata) {
slouken@4518
   596
        title = SDL_strdup(SDL_static_cast(char*, propdata));
slouken@4518
   597
        XFree(propdata);
slouken@4518
   598
    } else {
slouken@4518
   599
        status = XGetWindowProperty(display, xwindow, XA_WM_NAME,
slouken@4518
   600
                    0L, 8192L, False, XA_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_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1);
slouken@4518
   604
        } else {
slouken@4518
   605
            title = SDL_strdup("");
slouken@4518
   606
        }
slouken@4518
   607
    }
slouken@4518
   608
    return title;
slouken@4518
   609
}
slouken@4518
   610
slouken@1951
   611
void
slouken@1951
   612
X11_SetWindowTitle(_THIS, SDL_Window * window)
slouken@1951
   613
{
slouken@1951
   614
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   615
    Display *display = data->videodata->display;
slouken@1951
   616
    XTextProperty titleprop, iconprop;
slouken@1951
   617
    Status status;
slouken@1951
   618
    const char *title = window->title;
slouken@1951
   619
    const char *icon = NULL;
slouken@1951
   620
slouken@1951
   621
#ifdef X_HAVE_UTF8_STRING
slouken@4518
   622
    Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
slouken@4518
   623
    Atom _NET_WM_ICON_NAME = data->videodata->_NET_WM_ICON_NAME;
slouken@1951
   624
#endif
slouken@1951
   625
slouken@1951
   626
    if (title != NULL) {
slouken@2143
   627
        char *title_locale = SDL_iconv_utf8_locale(title);
slouken@2143
   628
        if (!title_locale) {
slouken@1951
   629
            SDL_OutOfMemory();
slouken@1951
   630
            return;
slouken@1951
   631
        }
slouken@2143
   632
        status = XStringListToTextProperty(&title_locale, 1, &titleprop);
slouken@2143
   633
        SDL_free(title_locale);
slouken@1951
   634
        if (status) {
slouken@3685
   635
            XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME);
slouken@1951
   636
            XFree(titleprop.value);
slouken@1951
   637
        }
slouken@1951
   638
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   639
        if (SDL_X11_HAVE_UTF8) {
slouken@1951
   640
            status =
slouken@1951
   641
                Xutf8TextListToTextProperty(display, (char **) &title, 1,
slouken@1951
   642
                                            XUTF8StringStyle, &titleprop);
slouken@1951
   643
            if (status == Success) {
slouken@3685
   644
                XSetTextProperty(display, data->xwindow, &titleprop,
slouken@1951
   645
                                 _NET_WM_NAME);
slouken@1951
   646
                XFree(titleprop.value);
slouken@1951
   647
            }
slouken@1951
   648
        }
slouken@1951
   649
#endif
slouken@1951
   650
    }
slouken@1951
   651
    if (icon != NULL) {
slouken@2143
   652
        char *icon_locale = SDL_iconv_utf8_locale(icon);
slouken@2143
   653
        if (!icon_locale) {
slouken@1951
   654
            SDL_OutOfMemory();
slouken@1951
   655
            return;
slouken@1951
   656
        }
slouken@2143
   657
        status = XStringListToTextProperty(&icon_locale, 1, &iconprop);
slouken@2143
   658
        SDL_free(icon_locale);
slouken@1951
   659
        if (status) {
slouken@3685
   660
            XSetTextProperty(display, data->xwindow, &iconprop,
slouken@1951
   661
                             XA_WM_ICON_NAME);
slouken@1951
   662
            XFree(iconprop.value);
slouken@1951
   663
        }
slouken@1951
   664
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   665
        if (SDL_X11_HAVE_UTF8) {
slouken@1951
   666
            status =
slouken@1951
   667
                Xutf8TextListToTextProperty(display, (char **) &icon, 1,
slouken@1951
   668
                                            XUTF8StringStyle, &iconprop);
slouken@1951
   669
            if (status == Success) {
slouken@3685
   670
                XSetTextProperty(display, data->xwindow, &iconprop,
slouken@1951
   671
                                 _NET_WM_ICON_NAME);
slouken@1951
   672
                XFree(iconprop.value);
slouken@1951
   673
            }
slouken@1951
   674
        }
slouken@1951
   675
#endif
slouken@1951
   676
    }
slouken@5031
   677
    XFlush(display);
slouken@1951
   678
}
slouken@1951
   679
slouken@1951
   680
void
slouken@2967
   681
X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
slouken@2967
   682
{
slouken@2967
   683
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@2967
   684
    Display *display = data->videodata->display;
slouken@4518
   685
    Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON;
slouken@2967
   686
slouken@2967
   687
    if (icon) {
slouken@2967
   688
        SDL_PixelFormat format;
slouken@2967
   689
        SDL_Surface *surface;
slouken@2967
   690
        int propsize;
slouken@4528
   691
        long *propdata;
slouken@2967
   692
slouken@2967
   693
        /* Convert the icon to ARGB for modern window managers */
slouken@5288
   694
        SDL_InitFormat(&format, SDL_PIXELFORMAT_ARGB8888);
slouken@2967
   695
        surface = SDL_ConvertSurface(icon, &format, 0);
slouken@2967
   696
        if (!surface) {
slouken@2967
   697
            return;
slouken@2967
   698
        }
slouken@2967
   699
slouken@2967
   700
        /* Set the _NET_WM_ICON property */
slouken@2990
   701
        propsize = 2 + (icon->w * icon->h);
slouken@4566
   702
        propdata = SDL_malloc(propsize * sizeof(long));
slouken@2967
   703
        if (propdata) {
slouken@4528
   704
            int x, y;
slouken@4528
   705
            Uint32 *src;
slouken@4528
   706
            long *dst;
slouken@4528
   707
slouken@2967
   708
            propdata[0] = icon->w;
slouken@2967
   709
            propdata[1] = icon->h;
slouken@4528
   710
            dst = &propdata[2];
slouken@4528
   711
            for (y = 0; y < icon->h; ++y) {
slouken@4528
   712
                src = (Uint32*)((Uint8*)surface->pixels + y * surface->pitch);
slouken@4528
   713
                for (x = 0; x < icon->w; ++x) {
slouken@4528
   714
                    *dst++ = *src++;
slouken@4528
   715
                }
slouken@4528
   716
            }
slouken@3685
   717
            XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL,
slouken@2990
   718
                            32, PropModeReplace, (unsigned char *) propdata,
slouken@2990
   719
                            propsize);
slouken@2967
   720
        }
icculus@6562
   721
        SDL_free(propdata);
slouken@2967
   722
        SDL_FreeSurface(surface);
slouken@2967
   723
    } else {
slouken@3685
   724
        XDeleteProperty(display, data->xwindow, _NET_WM_ICON);
slouken@2967
   725
    }
slouken@5031
   726
    XFlush(display);
slouken@2967
   727
}
slouken@2967
   728
slouken@2967
   729
void
slouken@1951
   730
X11_SetWindowPosition(_THIS, SDL_Window * window)
slouken@1951
   731
{
slouken@1951
   732
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   733
    Display *display = data->videodata->display;
slouken@1951
   734
slouken@5478
   735
    XMoveWindow(display, data->xwindow, window->x, window->y);
slouken@5031
   736
    XFlush(display);
slouken@1951
   737
}
slouken@1951
   738
slouken@1951
   739
void
slouken@1951
   740
X11_SetWindowSize(_THIS, SDL_Window * window)
slouken@1951
   741
{
slouken@1951
   742
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   743
    Display *display = data->videodata->display;
slouken@1951
   744
slouken@6481
   745
    if (SDL_IsShapedWindow(window)) {
eligottlieb@4782
   746
        X11_ResizeWindowShape(window);
slouken@6481
   747
    }
slouken@5531
   748
    if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
slouken@5531
   749
         /* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the XResizeWindow, thus
slouken@5531
   750
            we must set the size hints to adjust the window size.*/
slouken@5531
   751
         XSizeHints *sizehints = XAllocSizeHints();
slouken@5531
   752
         long userhints;
slouken@5531
   753
slouken@5531
   754
         XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
slouken@5531
   755
slouken@6343
   756
         sizehints->min_width = sizehints->max_width = window->w;
slouken@5531
   757
         sizehints->min_height = sizehints->max_height = window->h;
slouken@5531
   758
slouken@5531
   759
         XSetWMNormalHints(display, data->xwindow, sizehints);
slouken@5531
   760
slouken@5531
   761
         XFree(sizehints);
slouken@6541
   762
slouken@6541
   763
        /* From Pierre-Loup:
slouken@6541
   764
           For the windowed resize problem; WMs each have their little quirks with
slouken@6541
   765
           that.  When you change the size hints, they get a ConfigureNotify event
slouken@6541
   766
           with the WM_NORMAL_SIZE_HINTS Atom.  They all save the hints then, but
slouken@6541
   767
           they don't all resize the window right away to enforce the new hints.
slouken@6541
   768
           Those who do properly do it are:
slouken@6541
   769
          
slouken@6541
   770
             - XFWM
slouken@6541
   771
             - metacity
slouken@6541
   772
             - KWin
slouken@6541
   773
slouken@6541
   774
           These are great.  Now, others are more problematic as you could observe
slouken@6541
   775
           first hand.  Compiz/Unity only falls into the code that does it on select
slouken@6541
   776
           actions, such as window move, raise, map, etc.
slouken@6541
   777
slouken@6541
   778
           WindowMaker is even more difficult and will _only_ do it on map.
slouken@6541
   779
slouken@6541
   780
           Awesome only does it on user-initiated moves as far as I can tell.
slouken@6541
   781
          
slouken@6541
   782
           Your raise workaround only fixes compiz/Unity.  With that all "modern"
slouken@6541
   783
           window managers are covered.  Trying to Hide/Show on windowed resize
slouken@6541
   784
           (UnMap/Map) fixes both Unity and WindowMaker, but introduces subtle
slouken@6541
   785
           problems with transitioning from Windowed to Fullscreen on Unity.  Since
slouken@6541
   786
           some window moves happen after the transitions to fullscreen, that forces
slouken@6541
   787
           SDL to fall from windowed to fullscreen repeatedly and it sometimes leaves
slouken@6541
   788
           itself in a state where the fullscreen window is slightly offset by what
slouken@6541
   789
           used to be the window decoration titlebar.
slouken@6541
   790
        */
slouken@6541
   791
        XRaiseWindow(display, data->xwindow);
slouken@6481
   792
    } else {
slouken@5531
   793
        XResizeWindow(display, data->xwindow, window->w, window->h);
slouken@6481
   794
    }
slouken@5031
   795
    XFlush(display);
slouken@1951
   796
}
slouken@1951
   797
icculus@6422
   798
void
icculus@6422
   799
X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
icculus@6422
   800
{
icculus@6423
   801
    const SDL_bool focused = ((window->flags & SDL_WINDOW_INPUT_FOCUS) != 0);
icculus@6423
   802
    const SDL_bool visible = ((window->flags & SDL_WINDOW_HIDDEN) == 0);
icculus@6422
   803
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
icculus@6422
   804
    SDL_DisplayData *displaydata =
icculus@6422
   805
        (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
icculus@6422
   806
    Display *display = data->videodata->display;
icculus@6422
   807
    XEvent event;
icculus@6422
   808
icculus@6422
   809
    SetWindowBordered(display, displaydata->screen, data->xwindow, bordered);
icculus@6423
   810
    XFlush(display);
icculus@6422
   811
    XIfEvent(display, &event, &isConfigureNotify, (XPointer)&data->xwindow);
icculus@6422
   812
icculus@6423
   813
    if (visible) {
icculus@6423
   814
        XWindowAttributes attr;
icculus@6423
   815
        do {
icculus@6423
   816
            XSync(display, False);
icculus@6423
   817
            XGetWindowAttributes(display, data->xwindow, &attr);
icculus@6423
   818
        } while (attr.map_state != IsViewable);
icculus@6423
   819
icculus@6423
   820
        if (focused) {
icculus@6423
   821
            XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime);
icculus@6423
   822
        }
icculus@6423
   823
    }
icculus@6423
   824
icculus@6422
   825
    /* make sure these don't make it to the real event queue if they fired here. */
icculus@6423
   826
    XSync(display, False);
icculus@6423
   827
    XCheckIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
icculus@6423
   828
    XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
icculus@6422
   829
}
slouken@6336
   830
slouken@1951
   831
void
slouken@1951
   832
X11_ShowWindow(_THIS, SDL_Window * window)
slouken@1951
   833
{
slouken@1951
   834
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   835
    Display *display = data->videodata->display;
slouken@6336
   836
    XEvent event;
slouken@1951
   837
slouken@6483
   838
    if (!X11_IsWindowMapped(_this, window)) {
slouken@6483
   839
        XMapRaised(display, data->xwindow);
slouken@6483
   840
        /* Blocking wait for "MapNotify" event.
slouken@6483
   841
         * We use XIfEvent because XWindowEvent takes a mask rather than a type, 
slouken@6483
   842
         * and XCheckTypedWindowEvent doesn't block */
slouken@6483
   843
        XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
slouken@6483
   844
        XFlush(display);
slouken@6483
   845
    }
slouken@1951
   846
}
slouken@1951
   847
slouken@1951
   848
void
slouken@1951
   849
X11_HideWindow(_THIS, SDL_Window * window)
slouken@1951
   850
{
slouken@1951
   851
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   852
    Display *display = data->videodata->display;
slouken@6336
   853
    XEvent event;
slouken@1951
   854
slouken@6483
   855
    if (X11_IsWindowMapped(_this, window)) {
slouken@6483
   856
        XUnmapWindow(display, data->xwindow);
slouken@6483
   857
        /* Blocking wait for "UnmapNotify" event */
slouken@6483
   858
        XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);    
slouken@6483
   859
        XFlush(display);
slouken@6483
   860
    }
slouken@1951
   861
}
slouken@1951
   862
slouken@1951
   863
void
slouken@1951
   864
X11_RaiseWindow(_THIS, SDL_Window * window)
slouken@1951
   865
{
slouken@1951
   866
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   867
    Display *display = data->videodata->display;
slouken@1951
   868
slouken@3685
   869
    XRaiseWindow(display, data->xwindow);
slouken@5031
   870
    XFlush(display);
slouken@1951
   871
}
slouken@1951
   872
slouken@3077
   873
static void
slouken@5302
   874
SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized)
slouken@3077
   875
{
slouken@3077
   876
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@3077
   877
    SDL_DisplayData *displaydata =
slouken@5246
   878
        (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
slouken@3077
   879
    Display *display = data->videodata->display;
slouken@4518
   880
    Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
slouken@4518
   881
    Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
slouken@4518
   882
    Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
slouken@3077
   883
slouken@4522
   884
    if (X11_IsWindowMapped(_this, window)) {
slouken@4522
   885
        XEvent e;
slouken@3077
   886
slouken@4524
   887
        SDL_zero(e);
slouken@4522
   888
        e.xany.type = ClientMessage;
slouken@4522
   889
        e.xclient.message_type = _NET_WM_STATE;
slouken@4522
   890
        e.xclient.format = 32;
slouken@4522
   891
        e.xclient.window = data->xwindow;
slouken@4522
   892
        e.xclient.data.l[0] =
slouken@4522
   893
            maximized ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
slouken@4522
   894
        e.xclient.data.l[1] = _NET_WM_STATE_MAXIMIZED_VERT;
slouken@4522
   895
        e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ;
slouken@4522
   896
        e.xclient.data.l[3] = 0l;
slouken@4522
   897
slouken@4522
   898
        XSendEvent(display, RootWindow(display, displaydata->screen), 0,
slouken@4522
   899
                   SubstructureNotifyMask | SubstructureRedirectMask, &e);
slouken@4522
   900
    } else {
slouken@6481
   901
        Uint32 flags;
slouken@4522
   902
slouken@6481
   903
        flags = window->flags;
slouken@6481
   904
        if (maximized) {
slouken@6481
   905
            flags |= SDL_WINDOW_MAXIMIZED;
slouken@6481
   906
        } else {
slouken@6481
   907
            flags &= ~SDL_WINDOW_MAXIMIZED;
slouken@4522
   908
        }
slouken@6487
   909
        X11_SetNetWMState(_this, data->xwindow, flags);
slouken@4522
   910
    }
slouken@5031
   911
    XFlush(display);
slouken@3077
   912
}
slouken@3077
   913
slouken@1951
   914
void
slouken@1951
   915
X11_MaximizeWindow(_THIS, SDL_Window * window)
slouken@1951
   916
{
slouken@5302
   917
    SetWindowMaximized(_this, window, SDL_TRUE);
slouken@1951
   918
}
slouken@1951
   919
slouken@1951
   920
void
slouken@1951
   921
X11_MinimizeWindow(_THIS, SDL_Window * window)
slouken@1951
   922
{
slouken@4518
   923
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@4518
   924
    SDL_DisplayData *displaydata =
slouken@5246
   925
        (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
slouken@4518
   926
    Display *display = data->videodata->display;
slouken@4518
   927
 
slouken@4518
   928
    XIconifyWindow(display, data->xwindow, displaydata->screen);
slouken@5031
   929
    XFlush(display);
slouken@1951
   930
}
slouken@1951
   931
slouken@1951
   932
void
slouken@1951
   933
X11_RestoreWindow(_THIS, SDL_Window * window)
slouken@1951
   934
{
slouken@5302
   935
    SetWindowMaximized(_this, window, SDL_FALSE);
slouken@1951
   936
    X11_ShowWindow(_this, window);
slouken@1951
   937
}
slouken@1951
   938
icculus@6467
   939
/* This asks the Window Manager to handle fullscreen for us. Most don't do it right, though. */
icculus@6467
   940
static void
icculus@6467
   941
X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
slouken@5302
   942
{
slouken@5302
   943
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5305
   944
    SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
slouken@5302
   945
    Display *display = data->videodata->display;
slouken@5302
   946
    Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
slouken@5302
   947
    Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
slouken@5302
   948
slouken@5302
   949
    if (X11_IsWindowMapped(_this, window)) {
slouken@5302
   950
        XEvent e;
slouken@5302
   951
slouken@6539
   952
        if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
slouken@6539
   953
            /* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
slouken@6539
   954
               can be resized to the fullscreen resolution (or reset so we're not resizable again) */
slouken@6539
   955
            XSizeHints *sizehints = XAllocSizeHints();
slouken@6539
   956
            long flags = 0;
slouken@6539
   957
            XGetWMNormalHints(display, data->xwindow, sizehints, &flags);
slouken@6539
   958
            /* set the resize flags on */
slouken@6539
   959
            if (fullscreen) {
slouken@6539
   960
                /* we are going fullscreen so turn the flags off */
slouken@6539
   961
                sizehints->flags &= ~(PMinSize | PMaxSize);
slouken@6539
   962
            } else {
slouken@6539
   963
                /* Reset the min/max width height to make the window non-resizable again */
icculus@6466
   964
                sizehints->flags |= PMinSize | PMaxSize;
slouken@6540
   965
                sizehints->min_width = sizehints->max_width = window->windowed.w;
slouken@6540
   966
                sizehints->min_height = sizehints->max_height = window->windowed.h;
icculus@6466
   967
            }
slouken@6539
   968
            XSetWMNormalHints(display, data->xwindow, sizehints);
slouken@6539
   969
            XFree(sizehints);
icculus@6466
   970
        }
slouken@6539
   971
slouken@5302
   972
        SDL_zero(e);
slouken@5302
   973
        e.xany.type = ClientMessage;
slouken@5302
   974
        e.xclient.message_type = _NET_WM_STATE;
slouken@5302
   975
        e.xclient.format = 32;
slouken@5302
   976
        e.xclient.window = data->xwindow;
slouken@5302
   977
        e.xclient.data.l[0] =
slouken@5302
   978
            fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
slouken@5302
   979
        e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
slouken@5302
   980
        e.xclient.data.l[3] = 0l;
slouken@5302
   981
slouken@5302
   982
        XSendEvent(display, RootWindow(display, displaydata->screen), 0,
slouken@5302
   983
                   SubstructureNotifyMask | SubstructureRedirectMask, &e);
slouken@5302
   984
    } else {
slouken@6481
   985
        Uint32 flags;
slouken@5302
   986
slouken@6481
   987
        flags = window->flags;
slouken@5302
   988
        if (fullscreen) {
slouken@6481
   989
            flags |= SDL_WINDOW_FULLSCREEN;
slouken@6481
   990
        } else {
slouken@6481
   991
            flags &= ~SDL_WINDOW_FULLSCREEN;
slouken@5302
   992
        }
slouken@6487
   993
        X11_SetNetWMState(_this, data->xwindow, flags);
slouken@5302
   994
    }
mikesart@6568
   995
mikesart@6568
   996
	if( fullscreen ) {
mikesart@6568
   997
		XInstallColormap(display, data->colormap);
mikesart@6568
   998
	} else {
mikesart@6568
   999
		XUninstallColormap(display, data->colormap);
mikesart@6568
  1000
	}
mikesart@6568
  1001
slouken@5302
  1002
    XFlush(display);
slouken@5302
  1003
}
slouken@5302
  1004
icculus@6467
  1005
static __inline__ int
icculus@6467
  1006
maxint(const int a, const int b)
icculus@6467
  1007
{
icculus@6467
  1008
    return (a > b ? a : b);
icculus@6467
  1009
}
icculus@6467
  1010
icculus@6467
  1011
icculus@6467
  1012
/* This handles fullscreen itself, outside the Window Manager. */
icculus@6467
  1013
static void
icculus@6467
  1014
X11_BeginWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
icculus@6467
  1015
{
icculus@6467
  1016
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
icculus@6467
  1017
    SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
icculus@6467
  1018
    Visual *visual = data->visual;
icculus@6467
  1019
    Display *display = data->videodata->display;
icculus@6467
  1020
    const int screen = displaydata->screen;
icculus@6467
  1021
    Window root = RootWindow(display, screen);
icculus@6467
  1022
    const int def_vis = (visual == DefaultVisual(display, screen));
icculus@6467
  1023
    unsigned long xattrmask = 0;
icculus@6467
  1024
    XSetWindowAttributes xattr;
icculus@6467
  1025
    XEvent ev;
slouken@6475
  1026
    SDL_Rect rect;
icculus@6467
  1027
icculus@6467
  1028
    if ( data->fswindow ) {
icculus@6467
  1029
        return;  /* already fullscreen, I hope. */
icculus@6467
  1030
    }
icculus@6467
  1031
slouken@6475
  1032
    X11_GetDisplayBounds(_this, _display, &rect);
slouken@6475
  1033
icculus@6467
  1034
    SDL_zero(xattr);
icculus@6467
  1035
    xattr.override_redirect = True;
icculus@6467
  1036
    xattrmask |= CWOverrideRedirect;
icculus@6467
  1037
    xattr.background_pixel = def_vis ? BlackPixel(display, screen) : 0;
icculus@6467
  1038
    xattrmask |= CWBackPixel;
icculus@6467
  1039
    xattr.border_pixel = 0;
icculus@6467
  1040
    xattrmask |= CWBorderPixel;
icculus@6467
  1041
    xattr.colormap = data->colormap;
icculus@6467
  1042
    xattrmask |= CWColormap;
icculus@6467
  1043
slouken@6475
  1044
    data->fswindow = XCreateWindow(display, root,
slouken@6475
  1045
                                   rect.x, rect.y, rect.w, rect.h, 0,
icculus@6467
  1046
                                   displaydata->depth, InputOutput,
icculus@6467
  1047
                                   visual, xattrmask, &xattr);
icculus@6467
  1048
icculus@6467
  1049
    XSelectInput(display, data->fswindow, StructureNotifyMask);
icculus@6467
  1050
    XSetWindowBackground(display, data->fswindow, 0);
slouken@6500
  1051
    XInstallColormap(display, data->colormap);
icculus@6467
  1052
    XClearWindow(display, data->fswindow);
slouken@6480
  1053
    XMapRaised(display, data->fswindow);
icculus@6467
  1054
slouken@6480
  1055
    /* Make sure the fswindow is in view by warping mouse to the corner */
slouken@6500
  1056
    XUngrabPointer(display, CurrentTime);
slouken@6480
  1057
    XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
icculus@6467
  1058
icculus@6467
  1059
    /* Wait to be mapped, filter Unmap event out if it arrives. */
icculus@6467
  1060
    XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->fswindow);
icculus@6467
  1061
    XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->fswindow);
icculus@6467
  1062
icculus@6467
  1063
#if SDL_VIDEO_DRIVER_X11_XVIDMODE
icculus@6467
  1064
    if ( displaydata->use_vidmode ) {
icculus@6467
  1065
        XF86VidModeLockModeSwitch(display, screen, True);
icculus@6467
  1066
    }
icculus@6467
  1067
#endif
icculus@6467
  1068
icculus@6467
  1069
    SetWindowBordered(display, displaydata->screen, data->xwindow, SDL_FALSE);
icculus@6467
  1070
icculus@6467
  1071
    /* Center actual window within our cover-the-screen window. */
slouken@6501
  1072
    XReparentWindow(display, data->xwindow, data->fswindow,
slouken@6501
  1073
                    (rect.w - window->w) / 2, (rect.h - window->h) / 2);
icculus@6467
  1074
slouken@6501
  1075
    /* Center mouse in the fullscreen window. */
slouken@6501
  1076
    rect.x += (rect.w / 2);
slouken@6501
  1077
    rect.y += (rect.h / 2);
slouken@6475
  1078
    XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
icculus@6467
  1079
icculus@6467
  1080
    /* Wait to be mapped, filter Unmap event out if it arrives. */
icculus@6467
  1081
    XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
slouken@6480
  1082
    XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
icculus@6467
  1083
icculus@6467
  1084
    X11_SetWindowGrab(_this, window);
icculus@6467
  1085
}
icculus@6467
  1086
icculus@6467
  1087
static void
icculus@6467
  1088
X11_EndWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
icculus@6467
  1089
{
icculus@6467
  1090
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
icculus@6467
  1091
    SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
icculus@6467
  1092
    Display *display = data->videodata->display;
icculus@6467
  1093
    const int screen = displaydata->screen;
icculus@6467
  1094
    Window root = RootWindow(display, screen);
slouken@6480
  1095
    Window fswindow = data->fswindow;
icculus@6467
  1096
    XEvent ev;
icculus@6467
  1097
slouken@6480
  1098
    if (!data->fswindow) {
icculus@6467
  1099
        return;  /* already not fullscreen, I hope. */
slouken@6480
  1100
    }
icculus@6467
  1101
slouken@6480
  1102
    data->fswindow = None;
icculus@6467
  1103
icculus@6467
  1104
#if SDL_VIDEO_DRIVER_X11_VIDMODE
icculus@6467
  1105
    if ( displaydata->use_vidmode ) {
icculus@6467
  1106
        XF86VidModeLockModeSwitch(display, screen, False);
icculus@6467
  1107
    }
icculus@6467
  1108
#endif
icculus@6467
  1109
slouken@6480
  1110
    X11_SetWindowGrab(_this, window);
icculus@6467
  1111
slouken@6480
  1112
    XReparentWindow(display, data->xwindow, root, window->x, window->y);
slouken@6480
  1113
slouken@6480
  1114
    /* flush these events so they don't confuse normal event handling */
icculus@6467
  1115
    XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
icculus@6467
  1116
    XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
icculus@6467
  1117
icculus@6467
  1118
    SetWindowBordered(display, screen, data->xwindow,
icculus@6467
  1119
                      (window->flags & SDL_WINDOW_BORDERLESS) == 0);
icculus@6467
  1120
slouken@6480
  1121
    XUnmapWindow(display, fswindow);
slouken@6480
  1122
slouken@6480
  1123
    /* Wait to be unmapped. */
slouken@6480
  1124
    XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&fswindow);
slouken@6480
  1125
    XDestroyWindow(display, fswindow);
icculus@6467
  1126
}
icculus@6467
  1127
icculus@6467
  1128
icculus@6467
  1129
void
icculus@6467
  1130
X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
icculus@6467
  1131
{
icculus@6467
  1132
    /* !!! FIXME: SDL_Hint? */
icculus@6467
  1133
    SDL_bool legacy = SDL_FALSE;
icculus@6467
  1134
    const char *env = SDL_getenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN");
icculus@6467
  1135
    if (env) {
icculus@6467
  1136
        legacy = SDL_atoi(env);
icculus@6467
  1137
    } else {
slouken@6473
  1138
        SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
icculus@6467
  1139
        SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
icculus@6467
  1140
        if ( displaydata->use_vidmode ) {
icculus@6467
  1141
            legacy = SDL_TRUE;  /* the new stuff only works with XRandR. */
slouken@6473
  1142
        } else if ( !videodata->net_wm ) {
slouken@6473
  1143
            legacy = SDL_TRUE;  /* The window manager doesn't support it */
icculus@6467
  1144
        } else {
icculus@6467
  1145
            /* !!! FIXME: look at the window manager name, and blacklist certain ones? */
icculus@6467
  1146
            /* http://stackoverflow.com/questions/758648/find-the-name-of-the-x-window-manager */
icculus@6467
  1147
            legacy = SDL_FALSE;  /* try the new way. */
icculus@6467
  1148
        }
icculus@6467
  1149
    }
icculus@6467
  1150
icculus@6467
  1151
    if (legacy) {
icculus@6467
  1152
        if (fullscreen) {
icculus@6467
  1153
            X11_BeginWindowFullscreenLegacy(_this, window, _display);
icculus@6467
  1154
        } else {
icculus@6467
  1155
            X11_EndWindowFullscreenLegacy(_this, window, _display);
icculus@6467
  1156
        }
icculus@6467
  1157
    } else {
icculus@6467
  1158
        X11_SetWindowFullscreenViaWM(_this, window, _display, fullscreen);
icculus@6467
  1159
    }
icculus@6467
  1160
}
icculus@6467
  1161
icculus@6467
  1162
slouken@5466
  1163
int
slouken@5466
  1164
X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
slouken@5466
  1165
{
slouken@5466
  1166
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@5466
  1167
    Display *display = data->videodata->display;
slouken@5466
  1168
    Visual *visual = data->visual;
slouken@5466
  1169
    Colormap colormap = data->colormap;
slouken@5466
  1170
    XColor *colorcells;
slouken@5466
  1171
    int ncolors;
slouken@5466
  1172
    int rmask, gmask, bmask;
slouken@5466
  1173
    int rshift, gshift, bshift;
icculus@5981
  1174
    int i;
slouken@5466
  1175
slouken@5466
  1176
    if (visual->class != DirectColor) {
slouken@5466
  1177
        SDL_SetError("Window doesn't have DirectColor visual");
slouken@5466
  1178
        return -1;
slouken@5466
  1179
    }
slouken@5466
  1180
slouken@5466
  1181
    ncolors = visual->map_entries;
slouken@5466
  1182
    colorcells = SDL_malloc(ncolors * sizeof(XColor));
slouken@5466
  1183
    if (!colorcells) {
slouken@5466
  1184
        SDL_OutOfMemory();
slouken@5466
  1185
        return -1;
slouken@5466
  1186
    }
slouken@5466
  1187
slouken@5466
  1188
    rshift = 0;
slouken@5466
  1189
    rmask = visual->red_mask;
slouken@5466
  1190
    while (0 == (rmask & 1)) {
slouken@5466
  1191
        rshift++;
slouken@5466
  1192
        rmask >>= 1;
slouken@5466
  1193
    }
slouken@5466
  1194
slouken@5466
  1195
    gshift = 0;
slouken@5466
  1196
    gmask = visual->green_mask;
slouken@5466
  1197
    while (0 == (gmask & 1)) {
slouken@5466
  1198
        gshift++;
slouken@5466
  1199
        gmask >>= 1;
slouken@5466
  1200
    }
slouken@5466
  1201
slouken@5466
  1202
    bshift = 0;
slouken@5466
  1203
    bmask = visual->blue_mask;
slouken@5466
  1204
    while (0 == (bmask & 1)) {
slouken@5466
  1205
        bshift++;
slouken@5466
  1206
        bmask >>= 1;
slouken@5466
  1207
    }
slouken@5466
  1208
slouken@5466
  1209
    /* build the color table pixel values */
slouken@5466
  1210
    for (i = 0; i < ncolors; i++) {
slouken@5466
  1211
        Uint32 rbits = (rmask * i) / (ncolors - 1);
slouken@5466
  1212
        Uint32 gbits = (gmask * i) / (ncolors - 1);
slouken@5466
  1213
        Uint32 bbits = (bmask * i) / (ncolors - 1);
slouken@5466
  1214
        Uint32 pix = (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
slouken@5466
  1215
slouken@5466
  1216
        colorcells[i].pixel = pix;
slouken@5466
  1217
slouken@5466
  1218
        colorcells[i].red = ramp[(0 * 256) + i];
slouken@5466
  1219
        colorcells[i].green = ramp[(1 * 256) + i];
slouken@5466
  1220
        colorcells[i].blue = ramp[(2 * 256) + i];
slouken@5466
  1221
slouken@5466
  1222
        colorcells[i].flags = DoRed | DoGreen | DoBlue;
slouken@5466
  1223
    }
slouken@5466
  1224
slouken@5466
  1225
    XStoreColors(display, colormap, colorcells, ncolors);
slouken@5466
  1226
    XFlush(display);
slouken@5466
  1227
    SDL_free(colorcells);
slouken@5466
  1228
slouken@5466
  1229
    return 0;
slouken@5466
  1230
}
slouken@5466
  1231
slouken@5302
  1232
void
slouken@1951
  1233
X11_SetWindowGrab(_THIS, SDL_Window * window)
slouken@1951
  1234
{
slouken@2875
  1235
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@2875
  1236
    Display *display = data->videodata->display;
slouken@4518
  1237
    SDL_bool oldstyle_fullscreen;
slouken@2875
  1238
slouken@4518
  1239
    /* ICCCM2.0-compliant window managers can handle fullscreen windows */
icculus@6467
  1240
    oldstyle_fullscreen = X11_IsWindowLegacyFullscreen(_this, window);
slouken@4518
  1241
slouken@6500
  1242
    if (oldstyle_fullscreen ||
slouken@6500
  1243
        ((window->flags & SDL_WINDOW_INPUT_GRABBED) &&
slouken@6500
  1244
         (window->flags & SDL_WINDOW_INPUT_FOCUS))) {
slouken@6480
  1245
slouken@2875
  1246
        /* Try to grab the mouse */
slouken@2876
  1247
        for (;;) {
slouken@2876
  1248
            int result =
slouken@3685
  1249
                XGrabPointer(display, data->xwindow, True, 0, GrabModeAsync,
slouken@3685
  1250
                             GrabModeAsync, data->xwindow, None, CurrentTime);
slouken@2876
  1251
            if (result == GrabSuccess) {
slouken@2875
  1252
                break;
slouken@2875
  1253
            }
slouken@2875
  1254
            SDL_Delay(100);
slouken@2875
  1255
        }
slouken@2875
  1256
slouken@2875
  1257
        /* Raise the window if we grab the mouse */
slouken@3685
  1258
        XRaiseWindow(display, data->xwindow);
slouken@2875
  1259
slouken@2875
  1260
        /* Now grab the keyboard */
slouken@3685
  1261
        XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
slouken@2876
  1262
                      GrabModeAsync, CurrentTime);
slouken@2875
  1263
    } else {
slouken@2875
  1264
        XUngrabPointer(display, CurrentTime);
slouken@2875
  1265
        XUngrabKeyboard(display, CurrentTime);
slouken@2875
  1266
    }
slouken@6500
  1267
    XSync(display, False);
slouken@1951
  1268
}
slouken@1951
  1269
slouken@1951
  1270
void
slouken@1951
  1271
X11_DestroyWindow(_THIS, SDL_Window * window)
slouken@1951
  1272
{
slouken@1951
  1273
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
bob@2323
  1274
    window->driverdata = NULL;
slouken@1951
  1275
slouken@1951
  1276
    if (data) {
bob@2323
  1277
        SDL_VideoData *videodata = (SDL_VideoData *) data->videodata;
bob@2323
  1278
        Display *display = videodata->display;
bob@2323
  1279
        int numwindows = videodata->numwindows;
bob@2323
  1280
        SDL_WindowData **windowlist = videodata->windowlist;
bob@2323
  1281
        int i;
bob@2323
  1282
bob@2323
  1283
        if (windowlist) {
bob@2324
  1284
            for (i = 0; i < numwindows; ++i) {
slouken@3685
  1285
                if (windowlist[i] && (windowlist[i]->window == window)) {
bob@2324
  1286
                    windowlist[i] = windowlist[numwindows - 1];
bob@2324
  1287
                    windowlist[numwindows - 1] = NULL;
bob@2324
  1288
                    videodata->numwindows--;
bob@2324
  1289
                    break;
bob@2324
  1290
                }
bob@2323
  1291
            }
bob@2323
  1292
        }
slouken@1951
  1293
#ifdef X_HAVE_UTF8_STRING
slouken@1951
  1294
        if (data->ic) {
slouken@1951
  1295
            XDestroyIC(data->ic);
slouken@1951
  1296
        }
slouken@1951
  1297
#endif
slouken@1951
  1298
        if (data->created) {
slouken@3685
  1299
            XDestroyWindow(display, data->xwindow);
slouken@5031
  1300
            XFlush(display);
slouken@1951
  1301
        }
slouken@1951
  1302
        SDL_free(data);
slouken@1951
  1303
    }
slouken@1951
  1304
}
slouken@1951
  1305
slouken@1951
  1306
SDL_bool
slouken@1951
  1307
X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
slouken@1951
  1308
{
slouken@4510
  1309
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@4510
  1310
    Display *display = data->videodata->display;
slouken@4510
  1311
slouken@4510
  1312
    if (info->version.major == SDL_MAJOR_VERSION &&
slouken@4510
  1313
        info->version.minor == SDL_MINOR_VERSION) {
slouken@4510
  1314
        info->subsystem = SDL_SYSWM_X11;
slouken@5056
  1315
        info->info.x11.display = display;
slouken@5056
  1316
        info->info.x11.window = data->xwindow;
slouken@1951
  1317
        return SDL_TRUE;
slouken@1951
  1318
    } else {
slouken@1951
  1319
        SDL_SetError("Application not compiled with SDL %d.%d\n",
slouken@1951
  1320
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@1951
  1321
        return SDL_FALSE;
slouken@1951
  1322
    }
slouken@1951
  1323
}
slouken@1951
  1324
slouken@5481
  1325
#endif /* SDL_VIDEO_DRIVER_X11 */
slouken@5481
  1326
slouken@1951
  1327
/* vi: set ts=4 sw=4 expandtab: */