src/video/x11/SDL_x11window.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 18 Jul 2012 15:17:27 -0700
changeset 6370 93187f7f7d5d
parent 6369 a92fbd27127b
child 6373 494e0436525f
permissions -rwxr-xr-x
Improved simultaneous support for OpenGL and OpenGL ES

From Scott Percival

Okay, I think I have something for this. Tested it on GL and GLES
machines, it seems to work okay.

- Add a new SDL GL attribute SDL_GL_CONTEXT_EGL:
- Only useful for the X11 video driver at the moment
- Set to 1 for an EGL context, 0 to use the default for the video driver
- Default is 0, unless library is built for EGL only
- Should be set after SDL init, but before window/context
creation (i.e. same place you'd specify attributes for major/minor GL
version)
- After a lot of agony pondering the least-terrible way to go about
it, made it so that X11_GL_LoadLibrary and X11_GLES_LoadLibrary check
SDL_GL_CONTEXT_EGL. If no GL context exists yet, and the attribute
choice doesn't match with the checking function, then it changes all
the function pointers in the video driver and passes control on to the
new LoadLibrary method.
- Likewise, make X11_CreateWindow check this attribute before firing
off a call to X11_GL_GetVisual/X11_GLES_GetVisual
- Added a sanity check to the start of X11_GL_LoadLibrary
- Tidied up SDL_x11opengles.h
- Moved ownership of the gles_data structure over to
X11_GLES_LoadLibrary/UnloadLibrary
- Should incorporate the 3 fixes posted by Andre Heider

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