upgrade SDL to version 2.0.8
[platform/upstream/SDL.git] / src / video / x11 / SDL_x11window.c
old mode 100644 (file)
new mode 100755 (executable)
index 7ae166d..1b2ea0e
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -28,7 +28,6 @@
 #include "../SDL_pixels_c.h"
 #include "../../events/SDL_keyboard_c.h"
 #include "../../events/SDL_mouse_c.h"
-#include "../SDL_vulkan_c.h"
 
 #include "SDL_x11video.h"
 #include "SDL_x11mouse.h"
 
 #include "SDL_timer.h"
 #include "SDL_syswm.h"
-#include "SDL_assert.h"
+#include "SDL_log.h"
 
 #define _NET_WM_STATE_REMOVE    0l
 #define _NET_WM_STATE_ADD       1l
-#define _NET_WM_STATE_TOGGLE    2l
 
 static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win)
 {
@@ -131,13 +129,17 @@ X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
 {
     SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
     Display *display = videodata->display;
+    /* !!! FIXME: just dereference videodata below instead of copying to locals. */
     Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
     /* Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN; */
     Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
     Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
     Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
     Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
-    Atom atoms[5];
+    Atom _NET_WM_STATE_ABOVE = videodata->_NET_WM_STATE_ABOVE;
+    Atom _NET_WM_STATE_SKIP_TASKBAR = videodata->_NET_WM_STATE_SKIP_TASKBAR;
+    Atom _NET_WM_STATE_SKIP_PAGER = videodata->_NET_WM_STATE_SKIP_PAGER;
+    Atom atoms[16];
     int count = 0;
 
     /* The window manager sets this property, we shouldn't set it.
@@ -148,6 +150,14 @@ X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
         atoms[count++] = _NET_WM_STATE_HIDDEN;
     }
     */
+
+    if (flags & SDL_WINDOW_ALWAYS_ON_TOP) {
+        atoms[count++] = _NET_WM_STATE_ABOVE;
+    }
+    if (flags & SDL_WINDOW_SKIP_TASKBAR) {
+        atoms[count++] = _NET_WM_STATE_SKIP_TASKBAR;
+        atoms[count++] = _NET_WM_STATE_SKIP_PAGER;
+    }
     if (flags & SDL_WINDOW_INPUT_FOCUS) {
         atoms[count++] = _NET_WM_STATE_FOCUSED;
     }
@@ -158,6 +168,9 @@ X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
     if (flags & SDL_WINDOW_FULLSCREEN) {
         atoms[count++] = _NET_WM_STATE_FULLSCREEN;
     }
+
+    SDL_assert(count <= SDL_arraysize(atoms));
+
     if (count > 0) {
         X11_XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
                         PropModeReplace, (unsigned char *)atoms, count);
@@ -207,9 +220,24 @@ X11_GetNetWMState(_THIS, Window xwindow)
         }
         if (maximized == 3) {
             flags |= SDL_WINDOW_MAXIMIZED;
-        }  else if (fullscreen == 1) {
+        }
+
+        if (fullscreen == 1) {
             flags |= SDL_WINDOW_FULLSCREEN;
         }
+
+        /* If the window is unmapped, numItems will be zero and _NET_WM_STATE_HIDDEN
+         * will not be set. Do an additional check to see if the window is unmapped
+         * and mark it as SDL_WINDOW_HIDDEN if it is.
+         */
+        {
+            XWindowAttributes attr;
+            SDL_memset(&attr,0,sizeof(attr));
+            X11_XGetWindowAttributes(videodata->display, xwindow, &attr);
+            if (attr.map_state == IsUnmapped) {
+                flags |= SDL_WINDOW_HIDDEN;
+            }
+        }
         X11_XFree(propertyValue);
     }
 
@@ -356,10 +384,11 @@ X11_CreateWindow(_THIS, SDL_Window * window)
     XSizeHints *sizehints;
     XWMHints *wmhints;
     XClassHint *classhints;
-    const long _NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1;
     Atom _NET_WM_BYPASS_COMPOSITOR;
     Atom _NET_WM_WINDOW_TYPE;
-    Atom _NET_WM_WINDOW_TYPE_NORMAL;
+    Atom wintype;
+    const char *wintype_name = NULL;
+    long compositor = 1;
     Atom _NET_WM_PID;
     Atom XdndAware, xdnd_version = 5;
     long fevent = 0;
@@ -372,7 +401,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
 #if SDL_VIDEO_OPENGL_EGL
         if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES 
 #if SDL_VIDEO_OPENGL_GLX            
-            && ( !_this->gl_data || ! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile )
+            && ( !_this->gl_data || X11_GL_UseEGL(_this) )
 #endif
         ) {
             vinfo = X11_GLES_GetVisual(_this, display, screen);
@@ -397,19 +426,9 @@ X11_CreateWindow(_THIS, SDL_Window * window)
         depth = displaydata->depth;
     }
 
-#if SDL_VIDEO_VULKAN
-    if (window->flags & SDL_WINDOW_VULKAN) {
-        if (!_this->vulkan_GetInstanceExtensions) {
-            SDL_SetError("No Vulkan support in video driver");
-        }
 
-        if (_this->vulkan_LoadLibrary(_this, NULL) < 0) {
-            SDL_SetError("Fail to load Vulkan Library");
-        }
-    }
-#endif
 
-    xattr.override_redirect = False;
+    xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU)) ? True : False;
     xattr.background_pixmap = None;
     xattr.border_pixel = 0;
 
@@ -519,7 +538,8 @@ X11_CreateWindow(_THIS, SDL_Window * window)
     /* Setup the input hints so we get keyboard input */
     wmhints = X11_XAllocWMHints();
     wmhints->input = True;
-    wmhints->flags = InputHint;
+    wmhints->window_group = data->window_group;
+    wmhints->flags = InputHint | WindowGroupHint;
 
     /* Setup the class hints so we can get an icon (AfterStep) */
     classhints = X11_XAllocClassHint();
@@ -534,39 +554,50 @@ X11_CreateWindow(_THIS, SDL_Window * window)
     X11_XFree(classhints);
     /* Set the PID related to the window for the given hostname, if possible */
     if (data->pid > 0) {
+        long pid = (long) data->pid;
         _NET_WM_PID = X11_XInternAtom(display, "_NET_WM_PID", False);
         X11_XChangeProperty(display, w, _NET_WM_PID, XA_CARDINAL, 32, PropModeReplace,
-                        (unsigned char *)&data->pid, 1);
+                        (unsigned char *) &pid, 1);
     }
 
     /* Set the window manager state */
     X11_SetNetWMState(_this, w, window->flags);
 
-    /* Let the window manager know we're a "normal" window */
+    compositor = 2;  /* don't disable compositing except for "normal" windows */
+
+    if (window->flags & SDL_WINDOW_UTILITY) {
+        wintype_name = "_NET_WM_WINDOW_TYPE_UTILITY";
+    } else if (window->flags & SDL_WINDOW_TOOLTIP) {
+        wintype_name = "_NET_WM_WINDOW_TYPE_TOOLTIP";
+    } else if (window->flags & SDL_WINDOW_POPUP_MENU) {
+        wintype_name = "_NET_WM_WINDOW_TYPE_POPUP_MENU";
+    } else {
+        wintype_name = "_NET_WM_WINDOW_TYPE_NORMAL";
+        compositor = 1;  /* disable compositing for "normal" windows */
+    }
+
+    /* Let the window manager know what type of window we are. */
     _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
-    _NET_WM_WINDOW_TYPE_NORMAL = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
+    wintype = X11_XInternAtom(display, wintype_name, False);
     X11_XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
-                    PropModeReplace,
-                    (unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1);
-
-    _NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
-    X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
-                    PropModeReplace,
-                    (unsigned char *)&_NET_WM_BYPASS_COMPOSITOR_HINT_ON, 1);
+                    PropModeReplace, (unsigned char *)&wintype, 1);
+    if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, SDL_TRUE)) {
+        _NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
+        X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
+                        PropModeReplace,
+                        (unsigned char *)&compositor, 1);
+    }
 
     {
-        Atom protocols[2];
+        Atom protocols[3];
         int proto_count = 0;
-        const char *ping_hint;
 
-        protocols[proto_count] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */
-        proto_count++;
-        
-        ping_hint = SDL_GetHint(SDL_HINT_VIDEO_X11_NET_WM_PING);
+        protocols[proto_count++] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */
+        protocols[proto_count++] = data->WM_TAKE_FOCUS; /* Since we will want to set input focus explicitly */
+
         /* Default to using ping if there is no hint */
-        if (!ping_hint || SDL_atoi(ping_hint)) {
-            protocols[proto_count] = data->_NET_WM_PING; /* Respond so WM knows we're alive */
-            proto_count++;
+        if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_NET_WM_PING, SDL_TRUE)) {
+            protocols[proto_count++] = data->_NET_WM_PING; /* Respond so WM knows we're alive */
         }
 
         SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0]));
@@ -584,7 +615,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
     if ((window->flags & SDL_WINDOW_OPENGL) && 
         _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
 #if SDL_VIDEO_OPENGL_GLX            
-        && ( !_this->gl_data || ! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile )
+        && ( !_this->gl_data || X11_GL_UseEGL(_this) )
 #endif  
     ) {
 #if SDL_VIDEO_OPENGL_EGL  
@@ -601,7 +632,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
             return SDL_SetError("Could not create GLES window surface");
         }
 #else
-        return SDL_SetError("Could not create GLES window surface (no EGL support available)");
+        return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
 #endif /* SDL_VIDEO_OPENGL_EGL */
     }
 #endif
@@ -763,7 +794,7 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
     Display *display = data->videodata->display;
 
-    X11_XMoveWindow(display, data->xwindow, window->x, window->y);
+    X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
     X11_XFlush(display);
 }
 
@@ -789,7 +820,7 @@ X11_SetWindowMinimumSize(_THIS, SDL_Window * window)
 
         /* See comment in X11_SetWindowSize. */
         X11_XResizeWindow(display, data->xwindow, window->w, window->h);
-        X11_XMoveWindow(display, data->xwindow, window->x, window->y);
+        X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
         X11_XRaiseWindow(display, data->xwindow);
     }
 
@@ -818,7 +849,7 @@ X11_SetWindowMaximumSize(_THIS, SDL_Window * window)
 
         /* See comment in X11_SetWindowSize. */
         X11_XResizeWindow(display, data->xwindow, window->w, window->h);
-        X11_XMoveWindow(display, data->xwindow, window->x, window->y);
+        X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
         X11_XRaiseWindow(display, data->xwindow);
     }
 
@@ -867,7 +898,7 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
            and transitioning from windowed to fullscreen in Unity.
          */
         X11_XResizeWindow(display, data->xwindow, window->w, window->h);
-        X11_XMoveWindow(display, data->xwindow, window->x, window->y);
+        X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
         X11_XRaiseWindow(display, data->xwindow);
     } else {
         X11_XResizeWindow(display, data->xwindow, window->w, window->h);
@@ -876,6 +907,61 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
     X11_XFlush(display);
 }
 
+int
+X11_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right)
+{
+    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+
+    *left = data->border_left;
+    *right = data->border_right;
+    *top = data->border_top;
+    *bottom = data->border_bottom;
+
+    return 0;
+}
+
+int
+X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+    Display *display = data->videodata->display;
+    Atom _NET_WM_WINDOW_OPACITY = data->videodata->_NET_WM_WINDOW_OPACITY;
+
+    if (opacity == 1.0f) {
+        X11_XDeleteProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY);
+    } else  {
+        const Uint32 FullyOpaque = 0xFFFFFFFF;
+        const long alpha = (long) ((double)opacity * (double)FullyOpaque);
+        X11_XChangeProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
+            PropModeReplace, (unsigned char *)&alpha, 1);
+    }
+
+    return 0;
+}
+
+int 
+X11_SetWindowModalFor(_THIS, SDL_Window * modal_window, SDL_Window * parent_window) {
+    SDL_WindowData *data = (SDL_WindowData *) modal_window->driverdata;
+    SDL_WindowData *parent_data = (SDL_WindowData *) parent_window->driverdata;
+    Display *display = data->videodata->display;
+
+    X11_XSetTransientForHint(display, data->xwindow, parent_data->xwindow);
+    return 0;
+}
+
+int
+X11_SetWindowInputFocus(_THIS, SDL_Window * window) 
+{
+    if (X11_IsWindowMapped(_this, window)) {
+        SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+        Display *display = data->videodata->display;
+        X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime);
+        X11_XFlush(display);
+        return 0;
+    }
+    return -1;
+}
+
 void
 X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
 {
@@ -909,6 +995,44 @@ X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
 }
 
 void
+X11_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{
+    SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+    Display *display = data->videodata->display;
+
+    XSizeHints *sizehints = X11_XAllocSizeHints();
+    long userhints;
+
+    X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
+
+    if (resizable) {
+        /* FIXME: Is there a better way to get max window size from X? -flibit */
+        const int maxsize = 0x7FFFFFFF;
+        sizehints->min_width = window->min_w;
+        sizehints->min_height = window->min_h;
+        sizehints->max_width = (window->max_w == 0) ? maxsize : window->max_w;
+        sizehints->max_height = (window->max_h == 0) ? maxsize : window->max_h;
+    } else {
+        sizehints->min_width = window->w;
+        sizehints->min_height = window->h;
+        sizehints->max_width = window->w;
+        sizehints->max_height = window->h;
+    }
+    sizehints->flags |= PMinSize | PMaxSize;
+
+    X11_XSetWMNormalHints(display, data->xwindow, sizehints);
+
+    X11_XFree(sizehints);
+
+    /* See comment in X11_SetWindowSize. */
+    X11_XResizeWindow(display, data->xwindow, window->w, window->h);
+    X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
+    X11_XRaiseWindow(display, data->xwindow);
+
+    X11_XFlush(display);
+}
+
+void
 X11_ShowWindow(_THIS, SDL_Window * window)
 {
     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
@@ -920,7 +1044,8 @@ X11_ShowWindow(_THIS, SDL_Window * window)
         /* Blocking wait for "MapNotify" event.
          * We use X11_XIfEvent because pXWindowEvent takes a mask rather than a type,
          * and XCheckTypedWindowEvent doesn't block */
-        X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
+        if(!(window->flags & SDL_WINDOW_FOREIGN))
+            X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
         X11_XFlush(display);
     }
 
@@ -942,7 +1067,8 @@ X11_HideWindow(_THIS, SDL_Window * window)
     if (X11_IsWindowMapped(_this, window)) {
         X11_XWithdrawWindow(display, data->xwindow, displaydata->screen);
         /* Blocking wait for "UnmapNotify" event */
-        X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
+        if(!(window->flags & SDL_WINDOW_FOREIGN))
+            X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
         X11_XFlush(display);
     }
 }
@@ -959,13 +1085,15 @@ SetWindowActive(_THIS, SDL_Window * window)
     if (X11_IsWindowMapped(_this, window)) {
         XEvent e;
 
+        /*printf("SDL Window %p: sending _NET_ACTIVE_WINDOW with timestamp %lu\n", window, data->user_time);*/
+
         SDL_zero(e);
         e.xany.type = ClientMessage;
         e.xclient.message_type = _NET_ACTIVE_WINDOW;
         e.xclient.format = 32;
         e.xclient.window = data->xwindow;
         e.xclient.data.l[0] = 1;  /* source indication. 1 = application */
-        e.xclient.data.l[1] = CurrentTime;
+        e.xclient.data.l[1] = data->user_time;
         e.xclient.data.l[2] = 0;
 
         X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
@@ -1051,7 +1179,7 @@ X11_RestoreWindow(_THIS, SDL_Window * window)
     SetWindowActive(_this, window);
 }
 
-/* This asks the Window Manager to handle fullscreen for us. Most don't do it right, though. */
+/* This asks the Window Manager to handle fullscreen for us. This is the modern way. */
 static void
 X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
 {
@@ -1096,6 +1224,22 @@ X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _dis
 
         X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
                    SubstructureNotifyMask | SubstructureRedirectMask, &e);
+
+        /* Fullscreen windows sometimes end up being marked maximized by
+            window managers. Force it back to how we expect it to be. */
+        if (!fullscreen && ((window->flags & SDL_WINDOW_MAXIMIZED) == 0)) {
+            SDL_zero(e);
+            e.xany.type = ClientMessage;
+            e.xclient.message_type = _NET_WM_STATE;
+            e.xclient.format = 32;
+            e.xclient.window = data->xwindow;
+            e.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
+            e.xclient.data.l[1] = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
+            e.xclient.data.l[2] = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
+            e.xclient.data.l[3] = 0l;
+            X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
+                   SubstructureNotifyMask | SubstructureRedirectMask, &e);
+        }
     } else {
         Uint32 flags;
 
@@ -1348,7 +1492,6 @@ X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
     Display *display = data->videodata->display;
     SDL_bool oldstyle_fullscreen;
     SDL_bool grab_keyboard;
-    const char *hint;
 
     /* ICCCM2.0-compliant window managers can handle fullscreen windows
        If we're using XVidMode to change resolution we need to confine
@@ -1358,22 +1501,32 @@ X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
 
     if (oldstyle_fullscreen || grabbed) {
         /* Try to grab the mouse */
-        for (;;) {
-            int result =
-                X11_XGrabPointer(display, data->xwindow, True, 0, GrabModeAsync,
-                             GrabModeAsync, data->xwindow, None, CurrentTime);
-            if (result == GrabSuccess) {
-                break;
+        if (!data->videodata->broken_pointer_grab) {
+            const unsigned int mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
+            int attempts;
+            int result;
+
+            /* Try for up to 5000ms (5s) to grab. If it still fails, stop trying. */
+            for (attempts = 0; attempts < 100; attempts++) {
+                result = X11_XGrabPointer(display, data->xwindow, True, mask, GrabModeAsync,
+                                 GrabModeAsync, data->xwindow, None, CurrentTime);
+                if (result == GrabSuccess) {
+                    break;
+                }
+                SDL_Delay(50);
+            }
+
+            if (result != GrabSuccess) {
+                SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "The X server refused to let us grab the mouse. You might experience input bugs.");
+                data->videodata->broken_pointer_grab = SDL_TRUE;  /* don't try again. */
             }
-            SDL_Delay(50);
         }
 
         /* Raise the window if we grab the mouse */
         X11_XRaiseWindow(display, data->xwindow);
 
         /* Now grab the keyboard */
-        hint = SDL_GetHint(SDL_HINT_GRAB_KEYBOARD);
-        if (hint && SDL_atoi(hint)) {
+        if (SDL_GetHintBoolean(SDL_HINT_GRAB_KEYBOARD, SDL_FALSE)) {
             grab_keyboard = SDL_TRUE;
         } else {
             /* We need to do this with the old style override_redirect
@@ -1441,7 +1594,7 @@ X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
         info->info.x11.window = data->xwindow;
         return SDL_TRUE;
     } else {
-        SDL_SetError("Application not compiled with SDL %d.%d\n",
+        SDL_SetError("Application not compiled with SDL %d.%d",
                      SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
         return SDL_FALSE;
     }