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