src/video/x11/SDL_x11window.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 01 Jan 2009 18:58:26 +0000
changeset 2945 e38423786728
parent 2942 1e431c2631ee
child 2967 e4a469d6ddab
permissions -rw-r--r--
Fixed DirectColor visual window creation problem
slouken@1951
     1
/*
slouken@1951
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@1951
     4
slouken@1951
     5
    This library is free software; you can redistribute it and/or
slouken@1951
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1951
     7
    License as published by the Free Software Foundation; either
slouken@1951
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1951
     9
slouken@1951
    10
    This library is distributed in the hope that it will be useful,
slouken@1951
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1951
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1951
    13
    Lesser General Public License for more details.
slouken@1951
    14
slouken@1951
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1951
    16
    License along with this library; if not, write to the Free Software
slouken@1951
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1951
    18
slouken@1951
    19
    Sam Lantinga
slouken@1951
    20
    slouken@libsdl.org
slouken@1951
    21
*/
slouken@1951
    22
#include "SDL_config.h"
slouken@1951
    23
slouken@1951
    24
#include "SDL_syswm.h"
slouken@1951
    25
#include "../SDL_sysvideo.h"
slouken@1951
    26
#include "../../events/SDL_keyboard_c.h"
slouken@2940
    27
#include "../../events/SDL_mouse_c.h"
slouken@1951
    28
slouken@1951
    29
#include "SDL_x11video.h"
slouken@2940
    30
#include "SDL_x11mouse.h"
bob@2185
    31
#include "../Xext/extensions/StdCmap.h"
slouken@1951
    32
slouken@2931
    33
static void
slouken@2931
    34
X11_GetDisplaySize(_THIS, SDL_Window * window, int *w, int *h)
slouken@2931
    35
{
slouken@2931
    36
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@2931
    37
    SDL_DisplayData *displaydata =
slouken@2931
    38
        (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
slouken@2931
    39
    XWindowAttributes attr;
slouken@2931
    40
slouken@2931
    41
    XGetWindowAttributes(data->display, RootWindow(data->display,
slouken@2931
    42
                                                   displaydata->screen),
slouken@2931
    43
                         &attr);
slouken@2931
    44
    if (w) {
slouken@2931
    45
        *w = attr.width;
slouken@2931
    46
    }
slouken@2931
    47
    if (h) {
slouken@2931
    48
        *h = attr.height;
slouken@2931
    49
    }
slouken@2931
    50
}
slouken@2931
    51
slouken@1951
    52
static int
slouken@1951
    53
SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
slouken@1951
    54
{
slouken@1951
    55
    SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
slouken@1951
    56
    SDL_WindowData *data;
slouken@1951
    57
    int numwindows = videodata->numwindows;
bob@2324
    58
    int windowlistlength = videodata->windowlistlength;
slouken@1951
    59
    SDL_WindowData **windowlist = videodata->windowlist;
bob@2323
    60
    int index;
slouken@1951
    61
slouken@1951
    62
    /* Allocate the window data */
bob@2323
    63
    data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
slouken@1951
    64
    if (!data) {
slouken@1951
    65
        SDL_OutOfMemory();
slouken@1951
    66
        return -1;
slouken@1951
    67
    }
slouken@1951
    68
    data->windowID = window->id;
slouken@1951
    69
    data->window = w;
slouken@1951
    70
#ifdef X_HAVE_UTF8_STRING
slouken@1951
    71
    if (SDL_X11_HAVE_UTF8) {
slouken@1951
    72
        data->ic =
slouken@1951
    73
            pXCreateIC(videodata->im, XNClientWindow, w, XNFocusWindow, w,
slouken@1951
    74
                       XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
slouken@1951
    75
                       XNResourceName, videodata->classname, XNResourceClass,
slouken@1951
    76
                       videodata->classname, NULL);
slouken@1951
    77
    }
slouken@1951
    78
#endif
slouken@1951
    79
    data->created = created;
slouken@1951
    80
    data->videodata = videodata;
slouken@1951
    81
bob@2323
    82
    /* Associate the data with the window */
bob@2324
    83
bob@2324
    84
    if (numwindows < windowlistlength) {
bob@2324
    85
        windowlist[numwindows] = data;
bob@2324
    86
        videodata->numwindows++;
bob@2324
    87
    } else {
bob@2324
    88
        windowlist =
bob@2324
    89
            (SDL_WindowData **) SDL_realloc(windowlist,
bob@2324
    90
                                            (numwindows +
bob@2324
    91
                                             1) * sizeof(*windowlist));
bob@2324
    92
        if (!windowlist) {
bob@2324
    93
            SDL_OutOfMemory();
bob@2324
    94
            SDL_free(data);
bob@2324
    95
            return -1;
bob@2323
    96
        }
bob@2324
    97
        windowlist[numwindows] = data;
bob@2324
    98
        videodata->numwindows++;
bob@2324
    99
        videodata->windowlistlength++;
bob@2324
   100
        videodata->windowlist = windowlist;
bob@2323
   101
    }
bob@2323
   102
slouken@1951
   103
    /* Fill in the SDL window with the window data */
slouken@1951
   104
    {
slouken@1951
   105
        XWindowAttributes attrib;
slouken@1951
   106
slouken@1951
   107
        XGetWindowAttributes(data->videodata->display, w, &attrib);
slouken@1951
   108
        window->x = attrib.x;
slouken@1951
   109
        window->y = attrib.y;
slouken@1951
   110
        window->w = attrib.width;
slouken@1951
   111
        window->h = attrib.height;
slouken@1951
   112
        if (attrib.map_state != IsUnmapped) {
slouken@1951
   113
            window->flags |= SDL_WINDOW_SHOWN;
slouken@1951
   114
        } else {
slouken@1951
   115
            window->flags &= ~SDL_WINDOW_SHOWN;
slouken@1951
   116
        }
slouken@1951
   117
    }
slouken@1951
   118
    /* FIXME: How can I tell?
slouken@1951
   119
       {
slouken@1951
   120
       DWORD style = GetWindowLong(hwnd, GWL_STYLE);
slouken@1951
   121
       if (style & WS_VISIBLE) {
slouken@1951
   122
       if (style & (WS_BORDER | WS_THICKFRAME)) {
slouken@1951
   123
       window->flags &= ~SDL_WINDOW_BORDERLESS;
slouken@1951
   124
       } else {
slouken@1951
   125
       window->flags |= SDL_WINDOW_BORDERLESS;
slouken@1951
   126
       }
slouken@1951
   127
       if (style & WS_THICKFRAME) {
slouken@1951
   128
       window->flags |= SDL_WINDOW_RESIZABLE;
slouken@1951
   129
       } else {
slouken@1951
   130
       window->flags &= ~SDL_WINDOW_RESIZABLE;
slouken@1951
   131
       }
slouken@1951
   132
       if (style & WS_MAXIMIZE) {
slouken@1951
   133
       window->flags |= SDL_WINDOW_MAXIMIZED;
slouken@1951
   134
       } else {
slouken@1951
   135
       window->flags &= ~SDL_WINDOW_MAXIMIZED;
slouken@1951
   136
       }
slouken@1951
   137
       if (style & WS_MINIMIZE) {
slouken@1951
   138
       window->flags |= SDL_WINDOW_MINIMIZED;
slouken@1951
   139
       } else {
slouken@1951
   140
       window->flags &= ~SDL_WINDOW_MINIMIZED;
slouken@1951
   141
       }
slouken@1951
   142
       }
slouken@1951
   143
       if (GetFocus() == hwnd) {
slouken@1951
   144
       int index = data->videodata->keyboard;
slouken@1951
   145
       window->flags |= SDL_WINDOW_INPUT_FOCUS;
slouken@1951
   146
       SDL_SetKeyboardFocus(index, data->windowID);
slouken@1951
   147
slouken@1951
   148
       if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
slouken@1951
   149
       RECT rect;
slouken@1951
   150
       GetClientRect(hwnd, &rect);
slouken@1951
   151
       ClientToScreen(hwnd, (LPPOINT) & rect);
slouken@1951
   152
       ClientToScreen(hwnd, (LPPOINT) & rect + 1);
slouken@1951
   153
       ClipCursor(&rect);
slouken@1951
   154
       }
slouken@1951
   155
       }
slouken@1951
   156
     */
slouken@1951
   157
slouken@1951
   158
    /* All done! */
slouken@1951
   159
    window->driverdata = data;
slouken@1951
   160
    return 0;
slouken@1951
   161
}
slouken@1951
   162
slouken@1951
   163
int
slouken@1951
   164
X11_CreateWindow(_THIS, SDL_Window * window)
slouken@1951
   165
{
slouken@1951
   166
    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
slouken@1951
   167
    SDL_DisplayData *displaydata =
slouken@1952
   168
        (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
slouken@1951
   169
    Visual *visual;
slouken@1951
   170
    int depth;
slouken@1951
   171
    XSetWindowAttributes xattr;
slouken@1951
   172
    int x, y;
slouken@1951
   173
    Window w;
slouken@1951
   174
    XSizeHints *sizehints;
slouken@1951
   175
    XWMHints *wmhints;
slouken@1951
   176
    XClassHint *classhints;
slouken@1951
   177
slouken@1951
   178
#if SDL_VIDEO_DRIVER_X11_XINERAMA
slouken@1951
   179
/* FIXME
slouken@1951
   180
    if ( use_xinerama ) {
slouken@1951
   181
        x = xinerama_info.x_org;
slouken@1951
   182
        y = xinerama_info.y_org;
slouken@1951
   183
    }
slouken@1951
   184
*/
slouken@1951
   185
#endif
slouken@1952
   186
#ifdef SDL_VIDEO_OPENGL_GLX
slouken@1951
   187
    if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1952
   188
        XVisualInfo *vinfo;
slouken@1952
   189
slouken@1952
   190
        if (X11_GL_Initialize(_this) < 0) {
slouken@1952
   191
            return -1;
slouken@1952
   192
        }
slouken@1952
   193
        vinfo = X11_GL_GetVisual(_this, data->display, displaydata->screen);
slouken@1952
   194
        if (!vinfo) {
slouken@1952
   195
            return -1;
slouken@1952
   196
        }
slouken@1952
   197
        visual = vinfo->visual;
slouken@1952
   198
        depth = vinfo->depth;
slouken@1952
   199
        XFree(vinfo);
slouken@1952
   200
    } else
slouken@1952
   201
#endif
slouken@1952
   202
    {
slouken@1951
   203
        visual = displaydata->visual;
slouken@1951
   204
        depth = displaydata->depth;
slouken@1951
   205
    }
slouken@1951
   206
slouken@1951
   207
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1951
   208
        xattr.override_redirect = True;
slouken@1951
   209
    } else {
slouken@1951
   210
        xattr.override_redirect = False;
slouken@1951
   211
    }
slouken@1951
   212
    xattr.background_pixel = 0;
slouken@1951
   213
    xattr.border_pixel = 0;
bob@2214
   214
slouken@2945
   215
    if (visual->class == PseudoColor) {
bob@2185
   216
        int nmaps;
bob@2214
   217
        XStandardColormap cmap;
bob@2185
   218
        XStandardColormap *stdmaps;
bob@2214
   219
        XColor *colorcells;
bob@2214
   220
        Colormap colormap;
bob@2185
   221
        Bool found = False;
bob@2214
   222
        int i;
bob@2214
   223
        int ncolors;
bob@2214
   224
        int rmax, gmax, bmax;
bob@2214
   225
        int rmul, gmul, bmul;
bob@2185
   226
bob@2214
   227
        if (colormap =
bob@2214
   228
            X11_LookupColormap(data->display, displaydata->screen,
bob@2214
   229
                               visual->visualid)) {
bob@2214
   230
            xattr.colormap = colormap;
bob@2214
   231
        } else {
bob@2214
   232
            /* check to see if the colormap we need already exists */
bob@2214
   233
            if (0 != XGetRGBColormaps(data->display,
bob@2214
   234
                                      RootWindow(data->display,
bob@2214
   235
                                                 displaydata->screen),
bob@2214
   236
                                      &stdmaps, &nmaps, XA_RGB_BEST_MAP)) {
bob@2214
   237
                for (i = 0; i < nmaps; i++) {
bob@2214
   238
                    if (stdmaps[i].visualid == visual->visualid) {
bob@2214
   239
                        SDL_memcpy(&cmap, &stdmaps[i],
bob@2214
   240
                                   sizeof(XStandardColormap));
bob@2214
   241
                        found = True;
bob@2214
   242
                        break;
bob@2214
   243
                    }
bob@2185
   244
                }
bob@2214
   245
                XFree(stdmaps);
bob@2185
   246
            }
bob@2213
   247
bob@2214
   248
            /* it doesn't exist, so create it */
bob@2214
   249
            if (!found) {
bob@2214
   250
                int max = visual->map_entries - 1;
bob@2214
   251
                stdmaps =
bob@2214
   252
                    XmuStandardColormap(data->display, displaydata->screen,
bob@2214
   253
                                        visual->visualid, depth,
bob@2214
   254
                                        XA_RGB_BEST_MAP, None, max, max, max);
bob@2214
   255
                if (NULL == stdmaps || stdmaps->visualid != visual->visualid) {
bob@2214
   256
                    SDL_SetError
bob@2214
   257
                        ("Couldn't create window:XA_RGB_BEST_MAP not found and could not be created");
bob@2214
   258
                    return -1;
bob@2214
   259
                }
bob@2214
   260
                SDL_memcpy(&cmap, stdmaps, sizeof(XStandardColormap));
bob@2322
   261
                XFree(stdmaps);
bob@2214
   262
            }
bob@2214
   263
bob@2214
   264
            /* OK, we have the best color map, now copy it for use by the
bob@2214
   265
               program */
bob@2214
   266
bob@2214
   267
            colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
bob@2214
   268
            if (NULL == colorcells) {
bob@2214
   269
                SDL_SetError("out of memory in X11_CreateWindow");
bob@2185
   270
                return -1;
bob@2185
   271
            }
bob@2214
   272
            ncolors = visual->map_entries;
bob@2214
   273
            rmax = cmap.red_max + 1;
bob@2214
   274
            gmax = cmap.blue_max + 1;
bob@2214
   275
            bmax = cmap.green_max + 1;
bob@2214
   276
bob@2214
   277
            rmul = cmap.red_mult;
bob@2214
   278
            gmul = cmap.blue_mult;
bob@2214
   279
            bmul = cmap.green_mult;
bob@2214
   280
bob@2214
   281
            /* build the color table pixel values */
bob@2214
   282
            for (i = 0; i < ncolors; i++) {
bob@2214
   283
                Uint32 red = (rmax * i) / ncolors;
bob@2214
   284
                Uint32 green = (gmax * i) / ncolors;
bob@2214
   285
                Uint32 blue = (bmax * i) / ncolors;
bob@2214
   286
bob@2214
   287
                colorcells[i].pixel =
bob@2214
   288
                    (red * rmul) | (green * gmul) | (blue * bmul);
bob@2214
   289
            }
bob@2214
   290
            XQueryColors(data->display, cmap.colormap, colorcells, ncolors);
bob@2214
   291
            colormap = XCreateColormap(data->display,
bob@2214
   292
                                       RootWindow(data->display,
bob@2214
   293
                                                  displaydata->screen),
bob@2214
   294
                                       visual, AllocAll);
bob@2214
   295
            XStoreColors(data->display, colormap, colorcells, ncolors);
bob@2214
   296
            SDL_free(colorcells);
bob@2214
   297
bob@2214
   298
            xattr.colormap = colormap;
bob@2214
   299
            X11_TrackColormap(data->display, displaydata->screen, colormap,
bob@2214
   300
                              &cmap, visual);
bob@2185
   301
        }
slouken@2945
   302
    } else if (visual->class == DirectColor) {
slouken@2945
   303
        /* FIXME: Allocate a read-write colormap for gamma fading someday */
slouken@2945
   304
        xattr.colormap =
slouken@2945
   305
            XCreateColormap(data->display,
slouken@2945
   306
                            RootWindow(data->display, displaydata->screen),
slouken@2945
   307
                            visual, AllocNone);
slouken@1951
   308
    } else {
slouken@1951
   309
        xattr.colormap =
slouken@1951
   310
            XCreateColormap(data->display,
slouken@1951
   311
                            RootWindow(data->display, displaydata->screen),
slouken@1951
   312
                            visual, AllocNone);
slouken@1951
   313
    }
slouken@1951
   314
slouken@2876
   315
    if ((window->flags & SDL_WINDOW_FULLSCREEN)
slouken@2876
   316
        || window->x == SDL_WINDOWPOS_CENTERED) {
slouken@2931
   317
        X11_GetDisplaySize(_this, window, &x, NULL);
slouken@2931
   318
        x = (x - window->w) / 2;
slouken@1951
   319
    } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
slouken@1951
   320
        x = 0;
slouken@1951
   321
    } else {
slouken@1951
   322
        x = window->x;
slouken@1951
   323
    }
slouken@2876
   324
    if ((window->flags & SDL_WINDOW_FULLSCREEN)
slouken@2876
   325
        || window->y == SDL_WINDOWPOS_CENTERED) {
slouken@2931
   326
        X11_GetDisplaySize(_this, window, NULL, &y);
slouken@2931
   327
        y = (y - window->h) / 2;
slouken@1951
   328
    } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
slouken@1951
   329
        y = 0;
slouken@1951
   330
    } else {
slouken@1951
   331
        y = window->y;
slouken@1951
   332
    }
slouken@1951
   333
slouken@1951
   334
    w = XCreateWindow(data->display,
slouken@1951
   335
                      RootWindow(data->display, displaydata->screen), x, y,
slouken@1951
   336
                      window->w, window->h, 0, depth, InputOutput, visual,
slouken@1951
   337
                      (CWOverrideRedirect | CWBackPixel | CWBorderPixel |
slouken@1951
   338
                       CWColormap), &xattr);
slouken@1952
   339
    if (!w) {
slouken@1952
   340
#ifdef SDL_VIDEO_OPENGL_GLX
slouken@1952
   341
        if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1952
   342
            X11_GL_Shutdown(_this);
slouken@1952
   343
        }
slouken@1952
   344
#endif
slouken@1952
   345
        SDL_SetError("Couldn't create window");
slouken@1952
   346
        return -1;
slouken@1952
   347
    }
slouken@1951
   348
slouken@1951
   349
    sizehints = XAllocSizeHints();
slouken@1951
   350
    if (sizehints) {
slouken@2876
   351
        if ((window->flags & SDL_WINDOW_RESIZABLE)
slouken@2876
   352
            && !(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@1951
   353
            sizehints->min_width = 32;
slouken@1951
   354
            sizehints->min_height = 32;
slouken@1951
   355
            sizehints->max_height = 4096;
slouken@1951
   356
            sizehints->max_width = 4096;
slouken@1951
   357
        } else {
slouken@1951
   358
            sizehints->min_width = sizehints->max_width = window->w;
slouken@1951
   359
            sizehints->min_height = sizehints->max_height = window->h;
slouken@1951
   360
        }
slouken@1951
   361
        sizehints->flags = PMaxSize | PMinSize;
slouken@1951
   362
        if (!(window->flags & SDL_WINDOW_FULLSCREEN)
slouken@1951
   363
            && window->x != SDL_WINDOWPOS_UNDEFINED
slouken@1951
   364
            && window->y != SDL_WINDOWPOS_UNDEFINED) {
slouken@1951
   365
            sizehints->x = x;
slouken@1951
   366
            sizehints->y = y;
slouken@1951
   367
            sizehints->flags |= USPosition;
slouken@1951
   368
        }
slouken@1951
   369
        XSetWMNormalHints(data->display, w, sizehints);
slouken@1951
   370
        XFree(sizehints);
slouken@1951
   371
    }
slouken@1951
   372
slouken@2876
   373
    if (window->flags & (SDL_WINDOW_BORDERLESS | SDL_WINDOW_FULLSCREEN)) {
slouken@1951
   374
        SDL_bool set;
slouken@1951
   375
        Atom WM_HINTS;
slouken@1951
   376
slouken@1951
   377
        /* We haven't modified the window manager hints yet */
slouken@1951
   378
        set = SDL_FALSE;
slouken@1951
   379
slouken@1951
   380
        /* First try to set MWM hints */
slouken@1951
   381
        WM_HINTS = XInternAtom(data->display, "_MOTIF_WM_HINTS", True);
slouken@1951
   382
        if (WM_HINTS != None) {
slouken@1951
   383
            /* Hints used by Motif compliant window managers */
slouken@1951
   384
            struct
slouken@1951
   385
            {
slouken@1951
   386
                unsigned long flags;
slouken@1951
   387
                unsigned long functions;
slouken@1951
   388
                unsigned long decorations;
slouken@1951
   389
                long input_mode;
slouken@1951
   390
                unsigned long status;
slouken@1951
   391
            } MWMHints = {
slouken@1951
   392
            (1L << 1), 0, 0, 0, 0};
slouken@1951
   393
slouken@1951
   394
            XChangeProperty(data->display, w, WM_HINTS, WM_HINTS, 32,
slouken@1951
   395
                            PropModeReplace, (unsigned char *) &MWMHints,
slouken@1951
   396
                            sizeof(MWMHints) / sizeof(long));
slouken@1951
   397
            set = SDL_TRUE;
slouken@1951
   398
        }
slouken@1951
   399
        /* Now try to set KWM hints */
slouken@1951
   400
        WM_HINTS = XInternAtom(data->display, "KWM_WIN_DECORATION", True);
slouken@1951
   401
        if (WM_HINTS != None) {
slouken@1951
   402
            long KWMHints = 0;
slouken@1951
   403
slouken@1951
   404
            XChangeProperty(data->display, w,
slouken@1951
   405
                            WM_HINTS, WM_HINTS, 32,
slouken@1951
   406
                            PropModeReplace,
slouken@1951
   407
                            (unsigned char *) &KWMHints,
slouken@1951
   408
                            sizeof(KWMHints) / sizeof(long));
slouken@1951
   409
            set = SDL_TRUE;
slouken@1951
   410
        }
slouken@1951
   411
        /* Now try to set GNOME hints */
slouken@1951
   412
        WM_HINTS = XInternAtom(data->display, "_WIN_HINTS", True);
slouken@1951
   413
        if (WM_HINTS != None) {
slouken@1951
   414
            long GNOMEHints = 0;
slouken@1951
   415
slouken@1951
   416
            XChangeProperty(data->display, w,
slouken@1951
   417
                            WM_HINTS, WM_HINTS, 32,
slouken@1951
   418
                            PropModeReplace,
slouken@1951
   419
                            (unsigned char *) &GNOMEHints,
slouken@1951
   420
                            sizeof(GNOMEHints) / sizeof(long));
slouken@1951
   421
            set = SDL_TRUE;
slouken@1951
   422
        }
slouken@1951
   423
        /* Finally set the transient hints if necessary */
slouken@1951
   424
        if (!set) {
slouken@1951
   425
            XSetTransientForHint(data->display, w,
slouken@1951
   426
                                 RootWindow(data->display,
slouken@1951
   427
                                            displaydata->screen));
slouken@1951
   428
        }
slouken@1951
   429
    } else {
slouken@1951
   430
        SDL_bool set;
slouken@1951
   431
        Atom WM_HINTS;
slouken@1951
   432
slouken@1951
   433
        /* We haven't modified the window manager hints yet */
slouken@1951
   434
        set = SDL_FALSE;
slouken@1951
   435
slouken@1951
   436
        /* First try to unset MWM hints */
slouken@1951
   437
        WM_HINTS = XInternAtom(data->display, "_MOTIF_WM_HINTS", True);
slouken@1951
   438
        if (WM_HINTS != None) {
slouken@1951
   439
            XDeleteProperty(data->display, w, WM_HINTS);
slouken@1951
   440
            set = SDL_TRUE;
slouken@1951
   441
        }
slouken@1951
   442
        /* Now try to unset KWM hints */
slouken@1951
   443
        WM_HINTS = XInternAtom(data->display, "KWM_WIN_DECORATION", True);
slouken@1951
   444
        if (WM_HINTS != None) {
slouken@1951
   445
            XDeleteProperty(data->display, w, WM_HINTS);
slouken@1951
   446
            set = SDL_TRUE;
slouken@1951
   447
        }
slouken@1951
   448
        /* Now try to unset GNOME hints */
slouken@1951
   449
        WM_HINTS = XInternAtom(data->display, "_WIN_HINTS", True);
slouken@1951
   450
        if (WM_HINTS != None) {
slouken@1951
   451
            XDeleteProperty(data->display, w, WM_HINTS);
slouken@1951
   452
            set = SDL_TRUE;
slouken@1951
   453
        }
slouken@1951
   454
        /* Finally unset the transient hints if necessary */
slouken@1951
   455
        if (!set) {
slouken@1951
   456
            /* NOTE: Does this work? */
slouken@1951
   457
            XSetTransientForHint(data->display, w, None);
slouken@1951
   458
        }
slouken@1951
   459
    }
slouken@1951
   460
slouken@1951
   461
    /* Tell KDE to keep fullscreen windows on top */
slouken@1951
   462
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1951
   463
        XEvent ev;
slouken@1951
   464
        long mask;
slouken@1951
   465
slouken@1951
   466
        SDL_zero(ev);
slouken@1951
   467
        ev.xclient.type = ClientMessage;
slouken@1951
   468
        ev.xclient.window = RootWindow(data->display, displaydata->screen);
slouken@1951
   469
        ev.xclient.message_type =
slouken@1951
   470
            XInternAtom(data->display, "KWM_KEEP_ON_TOP", False);
slouken@1951
   471
        ev.xclient.format = 32;
slouken@1951
   472
        ev.xclient.data.l[0] = w;
slouken@1951
   473
        ev.xclient.data.l[1] = CurrentTime;
slouken@1951
   474
        XSendEvent(data->display,
slouken@1951
   475
                   RootWindow(data->display, displaydata->screen), False,
slouken@1951
   476
                   SubstructureRedirectMask, &ev);
slouken@1951
   477
    }
slouken@1951
   478
slouken@1951
   479
    /* Set the input hints so we get keyboard input */
slouken@1951
   480
    wmhints = XAllocWMHints();
slouken@1951
   481
    if (wmhints) {
slouken@1951
   482
        wmhints->input = True;
slouken@1956
   483
        wmhints->flags = InputHint;
slouken@1951
   484
        XSetWMHints(data->display, w, wmhints);
slouken@1951
   485
        XFree(wmhints);
slouken@1951
   486
    }
slouken@1951
   487
slouken@1951
   488
    /* Set the class hints so we can get an icon (AfterStep) */
slouken@1951
   489
    classhints = XAllocClassHint();
slouken@1951
   490
    if (classhints != NULL) {
slouken@1951
   491
        classhints->res_name = data->classname;
slouken@1951
   492
        classhints->res_class = data->classname;
slouken@1951
   493
        XSetClassHint(data->display, w, classhints);
slouken@1951
   494
        XFree(classhints);
slouken@1951
   495
    }
slouken@1951
   496
slouken@1951
   497
    /* Allow the window to be deleted by the window manager */
slouken@1951
   498
    XSetWMProtocols(data->display, w, &data->WM_DELETE_WINDOW, 1);
slouken@1951
   499
slouken@1951
   500
    if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
slouken@1952
   501
#ifdef SDL_VIDEO_OPENGL_GLX
slouken@1952
   502
        if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1952
   503
            X11_GL_Shutdown(_this);
slouken@1952
   504
        }
slouken@1952
   505
#endif
slouken@1951
   506
        XDestroyWindow(data->display, w);
slouken@1951
   507
        return -1;
slouken@1951
   508
    }
bob@2325
   509
#ifdef X_HAVE_UTF8_STRING
bob@2325
   510
    {
bob@2325
   511
        Uint32 fevent = 0;
bob@2325
   512
        pXGetICValues(((SDL_WindowData *) window->driverdata)->ic,
bob@2325
   513
                      XNFilterEvents, &fevent, NULL);
bob@2325
   514
        XSelectInput(data->display, w,
bob@2325
   515
                     (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
bob@2325
   516
                      ExposureMask | ButtonPressMask | ButtonReleaseMask |
bob@2325
   517
                      PointerMotionMask | KeyPressMask | KeyReleaseMask |
bob@2325
   518
                      PropertyChangeMask | StructureNotifyMask |
bob@2325
   519
                      KeymapStateMask | fevent));
bob@2325
   520
    }
bob@2325
   521
#else
kazeuser@2718
   522
    {
kazeuser@2718
   523
        XSelectInput(data->display, w,
slouken@2725
   524
                     (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
slouken@2725
   525
                      ExposureMask | ButtonPressMask | ButtonReleaseMask |
slouken@2725
   526
                      PointerMotionMask | KeyPressMask | KeyReleaseMask |
slouken@2725
   527
                      PropertyChangeMask | StructureNotifyMask |
slouken@2725
   528
                      KeymapStateMask));
kazeuser@2718
   529
    }
bob@2325
   530
#endif
bob@2325
   531
slouken@2940
   532
#if SDL_VIDEO_DRIVER_X11_XINPUT
slouken@2710
   533
    /* we're informing the display what extension events we want to receive from it */
slouken@2940
   534
    {
slouken@2940
   535
        int i, j, n = 0;
slouken@2940
   536
        XEventClass xevents[256];
slouken@2940
   537
slouken@2940
   538
        for (i = 0; i < SDL_GetNumMice(); ++i) {
slouken@2940
   539
            SDL_Mouse *mouse;
slouken@2940
   540
            X11_MouseData *data;
slouken@2940
   541
slouken@2940
   542
            mouse = SDL_GetMouse(i);
slouken@2942
   543
            data = (X11_MouseData *) mouse->driverdata;
slouken@2940
   544
            if (!data) {
slouken@2940
   545
                continue;
slouken@2940
   546
            }
slouken@2940
   547
slouken@2940
   548
            for (j = 0; j < data->num_xevents; ++j) {
slouken@2940
   549
                xevents[n++] = data->xevents[j];
slouken@2940
   550
            }
slouken@2940
   551
        }
slouken@2940
   552
        if (n > 0) {
slouken@2940
   553
            XSelectExtensionEvent(data->display, w, xevents, n);
slouken@2940
   554
        }
slouken@2940
   555
    }
slouken@2940
   556
#endif
slouken@2710
   557
slouken@1951
   558
    return 0;
slouken@1951
   559
}
slouken@1951
   560
slouken@1951
   561
int
bob@2324
   562
X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@1951
   563
{
slouken@1951
   564
    Window w = (Window) data;
slouken@1951
   565
slouken@1951
   566
    /* FIXME: Query the title from the existing window */
slouken@1951
   567
slouken@1951
   568
    if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
slouken@1951
   569
        return -1;
slouken@1951
   570
    }
slouken@1951
   571
    return 0;
slouken@1951
   572
}
slouken@1951
   573
slouken@1951
   574
void
slouken@1951
   575
X11_SetWindowTitle(_THIS, SDL_Window * window)
slouken@1951
   576
{
slouken@1951
   577
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   578
    Display *display = data->videodata->display;
slouken@1951
   579
    XTextProperty titleprop, iconprop;
slouken@1951
   580
    Status status;
slouken@1951
   581
    const char *title = window->title;
slouken@1951
   582
    const char *icon = NULL;
slouken@1951
   583
slouken@1951
   584
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   585
    Atom _NET_WM_NAME = 0;
slouken@1951
   586
    Atom _NET_WM_ICON_NAME = 0;
slouken@1951
   587
slouken@1951
   588
    /* Look up some useful Atoms */
slouken@1951
   589
    if (SDL_X11_HAVE_UTF8) {
slouken@1951
   590
        _NET_WM_NAME = XInternAtom(display, "_NET_WM_NAME", False);
slouken@1951
   591
        _NET_WM_ICON_NAME = XInternAtom(display, "_NET_WM_ICON_NAME", False);
slouken@1951
   592
    }
slouken@1951
   593
#endif
slouken@1951
   594
slouken@1951
   595
    if (title != NULL) {
slouken@2143
   596
        char *title_locale = SDL_iconv_utf8_locale(title);
slouken@2143
   597
        if (!title_locale) {
slouken@1951
   598
            SDL_OutOfMemory();
slouken@1951
   599
            return;
slouken@1951
   600
        }
slouken@2143
   601
        status = XStringListToTextProperty(&title_locale, 1, &titleprop);
slouken@2143
   602
        SDL_free(title_locale);
slouken@1951
   603
        if (status) {
slouken@1951
   604
            XSetTextProperty(display, data->window, &titleprop, XA_WM_NAME);
slouken@1951
   605
            XFree(titleprop.value);
slouken@1951
   606
        }
slouken@1951
   607
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   608
        if (SDL_X11_HAVE_UTF8) {
slouken@1951
   609
            status =
slouken@1951
   610
                Xutf8TextListToTextProperty(display, (char **) &title, 1,
slouken@1951
   611
                                            XUTF8StringStyle, &titleprop);
slouken@1951
   612
            if (status == Success) {
slouken@1951
   613
                XSetTextProperty(display, data->window, &titleprop,
slouken@1951
   614
                                 _NET_WM_NAME);
slouken@1951
   615
                XFree(titleprop.value);
slouken@1951
   616
            }
slouken@1951
   617
        }
slouken@1951
   618
#endif
slouken@1951
   619
    }
slouken@1951
   620
    if (icon != NULL) {
slouken@2143
   621
        char *icon_locale = SDL_iconv_utf8_locale(icon);
slouken@2143
   622
        if (!icon_locale) {
slouken@1951
   623
            SDL_OutOfMemory();
slouken@1951
   624
            return;
slouken@1951
   625
        }
slouken@2143
   626
        status = XStringListToTextProperty(&icon_locale, 1, &iconprop);
slouken@2143
   627
        SDL_free(icon_locale);
slouken@1951
   628
        if (status) {
slouken@1951
   629
            XSetTextProperty(display, data->window, &iconprop,
slouken@1951
   630
                             XA_WM_ICON_NAME);
slouken@1951
   631
            XFree(iconprop.value);
slouken@1951
   632
        }
slouken@1951
   633
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   634
        if (SDL_X11_HAVE_UTF8) {
slouken@1951
   635
            status =
slouken@1951
   636
                Xutf8TextListToTextProperty(display, (char **) &icon, 1,
slouken@1951
   637
                                            XUTF8StringStyle, &iconprop);
slouken@1951
   638
            if (status == Success) {
slouken@1951
   639
                XSetTextProperty(display, data->window, &iconprop,
slouken@1951
   640
                                 _NET_WM_ICON_NAME);
slouken@1951
   641
                XFree(iconprop.value);
slouken@1951
   642
            }
slouken@1951
   643
        }
slouken@1951
   644
#endif
slouken@1951
   645
    }
slouken@1951
   646
}
slouken@1951
   647
slouken@1951
   648
void
slouken@1951
   649
X11_SetWindowPosition(_THIS, SDL_Window * window)
slouken@1951
   650
{
slouken@1951
   651
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   652
    SDL_DisplayData *displaydata =
slouken@1952
   653
        (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
slouken@1951
   654
    Display *display = data->videodata->display;
slouken@2875
   655
    int x, y;
slouken@1951
   656
slouken@2876
   657
    if ((window->flags & SDL_WINDOW_FULLSCREEN)
slouken@2876
   658
        || window->x == SDL_WINDOWPOS_CENTERED) {
slouken@2931
   659
        X11_GetDisplaySize(_this, window, &x, NULL);
slouken@2931
   660
        x = (x - window->w) / 2;
slouken@2875
   661
    } else {
slouken@2875
   662
        x = window->x;
slouken@2875
   663
    }
slouken@2876
   664
    if ((window->flags & SDL_WINDOW_FULLSCREEN)
slouken@2876
   665
        || window->y == SDL_WINDOWPOS_CENTERED) {
slouken@2931
   666
        X11_GetDisplaySize(_this, window, NULL, &y);
slouken@2931
   667
        y = (y - window->h) / 2;
slouken@2875
   668
    } else {
slouken@2875
   669
        y = window->y;
slouken@2875
   670
    }
slouken@2875
   671
    XMoveWindow(display, data->window, x, y);
slouken@1951
   672
}
slouken@1951
   673
slouken@1951
   674
void
slouken@1951
   675
X11_SetWindowSize(_THIS, SDL_Window * window)
slouken@1951
   676
{
slouken@1951
   677
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   678
    Display *display = data->videodata->display;
slouken@1951
   679
slouken@2931
   680
    XResizeWindow(display, data->window, window->w, window->h);
slouken@1951
   681
}
slouken@1951
   682
slouken@1951
   683
void
slouken@1951
   684
X11_ShowWindow(_THIS, SDL_Window * window)
slouken@1951
   685
{
slouken@1951
   686
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   687
    Display *display = data->videodata->display;
slouken@1951
   688
slouken@1951
   689
    XMapRaised(display, data->window);
slouken@1951
   690
}
slouken@1951
   691
slouken@1951
   692
void
slouken@1951
   693
X11_HideWindow(_THIS, SDL_Window * window)
slouken@1951
   694
{
slouken@1951
   695
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   696
    Display *display = data->videodata->display;
slouken@1951
   697
slouken@1951
   698
    XUnmapWindow(display, data->window);
slouken@1951
   699
}
slouken@1951
   700
slouken@1951
   701
void
slouken@1951
   702
X11_RaiseWindow(_THIS, SDL_Window * window)
slouken@1951
   703
{
slouken@1951
   704
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   705
    Display *display = data->videodata->display;
slouken@1951
   706
slouken@1951
   707
    XRaiseWindow(display, data->window);
slouken@1951
   708
}
slouken@1951
   709
slouken@1951
   710
void
slouken@1951
   711
X11_MaximizeWindow(_THIS, SDL_Window * window)
slouken@1951
   712
{
slouken@1951
   713
    /* FIXME: is this even possible? */
slouken@1951
   714
}
slouken@1951
   715
slouken@1951
   716
void
slouken@1951
   717
X11_MinimizeWindow(_THIS, SDL_Window * window)
slouken@1951
   718
{
slouken@1951
   719
    X11_HideWindow(_this, window);
slouken@1951
   720
}
slouken@1951
   721
slouken@1951
   722
void
slouken@1951
   723
X11_RestoreWindow(_THIS, SDL_Window * window)
slouken@1951
   724
{
slouken@1951
   725
    X11_ShowWindow(_this, window);
slouken@1951
   726
}
slouken@1951
   727
slouken@1951
   728
void
slouken@1951
   729
X11_SetWindowGrab(_THIS, SDL_Window * window)
slouken@1951
   730
{
slouken@2875
   731
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@2875
   732
    Display *display = data->videodata->display;
slouken@2875
   733
slouken@2876
   734
    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
slouken@2876
   735
        && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@2875
   736
        /* Try to grab the mouse */
slouken@2876
   737
        for (;;) {
slouken@2876
   738
            int result =
slouken@2876
   739
                XGrabPointer(display, data->window, True, 0, GrabModeAsync,
slouken@2876
   740
                             GrabModeAsync, data->window, None, CurrentTime);
slouken@2876
   741
            if (result == GrabSuccess) {
slouken@2875
   742
                break;
slouken@2875
   743
            }
slouken@2875
   744
            SDL_Delay(100);
slouken@2875
   745
        }
slouken@2875
   746
slouken@2875
   747
        /* Raise the window if we grab the mouse */
slouken@2875
   748
        XRaiseWindow(display, data->window);
slouken@2875
   749
slouken@2875
   750
        /* Now grab the keyboard */
slouken@2876
   751
        XGrabKeyboard(display, data->window, True, GrabModeAsync,
slouken@2876
   752
                      GrabModeAsync, CurrentTime);
slouken@2875
   753
    } else {
slouken@2875
   754
        XUngrabPointer(display, CurrentTime);
slouken@2875
   755
        XUngrabKeyboard(display, CurrentTime);
slouken@2875
   756
    }
slouken@1951
   757
}
slouken@1951
   758
slouken@1951
   759
void
slouken@1951
   760
X11_DestroyWindow(_THIS, SDL_Window * window)
slouken@1951
   761
{
slouken@1951
   762
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
bob@2323
   763
    window->driverdata = NULL;
slouken@1951
   764
slouken@1951
   765
    if (data) {
bob@2323
   766
        SDL_VideoData *videodata = (SDL_VideoData *) data->videodata;
bob@2323
   767
        Display *display = videodata->display;
bob@2323
   768
        int numwindows = videodata->numwindows;
bob@2323
   769
        SDL_WindowData **windowlist = videodata->windowlist;
bob@2323
   770
        int i;
bob@2323
   771
bob@2323
   772
        if (windowlist) {
bob@2324
   773
            for (i = 0; i < numwindows; ++i) {
bob@2324
   774
                if (windowlist[i] && (windowlist[i]->windowID == window->id)) {
bob@2324
   775
                    windowlist[i] = windowlist[numwindows - 1];
bob@2324
   776
                    windowlist[numwindows - 1] = NULL;
bob@2324
   777
                    videodata->numwindows--;
bob@2324
   778
                    break;
bob@2324
   779
                }
bob@2323
   780
            }
bob@2323
   781
        }
slouken@1952
   782
#ifdef SDL_VIDEO_OPENGL_GLX
slouken@1952
   783
        if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1952
   784
            X11_GL_Shutdown(_this);
slouken@1952
   785
        }
slouken@1951
   786
#endif
slouken@1951
   787
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   788
        if (data->ic) {
slouken@1951
   789
            XDestroyIC(data->ic);
slouken@1951
   790
        }
slouken@1951
   791
#endif
slouken@1951
   792
        if (data->created) {
slouken@1951
   793
            XDestroyWindow(display, data->window);
slouken@1951
   794
        }
slouken@1951
   795
        SDL_free(data);
slouken@1951
   796
    }
slouken@1951
   797
}
slouken@1951
   798
slouken@1951
   799
SDL_bool
slouken@1951
   800
X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
slouken@1951
   801
{
slouken@1951
   802
    if (info->version.major <= SDL_MAJOR_VERSION) {
slouken@1951
   803
        /* FIXME! */
slouken@1951
   804
        return SDL_TRUE;
slouken@1951
   805
    } else {
slouken@1951
   806
        SDL_SetError("Application not compiled with SDL %d.%d\n",
slouken@1951
   807
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@1951
   808
        return SDL_FALSE;
slouken@1951
   809
    }
slouken@1951
   810
}
slouken@1951
   811
slouken@1951
   812
/* vi: set ts=4 sw=4 expandtab: */