src/video/x11/SDL_x11window.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 01 Jan 2009 07:59:08 +0000
changeset 2940 b93965a16fe0
parent 2931 e705adf6f3dc
child 2942 1e431c2631ee
permissions -rw-r--r--
Fixed X11 mouse motion/button events - it's not actually safe to cast mouse events to device events.
Fixed building SDL without XInput support
Simplified the process of registering a mouse device
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
bob@2211
   215
    if (visual->class == DirectColor || 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@1951
   302
    } else {
slouken@1951
   303
        xattr.colormap =
slouken@1951
   304
            XCreateColormap(data->display,
slouken@1951
   305
                            RootWindow(data->display, displaydata->screen),
slouken@1951
   306
                            visual, AllocNone);
slouken@1951
   307
    }
slouken@1951
   308
slouken@2876
   309
    if ((window->flags & SDL_WINDOW_FULLSCREEN)
slouken@2876
   310
        || window->x == SDL_WINDOWPOS_CENTERED) {
slouken@2931
   311
        X11_GetDisplaySize(_this, window, &x, NULL);
slouken@2931
   312
        x = (x - window->w) / 2;
slouken@1951
   313
    } else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
slouken@1951
   314
        x = 0;
slouken@1951
   315
    } else {
slouken@1951
   316
        x = window->x;
slouken@1951
   317
    }
slouken@2876
   318
    if ((window->flags & SDL_WINDOW_FULLSCREEN)
slouken@2876
   319
        || window->y == SDL_WINDOWPOS_CENTERED) {
slouken@2931
   320
        X11_GetDisplaySize(_this, window, NULL, &y);
slouken@2931
   321
        y = (y - window->h) / 2;
slouken@1951
   322
    } else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
slouken@1951
   323
        y = 0;
slouken@1951
   324
    } else {
slouken@1951
   325
        y = window->y;
slouken@1951
   326
    }
slouken@1951
   327
slouken@1951
   328
    w = XCreateWindow(data->display,
slouken@1951
   329
                      RootWindow(data->display, displaydata->screen), x, y,
slouken@1951
   330
                      window->w, window->h, 0, depth, InputOutput, visual,
slouken@1951
   331
                      (CWOverrideRedirect | CWBackPixel | CWBorderPixel |
slouken@1951
   332
                       CWColormap), &xattr);
slouken@1952
   333
    if (!w) {
slouken@1952
   334
#ifdef SDL_VIDEO_OPENGL_GLX
slouken@1952
   335
        if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1952
   336
            X11_GL_Shutdown(_this);
slouken@1952
   337
        }
slouken@1952
   338
#endif
slouken@1952
   339
        SDL_SetError("Couldn't create window");
slouken@1952
   340
        return -1;
slouken@1952
   341
    }
slouken@1951
   342
slouken@1951
   343
    sizehints = XAllocSizeHints();
slouken@1951
   344
    if (sizehints) {
slouken@2876
   345
        if ((window->flags & SDL_WINDOW_RESIZABLE)
slouken@2876
   346
            && !(window->flags & SDL_WINDOW_FULLSCREEN)) {
slouken@1951
   347
            sizehints->min_width = 32;
slouken@1951
   348
            sizehints->min_height = 32;
slouken@1951
   349
            sizehints->max_height = 4096;
slouken@1951
   350
            sizehints->max_width = 4096;
slouken@1951
   351
        } else {
slouken@1951
   352
            sizehints->min_width = sizehints->max_width = window->w;
slouken@1951
   353
            sizehints->min_height = sizehints->max_height = window->h;
slouken@1951
   354
        }
slouken@1951
   355
        sizehints->flags = PMaxSize | PMinSize;
slouken@1951
   356
        if (!(window->flags & SDL_WINDOW_FULLSCREEN)
slouken@1951
   357
            && window->x != SDL_WINDOWPOS_UNDEFINED
slouken@1951
   358
            && window->y != SDL_WINDOWPOS_UNDEFINED) {
slouken@1951
   359
            sizehints->x = x;
slouken@1951
   360
            sizehints->y = y;
slouken@1951
   361
            sizehints->flags |= USPosition;
slouken@1951
   362
        }
slouken@1951
   363
        XSetWMNormalHints(data->display, w, sizehints);
slouken@1951
   364
        XFree(sizehints);
slouken@1951
   365
    }
slouken@1951
   366
slouken@2876
   367
    if (window->flags & (SDL_WINDOW_BORDERLESS | SDL_WINDOW_FULLSCREEN)) {
slouken@1951
   368
        SDL_bool set;
slouken@1951
   369
        Atom WM_HINTS;
slouken@1951
   370
slouken@1951
   371
        /* We haven't modified the window manager hints yet */
slouken@1951
   372
        set = SDL_FALSE;
slouken@1951
   373
slouken@1951
   374
        /* First try to set MWM hints */
slouken@1951
   375
        WM_HINTS = XInternAtom(data->display, "_MOTIF_WM_HINTS", True);
slouken@1951
   376
        if (WM_HINTS != None) {
slouken@1951
   377
            /* Hints used by Motif compliant window managers */
slouken@1951
   378
            struct
slouken@1951
   379
            {
slouken@1951
   380
                unsigned long flags;
slouken@1951
   381
                unsigned long functions;
slouken@1951
   382
                unsigned long decorations;
slouken@1951
   383
                long input_mode;
slouken@1951
   384
                unsigned long status;
slouken@1951
   385
            } MWMHints = {
slouken@1951
   386
            (1L << 1), 0, 0, 0, 0};
slouken@1951
   387
slouken@1951
   388
            XChangeProperty(data->display, w, WM_HINTS, WM_HINTS, 32,
slouken@1951
   389
                            PropModeReplace, (unsigned char *) &MWMHints,
slouken@1951
   390
                            sizeof(MWMHints) / sizeof(long));
slouken@1951
   391
            set = SDL_TRUE;
slouken@1951
   392
        }
slouken@1951
   393
        /* Now try to set KWM hints */
slouken@1951
   394
        WM_HINTS = XInternAtom(data->display, "KWM_WIN_DECORATION", True);
slouken@1951
   395
        if (WM_HINTS != None) {
slouken@1951
   396
            long KWMHints = 0;
slouken@1951
   397
slouken@1951
   398
            XChangeProperty(data->display, w,
slouken@1951
   399
                            WM_HINTS, WM_HINTS, 32,
slouken@1951
   400
                            PropModeReplace,
slouken@1951
   401
                            (unsigned char *) &KWMHints,
slouken@1951
   402
                            sizeof(KWMHints) / sizeof(long));
slouken@1951
   403
            set = SDL_TRUE;
slouken@1951
   404
        }
slouken@1951
   405
        /* Now try to set GNOME hints */
slouken@1951
   406
        WM_HINTS = XInternAtom(data->display, "_WIN_HINTS", True);
slouken@1951
   407
        if (WM_HINTS != None) {
slouken@1951
   408
            long GNOMEHints = 0;
slouken@1951
   409
slouken@1951
   410
            XChangeProperty(data->display, w,
slouken@1951
   411
                            WM_HINTS, WM_HINTS, 32,
slouken@1951
   412
                            PropModeReplace,
slouken@1951
   413
                            (unsigned char *) &GNOMEHints,
slouken@1951
   414
                            sizeof(GNOMEHints) / sizeof(long));
slouken@1951
   415
            set = SDL_TRUE;
slouken@1951
   416
        }
slouken@1951
   417
        /* Finally set the transient hints if necessary */
slouken@1951
   418
        if (!set) {
slouken@1951
   419
            XSetTransientForHint(data->display, w,
slouken@1951
   420
                                 RootWindow(data->display,
slouken@1951
   421
                                            displaydata->screen));
slouken@1951
   422
        }
slouken@1951
   423
    } else {
slouken@1951
   424
        SDL_bool set;
slouken@1951
   425
        Atom WM_HINTS;
slouken@1951
   426
slouken@1951
   427
        /* We haven't modified the window manager hints yet */
slouken@1951
   428
        set = SDL_FALSE;
slouken@1951
   429
slouken@1951
   430
        /* First try to unset MWM hints */
slouken@1951
   431
        WM_HINTS = XInternAtom(data->display, "_MOTIF_WM_HINTS", True);
slouken@1951
   432
        if (WM_HINTS != None) {
slouken@1951
   433
            XDeleteProperty(data->display, w, WM_HINTS);
slouken@1951
   434
            set = SDL_TRUE;
slouken@1951
   435
        }
slouken@1951
   436
        /* Now try to unset KWM hints */
slouken@1951
   437
        WM_HINTS = XInternAtom(data->display, "KWM_WIN_DECORATION", 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 GNOME hints */
slouken@1951
   443
        WM_HINTS = XInternAtom(data->display, "_WIN_HINTS", 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
        /* Finally unset the transient hints if necessary */
slouken@1951
   449
        if (!set) {
slouken@1951
   450
            /* NOTE: Does this work? */
slouken@1951
   451
            XSetTransientForHint(data->display, w, None);
slouken@1951
   452
        }
slouken@1951
   453
    }
slouken@1951
   454
slouken@1951
   455
    /* Tell KDE to keep fullscreen windows on top */
slouken@1951
   456
    if (window->flags & SDL_WINDOW_FULLSCREEN) {
slouken@1951
   457
        XEvent ev;
slouken@1951
   458
        long mask;
slouken@1951
   459
slouken@1951
   460
        SDL_zero(ev);
slouken@1951
   461
        ev.xclient.type = ClientMessage;
slouken@1951
   462
        ev.xclient.window = RootWindow(data->display, displaydata->screen);
slouken@1951
   463
        ev.xclient.message_type =
slouken@1951
   464
            XInternAtom(data->display, "KWM_KEEP_ON_TOP", False);
slouken@1951
   465
        ev.xclient.format = 32;
slouken@1951
   466
        ev.xclient.data.l[0] = w;
slouken@1951
   467
        ev.xclient.data.l[1] = CurrentTime;
slouken@1951
   468
        XSendEvent(data->display,
slouken@1951
   469
                   RootWindow(data->display, displaydata->screen), False,
slouken@1951
   470
                   SubstructureRedirectMask, &ev);
slouken@1951
   471
    }
slouken@1951
   472
slouken@1951
   473
    /* Set the input hints so we get keyboard input */
slouken@1951
   474
    wmhints = XAllocWMHints();
slouken@1951
   475
    if (wmhints) {
slouken@1951
   476
        wmhints->input = True;
slouken@1956
   477
        wmhints->flags = InputHint;
slouken@1951
   478
        XSetWMHints(data->display, w, wmhints);
slouken@1951
   479
        XFree(wmhints);
slouken@1951
   480
    }
slouken@1951
   481
slouken@1951
   482
    /* Set the class hints so we can get an icon (AfterStep) */
slouken@1951
   483
    classhints = XAllocClassHint();
slouken@1951
   484
    if (classhints != NULL) {
slouken@1951
   485
        classhints->res_name = data->classname;
slouken@1951
   486
        classhints->res_class = data->classname;
slouken@1951
   487
        XSetClassHint(data->display, w, classhints);
slouken@1951
   488
        XFree(classhints);
slouken@1951
   489
    }
slouken@1951
   490
slouken@1951
   491
    /* Allow the window to be deleted by the window manager */
slouken@1951
   492
    XSetWMProtocols(data->display, w, &data->WM_DELETE_WINDOW, 1);
slouken@1951
   493
slouken@1951
   494
    if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
slouken@1952
   495
#ifdef SDL_VIDEO_OPENGL_GLX
slouken@1952
   496
        if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1952
   497
            X11_GL_Shutdown(_this);
slouken@1952
   498
        }
slouken@1952
   499
#endif
slouken@1951
   500
        XDestroyWindow(data->display, w);
slouken@1951
   501
        return -1;
slouken@1951
   502
    }
bob@2325
   503
#ifdef X_HAVE_UTF8_STRING
bob@2325
   504
    {
bob@2325
   505
        Uint32 fevent = 0;
bob@2325
   506
        pXGetICValues(((SDL_WindowData *) window->driverdata)->ic,
bob@2325
   507
                      XNFilterEvents, &fevent, NULL);
bob@2325
   508
        XSelectInput(data->display, w,
bob@2325
   509
                     (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
bob@2325
   510
                      ExposureMask | ButtonPressMask | ButtonReleaseMask |
bob@2325
   511
                      PointerMotionMask | KeyPressMask | KeyReleaseMask |
bob@2325
   512
                      PropertyChangeMask | StructureNotifyMask |
bob@2325
   513
                      KeymapStateMask | fevent));
bob@2325
   514
    }
bob@2325
   515
#else
kazeuser@2718
   516
    {
kazeuser@2718
   517
        XSelectInput(data->display, w,
slouken@2725
   518
                     (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
slouken@2725
   519
                      ExposureMask | ButtonPressMask | ButtonReleaseMask |
slouken@2725
   520
                      PointerMotionMask | KeyPressMask | KeyReleaseMask |
slouken@2725
   521
                      PropertyChangeMask | StructureNotifyMask |
slouken@2725
   522
                      KeymapStateMask));
kazeuser@2718
   523
    }
bob@2325
   524
#endif
bob@2325
   525
slouken@2940
   526
#if SDL_VIDEO_DRIVER_X11_XINPUT
slouken@2710
   527
    /* we're informing the display what extension events we want to receive from it */
slouken@2940
   528
    {
slouken@2940
   529
        int i, j, n = 0;
slouken@2940
   530
        XEventClass xevents[256];
slouken@2940
   531
slouken@2940
   532
        for (i = 0; i < SDL_GetNumMice(); ++i) {
slouken@2940
   533
            SDL_Mouse *mouse;
slouken@2940
   534
            X11_MouseData *data;
slouken@2940
   535
slouken@2940
   536
            mouse = SDL_GetMouse(i);
slouken@2940
   537
            data = (X11_MouseData *)mouse->driverdata;
slouken@2940
   538
            if (!data) {
slouken@2940
   539
                continue;
slouken@2940
   540
            }
slouken@2940
   541
slouken@2940
   542
            for (j = 0; j < data->num_xevents; ++j) {
slouken@2940
   543
                xevents[n++] = data->xevents[j];
slouken@2940
   544
            }
slouken@2940
   545
        }
slouken@2940
   546
        if (n > 0) {
slouken@2940
   547
            XSelectExtensionEvent(data->display, w, xevents, n);
slouken@2940
   548
        }
slouken@2940
   549
    }
slouken@2940
   550
#endif
slouken@2710
   551
slouken@1951
   552
    return 0;
slouken@1951
   553
}
slouken@1951
   554
slouken@1951
   555
int
bob@2324
   556
X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
slouken@1951
   557
{
slouken@1951
   558
    Window w = (Window) data;
slouken@1951
   559
slouken@1951
   560
    /* FIXME: Query the title from the existing window */
slouken@1951
   561
slouken@1951
   562
    if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
slouken@1951
   563
        return -1;
slouken@1951
   564
    }
slouken@1951
   565
    return 0;
slouken@1951
   566
}
slouken@1951
   567
slouken@1951
   568
void
slouken@1951
   569
X11_SetWindowTitle(_THIS, SDL_Window * window)
slouken@1951
   570
{
slouken@1951
   571
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   572
    Display *display = data->videodata->display;
slouken@1951
   573
    XTextProperty titleprop, iconprop;
slouken@1951
   574
    Status status;
slouken@1951
   575
    const char *title = window->title;
slouken@1951
   576
    const char *icon = NULL;
slouken@1951
   577
slouken@1951
   578
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   579
    Atom _NET_WM_NAME = 0;
slouken@1951
   580
    Atom _NET_WM_ICON_NAME = 0;
slouken@1951
   581
slouken@1951
   582
    /* Look up some useful Atoms */
slouken@1951
   583
    if (SDL_X11_HAVE_UTF8) {
slouken@1951
   584
        _NET_WM_NAME = XInternAtom(display, "_NET_WM_NAME", False);
slouken@1951
   585
        _NET_WM_ICON_NAME = XInternAtom(display, "_NET_WM_ICON_NAME", False);
slouken@1951
   586
    }
slouken@1951
   587
#endif
slouken@1951
   588
slouken@1951
   589
    if (title != NULL) {
slouken@2143
   590
        char *title_locale = SDL_iconv_utf8_locale(title);
slouken@2143
   591
        if (!title_locale) {
slouken@1951
   592
            SDL_OutOfMemory();
slouken@1951
   593
            return;
slouken@1951
   594
        }
slouken@2143
   595
        status = XStringListToTextProperty(&title_locale, 1, &titleprop);
slouken@2143
   596
        SDL_free(title_locale);
slouken@1951
   597
        if (status) {
slouken@1951
   598
            XSetTextProperty(display, data->window, &titleprop, XA_WM_NAME);
slouken@1951
   599
            XFree(titleprop.value);
slouken@1951
   600
        }
slouken@1951
   601
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   602
        if (SDL_X11_HAVE_UTF8) {
slouken@1951
   603
            status =
slouken@1951
   604
                Xutf8TextListToTextProperty(display, (char **) &title, 1,
slouken@1951
   605
                                            XUTF8StringStyle, &titleprop);
slouken@1951
   606
            if (status == Success) {
slouken@1951
   607
                XSetTextProperty(display, data->window, &titleprop,
slouken@1951
   608
                                 _NET_WM_NAME);
slouken@1951
   609
                XFree(titleprop.value);
slouken@1951
   610
            }
slouken@1951
   611
        }
slouken@1951
   612
#endif
slouken@1951
   613
    }
slouken@1951
   614
    if (icon != NULL) {
slouken@2143
   615
        char *icon_locale = SDL_iconv_utf8_locale(icon);
slouken@2143
   616
        if (!icon_locale) {
slouken@1951
   617
            SDL_OutOfMemory();
slouken@1951
   618
            return;
slouken@1951
   619
        }
slouken@2143
   620
        status = XStringListToTextProperty(&icon_locale, 1, &iconprop);
slouken@2143
   621
        SDL_free(icon_locale);
slouken@1951
   622
        if (status) {
slouken@1951
   623
            XSetTextProperty(display, data->window, &iconprop,
slouken@1951
   624
                             XA_WM_ICON_NAME);
slouken@1951
   625
            XFree(iconprop.value);
slouken@1951
   626
        }
slouken@1951
   627
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   628
        if (SDL_X11_HAVE_UTF8) {
slouken@1951
   629
            status =
slouken@1951
   630
                Xutf8TextListToTextProperty(display, (char **) &icon, 1,
slouken@1951
   631
                                            XUTF8StringStyle, &iconprop);
slouken@1951
   632
            if (status == Success) {
slouken@1951
   633
                XSetTextProperty(display, data->window, &iconprop,
slouken@1951
   634
                                 _NET_WM_ICON_NAME);
slouken@1951
   635
                XFree(iconprop.value);
slouken@1951
   636
            }
slouken@1951
   637
        }
slouken@1951
   638
#endif
slouken@1951
   639
    }
slouken@1951
   640
}
slouken@1951
   641
slouken@1951
   642
void
slouken@1951
   643
X11_SetWindowPosition(_THIS, SDL_Window * window)
slouken@1951
   644
{
slouken@1951
   645
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   646
    SDL_DisplayData *displaydata =
slouken@1952
   647
        (SDL_DisplayData *) SDL_GetDisplayFromWindow(window)->driverdata;
slouken@1951
   648
    Display *display = data->videodata->display;
slouken@2875
   649
    int x, y;
slouken@1951
   650
slouken@2876
   651
    if ((window->flags & SDL_WINDOW_FULLSCREEN)
slouken@2876
   652
        || window->x == SDL_WINDOWPOS_CENTERED) {
slouken@2931
   653
        X11_GetDisplaySize(_this, window, &x, NULL);
slouken@2931
   654
        x = (x - window->w) / 2;
slouken@2875
   655
    } else {
slouken@2875
   656
        x = window->x;
slouken@2875
   657
    }
slouken@2876
   658
    if ((window->flags & SDL_WINDOW_FULLSCREEN)
slouken@2876
   659
        || window->y == SDL_WINDOWPOS_CENTERED) {
slouken@2931
   660
        X11_GetDisplaySize(_this, window, NULL, &y);
slouken@2931
   661
        y = (y - window->h) / 2;
slouken@2875
   662
    } else {
slouken@2875
   663
        y = window->y;
slouken@2875
   664
    }
slouken@2875
   665
    XMoveWindow(display, data->window, x, y);
slouken@1951
   666
}
slouken@1951
   667
slouken@1951
   668
void
slouken@1951
   669
X11_SetWindowSize(_THIS, SDL_Window * window)
slouken@1951
   670
{
slouken@1951
   671
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   672
    Display *display = data->videodata->display;
slouken@1951
   673
slouken@2931
   674
    XResizeWindow(display, data->window, window->w, window->h);
slouken@1951
   675
}
slouken@1951
   676
slouken@1951
   677
void
slouken@1951
   678
X11_ShowWindow(_THIS, SDL_Window * window)
slouken@1951
   679
{
slouken@1951
   680
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   681
    Display *display = data->videodata->display;
slouken@1951
   682
slouken@1951
   683
    XMapRaised(display, data->window);
slouken@1951
   684
}
slouken@1951
   685
slouken@1951
   686
void
slouken@1951
   687
X11_HideWindow(_THIS, SDL_Window * window)
slouken@1951
   688
{
slouken@1951
   689
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   690
    Display *display = data->videodata->display;
slouken@1951
   691
slouken@1951
   692
    XUnmapWindow(display, data->window);
slouken@1951
   693
}
slouken@1951
   694
slouken@1951
   695
void
slouken@1951
   696
X11_RaiseWindow(_THIS, SDL_Window * window)
slouken@1951
   697
{
slouken@1951
   698
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@1951
   699
    Display *display = data->videodata->display;
slouken@1951
   700
slouken@1951
   701
    XRaiseWindow(display, data->window);
slouken@1951
   702
}
slouken@1951
   703
slouken@1951
   704
void
slouken@1951
   705
X11_MaximizeWindow(_THIS, SDL_Window * window)
slouken@1951
   706
{
slouken@1951
   707
    /* FIXME: is this even possible? */
slouken@1951
   708
}
slouken@1951
   709
slouken@1951
   710
void
slouken@1951
   711
X11_MinimizeWindow(_THIS, SDL_Window * window)
slouken@1951
   712
{
slouken@1951
   713
    X11_HideWindow(_this, window);
slouken@1951
   714
}
slouken@1951
   715
slouken@1951
   716
void
slouken@1951
   717
X11_RestoreWindow(_THIS, SDL_Window * window)
slouken@1951
   718
{
slouken@1951
   719
    X11_ShowWindow(_this, window);
slouken@1951
   720
}
slouken@1951
   721
slouken@1951
   722
void
slouken@1951
   723
X11_SetWindowGrab(_THIS, SDL_Window * window)
slouken@1951
   724
{
slouken@2875
   725
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
slouken@2875
   726
    Display *display = data->videodata->display;
slouken@2875
   727
slouken@2876
   728
    if ((window->flags & (SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN))
slouken@2876
   729
        && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
slouken@2875
   730
        /* Try to grab the mouse */
slouken@2876
   731
        for (;;) {
slouken@2876
   732
            int result =
slouken@2876
   733
                XGrabPointer(display, data->window, True, 0, GrabModeAsync,
slouken@2876
   734
                             GrabModeAsync, data->window, None, CurrentTime);
slouken@2876
   735
            if (result == GrabSuccess) {
slouken@2875
   736
                break;
slouken@2875
   737
            }
slouken@2875
   738
            SDL_Delay(100);
slouken@2875
   739
        }
slouken@2875
   740
slouken@2875
   741
        /* Raise the window if we grab the mouse */
slouken@2875
   742
        XRaiseWindow(display, data->window);
slouken@2875
   743
slouken@2875
   744
        /* Now grab the keyboard */
slouken@2876
   745
        XGrabKeyboard(display, data->window, True, GrabModeAsync,
slouken@2876
   746
                      GrabModeAsync, CurrentTime);
slouken@2875
   747
    } else {
slouken@2875
   748
        XUngrabPointer(display, CurrentTime);
slouken@2875
   749
        XUngrabKeyboard(display, CurrentTime);
slouken@2875
   750
    }
slouken@1951
   751
}
slouken@1951
   752
slouken@1951
   753
void
slouken@1951
   754
X11_DestroyWindow(_THIS, SDL_Window * window)
slouken@1951
   755
{
slouken@1951
   756
    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
bob@2323
   757
    window->driverdata = NULL;
slouken@1951
   758
slouken@1951
   759
    if (data) {
bob@2323
   760
        SDL_VideoData *videodata = (SDL_VideoData *) data->videodata;
bob@2323
   761
        Display *display = videodata->display;
bob@2323
   762
        int numwindows = videodata->numwindows;
bob@2323
   763
        SDL_WindowData **windowlist = videodata->windowlist;
bob@2323
   764
        int i;
bob@2323
   765
bob@2323
   766
        if (windowlist) {
bob@2324
   767
            for (i = 0; i < numwindows; ++i) {
bob@2324
   768
                if (windowlist[i] && (windowlist[i]->windowID == window->id)) {
bob@2324
   769
                    windowlist[i] = windowlist[numwindows - 1];
bob@2324
   770
                    windowlist[numwindows - 1] = NULL;
bob@2324
   771
                    videodata->numwindows--;
bob@2324
   772
                    break;
bob@2324
   773
                }
bob@2323
   774
            }
bob@2323
   775
        }
slouken@1952
   776
#ifdef SDL_VIDEO_OPENGL_GLX
slouken@1952
   777
        if (window->flags & SDL_WINDOW_OPENGL) {
slouken@1952
   778
            X11_GL_Shutdown(_this);
slouken@1952
   779
        }
slouken@1951
   780
#endif
slouken@1951
   781
#ifdef X_HAVE_UTF8_STRING
slouken@1951
   782
        if (data->ic) {
slouken@1951
   783
            XDestroyIC(data->ic);
slouken@1951
   784
        }
slouken@1951
   785
#endif
slouken@1951
   786
        if (data->created) {
slouken@1951
   787
            XDestroyWindow(display, data->window);
slouken@1951
   788
        }
slouken@1951
   789
        SDL_free(data);
slouken@1951
   790
    }
slouken@1951
   791
}
slouken@1951
   792
slouken@1951
   793
SDL_bool
slouken@1951
   794
X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
slouken@1951
   795
{
slouken@1951
   796
    if (info->version.major <= SDL_MAJOR_VERSION) {
slouken@1951
   797
        /* FIXME! */
slouken@1951
   798
        return SDL_TRUE;
slouken@1951
   799
    } else {
slouken@1951
   800
        SDL_SetError("Application not compiled with SDL %d.%d\n",
slouken@1951
   801
                     SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
slouken@1951
   802
        return SDL_FALSE;
slouken@1951
   803
    }
slouken@1951
   804
}
slouken@1951
   805
slouken@1951
   806
/* vi: set ts=4 sw=4 expandtab: */