src/video/x11/SDL_x11window.c
author Sam Lantinga
Fri, 27 Nov 2020 18:57:42 -0800
changeset 14413 0ba75e4da3e1
parent 14351 71ba33032c2f
permissions -rw-r--r--
Remember to close the game controller when we're done with it
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 
    23 #if SDL_VIDEO_DRIVER_X11
    24 
    25 #include "SDL_assert.h"
    26 #include "SDL_hints.h"
    27 #include "../SDL_sysvideo.h"
    28 #include "../SDL_pixels_c.h"
    29 #include "../../events/SDL_keyboard_c.h"
    30 #include "../../events/SDL_mouse_c.h"
    31 
    32 #include "SDL_x11video.h"
    33 #include "SDL_x11mouse.h"
    34 #include "SDL_x11shape.h"
    35 #include "SDL_x11xinput2.h"
    36 
    37 #if SDL_VIDEO_OPENGL_EGL
    38 #include "SDL_x11opengles.h"
    39 #endif
    40 
    41 #include "SDL_timer.h"
    42 #include "SDL_syswm.h"
    43 
    44 #define _NET_WM_STATE_REMOVE    0l
    45 #define _NET_WM_STATE_ADD       1l
    46 
    47 static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win)
    48 {
    49     return ev->type == MapNotify && ev->xmap.window == *((Window*)win);
    50 }
    51 static Bool isUnmapNotify(Display *dpy, XEvent *ev, XPointer win)
    52 {
    53     return ev->type == UnmapNotify && ev->xunmap.window == *((Window*)win);
    54 }
    55 
    56 /*
    57 static Bool isConfigureNotify(Display *dpy, XEvent *ev, XPointer win)
    58 {
    59     return ev->type == ConfigureNotify && ev->xconfigure.window == *((Window*)win);
    60 }
    61 static Bool
    62 X11_XIfEventTimeout(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg, int timeoutMS)
    63 {
    64     Uint32 start = SDL_GetTicks();
    65 
    66     while (!X11_XCheckIfEvent(display, event_return, predicate, arg)) {
    67         if (SDL_TICKS_PASSED(SDL_GetTicks(), start + timeoutMS)) {
    68             return False;
    69         }
    70     }
    71     return True;
    72 }
    73 */
    74 
    75 static SDL_bool
    76 X11_IsWindowLegacyFullscreen(_THIS, SDL_Window * window)
    77 {
    78     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    79     return (data->fswindow != 0);
    80 }
    81 
    82 static SDL_bool
    83 X11_IsWindowMapped(_THIS, SDL_Window * window)
    84 {
    85     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
    86     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
    87     XWindowAttributes attr;
    88 
    89     X11_XGetWindowAttributes(videodata->display, data->xwindow, &attr);
    90     if (attr.map_state != IsUnmapped) {
    91         return SDL_TRUE;
    92     } else {
    93         return SDL_FALSE;
    94     }
    95 }
    96 
    97 #if 0
    98 static SDL_bool
    99 X11_IsActionAllowed(SDL_Window *window, Atom action)
   100 {
   101     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   102     Atom _NET_WM_ALLOWED_ACTIONS = data->videodata->_NET_WM_ALLOWED_ACTIONS;
   103     Atom type;
   104     Display *display = data->videodata->display;
   105     int form;
   106     unsigned long remain;
   107     unsigned long len, i;
   108     Atom *list;
   109     SDL_bool ret = SDL_FALSE;
   110 
   111     if (X11_XGetWindowProperty(display, data->xwindow, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, XA_ATOM, &type, &form, &len, &remain, (unsigned char **)&list) == Success)
   112     {
   113         for (i=0; i<len; ++i)
   114         {
   115             if (list[i] == action) {
   116                 ret = SDL_TRUE;
   117                 break;
   118             }
   119         }
   120         X11_XFree(list);
   121     }
   122     return ret;
   123 }
   124 #endif /* 0 */
   125 
   126 void
   127 X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
   128 {
   129     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   130     Display *display = videodata->display;
   131     /* !!! FIXME: just dereference videodata below instead of copying to locals. */
   132     Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
   133     /* Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN; */
   134     Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
   135     Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
   136     Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
   137     Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
   138     Atom _NET_WM_STATE_ABOVE = videodata->_NET_WM_STATE_ABOVE;
   139     Atom _NET_WM_STATE_SKIP_TASKBAR = videodata->_NET_WM_STATE_SKIP_TASKBAR;
   140     Atom _NET_WM_STATE_SKIP_PAGER = videodata->_NET_WM_STATE_SKIP_PAGER;
   141     Atom atoms[16];
   142     int count = 0;
   143 
   144     /* The window manager sets this property, we shouldn't set it.
   145        If we did, this would indicate to the window manager that we don't
   146        actually want to be mapped during X11_XMapRaised(), which would be bad.
   147      *
   148     if (flags & SDL_WINDOW_HIDDEN) {
   149         atoms[count++] = _NET_WM_STATE_HIDDEN;
   150     }
   151     */
   152 
   153     if (flags & SDL_WINDOW_ALWAYS_ON_TOP) {
   154         atoms[count++] = _NET_WM_STATE_ABOVE;
   155     }
   156     if (flags & SDL_WINDOW_SKIP_TASKBAR) {
   157         atoms[count++] = _NET_WM_STATE_SKIP_TASKBAR;
   158         atoms[count++] = _NET_WM_STATE_SKIP_PAGER;
   159     }
   160     if (flags & SDL_WINDOW_INPUT_FOCUS) {
   161         atoms[count++] = _NET_WM_STATE_FOCUSED;
   162     }
   163     if (flags & SDL_WINDOW_MAXIMIZED) {
   164         atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
   165         atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
   166     }
   167     if (flags & SDL_WINDOW_FULLSCREEN) {
   168         atoms[count++] = _NET_WM_STATE_FULLSCREEN;
   169     }
   170 
   171     SDL_assert(count <= SDL_arraysize(atoms));
   172 
   173     if (count > 0) {
   174         X11_XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
   175                         PropModeReplace, (unsigned char *)atoms, count);
   176     } else {
   177         X11_XDeleteProperty(display, xwindow, _NET_WM_STATE);
   178     }
   179 }
   180 
   181 Uint32
   182 X11_GetNetWMState(_THIS, Window xwindow)
   183 {
   184     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   185     Display *display = videodata->display;
   186     Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
   187     Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;
   188     Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
   189     Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
   190     Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
   191     Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
   192     Atom actualType;
   193     int actualFormat;
   194     unsigned long i, numItems, bytesAfter;
   195     unsigned char *propertyValue = NULL;
   196     long maxLength = 1024;
   197     Uint32 flags = 0;
   198 
   199     if (X11_XGetWindowProperty(display, xwindow, _NET_WM_STATE,
   200                            0l, maxLength, False, XA_ATOM, &actualType,
   201                            &actualFormat, &numItems, &bytesAfter,
   202                            &propertyValue) == Success) {
   203         Atom *atoms = (Atom *) propertyValue;
   204         int maximized = 0;
   205         int fullscreen = 0;
   206 
   207         for (i = 0; i < numItems; ++i) {
   208             if (atoms[i] == _NET_WM_STATE_HIDDEN) {
   209                 flags |= SDL_WINDOW_HIDDEN;
   210             } else if (atoms[i] == _NET_WM_STATE_FOCUSED) {
   211                 flags |= SDL_WINDOW_INPUT_FOCUS;
   212             } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) {
   213                 maximized |= 1;
   214             } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
   215                 maximized |= 2;
   216             } else if ( atoms[i] == _NET_WM_STATE_FULLSCREEN) {
   217                 fullscreen = 1;
   218             }
   219         }
   220         if (maximized == 3) {
   221             flags |= SDL_WINDOW_MAXIMIZED;
   222         }
   223 
   224         if (fullscreen == 1) {
   225             flags |= SDL_WINDOW_FULLSCREEN;
   226         }
   227 
   228         /* If the window is unmapped, numItems will be zero and _NET_WM_STATE_HIDDEN
   229          * will not be set. Do an additional check to see if the window is unmapped
   230          * and mark it as SDL_WINDOW_HIDDEN if it is.
   231          */
   232         {
   233             XWindowAttributes attr;
   234             SDL_memset(&attr,0,sizeof(attr));
   235             X11_XGetWindowAttributes(videodata->display, xwindow, &attr);
   236             if (attr.map_state == IsUnmapped) {
   237                 flags |= SDL_WINDOW_HIDDEN;
   238             }
   239         }
   240         X11_XFree(propertyValue);
   241     }
   242 
   243     /* FIXME, check the size hints for resizable */
   244     /* flags |= SDL_WINDOW_RESIZABLE; */
   245 
   246     return flags;
   247 }
   248 
   249 static int
   250 SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
   251 {
   252     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   253     SDL_WindowData *data;
   254     int numwindows = videodata->numwindows;
   255     int windowlistlength = videodata->windowlistlength;
   256     SDL_WindowData **windowlist = videodata->windowlist;
   257 
   258     /* Allocate the window data */
   259     data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
   260     if (!data) {
   261         return SDL_OutOfMemory();
   262     }
   263     data->window = window;
   264     data->xwindow = w;
   265 #ifdef X_HAVE_UTF8_STRING
   266     if (SDL_X11_HAVE_UTF8 && videodata->im) {
   267         data->ic =
   268             X11_XCreateIC(videodata->im, XNClientWindow, w, XNFocusWindow, w,
   269                        XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
   270                        NULL);
   271     }
   272 #endif
   273     data->created = created;
   274     data->videodata = videodata;
   275 
   276     /* Associate the data with the window */
   277 
   278     if (numwindows < windowlistlength) {
   279         windowlist[numwindows] = data;
   280         videodata->numwindows++;
   281     } else {
   282         windowlist =
   283             (SDL_WindowData **) SDL_realloc(windowlist,
   284                                             (numwindows +
   285                                              1) * sizeof(*windowlist));
   286         if (!windowlist) {
   287             SDL_free(data);
   288             return SDL_OutOfMemory();
   289         }
   290         windowlist[numwindows] = data;
   291         videodata->numwindows++;
   292         videodata->windowlistlength++;
   293         videodata->windowlist = windowlist;
   294     }
   295 
   296     /* Fill in the SDL window with the window data */
   297     {
   298         XWindowAttributes attrib;
   299 
   300         X11_XGetWindowAttributes(data->videodata->display, w, &attrib);
   301         window->x = attrib.x;
   302         window->y = attrib.y;
   303         window->w = attrib.width;
   304         window->h = attrib.height;
   305         if (attrib.map_state != IsUnmapped) {
   306             window->flags |= SDL_WINDOW_SHOWN;
   307         } else {
   308             window->flags &= ~SDL_WINDOW_SHOWN;
   309         }
   310         data->visual = attrib.visual;
   311         data->colormap = attrib.colormap;
   312     }
   313 
   314     window->flags |= X11_GetNetWMState(_this, w);
   315 
   316     {
   317         Window FocalWindow;
   318         int RevertTo=0;
   319         X11_XGetInputFocus(data->videodata->display, &FocalWindow, &RevertTo);
   320         if (FocalWindow==w)
   321         {
   322             window->flags |= SDL_WINDOW_INPUT_FOCUS;
   323         }
   324 
   325         if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
   326             SDL_SetKeyboardFocus(data->window);
   327         }
   328 
   329         if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
   330             /* Tell x11 to clip mouse */
   331         }
   332     }
   333 
   334     /* All done! */
   335     window->driverdata = data;
   336     return 0;
   337 }
   338 
   339 static void
   340 SetWindowBordered(Display *display, int screen, Window window, SDL_bool border)
   341 {
   342     /*
   343      * this code used to check for KWM_WIN_DECORATION, but KDE hasn't
   344      *  supported it for years and years. It now respects _MOTIF_WM_HINTS.
   345      *  Gnome is similar: just use the Motif atom.
   346      */
   347 
   348     Atom WM_HINTS = X11_XInternAtom(display, "_MOTIF_WM_HINTS", True);
   349     if (WM_HINTS != None) {
   350         /* Hints used by Motif compliant window managers */
   351         struct
   352         {
   353             unsigned long flags;
   354             unsigned long functions;
   355             unsigned long decorations;
   356             long input_mode;
   357             unsigned long status;
   358         } MWMHints = {
   359             (1L << 1), 0, border ? 1 : 0, 0, 0
   360         };
   361 
   362         X11_XChangeProperty(display, window, WM_HINTS, WM_HINTS, 32,
   363                         PropModeReplace, (unsigned char *) &MWMHints,
   364                         sizeof(MWMHints) / sizeof(long));
   365     } else {  /* set the transient hints instead, if necessary */
   366         X11_XSetTransientForHint(display, window, RootWindow(display, screen));
   367     }
   368 }
   369 
   370 int
   371 X11_CreateWindow(_THIS, SDL_Window * window)
   372 {
   373     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   374     SDL_DisplayData *displaydata =
   375         (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
   376     SDL_WindowData *windowdata;
   377     Display *display = data->display;
   378     int screen = displaydata->screen;
   379     Visual *visual;
   380     int depth;
   381     XSetWindowAttributes xattr;
   382     Window w;
   383     XSizeHints *sizehints;
   384     XWMHints *wmhints;
   385     XClassHint *classhints;
   386     Atom _NET_WM_BYPASS_COMPOSITOR;
   387     Atom _NET_WM_WINDOW_TYPE;
   388     Atom wintype;
   389     const char *wintype_name = NULL;
   390     long compositor = 1;
   391     Atom _NET_WM_PID;
   392     long fevent = 0;
   393 
   394 #if SDL_VIDEO_OPENGL_GLX || SDL_VIDEO_OPENGL_EGL
   395     const char *forced_visual_id = SDL_GetHint(SDL_HINT_VIDEO_X11_WINDOW_VISUALID);
   396 
   397     if (forced_visual_id != NULL && forced_visual_id[0] != '\0')
   398     {
   399         XVisualInfo *vi, template;
   400         int nvis;
   401 
   402         SDL_zero(template);
   403         template.visualid = SDL_strtol(forced_visual_id, NULL, 0);
   404         vi = X11_XGetVisualInfo(display, VisualIDMask, &template, &nvis);
   405         if (vi) {
   406             visual = vi->visual;
   407             depth = vi->depth;
   408             X11_XFree(vi);
   409         }
   410         else
   411         {
   412             return -1;
   413         }
   414     }
   415     else if ((window->flags & SDL_WINDOW_OPENGL) &&
   416         !SDL_getenv("SDL_VIDEO_X11_VISUALID")) {
   417         XVisualInfo *vinfo = NULL;
   418 
   419 #if SDL_VIDEO_OPENGL_EGL
   420         if (((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) ||
   421              SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE))
   422 #if SDL_VIDEO_OPENGL_GLX            
   423             && ( !_this->gl_data || X11_GL_UseEGL(_this) )
   424 #endif
   425         ) {
   426             vinfo = X11_GLES_GetVisual(_this, display, screen);
   427         } else
   428 #endif
   429         {
   430 #if SDL_VIDEO_OPENGL_GLX
   431             vinfo = X11_GL_GetVisual(_this, display, screen);
   432 #endif
   433         }
   434 
   435         if (!vinfo) {
   436             return -1;
   437         }
   438         visual = vinfo->visual;
   439         depth = vinfo->depth;
   440         X11_XFree(vinfo);
   441     } else
   442 #endif
   443     {
   444         visual = displaydata->visual;
   445         depth = displaydata->depth;
   446     }
   447 
   448     xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU)) ? True : False;
   449     xattr.background_pixmap = None;
   450     xattr.border_pixel = 0;
   451 
   452     if (visual->class == DirectColor) {
   453         XColor *colorcells;
   454         int i;
   455         int ncolors;
   456         int rmax, gmax, bmax;
   457         int rmask, gmask, bmask;
   458         int rshift, gshift, bshift;
   459 
   460         xattr.colormap =
   461             X11_XCreateColormap(display, RootWindow(display, screen),
   462                             visual, AllocAll);
   463 
   464         /* If we can't create a colormap, then we must die */
   465         if (!xattr.colormap) {
   466             return SDL_SetError("Could not create writable colormap");
   467         }
   468 
   469         /* OK, we got a colormap, now fill it in as best as we can */
   470         colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
   471         if (!colorcells) {
   472             return SDL_OutOfMemory();
   473         }
   474         ncolors = visual->map_entries;
   475         rmax = 0xffff;
   476         gmax = 0xffff;
   477         bmax = 0xffff;
   478 
   479         rshift = 0;
   480         rmask = visual->red_mask;
   481         while (0 == (rmask & 1)) {
   482             rshift++;
   483             rmask >>= 1;
   484         }
   485 
   486         gshift = 0;
   487         gmask = visual->green_mask;
   488         while (0 == (gmask & 1)) {
   489             gshift++;
   490             gmask >>= 1;
   491         }
   492 
   493         bshift = 0;
   494         bmask = visual->blue_mask;
   495         while (0 == (bmask & 1)) {
   496             bshift++;
   497             bmask >>= 1;
   498         }
   499 
   500         /* build the color table pixel values */
   501         for (i = 0; i < ncolors; i++) {
   502             Uint32 red = (rmax * i) / (ncolors - 1);
   503             Uint32 green = (gmax * i) / (ncolors - 1);
   504             Uint32 blue = (bmax * i) / (ncolors - 1);
   505 
   506             Uint32 rbits = (rmask * i) / (ncolors - 1);
   507             Uint32 gbits = (gmask * i) / (ncolors - 1);
   508             Uint32 bbits = (bmask * i) / (ncolors - 1);
   509 
   510             Uint32 pix =
   511                 (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
   512 
   513             colorcells[i].pixel = pix;
   514 
   515             colorcells[i].red = red;
   516             colorcells[i].green = green;
   517             colorcells[i].blue = blue;
   518 
   519             colorcells[i].flags = DoRed | DoGreen | DoBlue;
   520         }
   521 
   522         X11_XStoreColors(display, xattr.colormap, colorcells, ncolors);
   523 
   524         SDL_free(colorcells);
   525     } else {
   526         xattr.colormap =
   527             X11_XCreateColormap(display, RootWindow(display, screen),
   528                             visual, AllocNone);
   529     }
   530 
   531     w = X11_XCreateWindow(display, RootWindow(display, screen),
   532                       window->x, window->y, window->w, window->h,
   533                       0, depth, InputOutput, visual,
   534                       (CWOverrideRedirect | CWBackPixmap | CWBorderPixel |
   535                        CWColormap), &xattr);
   536     if (!w) {
   537         return SDL_SetError("Couldn't create window");
   538     }
   539 
   540     SetWindowBordered(display, screen, w,
   541                       (window->flags & SDL_WINDOW_BORDERLESS) == 0);
   542 
   543     sizehints = X11_XAllocSizeHints();
   544     /* Setup the normal size hints */
   545     sizehints->flags = 0;
   546     if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
   547         sizehints->min_width = sizehints->max_width = window->w;
   548         sizehints->min_height = sizehints->max_height = window->h;
   549         sizehints->flags |= (PMaxSize | PMinSize);
   550     }
   551     sizehints->x = window->x;
   552     sizehints->y = window->y;
   553     sizehints->flags |= USPosition;
   554 
   555     /* Setup the input hints so we get keyboard input */
   556     wmhints = X11_XAllocWMHints();
   557     wmhints->input = True;
   558     wmhints->window_group = data->window_group;
   559     wmhints->flags = InputHint | WindowGroupHint;
   560 
   561     /* Setup the class hints so we can get an icon (AfterStep) */
   562     classhints = X11_XAllocClassHint();
   563     classhints->res_name = data->classname;
   564     classhints->res_class = data->classname;
   565 
   566     /* Set the size, input and class hints, and define WM_CLIENT_MACHINE and WM_LOCALE_NAME */
   567     X11_XSetWMProperties(display, w, NULL, NULL, NULL, 0, sizehints, wmhints, classhints);
   568 
   569     X11_XFree(sizehints);
   570     X11_XFree(wmhints);
   571     X11_XFree(classhints);
   572     /* Set the PID related to the window for the given hostname, if possible */
   573     if (data->pid > 0) {
   574         long pid = (long) data->pid;
   575         _NET_WM_PID = X11_XInternAtom(display, "_NET_WM_PID", False);
   576         X11_XChangeProperty(display, w, _NET_WM_PID, XA_CARDINAL, 32, PropModeReplace,
   577                         (unsigned char *) &pid, 1);
   578     }
   579 
   580     /* Set the window manager state */
   581     X11_SetNetWMState(_this, w, window->flags);
   582 
   583     compositor = 2;  /* don't disable compositing except for "normal" windows */
   584 
   585     if (window->flags & SDL_WINDOW_UTILITY) {
   586         wintype_name = "_NET_WM_WINDOW_TYPE_UTILITY";
   587     } else if (window->flags & SDL_WINDOW_TOOLTIP) {
   588         wintype_name = "_NET_WM_WINDOW_TYPE_TOOLTIP";
   589     } else if (window->flags & SDL_WINDOW_POPUP_MENU) {
   590         wintype_name = "_NET_WM_WINDOW_TYPE_POPUP_MENU";
   591     } else {
   592         wintype_name = "_NET_WM_WINDOW_TYPE_NORMAL";
   593         compositor = 1;  /* disable compositing for "normal" windows */
   594     }
   595 
   596     /* Let the window manager know what type of window we are. */
   597     _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
   598     wintype = X11_XInternAtom(display, wintype_name, False);
   599     X11_XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
   600                     PropModeReplace, (unsigned char *)&wintype, 1);
   601     if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, SDL_TRUE)) {
   602         _NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
   603         X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
   604                         PropModeReplace,
   605                         (unsigned char *)&compositor, 1);
   606     }
   607 
   608     {
   609         Atom protocols[3];
   610         int proto_count = 0;
   611 
   612         protocols[proto_count++] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */
   613         protocols[proto_count++] = data->WM_TAKE_FOCUS; /* Since we will want to set input focus explicitly */
   614 
   615         /* Default to using ping if there is no hint */
   616         if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_NET_WM_PING, SDL_TRUE)) {
   617             protocols[proto_count++] = data->_NET_WM_PING; /* Respond so WM knows we're alive */
   618         }
   619 
   620         SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0]));
   621 
   622         X11_XSetWMProtocols(display, w, protocols, proto_count);
   623     }
   624 
   625     if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
   626         X11_XDestroyWindow(display, w);
   627         return -1;
   628     }
   629     windowdata = (SDL_WindowData *) window->driverdata;
   630 
   631 #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2 || SDL_VIDEO_OPENGL_EGL
   632     if ((window->flags & SDL_WINDOW_OPENGL) && 
   633         ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) ||
   634          SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE))
   635 #if SDL_VIDEO_OPENGL_GLX            
   636         && ( !_this->gl_data || X11_GL_UseEGL(_this) )
   637 #endif  
   638     ) {
   639 #if SDL_VIDEO_OPENGL_EGL  
   640         if (!_this->egl_data) {
   641             return -1;
   642         }
   643 
   644         /* Create the GLES window surface */
   645         windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) w);
   646 
   647         if (windowdata->egl_surface == EGL_NO_SURFACE) {
   648             return SDL_SetError("Could not create GLES window surface");
   649         }
   650 #else
   651         return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
   652 #endif /* SDL_VIDEO_OPENGL_EGL */
   653     }
   654 #endif
   655     
   656 
   657 #ifdef X_HAVE_UTF8_STRING
   658     if (SDL_X11_HAVE_UTF8 && windowdata->ic) {
   659         X11_XGetICValues(windowdata->ic, XNFilterEvents, &fevent, NULL);
   660     }
   661 #endif
   662 
   663     X11_Xinput2SelectTouch(_this, window);
   664 
   665     X11_XSelectInput(display, w,
   666                  (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
   667                  ExposureMask | ButtonPressMask | ButtonReleaseMask |
   668                  PointerMotionMask | KeyPressMask | KeyReleaseMask |
   669                  PropertyChangeMask | StructureNotifyMask |
   670                  KeymapStateMask | fevent));
   671 
   672     X11_XFlush(display);
   673 
   674     return 0;
   675 }
   676 
   677 int
   678 X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
   679 {
   680     Window w = (Window) data;
   681 
   682     window->title = X11_GetWindowTitle(_this, w);
   683 
   684     if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
   685         return -1;
   686     }
   687     return 0;
   688 }
   689 
   690 char *
   691 X11_GetWindowTitle(_THIS, Window xwindow)
   692 {
   693     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
   694     Display *display = data->display;
   695     int status, real_format;
   696     Atom real_type;
   697     unsigned long items_read, items_left;
   698     unsigned char *propdata;
   699     char *title = NULL;
   700 
   701     status = X11_XGetWindowProperty(display, xwindow, data->_NET_WM_NAME,
   702                 0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
   703                 &items_read, &items_left, &propdata);
   704     if (status == Success && propdata) {
   705         title = SDL_strdup(SDL_static_cast(char*, propdata));
   706         X11_XFree(propdata);
   707     } else {
   708         status = X11_XGetWindowProperty(display, xwindow, XA_WM_NAME,
   709                     0L, 8192L, False, XA_STRING, &real_type, &real_format,
   710                     &items_read, &items_left, &propdata);
   711         if (status == Success && propdata) {
   712             title = SDL_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1);
   713             X11_XFree(propdata);
   714         } else {
   715             title = SDL_strdup("");
   716         }
   717     }
   718     return title;
   719 }
   720 
   721 void
   722 X11_SetWindowTitle(_THIS, SDL_Window * window)
   723 {
   724     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   725     Display *display = data->videodata->display;
   726     XTextProperty titleprop;
   727     Status status;
   728     const char *title = window->title ? window->title : "";
   729     char *title_locale = NULL;
   730 
   731 #ifdef X_HAVE_UTF8_STRING
   732     Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
   733 #endif
   734 
   735     title_locale = SDL_iconv_utf8_locale(title);
   736     if (!title_locale) {
   737         SDL_OutOfMemory();
   738         return;
   739     }
   740 
   741     status = X11_XStringListToTextProperty(&title_locale, 1, &titleprop);
   742     SDL_free(title_locale);
   743     if (status) {
   744         X11_XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME);
   745         X11_XFree(titleprop.value);
   746     }
   747 #ifdef X_HAVE_UTF8_STRING
   748     if (SDL_X11_HAVE_UTF8) {
   749         status = X11_Xutf8TextListToTextProperty(display, (char **) &title, 1,
   750                                             XUTF8StringStyle, &titleprop);
   751         if (status == Success) {
   752             X11_XSetTextProperty(display, data->xwindow, &titleprop,
   753                                  _NET_WM_NAME);
   754             X11_XFree(titleprop.value);
   755         }
   756     }
   757 #endif
   758 
   759     X11_XFlush(display);
   760 }
   761 
   762 void
   763 X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
   764 {
   765     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   766     Display *display = data->videodata->display;
   767     Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON;
   768 
   769     if (icon) {
   770         int propsize;
   771         long *propdata;
   772 
   773         /* Set the _NET_WM_ICON property */
   774         SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888);
   775         propsize = 2 + (icon->w * icon->h);
   776         propdata = SDL_malloc(propsize * sizeof(long));
   777         if (propdata) {
   778             int x, y;
   779             Uint32 *src;
   780             long *dst;
   781 
   782             propdata[0] = icon->w;
   783             propdata[1] = icon->h;
   784             dst = &propdata[2];
   785             for (y = 0; y < icon->h; ++y) {
   786                 src = (Uint32*)((Uint8*)icon->pixels + y * icon->pitch);
   787                 for (x = 0; x < icon->w; ++x) {
   788                     *dst++ = *src++;
   789                 }
   790             }
   791             X11_XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL,
   792                             32, PropModeReplace, (unsigned char *) propdata,
   793                             propsize);
   794         }
   795         SDL_free(propdata);
   796     } else {
   797         X11_XDeleteProperty(display, data->xwindow, _NET_WM_ICON);
   798     }
   799     X11_XFlush(display);
   800 }
   801 
   802 void
   803 X11_SetWindowPosition(_THIS, SDL_Window * window)
   804 {
   805     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   806     Display *display = data->videodata->display;
   807     unsigned int childCount;
   808     Window childReturn, root, parent;
   809     Window* children;
   810     XWindowAttributes attrs;
   811     int orig_x, orig_y;
   812     Uint32 timeout;
   813 
   814     X11_XSync(display, False);
   815     X11_XQueryTree(display, data->xwindow, &root, &parent, &children, &childCount);
   816     X11_XGetWindowAttributes(display, data->xwindow, &attrs);
   817     X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
   818                               attrs.x, attrs.y, &orig_x, &orig_y, &childReturn);
   819 
   820     /*Attempt to move the window*/
   821     X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
   822 
   823     /* Wait a brief time to see if the window manager decided to let this move happen.
   824        If the window changes at all, even to an unexpected value, we break out. */
   825     timeout = SDL_GetTicks() + 100;
   826     while (SDL_TRUE) {
   827         int x, y;
   828         X11_XSync(display, False);
   829         X11_XGetWindowAttributes(display, data->xwindow, &attrs);
   830         X11_XTranslateCoordinates(display, parent, DefaultRootWindow(display),
   831                                   attrs.x, attrs.y, &x, &y, &childReturn);
   832 
   833         if ((x != orig_x) || (y != orig_y)) {
   834             window->x = x;
   835             window->y = y;
   836             break;  /* window moved, time to go. */
   837         } else if ((x == window->x) && (y == window->y)) {
   838             break;  /* we're at the place we wanted to be anyhow, drop out. */
   839         }
   840 
   841         if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
   842             break;
   843         }
   844 
   845         SDL_Delay(10);
   846     }
   847 }
   848 
   849 void
   850 X11_SetWindowMinimumSize(_THIS, SDL_Window * window)
   851 {
   852     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   853     Display *display = data->videodata->display;
   854 
   855     if (window->flags & SDL_WINDOW_RESIZABLE) {
   856          XSizeHints *sizehints = X11_XAllocSizeHints();
   857          long userhints;
   858 
   859          X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
   860 
   861          sizehints->min_width = window->min_w;
   862          sizehints->min_height = window->min_h;
   863          sizehints->flags |= PMinSize;
   864 
   865          X11_XSetWMNormalHints(display, data->xwindow, sizehints);
   866 
   867          X11_XFree(sizehints);
   868 
   869         /* See comment in X11_SetWindowSize. */
   870         X11_XResizeWindow(display, data->xwindow, window->w, window->h);
   871         X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
   872         X11_XRaiseWindow(display, data->xwindow);
   873     }
   874 
   875     X11_XFlush(display);
   876 }
   877 
   878 void
   879 X11_SetWindowMaximumSize(_THIS, SDL_Window * window)
   880 {
   881     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   882     Display *display = data->videodata->display;
   883 
   884     if (window->flags & SDL_WINDOW_RESIZABLE) {
   885          XSizeHints *sizehints = X11_XAllocSizeHints();
   886          long userhints;
   887 
   888          X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
   889 
   890          sizehints->max_width = window->max_w;
   891          sizehints->max_height = window->max_h;
   892          sizehints->flags |= PMaxSize;
   893 
   894          X11_XSetWMNormalHints(display, data->xwindow, sizehints);
   895 
   896          X11_XFree(sizehints);
   897 
   898         /* See comment in X11_SetWindowSize. */
   899         X11_XResizeWindow(display, data->xwindow, window->w, window->h);
   900         X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
   901         X11_XRaiseWindow(display, data->xwindow);
   902     }
   903 
   904     X11_XFlush(display);
   905 }
   906 
   907 void
   908 X11_SetWindowSize(_THIS, SDL_Window * window)
   909 {
   910     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   911     Display *display = data->videodata->display;
   912     XWindowAttributes attrs;
   913     int orig_w, orig_h;
   914     Uint32 timeout;
   915 
   916     X11_XSync(display, False);
   917     X11_XGetWindowAttributes(display, data->xwindow, &attrs);
   918     orig_w = attrs.width;
   919     orig_h = attrs.height;
   920 
   921     if (SDL_IsShapedWindow(window)) {
   922         X11_ResizeWindowShape(window);
   923     }
   924     if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
   925          /* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the X11_XResizeWindow, thus
   926             we must set the size hints to adjust the window size. */
   927          XSizeHints *sizehints = X11_XAllocSizeHints();
   928          long userhints;
   929 
   930          X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
   931 
   932          sizehints->min_width = sizehints->max_width = window->w;
   933          sizehints->min_height = sizehints->max_height = window->h;
   934          sizehints->flags |= PMinSize | PMaxSize;
   935 
   936          X11_XSetWMNormalHints(display, data->xwindow, sizehints);
   937 
   938          X11_XFree(sizehints);
   939 
   940         /* From Pierre-Loup:
   941            WMs each have their little quirks with that.  When you change the
   942            size hints, they get a ConfigureNotify event with the
   943            WM_NORMAL_SIZE_HINTS Atom.  They all save the hints then, but they
   944            don't all resize the window right away to enforce the new hints.
   945 
   946            Some of them resize only after:
   947             - A user-initiated move or resize
   948             - A code-initiated move or resize
   949             - Hiding & showing window (Unmap & map)
   950 
   951            The following move & resize seems to help a lot of WMs that didn't
   952            properly update after the hints were changed. We don't do a
   953            hide/show, because there are supposedly subtle problems with doing so
   954            and transitioning from windowed to fullscreen in Unity.
   955          */
   956         X11_XResizeWindow(display, data->xwindow, window->w, window->h);
   957         X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
   958         X11_XRaiseWindow(display, data->xwindow);
   959     } else {
   960         X11_XResizeWindow(display, data->xwindow, window->w, window->h);
   961     }
   962 
   963     /* Wait a brief time to see if the window manager decided to let this resize happen.
   964        If the window changes at all, even to an unexpected value, we break out. */
   965     timeout = SDL_GetTicks() + 100;
   966     while (SDL_TRUE) {
   967         X11_XSync(display, False);
   968         X11_XGetWindowAttributes(display, data->xwindow, &attrs);
   969 
   970         if ((attrs.width != orig_w) || (attrs.height != orig_h)) {
   971             window->w = attrs.width;
   972             window->h = attrs.height;
   973             break;  /* window changed, time to go. */
   974         } else if ((attrs.width == window->w) && (attrs.height == window->h)) {
   975             break;  /* we're at the place we wanted to be anyhow, drop out. */
   976         }
   977 
   978         if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
   979             break;
   980         }
   981 
   982         SDL_Delay(10);
   983     }
   984 }
   985 
   986 int
   987 X11_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right)
   988 {
   989     SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
   990 
   991     *left = data->border_left;
   992     *right = data->border_right;
   993     *top = data->border_top;
   994     *bottom = data->border_bottom;
   995 
   996     return 0;
   997 }
   998 
   999 int
  1000 X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
  1001 {
  1002     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1003     Display *display = data->videodata->display;
  1004     Atom _NET_WM_WINDOW_OPACITY = data->videodata->_NET_WM_WINDOW_OPACITY;
  1005 
  1006     if (opacity == 1.0f) {
  1007         X11_XDeleteProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY);
  1008     } else  {
  1009         const Uint32 FullyOpaque = 0xFFFFFFFF;
  1010         const long alpha = (long) ((double)opacity * (double)FullyOpaque);
  1011         X11_XChangeProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
  1012             PropModeReplace, (unsigned char *)&alpha, 1);
  1013     }
  1014 
  1015     return 0;
  1016 }
  1017 
  1018 int 
  1019 X11_SetWindowModalFor(_THIS, SDL_Window * modal_window, SDL_Window * parent_window) {
  1020     SDL_WindowData *data = (SDL_WindowData *) modal_window->driverdata;
  1021     SDL_WindowData *parent_data = (SDL_WindowData *) parent_window->driverdata;
  1022     Display *display = data->videodata->display;
  1023 
  1024     X11_XSetTransientForHint(display, data->xwindow, parent_data->xwindow);
  1025     return 0;
  1026 }
  1027 
  1028 int
  1029 X11_SetWindowInputFocus(_THIS, SDL_Window * window) 
  1030 {
  1031     if (X11_IsWindowMapped(_this, window)) {
  1032         SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1033         Display *display = data->videodata->display;
  1034         X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime);
  1035         X11_XFlush(display);
  1036         return 0;
  1037     }
  1038     return -1;
  1039 }
  1040 
  1041 void
  1042 X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
  1043 {
  1044     const SDL_bool focused = ((window->flags & SDL_WINDOW_INPUT_FOCUS) != 0);
  1045     const SDL_bool visible = ((window->flags & SDL_WINDOW_HIDDEN) == 0);
  1046     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1047     SDL_DisplayData *displaydata =
  1048         (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
  1049     Display *display = data->videodata->display;
  1050     XEvent event;
  1051 
  1052     SetWindowBordered(display, displaydata->screen, data->xwindow, bordered);
  1053     X11_XFlush(display);
  1054 
  1055     if (visible) {
  1056         XWindowAttributes attr;
  1057         do {
  1058             X11_XSync(display, False);
  1059             X11_XGetWindowAttributes(display, data->xwindow, &attr);
  1060         } while (attr.map_state != IsViewable);
  1061 
  1062         if (focused) {
  1063             X11_XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime);
  1064         }
  1065     }
  1066 
  1067     /* make sure these don't make it to the real event queue if they fired here. */
  1068     X11_XSync(display, False);
  1069     X11_XCheckIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
  1070     X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
  1071 }
  1072 
  1073 void
  1074 X11_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
  1075 {
  1076     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1077     Display *display = data->videodata->display;
  1078 
  1079     XSizeHints *sizehints = X11_XAllocSizeHints();
  1080     long userhints;
  1081 
  1082     X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
  1083 
  1084     if (resizable) {
  1085         /* FIXME: Is there a better way to get max window size from X? -flibit */
  1086         const int maxsize = 0x7FFFFFFF;
  1087         sizehints->min_width = window->min_w;
  1088         sizehints->min_height = window->min_h;
  1089         sizehints->max_width = (window->max_w == 0) ? maxsize : window->max_w;
  1090         sizehints->max_height = (window->max_h == 0) ? maxsize : window->max_h;
  1091     } else {
  1092         sizehints->min_width = window->w;
  1093         sizehints->min_height = window->h;
  1094         sizehints->max_width = window->w;
  1095         sizehints->max_height = window->h;
  1096     }
  1097     sizehints->flags |= PMinSize | PMaxSize;
  1098 
  1099     X11_XSetWMNormalHints(display, data->xwindow, sizehints);
  1100 
  1101     X11_XFree(sizehints);
  1102 
  1103     /* See comment in X11_SetWindowSize. */
  1104     X11_XResizeWindow(display, data->xwindow, window->w, window->h);
  1105     X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
  1106     X11_XRaiseWindow(display, data->xwindow);
  1107 
  1108     X11_XFlush(display);
  1109 }
  1110 
  1111 void
  1112 X11_ShowWindow(_THIS, SDL_Window * window)
  1113 {
  1114     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1115     Display *display = data->videodata->display;
  1116     XEvent event;
  1117 
  1118     if (!X11_IsWindowMapped(_this, window)) {
  1119         X11_XMapRaised(display, data->xwindow);
  1120         /* Blocking wait for "MapNotify" event.
  1121          * We use X11_XIfEvent because pXWindowEvent takes a mask rather than a type,
  1122          * and XCheckTypedWindowEvent doesn't block */
  1123         if(!(window->flags & SDL_WINDOW_FOREIGN))
  1124             X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
  1125         X11_XFlush(display);
  1126     }
  1127 
  1128     if (!data->videodata->net_wm) {
  1129         /* no WM means no FocusIn event, which confuses us. Force it. */
  1130         X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime);
  1131         X11_XFlush(display);
  1132     }
  1133 }
  1134 
  1135 void
  1136 X11_HideWindow(_THIS, SDL_Window * window)
  1137 {
  1138     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1139     SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
  1140     Display *display = data->videodata->display;
  1141     XEvent event;
  1142 
  1143     if (X11_IsWindowMapped(_this, window)) {
  1144         X11_XWithdrawWindow(display, data->xwindow, displaydata->screen);
  1145         /* Blocking wait for "UnmapNotify" event */
  1146         if(!(window->flags & SDL_WINDOW_FOREIGN))
  1147             X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
  1148         X11_XFlush(display);
  1149     }
  1150 }
  1151 
  1152 static void
  1153 SetWindowActive(_THIS, SDL_Window * window)
  1154 {
  1155     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1156     SDL_DisplayData *displaydata =
  1157         (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
  1158     Display *display = data->videodata->display;
  1159     Atom _NET_ACTIVE_WINDOW = data->videodata->_NET_ACTIVE_WINDOW;
  1160 
  1161     if (X11_IsWindowMapped(_this, window)) {
  1162         XEvent e;
  1163 
  1164         /*printf("SDL Window %p: sending _NET_ACTIVE_WINDOW with timestamp %lu\n", window, data->user_time);*/
  1165 
  1166         SDL_zero(e);
  1167         e.xany.type = ClientMessage;
  1168         e.xclient.message_type = _NET_ACTIVE_WINDOW;
  1169         e.xclient.format = 32;
  1170         e.xclient.window = data->xwindow;
  1171         e.xclient.data.l[0] = 1;  /* source indication. 1 = application */
  1172         e.xclient.data.l[1] = data->user_time;
  1173         e.xclient.data.l[2] = 0;
  1174 
  1175         X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
  1176                    SubstructureNotifyMask | SubstructureRedirectMask, &e);
  1177 
  1178         X11_XFlush(display);
  1179     }
  1180 }
  1181 
  1182 void
  1183 X11_RaiseWindow(_THIS, SDL_Window * window)
  1184 {
  1185     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1186     Display *display = data->videodata->display;
  1187 
  1188     X11_XRaiseWindow(display, data->xwindow);
  1189     SetWindowActive(_this, window);
  1190     X11_XFlush(display);
  1191 }
  1192 
  1193 static void
  1194 SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized)
  1195 {
  1196     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1197     SDL_DisplayData *displaydata =
  1198         (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
  1199     Display *display = data->videodata->display;
  1200     Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
  1201     Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
  1202     Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
  1203 
  1204     if (maximized) {
  1205         window->flags |= SDL_WINDOW_MAXIMIZED;
  1206     } else {
  1207         window->flags &= ~SDL_WINDOW_MAXIMIZED;
  1208     }
  1209 
  1210     if (X11_IsWindowMapped(_this, window)) {
  1211         XEvent e;
  1212 
  1213         SDL_zero(e);
  1214         e.xany.type = ClientMessage;
  1215         e.xclient.message_type = _NET_WM_STATE;
  1216         e.xclient.format = 32;
  1217         e.xclient.window = data->xwindow;
  1218         e.xclient.data.l[0] =
  1219             maximized ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
  1220         e.xclient.data.l[1] = _NET_WM_STATE_MAXIMIZED_VERT;
  1221         e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ;
  1222         e.xclient.data.l[3] = 0l;
  1223 
  1224         X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
  1225                    SubstructureNotifyMask | SubstructureRedirectMask, &e);
  1226     } else {
  1227         X11_SetNetWMState(_this, data->xwindow, window->flags);
  1228     }
  1229     X11_XFlush(display);
  1230 }
  1231 
  1232 void
  1233 X11_MaximizeWindow(_THIS, SDL_Window * window)
  1234 {
  1235     SetWindowMaximized(_this, window, SDL_TRUE);
  1236 }
  1237 
  1238 void
  1239 X11_MinimizeWindow(_THIS, SDL_Window * window)
  1240 {
  1241     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1242     SDL_DisplayData *displaydata =
  1243         (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
  1244     Display *display = data->videodata->display;
  1245 
  1246     X11_XIconifyWindow(display, data->xwindow, displaydata->screen);
  1247     X11_XFlush(display);
  1248 }
  1249 
  1250 void
  1251 X11_RestoreWindow(_THIS, SDL_Window * window)
  1252 {
  1253     SetWindowMaximized(_this, window, SDL_FALSE);
  1254     X11_ShowWindow(_this, window);
  1255     SetWindowActive(_this, window);
  1256 }
  1257 
  1258 /* This asks the Window Manager to handle fullscreen for us. This is the modern way. */
  1259 static void
  1260 X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
  1261 {
  1262     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1263     SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
  1264     Display *display = data->videodata->display;
  1265     Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
  1266     Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
  1267 
  1268     if (X11_IsWindowMapped(_this, window)) {
  1269         XEvent e;
  1270 
  1271         if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
  1272             /* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
  1273                can be resized to the fullscreen resolution (or reset so we're not resizable again) */
  1274             XSizeHints *sizehints = X11_XAllocSizeHints();
  1275             long flags = 0;
  1276             X11_XGetWMNormalHints(display, data->xwindow, sizehints, &flags);
  1277             /* set the resize flags on */
  1278             if (fullscreen) {
  1279                 /* we are going fullscreen so turn the flags off */
  1280                 sizehints->flags &= ~(PMinSize | PMaxSize);
  1281             } else {
  1282                 /* Reset the min/max width height to make the window non-resizable again */
  1283                 sizehints->flags |= PMinSize | PMaxSize;
  1284                 sizehints->min_width = sizehints->max_width = window->windowed.w;
  1285                 sizehints->min_height = sizehints->max_height = window->windowed.h;
  1286             }
  1287             X11_XSetWMNormalHints(display, data->xwindow, sizehints);
  1288             X11_XFree(sizehints);
  1289         }
  1290 
  1291         SDL_zero(e);
  1292         e.xany.type = ClientMessage;
  1293         e.xclient.message_type = _NET_WM_STATE;
  1294         e.xclient.format = 32;
  1295         e.xclient.window = data->xwindow;
  1296         e.xclient.data.l[0] =
  1297             fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
  1298         e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
  1299         e.xclient.data.l[3] = 0l;
  1300 
  1301         X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
  1302                    SubstructureNotifyMask | SubstructureRedirectMask, &e);
  1303 
  1304         /* Fullscreen windows sometimes end up being marked maximized by
  1305             window managers. Force it back to how we expect it to be. */
  1306         if (!fullscreen && ((window->flags & SDL_WINDOW_MAXIMIZED) == 0)) {
  1307             SDL_zero(e);
  1308             e.xany.type = ClientMessage;
  1309             e.xclient.message_type = _NET_WM_STATE;
  1310             e.xclient.format = 32;
  1311             e.xclient.window = data->xwindow;
  1312             e.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
  1313             e.xclient.data.l[1] = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
  1314             e.xclient.data.l[2] = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
  1315             e.xclient.data.l[3] = 0l;
  1316             X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
  1317                    SubstructureNotifyMask | SubstructureRedirectMask, &e);
  1318         }
  1319     } else {
  1320         Uint32 flags;
  1321 
  1322         flags = window->flags;
  1323         if (fullscreen) {
  1324             flags |= SDL_WINDOW_FULLSCREEN;
  1325         } else {
  1326             flags &= ~SDL_WINDOW_FULLSCREEN;
  1327         }
  1328         X11_SetNetWMState(_this, data->xwindow, flags);
  1329     }
  1330 
  1331     if (data->visual->class == DirectColor) {
  1332         if ( fullscreen ) {
  1333             X11_XInstallColormap(display, data->colormap);
  1334         } else {
  1335             X11_XUninstallColormap(display, data->colormap);
  1336         }
  1337     }
  1338 
  1339     X11_XFlush(display);
  1340 }
  1341 
  1342 /* This handles fullscreen itself, outside the Window Manager. */
  1343 static void
  1344 X11_BeginWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
  1345 {
  1346     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1347     SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
  1348     Visual *visual = data->visual;
  1349     Display *display = data->videodata->display;
  1350     const int screen = displaydata->screen;
  1351     Window root = RootWindow(display, screen);
  1352     const int def_vis = (visual == DefaultVisual(display, screen));
  1353     unsigned long xattrmask = 0;
  1354     XSetWindowAttributes xattr;
  1355     XEvent ev;
  1356     SDL_Rect rect;
  1357 
  1358     if ( data->fswindow ) {
  1359         return;  /* already fullscreen, I hope. */
  1360     }
  1361 
  1362     X11_GetDisplayBounds(_this, _display, &rect);
  1363 
  1364     SDL_zero(xattr);
  1365     xattr.override_redirect = True;
  1366     xattrmask |= CWOverrideRedirect;
  1367     xattr.background_pixel = def_vis ? BlackPixel(display, screen) : 0;
  1368     xattrmask |= CWBackPixel;
  1369     xattr.border_pixel = 0;
  1370     xattrmask |= CWBorderPixel;
  1371     xattr.colormap = data->colormap;
  1372     xattrmask |= CWColormap;
  1373 
  1374     data->fswindow = X11_XCreateWindow(display, root,
  1375                                    rect.x, rect.y, rect.w, rect.h, 0,
  1376                                    displaydata->depth, InputOutput,
  1377                                    visual, xattrmask, &xattr);
  1378 
  1379     X11_XSelectInput(display, data->fswindow, StructureNotifyMask);
  1380     X11_XSetWindowBackground(display, data->fswindow, 0);
  1381     X11_XInstallColormap(display, data->colormap);
  1382     X11_XClearWindow(display, data->fswindow);
  1383     X11_XMapRaised(display, data->fswindow);
  1384 
  1385     /* Make sure the fswindow is in view by warping mouse to the corner */
  1386     X11_XUngrabPointer(display, CurrentTime);
  1387     X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
  1388 
  1389     /* Wait to be mapped, filter Unmap event out if it arrives. */
  1390     X11_XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->fswindow);
  1391     X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->fswindow);
  1392 
  1393 #if SDL_VIDEO_DRIVER_X11_XVIDMODE
  1394     if ( displaydata->use_vidmode ) {
  1395         X11_XF86VidModeLockModeSwitch(display, screen, True);
  1396     }
  1397 #endif
  1398 
  1399     SetWindowBordered(display, displaydata->screen, data->xwindow, SDL_FALSE);
  1400 
  1401     /* Center actual window within our cover-the-screen window. */
  1402     X11_XReparentWindow(display, data->xwindow, data->fswindow,
  1403                     (rect.w - window->w) / 2, (rect.h - window->h) / 2);
  1404 
  1405     /* Move the mouse to the upper left to make sure it's on-screen */
  1406     X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
  1407 
  1408     /* Center mouse in the fullscreen window. */
  1409     rect.x += (rect.w / 2);
  1410     rect.y += (rect.h / 2);
  1411     X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
  1412 
  1413     /* Wait to be mapped, filter Unmap event out if it arrives. */
  1414     X11_XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
  1415     X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
  1416 
  1417     SDL_UpdateWindowGrab(window);
  1418 }
  1419 
  1420 static void
  1421 X11_EndWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
  1422 {
  1423     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1424     SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
  1425     Display *display = data->videodata->display;
  1426     const int screen = displaydata->screen;
  1427     Window root = RootWindow(display, screen);
  1428     Window fswindow = data->fswindow;
  1429     XEvent ev;
  1430 
  1431     if (!data->fswindow) {
  1432         return;  /* already not fullscreen, I hope. */
  1433     }
  1434 
  1435     data->fswindow = None;
  1436 
  1437 #if SDL_VIDEO_DRIVER_X11_VIDMODE
  1438     if ( displaydata->use_vidmode ) {
  1439         X11_XF86VidModeLockModeSwitch(display, screen, False);
  1440     }
  1441 #endif
  1442 
  1443     SDL_UpdateWindowGrab(window);
  1444 
  1445     X11_XReparentWindow(display, data->xwindow, root, window->x, window->y);
  1446 
  1447     /* flush these events so they don't confuse normal event handling */
  1448     X11_XSync(display, False);
  1449     X11_XCheckIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
  1450     X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
  1451 
  1452     SetWindowBordered(display, screen, data->xwindow,
  1453                       (window->flags & SDL_WINDOW_BORDERLESS) == 0);
  1454 
  1455     X11_XWithdrawWindow(display, fswindow, screen);
  1456 
  1457     /* Wait to be unmapped. */
  1458     X11_XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&fswindow);
  1459     X11_XDestroyWindow(display, fswindow);
  1460 }
  1461 
  1462 
  1463 void
  1464 X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
  1465 {
  1466     /* !!! FIXME: SDL_Hint? */
  1467     SDL_bool legacy = SDL_FALSE;
  1468     const char *env = SDL_getenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN");
  1469     if (env) {
  1470         legacy = SDL_atoi(env);
  1471     } else {
  1472         SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
  1473         SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
  1474         if ( displaydata->use_vidmode ) {
  1475             legacy = SDL_TRUE;  /* the new stuff only works with XRandR. */
  1476         } else if ( !videodata->net_wm ) {
  1477             legacy = SDL_TRUE;  /* The window manager doesn't support it */
  1478         } else {
  1479             /* !!! FIXME: look at the window manager name, and blacklist certain ones? */
  1480             /* http://stackoverflow.com/questions/758648/find-the-name-of-the-x-window-manager */
  1481             legacy = SDL_FALSE;  /* try the new way. */
  1482         }
  1483     }
  1484 
  1485     if (legacy) {
  1486         if (fullscreen) {
  1487             X11_BeginWindowFullscreenLegacy(_this, window, _display);
  1488         } else {
  1489             X11_EndWindowFullscreenLegacy(_this, window, _display);
  1490         }
  1491     } else {
  1492         X11_SetWindowFullscreenViaWM(_this, window, _display, fullscreen);
  1493     }
  1494 }
  1495 
  1496 
  1497 int
  1498 X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
  1499 {
  1500     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1501     Display *display = data->videodata->display;
  1502     Visual *visual = data->visual;
  1503     Colormap colormap = data->colormap;
  1504     XColor *colorcells;
  1505     int ncolors;
  1506     int rmask, gmask, bmask;
  1507     int rshift, gshift, bshift;
  1508     int i;
  1509 
  1510     if (visual->class != DirectColor) {
  1511         return SDL_SetError("Window doesn't have DirectColor visual");
  1512     }
  1513 
  1514     ncolors = visual->map_entries;
  1515     colorcells = SDL_malloc(ncolors * sizeof(XColor));
  1516     if (!colorcells) {
  1517         return SDL_OutOfMemory();
  1518     }
  1519 
  1520     rshift = 0;
  1521     rmask = visual->red_mask;
  1522     while (0 == (rmask & 1)) {
  1523         rshift++;
  1524         rmask >>= 1;
  1525     }
  1526 
  1527     gshift = 0;
  1528     gmask = visual->green_mask;
  1529     while (0 == (gmask & 1)) {
  1530         gshift++;
  1531         gmask >>= 1;
  1532     }
  1533 
  1534     bshift = 0;
  1535     bmask = visual->blue_mask;
  1536     while (0 == (bmask & 1)) {
  1537         bshift++;
  1538         bmask >>= 1;
  1539     }
  1540 
  1541     /* build the color table pixel values */
  1542     for (i = 0; i < ncolors; i++) {
  1543         Uint32 rbits = (rmask * i) / (ncolors - 1);
  1544         Uint32 gbits = (gmask * i) / (ncolors - 1);
  1545         Uint32 bbits = (bmask * i) / (ncolors - 1);
  1546         Uint32 pix = (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
  1547 
  1548         colorcells[i].pixel = pix;
  1549 
  1550         colorcells[i].red = ramp[(0 * 256) + i];
  1551         colorcells[i].green = ramp[(1 * 256) + i];
  1552         colorcells[i].blue = ramp[(2 * 256) + i];
  1553 
  1554         colorcells[i].flags = DoRed | DoGreen | DoBlue;
  1555     }
  1556 
  1557     X11_XStoreColors(display, colormap, colorcells, ncolors);
  1558     X11_XFlush(display);
  1559     SDL_free(colorcells);
  1560 
  1561     return 0;
  1562 }
  1563 
  1564 void
  1565 X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
  1566 {
  1567     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1568     Display *display = data->videodata->display;
  1569     SDL_bool oldstyle_fullscreen;
  1570     SDL_bool grab_keyboard;
  1571 
  1572     /* ICCCM2.0-compliant window managers can handle fullscreen windows
  1573        If we're using XVidMode to change resolution we need to confine
  1574        the cursor so we don't pan around the virtual desktop.
  1575      */
  1576     oldstyle_fullscreen = X11_IsWindowLegacyFullscreen(_this, window);
  1577 
  1578     if (oldstyle_fullscreen || grabbed) {
  1579         /* If the window is unmapped, XGrab calls return GrabNotViewable,
  1580            so when we get a MapNotify later, we'll try to update the grab as
  1581            appropriate. */
  1582         if (window->flags & SDL_WINDOW_HIDDEN) {
  1583             return;
  1584         }
  1585 
  1586         /* Try to grab the mouse */
  1587         if (!data->videodata->broken_pointer_grab) {
  1588             const unsigned int mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
  1589             int attempts;
  1590             int result;
  1591 
  1592             /* Try for up to 5000ms (5s) to grab. If it still fails, stop trying. */
  1593             for (attempts = 0; attempts < 100; attempts++) {
  1594                 result = X11_XGrabPointer(display, data->xwindow, True, mask, GrabModeAsync,
  1595                                  GrabModeAsync, data->xwindow, None, CurrentTime);
  1596                 if (result == GrabSuccess) {
  1597                     break;
  1598                 }
  1599                 SDL_Delay(50);
  1600             }
  1601 
  1602             if (result != GrabSuccess) {
  1603                 SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "The X server refused to let us grab the mouse. You might experience input bugs.");
  1604                 data->videodata->broken_pointer_grab = SDL_TRUE;  /* don't try again. */
  1605             }
  1606         }
  1607 
  1608         /* Raise the window if we grab the mouse */
  1609         X11_XRaiseWindow(display, data->xwindow);
  1610 
  1611         /* Now grab the keyboard */
  1612         if (SDL_GetHintBoolean(SDL_HINT_GRAB_KEYBOARD, SDL_FALSE)) {
  1613             grab_keyboard = SDL_TRUE;
  1614         } else {
  1615             /* We need to do this with the old style override_redirect
  1616                fullscreen window otherwise we won't get keyboard focus.
  1617             */
  1618             grab_keyboard = oldstyle_fullscreen;
  1619         }
  1620         if (grab_keyboard) {
  1621             X11_XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
  1622                           GrabModeAsync, CurrentTime);
  1623         }
  1624     } else {
  1625         X11_XUngrabPointer(display, CurrentTime);
  1626         X11_XUngrabKeyboard(display, CurrentTime);
  1627     }
  1628     X11_XSync(display, False);
  1629 }
  1630 
  1631 void
  1632 X11_DestroyWindow(_THIS, SDL_Window * window)
  1633 {
  1634     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1635 
  1636     if (data) {
  1637         SDL_VideoData *videodata = (SDL_VideoData *) data->videodata;
  1638         Display *display = videodata->display;
  1639         int numwindows = videodata->numwindows;
  1640         SDL_WindowData **windowlist = videodata->windowlist;
  1641         int i;
  1642 
  1643         if (windowlist) {
  1644             for (i = 0; i < numwindows; ++i) {
  1645                 if (windowlist[i] && (windowlist[i]->window == window)) {
  1646                     windowlist[i] = windowlist[numwindows - 1];
  1647                     windowlist[numwindows - 1] = NULL;
  1648                     videodata->numwindows--;
  1649                     break;
  1650                 }
  1651             }
  1652         }
  1653 #ifdef X_HAVE_UTF8_STRING
  1654         if (data->ic) {
  1655             X11_XDestroyIC(data->ic);
  1656         }
  1657 #endif
  1658         if (data->created) {
  1659             X11_XDestroyWindow(display, data->xwindow);
  1660             X11_XFlush(display);
  1661         }
  1662         SDL_free(data);
  1663     }
  1664     window->driverdata = NULL;
  1665 }
  1666 
  1667 SDL_bool
  1668 X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
  1669 {
  1670     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1671     Display *display;
  1672 
  1673     if (!data) {
  1674         /* This sometimes happens in SDL_IBus_UpdateTextRect() while creating the window */
  1675         SDL_SetError("Window not initialized");
  1676         return SDL_FALSE;
  1677     }
  1678 
  1679     display = data->videodata->display;
  1680 
  1681     if (info->version.major == SDL_MAJOR_VERSION &&
  1682         info->version.minor == SDL_MINOR_VERSION) {
  1683         info->subsystem = SDL_SYSWM_X11;
  1684         info->info.x11.display = display;
  1685         info->info.x11.window = data->xwindow;
  1686         return SDL_TRUE;
  1687     } else {
  1688         SDL_SetError("Application not compiled with SDL %d.%d",
  1689                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
  1690         return SDL_FALSE;
  1691     }
  1692 }
  1693 
  1694 int
  1695 X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
  1696 {
  1697     return 0;  /* just succeed, the real work is done elsewhere. */
  1698 }
  1699 
  1700 void
  1701 X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
  1702 {
  1703     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
  1704     Display *display = data->videodata->display;
  1705     Atom XdndAware = X11_XInternAtom(display, "XdndAware", False);
  1706 
  1707     if (accept) {
  1708         Atom xdnd_version = 5;
  1709         X11_XChangeProperty(display, data->xwindow, XdndAware, XA_ATOM, 32,
  1710                      PropModeReplace, (unsigned char*)&xdnd_version, 1);
  1711     } else {
  1712         X11_XDeleteProperty(display, data->xwindow, XdndAware);
  1713     }
  1714 }
  1715 
  1716 #endif /* SDL_VIDEO_DRIVER_X11 */
  1717 
  1718 /* vi: set ts=4 sw=4 expandtab: */