summaryrefslogtreecommitdiff
path: root/source/3rd-party/SDL2/src/video/x11
diff options
context:
space:
mode:
Diffstat (limited to 'source/3rd-party/SDL2/src/video/x11')
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11clipboard.c199
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11clipboard.h33
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11dyn.c212
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11dyn.h111
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11events.c1500
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11events.h31
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11framebuffer.c257
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11framebuffer.h37
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11keyboard.c543
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11keyboard.h36
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11messagebox.c872
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11messagebox.h33
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11modes.c1112
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11modes.h85
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11mouse.c448
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11mouse.h31
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11opengl.c946
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11opengl.h84
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11opengles.c109
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11opengles.h56
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11shape.c115
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11shape.h39
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11sym.h337
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11touch.c54
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11touch.h32
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11video.c497
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11video.h156
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11vulkan.c243
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11vulkan.h48
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11window.c1619
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11window.h111
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11xinput2.c313
-rw-r--r--source/3rd-party/SDL2/src/video/x11/SDL_x11xinput2.h42
-rw-r--r--source/3rd-party/SDL2/src/video/x11/edid-parse.c754
-rw-r--r--source/3rd-party/SDL2/src/video/x11/edid.h167
-rw-r--r--source/3rd-party/SDL2/src/video/x11/imKStoUCS.c350
-rw-r--r--source/3rd-party/SDL2/src/video/x11/imKStoUCS.h32
37 files changed, 11644 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11clipboard.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11clipboard.c
new file mode 100644
index 0000000..fad8c9c
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11clipboard.c
@@ -0,0 +1,199 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include <limits.h> /* For INT_MAX */
+
+#include "SDL_events.h"
+#include "SDL_x11video.h"
+#include "SDL_timer.h"
+
+
+/* If you don't support UTF-8, you might use XA_STRING here */
+#ifdef X_HAVE_UTF8_STRING
+#define TEXT_FORMAT X11_XInternAtom(display, "UTF8_STRING", False)
+#else
+#define TEXT_FORMAT XA_STRING
+#endif
+
+/* Get any application owned window handle for clipboard association */
+static Window
+GetWindow(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ /* We create an unmapped window that exists just to manage the clipboard,
+ since X11 selection data is tied to a specific window and dies with it.
+ We create the window on demand, so apps that don't use the clipboard
+ don't have to keep an unnecessary resource around. */
+ if (data->clipboard_window == None) {
+ Display *dpy = data->display;
+ Window parent = RootWindow(dpy, DefaultScreen(dpy));
+ XSetWindowAttributes xattr;
+ data->clipboard_window = X11_XCreateWindow(dpy, parent, -10, -10, 1, 1, 0,
+ CopyFromParent, InputOnly,
+ CopyFromParent, 0, &xattr);
+ X11_XFlush(data->display);
+ }
+
+ return data->clipboard_window;
+}
+
+/* We use our own cut-buffer for intermediate storage instead of
+ XA_CUT_BUFFER0 because their use isn't really defined for holding UTF8. */
+Atom
+X11_GetSDLCutBufferClipboardType(Display *display)
+{
+ return X11_XInternAtom(display, "SDL_CUTBUFFER", False);
+}
+
+int
+X11_SetClipboardText(_THIS, const char *text)
+{
+ Display *display = ((SDL_VideoData *) _this->driverdata)->display;
+ Atom format;
+ Window window;
+ Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
+
+ /* Get the SDL window that will own the selection */
+ window = GetWindow(_this);
+ if (window == None) {
+ return SDL_SetError("Couldn't find a window to own the selection");
+ }
+
+ /* Save the selection on the root window */
+ format = TEXT_FORMAT;
+ X11_XChangeProperty(display, DefaultRootWindow(display),
+ X11_GetSDLCutBufferClipboardType(display), format, 8, PropModeReplace,
+ (const unsigned char *)text, SDL_strlen(text));
+
+ if (XA_CLIPBOARD != None &&
+ X11_XGetSelectionOwner(display, XA_CLIPBOARD) != window) {
+ X11_XSetSelectionOwner(display, XA_CLIPBOARD, window, CurrentTime);
+ }
+
+ if (X11_XGetSelectionOwner(display, XA_PRIMARY) != window) {
+ X11_XSetSelectionOwner(display, XA_PRIMARY, window, CurrentTime);
+ }
+ return 0;
+}
+
+char *
+X11_GetClipboardText(_THIS)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ Display *display = videodata->display;
+ Atom format;
+ Window window;
+ Window owner;
+ Atom selection;
+ Atom seln_type;
+ int seln_format;
+ unsigned long nbytes;
+ unsigned long overflow;
+ unsigned char *src;
+ char *text;
+ Uint32 waitStart;
+ Uint32 waitElapsed;
+ Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
+ if (XA_CLIPBOARD == None) {
+ SDL_SetError("Couldn't access X clipboard");
+ return SDL_strdup("");
+ }
+
+ text = NULL;
+
+ /* Get the window that holds the selection */
+ window = GetWindow(_this);
+ format = TEXT_FORMAT;
+ owner = X11_XGetSelectionOwner(display, XA_CLIPBOARD);
+ if (owner == None) {
+ /* Fall back to ancient X10 cut-buffers which do not support UTF8 strings*/
+ owner = DefaultRootWindow(display);
+ selection = XA_CUT_BUFFER0;
+ format = XA_STRING;
+ } else if (owner == window) {
+ owner = DefaultRootWindow(display);
+ selection = X11_GetSDLCutBufferClipboardType(display);
+ } else {
+ /* Request that the selection owner copy the data to our window */
+ owner = window;
+ selection = X11_XInternAtom(display, "SDL_SELECTION", False);
+ X11_XConvertSelection(display, XA_CLIPBOARD, format, selection, owner,
+ CurrentTime);
+
+ /* When using synergy on Linux and when data has been put in the clipboard
+ on the remote (Windows anyway) machine then selection_waiting may never
+ be set to False. Time out after a while. */
+ waitStart = SDL_GetTicks();
+ videodata->selection_waiting = SDL_TRUE;
+ while (videodata->selection_waiting) {
+ SDL_PumpEvents();
+ waitElapsed = SDL_GetTicks() - waitStart;
+ /* Wait one second for a clipboard response. */
+ if (waitElapsed > 1000) {
+ videodata->selection_waiting = SDL_FALSE;
+ SDL_SetError("Clipboard timeout");
+ /* We need to set the clipboard text so that next time we won't
+ timeout, otherwise we will hang on every call to this function. */
+ X11_SetClipboardText(_this, "");
+ return SDL_strdup("");
+ }
+ }
+ }
+
+ if (X11_XGetWindowProperty(display, owner, selection, 0, INT_MAX/4, False,
+ format, &seln_type, &seln_format, &nbytes, &overflow, &src)
+ == Success) {
+ if (seln_type == format) {
+ text = (char *)SDL_malloc(nbytes+1);
+ if (text) {
+ SDL_memcpy(text, src, nbytes);
+ text[nbytes] = '\0';
+ }
+ }
+ X11_XFree(src);
+ }
+
+ if (!text) {
+ text = SDL_strdup("");
+ }
+
+ return text;
+}
+
+SDL_bool
+X11_HasClipboardText(_THIS)
+{
+ SDL_bool result = SDL_FALSE;
+ char *text = X11_GetClipboardText(_this);
+ if (text) {
+ result = text[0] != '\0' ? SDL_TRUE : SDL_FALSE;
+ SDL_free(text);
+ }
+ return result;
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11clipboard.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11clipboard.h
new file mode 100644
index 0000000..97aff1b
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11clipboard.h
@@ -0,0 +1,33 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11clipboard_h_
+#define SDL_x11clipboard_h_
+
+extern int X11_SetClipboardText(_THIS, const char *text);
+extern char *X11_GetClipboardText(_THIS);
+extern SDL_bool X11_HasClipboardText(_THIS);
+extern Atom X11_GetSDLCutBufferClipboardType(Display *display);
+
+#endif /* SDL_x11clipboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11dyn.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11dyn.c
new file mode 100644
index 0000000..89f736a
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11dyn.c
@@ -0,0 +1,212 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#define DEBUG_DYNAMIC_X11 0
+
+#include "SDL_x11dyn.h"
+
+#if DEBUG_DYNAMIC_X11
+#include <stdio.h>
+#endif
+
+#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
+
+#include "SDL_name.h"
+#include "SDL_loadso.h"
+
+typedef struct
+{
+ void *lib;
+ const char *libname;
+} x11dynlib;
+
+#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC NULL
+#endif
+#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT NULL
+#endif
+#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR NULL
+#endif
+#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA NULL
+#endif
+#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 NULL
+#endif
+#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR NULL
+#endif
+#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS NULL
+#endif
+#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE NULL
+#endif
+
+static x11dynlib x11libs[] = {
+ {NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC},
+ {NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT},
+ {NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR},
+ {NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XINERAMA},
+ {NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2},
+ {NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR},
+ {NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS},
+ {NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XVIDMODE}
+};
+
+static void *
+X11_GetSym(const char *fnname, int *pHasModule)
+{
+ int i;
+ void *fn = NULL;
+ for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
+ if (x11libs[i].lib != NULL) {
+ fn = SDL_LoadFunction(x11libs[i].lib, fnname);
+ if (fn != NULL)
+ break;
+ }
+ }
+
+#if DEBUG_DYNAMIC_X11
+ if (fn != NULL)
+ printf("X11: Found '%s' in %s (%p)\n", fnname, x11libs[i].libname, fn);
+ else
+ printf("X11: Symbol '%s' NOT FOUND!\n", fnname);
+#endif
+
+ if (fn == NULL)
+ *pHasModule = 0; /* kill this module. */
+
+ return fn;
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11_DYNAMIC */
+
+/* Define all the function pointers and wrappers... */
+#define SDL_X11_SYM(rc,fn,params,args,ret) SDL_DYNX11FN_##fn X11_##fn = NULL;
+#include "SDL_x11sym.h"
+
+/* Annoying varargs entry point... */
+#ifdef X_HAVE_UTF8_STRING
+SDL_DYNX11FN_XCreateIC X11_XCreateIC = NULL;
+SDL_DYNX11FN_XGetICValues X11_XGetICValues = NULL;
+#endif
+
+/* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */
+#define SDL_X11_MODULE(modname) int SDL_X11_HAVE_##modname = 0;
+#include "SDL_x11sym.h"
+
+static int x11_load_refcount = 0;
+
+void
+SDL_X11_UnloadSymbols(void)
+{
+ /* Don't actually unload if more than one module is using the libs... */
+ if (x11_load_refcount > 0) {
+ if (--x11_load_refcount == 0) {
+ int i;
+
+ /* set all the function pointers to NULL. */
+#define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 0;
+#define SDL_X11_SYM(rc,fn,params,args,ret) X11_##fn = NULL;
+#include "SDL_x11sym.h"
+
+#ifdef X_HAVE_UTF8_STRING
+ X11_XCreateIC = NULL;
+ X11_XGetICValues = NULL;
+#endif
+
+#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
+ for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
+ if (x11libs[i].lib != NULL) {
+ SDL_UnloadObject(x11libs[i].lib);
+ x11libs[i].lib = NULL;
+ }
+ }
+#endif
+ }
+ }
+}
+
+/* returns non-zero if all needed symbols were loaded. */
+int
+SDL_X11_LoadSymbols(void)
+{
+ int rc = 1; /* always succeed if not using Dynamic X11 stuff. */
+
+ /* deal with multiple modules (dga, x11, etc) needing these symbols... */
+ if (x11_load_refcount++ == 0) {
+#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
+ int i;
+ int *thismod = NULL;
+ for (i = 0; i < SDL_TABLESIZE(x11libs); i++) {
+ if (x11libs[i].libname != NULL) {
+ x11libs[i].lib = SDL_LoadObject(x11libs[i].libname);
+ }
+ }
+
+#define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 1; /* default yes */
+#include "SDL_x11sym.h"
+
+#define SDL_X11_MODULE(modname) thismod = &SDL_X11_HAVE_##modname;
+#define SDL_X11_SYM(a,fn,x,y,z) X11_##fn = (SDL_DYNX11FN_##fn) X11_GetSym(#fn,thismod);
+#include "SDL_x11sym.h"
+
+#ifdef X_HAVE_UTF8_STRING
+ X11_XCreateIC = (SDL_DYNX11FN_XCreateIC)
+ X11_GetSym("XCreateIC", &SDL_X11_HAVE_UTF8);
+ X11_XGetICValues = (SDL_DYNX11FN_XGetICValues)
+ X11_GetSym("XGetICValues", &SDL_X11_HAVE_UTF8);
+#endif
+
+ if (SDL_X11_HAVE_BASEXLIB) {
+ /* all required symbols loaded. */
+ SDL_ClearError();
+ } else {
+ /* in case something got loaded... */
+ SDL_X11_UnloadSymbols();
+ rc = 0;
+ }
+
+#else /* no dynamic X11 */
+
+#define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 1; /* default yes */
+#define SDL_X11_SYM(a,fn,x,y,z) X11_##fn = (SDL_DYNX11FN_##fn) fn;
+#include "SDL_x11sym.h"
+
+#ifdef X_HAVE_UTF8_STRING
+ X11_XCreateIC = XCreateIC;
+ X11_XGetICValues = XGetICValues;
+#endif
+#endif
+ }
+
+ return rc;
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11dyn.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11dyn.h
new file mode 100644
index 0000000..d3866e7
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11dyn.h
@@ -0,0 +1,111 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11dyn_h_
+#define SDL_x11dyn_h_
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+#include <X11/XKBlib.h>
+#endif
+
+/* Apparently some X11 systems can't include this multiple times... */
+#ifndef SDL_INCLUDED_XLIBINT_H
+#define SDL_INCLUDED_XLIBINT_H 1
+#include <X11/Xlibint.h>
+#endif
+
+#include <X11/Xproto.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
+
+#ifndef NO_SHARED_MEMORY
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+#endif
+
+#if SDL_VIDEO_DRIVER_X11_XCURSOR
+#include <X11/Xcursor/Xcursor.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XDBE
+#include <X11/extensions/Xdbe.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+#include <X11/extensions/XInput2.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
+#include <X11/extensions/scrnsaver.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XSHAPE
+#include <X11/extensions/shape.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+#include <X11/extensions/xf86vmode.h>
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* evil function signatures... */
+typedef Bool(*SDL_X11_XESetWireToEventRetType) (Display *, XEvent *, xEvent *);
+typedef int (*SDL_X11_XSynchronizeRetType) (Display *);
+typedef Status(*SDL_X11_XESetEventToWireRetType) (Display *, XEvent *, xEvent *);
+
+int SDL_X11_LoadSymbols(void);
+void SDL_X11_UnloadSymbols(void);
+
+/* Declare all the function pointers and wrappers... */
+#define SDL_X11_SYM(rc,fn,params,args,ret) \
+ typedef rc (*SDL_DYNX11FN_##fn) params; \
+ extern SDL_DYNX11FN_##fn X11_##fn;
+#include "SDL_x11sym.h"
+
+/* Annoying varargs entry point... */
+#ifdef X_HAVE_UTF8_STRING
+typedef XIC(*SDL_DYNX11FN_XCreateIC) (XIM,...);
+typedef char *(*SDL_DYNX11FN_XGetICValues) (XIC, ...);
+extern SDL_DYNX11FN_XCreateIC X11_XCreateIC;
+extern SDL_DYNX11FN_XGetICValues X11_XGetICValues;
+#endif
+
+/* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */
+#define SDL_X11_MODULE(modname) extern int SDL_X11_HAVE_##modname;
+#include "SDL_x11sym.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined SDL_x11dyn_h_ */
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11events.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11events.c
new file mode 100644
index 0000000..d293a5e
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11events.c
@@ -0,0 +1,1500 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <unistd.h>
+#include <limits.h> /* For INT_MAX */
+
+#include "SDL_x11video.h"
+#include "SDL_x11touch.h"
+#include "SDL_x11xinput2.h"
+#include "../../core/unix/SDL_poll.h"
+#include "../../events/SDL_events_c.h"
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_touch_c.h"
+
+#include "SDL_hints.h"
+#include "SDL_timer.h"
+#include "SDL_syswm.h"
+#include "SDL_assert.h"
+
+#include <stdio.h>
+
+/*#define DEBUG_XEVENTS*/
+
+#ifndef _NET_WM_MOVERESIZE_SIZE_TOPLEFT
+#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
+#endif
+
+#ifndef _NET_WM_MOVERESIZE_SIZE_TOP
+#define _NET_WM_MOVERESIZE_SIZE_TOP 1
+#endif
+
+#ifndef _NET_WM_MOVERESIZE_SIZE_TOPRIGHT
+#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
+#endif
+
+#ifndef _NET_WM_MOVERESIZE_SIZE_RIGHT
+#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
+#endif
+
+#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
+#endif
+
+#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOM
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
+#endif
+
+#ifndef _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
+#endif
+
+#ifndef _NET_WM_MOVERESIZE_SIZE_LEFT
+#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
+#endif
+
+#ifndef _NET_WM_MOVERESIZE_MOVE
+#define _NET_WM_MOVERESIZE_MOVE 8
+#endif
+
+typedef struct {
+ unsigned char *data;
+ int format, count;
+ Atom type;
+} SDL_x11Prop;
+
+/* Reads property
+ Must call X11_XFree on results
+ */
+static void X11_ReadProperty(SDL_x11Prop *p, Display *disp, Window w, Atom prop)
+{
+ unsigned char *ret=NULL;
+ Atom type;
+ int fmt;
+ unsigned long count;
+ unsigned long bytes_left;
+ int bytes_fetch = 0;
+
+ do {
+ if (ret != 0) X11_XFree(ret);
+ X11_XGetWindowProperty(disp, w, prop, 0, bytes_fetch, False, AnyPropertyType, &type, &fmt, &count, &bytes_left, &ret);
+ bytes_fetch += bytes_left;
+ } while (bytes_left != 0);
+
+ p->data=ret;
+ p->format=fmt;
+ p->count=count;
+ p->type=type;
+}
+
+/* Find text-uri-list in a list of targets and return it's atom
+ if available, else return None */
+static Atom X11_PickTarget(Display *disp, Atom list[], int list_count)
+{
+ Atom request = None;
+ char *name;
+ int i;
+ for (i=0; i < list_count && request == None; i++) {
+ name = X11_XGetAtomName(disp, list[i]);
+ if ((SDL_strcmp("text/uri-list", name) == 0) || (SDL_strcmp("text/plain", name) == 0)) {
+ request = list[i];
+ }
+ X11_XFree(name);
+ }
+ return request;
+}
+
+/* Wrapper for X11_PickTarget for a maximum of three targets, a special
+ case in the Xdnd protocol */
+static Atom X11_PickTargetFromAtoms(Display *disp, Atom a0, Atom a1, Atom a2)
+{
+ int count=0;
+ Atom atom[3];
+ if (a0 != None) atom[count++] = a0;
+ if (a1 != None) atom[count++] = a1;
+ if (a2 != None) atom[count++] = a2;
+ return X11_PickTarget(disp, atom, count);
+}
+
+struct KeyRepeatCheckData
+{
+ XEvent *event;
+ SDL_bool found;
+};
+
+static Bool X11_KeyRepeatCheckIfEvent(Display *display, XEvent *chkev,
+ XPointer arg)
+{
+ struct KeyRepeatCheckData *d = (struct KeyRepeatCheckData *) arg;
+ if (chkev->type == KeyPress &&
+ chkev->xkey.keycode == d->event->xkey.keycode &&
+ chkev->xkey.time - d->event->xkey.time < 2)
+ d->found = SDL_TRUE;
+ return False;
+}
+
+/* Check to see if this is a repeated key.
+ (idea shamelessly lifted from GII -- thanks guys! :)
+ */
+static SDL_bool X11_KeyRepeat(Display *display, XEvent *event)
+{
+ XEvent dummyev;
+ struct KeyRepeatCheckData d;
+ d.event = event;
+ d.found = SDL_FALSE;
+ if (X11_XPending(display))
+ X11_XCheckIfEvent(display, &dummyev, X11_KeyRepeatCheckIfEvent,
+ (XPointer) &d);
+ return d.found;
+}
+
+static SDL_bool
+X11_IsWheelEvent(Display * display,XEvent * event,int * xticks,int * yticks)
+{
+ /* according to the xlib docs, no specific mouse wheel events exist.
+ However, the defacto standard is that the vertical wheel is X buttons
+ 4 (up) and 5 (down) and a horizontal wheel is 6 (left) and 7 (right). */
+
+ /* Xlib defines "Button1" through 5, so we just use literals here. */
+ switch (event->xbutton.button) {
+ case 4: *yticks = 1; return SDL_TRUE;
+ case 5: *yticks = -1; return SDL_TRUE;
+ case 6: *xticks = 1; return SDL_TRUE;
+ case 7: *xticks = -1; return SDL_TRUE;
+ default: break;
+ }
+ return SDL_FALSE;
+}
+
+/* Decodes URI escape sequences in string buf of len bytes
+ (excluding the terminating NULL byte) in-place. Since
+ URI-encoded characters take three times the space of
+ normal characters, this should not be an issue.
+
+ Returns the number of decoded bytes that wound up in
+ the buffer, excluding the terminating NULL byte.
+
+ The buffer is guaranteed to be NULL-terminated but
+ may contain embedded NULL bytes.
+
+ On error, -1 is returned.
+ */
+static int X11_URIDecode(char *buf, int len) {
+ int ri, wi, di;
+ char decode = '\0';
+ if (buf == NULL || len < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (len == 0) {
+ len = SDL_strlen(buf);
+ }
+ for (ri = 0, wi = 0, di = 0; ri < len && wi < len; ri += 1) {
+ if (di == 0) {
+ /* start decoding */
+ if (buf[ri] == '%') {
+ decode = '\0';
+ di += 1;
+ continue;
+ }
+ /* normal write */
+ buf[wi] = buf[ri];
+ wi += 1;
+ continue;
+ } else if (di == 1 || di == 2) {
+ char off = '\0';
+ char isa = buf[ri] >= 'a' && buf[ri] <= 'f';
+ char isA = buf[ri] >= 'A' && buf[ri] <= 'F';
+ char isn = buf[ri] >= '0' && buf[ri] <= '9';
+ if (!(isa || isA || isn)) {
+ /* not a hexadecimal */
+ int sri;
+ for (sri = ri - di; sri <= ri; sri += 1) {
+ buf[wi] = buf[sri];
+ wi += 1;
+ }
+ di = 0;
+ continue;
+ }
+ /* itsy bitsy magicsy */
+ if (isn) {
+ off = 0 - '0';
+ } else if (isa) {
+ off = 10 - 'a';
+ } else if (isA) {
+ off = 10 - 'A';
+ }
+ decode |= (buf[ri] + off) << (2 - di) * 4;
+ if (di == 2) {
+ buf[wi] = decode;
+ wi += 1;
+ di = 0;
+ } else {
+ di += 1;
+ }
+ continue;
+ }
+ }
+ buf[wi] = '\0';
+ return wi;
+}
+
+/* Convert URI to local filename
+ return filename if possible, else NULL
+*/
+static char* X11_URIToLocal(char* uri) {
+ char *file = NULL;
+ SDL_bool local;
+
+ if (memcmp(uri,"file:/",6) == 0) uri += 6; /* local file? */
+ else if (strstr(uri,":/") != NULL) return file; /* wrong scheme */
+
+ local = uri[0] != '/' || (uri[0] != '\0' && uri[1] == '/');
+
+ /* got a hostname? */
+ if (!local && uri[0] == '/' && uri[2] != '/') {
+ char* hostname_end = strchr(uri+1, '/');
+ if (hostname_end != NULL) {
+ char hostname[ 257 ];
+ if (gethostname(hostname, 255) == 0) {
+ hostname[ 256 ] = '\0';
+ if (memcmp(uri+1, hostname, hostname_end - (uri+1)) == 0) {
+ uri = hostname_end + 1;
+ local = SDL_TRUE;
+ }
+ }
+ }
+ }
+ if (local) {
+ file = uri;
+ /* Convert URI escape sequences to real characters */
+ X11_URIDecode(file, 0);
+ if (uri[1] == '/') {
+ file++;
+ } else {
+ file--;
+ }
+ }
+ return file;
+}
+
+#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
+static void X11_HandleGenericEvent(SDL_VideoData *videodata, XEvent *xev)
+{
+ /* event is a union, so cookie == &event, but this is type safe. */
+ XGenericEventCookie *cookie = &xev->xcookie;
+ if (X11_XGetEventData(videodata->display, cookie)) {
+ X11_HandleXinput2Event(videodata, cookie);
+ X11_XFreeEventData(videodata->display, cookie);
+ }
+}
+#endif /* SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS */
+
+static unsigned
+X11_GetNumLockModifierMask(_THIS)
+{
+ SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+ Display *display = viddata->display;
+ unsigned num_mask = 0;
+ int i, j;
+ XModifierKeymap *xmods;
+ unsigned n;
+
+ xmods = X11_XGetModifierMapping(display);
+ n = xmods->max_keypermod;
+ for(i = 3; i < 8; i++) {
+ for(j = 0; j < n; j++) {
+ KeyCode kc = xmods->modifiermap[i * n + j];
+ if (viddata->key_layout[kc] == SDL_SCANCODE_NUMLOCKCLEAR) {
+ num_mask = 1 << i;
+ break;
+ }
+ }
+ }
+ X11_XFreeModifiermap(xmods);
+
+ return num_mask;
+}
+
+static void
+X11_ReconcileKeyboardState(_THIS)
+{
+ SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+ Display *display = viddata->display;
+ char keys[32];
+ int keycode;
+ Window junk_window;
+ int x, y;
+ unsigned int mask;
+ const Uint8 *keyboardState;
+
+ X11_XQueryKeymap(display, keys);
+
+ /* Sync up the keyboard modifier state */
+ if (X11_XQueryPointer(display, DefaultRootWindow(display), &junk_window, &junk_window, &x, &y, &x, &y, &mask)) {
+ SDL_ToggleModState(KMOD_CAPS, (mask & LockMask) != 0);
+ SDL_ToggleModState(KMOD_NUM, (mask & X11_GetNumLockModifierMask(_this)) != 0);
+ }
+
+ keyboardState = SDL_GetKeyboardState(0);
+ for (keycode = 0; keycode < 256; ++keycode) {
+ SDL_Scancode scancode = viddata->key_layout[keycode];
+ SDL_bool x11KeyPressed = (keys[keycode / 8] & (1 << (keycode % 8))) != 0;
+ SDL_bool sdlKeyPressed = keyboardState[scancode] == SDL_PRESSED;
+
+ if (x11KeyPressed && !sdlKeyPressed) {
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+ } else if (!x11KeyPressed && sdlKeyPressed) {
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+ }
+ }
+}
+
+
+static void
+X11_DispatchFocusIn(_THIS, SDL_WindowData *data)
+{
+#ifdef DEBUG_XEVENTS
+ printf("window %p: Dispatching FocusIn\n", data);
+#endif
+ SDL_SetKeyboardFocus(data->window);
+ X11_ReconcileKeyboardState(_this);
+#ifdef X_HAVE_UTF8_STRING
+ if (data->ic) {
+ X11_XSetICFocus(data->ic);
+ }
+#endif
+#ifdef SDL_USE_IME
+ SDL_IME_SetFocus(SDL_TRUE);
+#endif
+}
+
+static void
+X11_DispatchFocusOut(_THIS, SDL_WindowData *data)
+{
+#ifdef DEBUG_XEVENTS
+ printf("window %p: Dispatching FocusOut\n", data);
+#endif
+ /* If another window has already processed a focus in, then don't try to
+ * remove focus here. Doing so will incorrectly remove focus from that
+ * window, and the focus lost event for this window will have already
+ * been dispatched anyway. */
+ if (data->window == SDL_GetKeyboardFocus()) {
+ SDL_SetKeyboardFocus(NULL);
+ }
+#ifdef X_HAVE_UTF8_STRING
+ if (data->ic) {
+ X11_XUnsetICFocus(data->ic);
+ }
+#endif
+#ifdef SDL_USE_IME
+ SDL_IME_SetFocus(SDL_FALSE);
+#endif
+}
+
+static void
+X11_DispatchMapNotify(SDL_WindowData *data)
+{
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
+}
+
+static void
+X11_DispatchUnmapNotify(SDL_WindowData *data)
+{
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
+}
+
+static void
+InitiateWindowMove(_THIS, const SDL_WindowData *data, const SDL_Point *point)
+{
+ SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+ SDL_Window* window = data->window;
+ Display *display = viddata->display;
+ XEvent evt;
+
+ /* !!! FIXME: we need to regrab this if necessary when the drag is done. */
+ X11_XUngrabPointer(display, 0L);
+ X11_XFlush(display);
+
+ evt.xclient.type = ClientMessage;
+ evt.xclient.window = data->xwindow;
+ evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
+ evt.xclient.format = 32;
+ evt.xclient.data.l[0] = window->x + point->x;
+ evt.xclient.data.l[1] = window->y + point->y;
+ evt.xclient.data.l[2] = _NET_WM_MOVERESIZE_MOVE;
+ evt.xclient.data.l[3] = Button1;
+ evt.xclient.data.l[4] = 0;
+ X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
+
+ X11_XSync(display, 0);
+}
+
+static void
+InitiateWindowResize(_THIS, const SDL_WindowData *data, const SDL_Point *point, int direction)
+{
+ SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+ SDL_Window* window = data->window;
+ Display *display = viddata->display;
+ XEvent evt;
+
+ if (direction < _NET_WM_MOVERESIZE_SIZE_TOPLEFT || direction > _NET_WM_MOVERESIZE_SIZE_LEFT)
+ return;
+
+ /* !!! FIXME: we need to regrab this if necessary when the drag is done. */
+ X11_XUngrabPointer(display, 0L);
+ X11_XFlush(display);
+
+ evt.xclient.type = ClientMessage;
+ evt.xclient.window = data->xwindow;
+ evt.xclient.message_type = X11_XInternAtom(display, "_NET_WM_MOVERESIZE", True);
+ evt.xclient.format = 32;
+ evt.xclient.data.l[0] = window->x + point->x;
+ evt.xclient.data.l[1] = window->y + point->y;
+ evt.xclient.data.l[2] = direction;
+ evt.xclient.data.l[3] = Button1;
+ evt.xclient.data.l[4] = 0;
+ X11_XSendEvent(display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &evt);
+
+ X11_XSync(display, 0);
+}
+
+static SDL_bool
+ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev)
+{
+ SDL_Window *window = data->window;
+
+ if (window->hit_test) {
+ const SDL_Point point = { xev->xbutton.x, xev->xbutton.y };
+ const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
+ static const int directions[] = {
+ _NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP,
+ _NET_WM_MOVERESIZE_SIZE_TOPRIGHT, _NET_WM_MOVERESIZE_SIZE_RIGHT,
+ _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT, _NET_WM_MOVERESIZE_SIZE_BOTTOM,
+ _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, _NET_WM_MOVERESIZE_SIZE_LEFT
+ };
+
+ switch (rc) {
+ case SDL_HITTEST_DRAGGABLE:
+ InitiateWindowMove(_this, data, &point);
+ return SDL_TRUE;
+
+ case SDL_HITTEST_RESIZE_TOPLEFT:
+ case SDL_HITTEST_RESIZE_TOP:
+ case SDL_HITTEST_RESIZE_TOPRIGHT:
+ case SDL_HITTEST_RESIZE_RIGHT:
+ case SDL_HITTEST_RESIZE_BOTTOMRIGHT:
+ case SDL_HITTEST_RESIZE_BOTTOM:
+ case SDL_HITTEST_RESIZE_BOTTOMLEFT:
+ case SDL_HITTEST_RESIZE_LEFT:
+ InitiateWindowResize(_this, data, &point, directions[rc - SDL_HITTEST_RESIZE_TOPLEFT]);
+ return SDL_TRUE;
+
+ default: return SDL_FALSE;
+ }
+ }
+
+ return SDL_FALSE;
+}
+
+static void
+X11_UpdateUserTime(SDL_WindowData *data, const unsigned long latest)
+{
+ if (latest && (latest != data->user_time)) {
+ SDL_VideoData *videodata = data->videodata;
+ Display *display = videodata->display;
+ X11_XChangeProperty(display, data->xwindow, videodata->_NET_WM_USER_TIME,
+ XA_CARDINAL, 32, PropModeReplace,
+ (const unsigned char *) &latest, 1);
+#ifdef DEBUG_XEVENTS
+ printf("window %p: updating _NET_WM_USER_TIME to %lu\n", data, latest);
+#endif
+ data->user_time = latest;
+ }
+}
+
+static void
+X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ Display *display = videodata->display;
+
+ SDL_assert(videodata->clipboard_window != None);
+ SDL_assert(xevent->xany.window == videodata->clipboard_window);
+
+ switch (xevent->type) {
+ /* Copy the selection from our own CUTBUFFER to the requested property */
+ case SelectionRequest: {
+ const XSelectionRequestEvent *req = &xevent->xselectionrequest;
+ XEvent sevent;
+ int seln_format;
+ unsigned long nbytes;
+ unsigned long overflow;
+ unsigned char *seln_data;
+
+#ifdef DEBUG_XEVENTS
+ printf("window CLIPBOARD: SelectionRequest (requestor = %ld, target = %ld)\n",
+ req->requestor, req->target);
+#endif
+
+ SDL_zero(sevent);
+ sevent.xany.type = SelectionNotify;
+ sevent.xselection.selection = req->selection;
+ sevent.xselection.target = None;
+ sevent.xselection.property = None; /* tell them no by default */
+ sevent.xselection.requestor = req->requestor;
+ sevent.xselection.time = req->time;
+
+ /* !!! FIXME: We were probably storing this on the root window
+ because an SDL window might go away...? but we don't have to do
+ this now (or ever, really). */
+ if (X11_XGetWindowProperty(display, DefaultRootWindow(display),
+ X11_GetSDLCutBufferClipboardType(display), 0, INT_MAX/4, False, req->target,
+ &sevent.xselection.target, &seln_format, &nbytes,
+ &overflow, &seln_data) == Success) {
+ /* !!! FIXME: cache atoms */
+ Atom XA_TARGETS = X11_XInternAtom(display, "TARGETS", 0);
+ if (sevent.xselection.target == req->target) {
+ X11_XChangeProperty(display, req->requestor, req->property,
+ sevent.xselection.target, seln_format, PropModeReplace,
+ seln_data, nbytes);
+ sevent.xselection.property = req->property;
+ } else if (XA_TARGETS == req->target) {
+ Atom SupportedFormats[] = { XA_TARGETS, sevent.xselection.target };
+ X11_XChangeProperty(display, req->requestor, req->property,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char*)SupportedFormats,
+ SDL_arraysize(SupportedFormats));
+ sevent.xselection.property = req->property;
+ sevent.xselection.target = XA_TARGETS;
+ }
+ X11_XFree(seln_data);
+ }
+ X11_XSendEvent(display, req->requestor, False, 0, &sevent);
+ X11_XSync(display, False);
+ }
+ break;
+
+ case SelectionNotify: {
+#ifdef DEBUG_XEVENTS
+ printf("window CLIPBOARD: SelectionNotify (requestor = %ld, target = %ld)\n",
+ xevent->xselection.requestor, xevent->xselection.target);
+#endif
+ videodata->selection_waiting = SDL_FALSE;
+ }
+ break;
+
+ case SelectionClear: {
+ /* !!! FIXME: cache atoms */
+ Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
+
+#ifdef DEBUG_XEVENTS
+ printf("window CLIPBOARD: SelectionClear (requestor = %ld, target = %ld)\n",
+ xevent->xselection.requestor, xevent->xselection.target);
+#endif
+
+ if (xevent->xselectionclear.selection == XA_PRIMARY ||
+ (XA_CLIPBOARD != None && xevent->xselectionclear.selection == XA_CLIPBOARD)) {
+ SDL_SendClipboardUpdate();
+ }
+ }
+ break;
+ }
+}
+
+
+static void
+X11_DispatchEvent(_THIS)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ Display *display;
+ SDL_WindowData *data;
+ XEvent xevent;
+ int orig_event_type;
+ KeyCode orig_keycode;
+ XClientMessageEvent m;
+ int i;
+
+ if (!videodata) {
+ return;
+ }
+ display = videodata->display;
+
+ SDL_zero(xevent); /* valgrind fix. --ryan. */
+ X11_XNextEvent(display, &xevent);
+
+ /* Save the original keycode for dead keys, which are filtered out by
+ the XFilterEvent() call below.
+ */
+ orig_event_type = xevent.type;
+ if (orig_event_type == KeyPress || orig_event_type == KeyRelease) {
+ orig_keycode = xevent.xkey.keycode;
+ } else {
+ orig_keycode = 0;
+ }
+
+ /* filter events catchs XIM events and sends them to the correct handler */
+ if (X11_XFilterEvent(&xevent, None) == True) {
+#if 0
+ printf("Filtered event type = %d display = %d window = %d\n",
+ xevent.type, xevent.xany.display, xevent.xany.window);
+#endif
+ /* Make sure dead key press/release events are sent */
+ /* But only if we're using one of the DBus IMEs, otherwise
+ some XIM IMEs will generate duplicate events */
+ if (orig_keycode) {
+#if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX_FRONTEND_H)
+ SDL_Scancode scancode = videodata->key_layout[orig_keycode];
+ videodata->filter_code = orig_keycode;
+ videodata->filter_time = xevent.xkey.time;
+
+ if (orig_event_type == KeyPress) {
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+ } else {
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+ }
+#endif
+ }
+ return;
+ }
+
+ /* Send a SDL_SYSWMEVENT if the application wants them */
+ if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
+ SDL_SysWMmsg wmmsg;
+
+ SDL_VERSION(&wmmsg.version);
+ wmmsg.subsystem = SDL_SYSWM_X11;
+ wmmsg.msg.x11.event = xevent;
+ SDL_SendSysWMEvent(&wmmsg);
+ }
+
+#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
+ if(xevent.type == GenericEvent) {
+ X11_HandleGenericEvent(videodata, &xevent);
+ return;
+ }
+#endif
+
+#if 0
+ printf("type = %d display = %d window = %d\n",
+ xevent.type, xevent.xany.display, xevent.xany.window);
+#endif
+
+ if ((videodata->clipboard_window != None) &&
+ (videodata->clipboard_window == xevent.xany.window)) {
+ X11_HandleClipboardEvent(_this, &xevent);
+ return;
+ }
+
+ data = NULL;
+ if (videodata && videodata->windowlist) {
+ for (i = 0; i < videodata->numwindows; ++i) {
+ if ((videodata->windowlist[i] != NULL) &&
+ (videodata->windowlist[i]->xwindow == xevent.xany.window)) {
+ data = videodata->windowlist[i];
+ break;
+ }
+ }
+ }
+ if (!data) {
+ /* The window for KeymapNotify, etc events is 0 */
+ if (xevent.type == KeymapNotify) {
+ if (SDL_GetKeyboardFocus() != NULL) {
+ X11_ReconcileKeyboardState(_this);
+ }
+ } else if (xevent.type == MappingNotify) {
+ /* Has the keyboard layout changed? */
+ const int request = xevent.xmapping.request;
+
+#ifdef DEBUG_XEVENTS
+ printf("window %p: MappingNotify!\n", data);
+#endif
+ if ((request == MappingKeyboard) || (request == MappingModifier)) {
+ X11_XRefreshKeyboardMapping(&xevent.xmapping);
+ }
+
+ X11_UpdateKeymap(_this);
+ SDL_SendKeymapChangedEvent();
+ }
+ return;
+ }
+
+ switch (xevent.type) {
+
+ /* Gaining mouse coverage? */
+ case EnterNotify:{
+ SDL_Mouse *mouse = SDL_GetMouse();
+#ifdef DEBUG_XEVENTS
+ printf("window %p: EnterNotify! (%d,%d,%d)\n", data,
+ xevent.xcrossing.x,
+ xevent.xcrossing.y,
+ xevent.xcrossing.mode);
+ if (xevent.xcrossing.mode == NotifyGrab)
+ printf("Mode: NotifyGrab\n");
+ if (xevent.xcrossing.mode == NotifyUngrab)
+ printf("Mode: NotifyUngrab\n");
+#endif
+ SDL_SetMouseFocus(data->window);
+
+ mouse->last_x = xevent.xcrossing.x;
+ mouse->last_y = xevent.xcrossing.y;
+
+ if (!mouse->relative_mode) {
+ SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
+ }
+ }
+ break;
+ /* Losing mouse coverage? */
+ case LeaveNotify:{
+#ifdef DEBUG_XEVENTS
+ printf("window %p: LeaveNotify! (%d,%d,%d)\n", data,
+ xevent.xcrossing.x,
+ xevent.xcrossing.y,
+ xevent.xcrossing.mode);
+ if (xevent.xcrossing.mode == NotifyGrab)
+ printf("Mode: NotifyGrab\n");
+ if (xevent.xcrossing.mode == NotifyUngrab)
+ printf("Mode: NotifyUngrab\n");
+#endif
+ if (!SDL_GetMouse()->relative_mode) {
+ SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
+ }
+
+ if (xevent.xcrossing.mode != NotifyGrab &&
+ xevent.xcrossing.mode != NotifyUngrab &&
+ xevent.xcrossing.detail != NotifyInferior) {
+ SDL_SetMouseFocus(NULL);
+ }
+ }
+ break;
+
+ /* Gaining input focus? */
+ case FocusIn:{
+ if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
+ /* Someone is handling a global hotkey, ignore it */
+#ifdef DEBUG_XEVENTS
+ printf("window %p: FocusIn (NotifyGrab/NotifyUngrab, ignoring)\n", data);
+#endif
+ break;
+ }
+
+ if (xevent.xfocus.detail == NotifyInferior) {
+#ifdef DEBUG_XEVENTS
+ printf("window %p: FocusIn (NotifierInferior, ignoring)\n", data);
+#endif
+ break;
+ }
+#ifdef DEBUG_XEVENTS
+ printf("window %p: FocusIn!\n", data);
+#endif
+ if (!videodata->last_mode_change_deadline) /* no recent mode changes */
+ {
+ data->pending_focus = PENDING_FOCUS_NONE;
+ data->pending_focus_time = 0;
+ X11_DispatchFocusIn(_this, data);
+ }
+ else
+ {
+ data->pending_focus = PENDING_FOCUS_IN;
+ data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
+ }
+ data->last_focus_event_time = SDL_GetTicks();
+ }
+ break;
+
+ /* Losing input focus? */
+ case FocusOut:{
+ if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) {
+ /* Someone is handling a global hotkey, ignore it */
+#ifdef DEBUG_XEVENTS
+ printf("window %p: FocusOut (NotifyGrab/NotifyUngrab, ignoring)\n", data);
+#endif
+ break;
+ }
+ if (xevent.xfocus.detail == NotifyInferior) {
+ /* We still have focus if a child gets focus */
+#ifdef DEBUG_XEVENTS
+ printf("window %p: FocusOut (NotifierInferior, ignoring)\n", data);
+#endif
+ break;
+ }
+#ifdef DEBUG_XEVENTS
+ printf("window %p: FocusOut!\n", data);
+#endif
+ if (!videodata->last_mode_change_deadline) /* no recent mode changes */
+ {
+ data->pending_focus = PENDING_FOCUS_NONE;
+ data->pending_focus_time = 0;
+ X11_DispatchFocusOut(_this, data);
+ }
+ else
+ {
+ data->pending_focus = PENDING_FOCUS_OUT;
+ data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
+ }
+ }
+ break;
+
+ /* Key press? */
+ case KeyPress:{
+ KeyCode keycode = xevent.xkey.keycode;
+ KeySym keysym = NoSymbol;
+ char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
+ Status status = 0;
+ SDL_bool handled_by_ime = SDL_FALSE;
+
+#ifdef DEBUG_XEVENTS
+ printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
+#endif
+#if 1
+ if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
+ int min_keycode, max_keycode;
+ X11_XDisplayKeycodes(display, &min_keycode, &max_keycode);
+ keysym = X11_KeyCodeToSym(_this, keycode, xevent.xkey.state >> 13);
+ fprintf(stderr,
+ "The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL forums/mailing list <https://discourse.libsdl.org/> X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n",
+ keycode, keycode - min_keycode, keysym,
+ X11_XKeysymToString(keysym));
+ }
+#endif
+ /* */
+ SDL_zero(text);
+#ifdef X_HAVE_UTF8_STRING
+ if (data->ic) {
+ X11_Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
+ &keysym, &status);
+ } else {
+ X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
+ }
+#else
+ X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
+#endif
+
+#ifdef SDL_USE_IME
+ if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
+ handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode);
+ }
+#endif
+ if (!handled_by_ime) {
+ /* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
+ if (xevent.xkey.keycode != videodata->filter_code || xevent.xkey.time != videodata->filter_time) {
+ SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
+ }
+ if(*text) {
+ SDL_SendKeyboardText(text);
+ }
+ }
+
+ X11_UpdateUserTime(data, xevent.xkey.time);
+ }
+ break;
+
+ /* Key release? */
+ case KeyRelease:{
+ KeyCode keycode = xevent.xkey.keycode;
+
+#ifdef DEBUG_XEVENTS
+ printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode);
+#endif
+ if (X11_KeyRepeat(display, &xevent)) {
+ /* We're about to get a repeated key down, ignore the key up */
+ break;
+ }
+ SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
+ }
+ break;
+
+ /* Have we been iconified? */
+ case UnmapNotify:{
+#ifdef DEBUG_XEVENTS
+ printf("window %p: UnmapNotify!\n", data);
+#endif
+ X11_DispatchUnmapNotify(data);
+ }
+ break;
+
+ /* Have we been restored? */
+ case MapNotify:{
+#ifdef DEBUG_XEVENTS
+ printf("window %p: MapNotify!\n", data);
+#endif
+ X11_DispatchMapNotify(data);
+ }
+ break;
+
+ /* Have we been resized or moved? */
+ case ConfigureNotify:{
+#ifdef DEBUG_XEVENTS
+ printf("window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n", data,
+ xevent.xconfigure.x, xevent.xconfigure.y,
+ xevent.xconfigure.width, xevent.xconfigure.height);
+#endif
+ /* Real configure notify events are relative to the parent, synthetic events are absolute. */
+ if (!xevent.xconfigure.send_event) {
+ unsigned int NumChildren;
+ Window ChildReturn, Root, Parent;
+ Window * Children;
+ /* Translate these coodinates back to relative to root */
+ X11_XQueryTree(data->videodata->display, xevent.xconfigure.window, &Root, &Parent, &Children, &NumChildren);
+ X11_XTranslateCoordinates(xevent.xconfigure.display,
+ Parent, DefaultRootWindow(xevent.xconfigure.display),
+ xevent.xconfigure.x, xevent.xconfigure.y,
+ &xevent.xconfigure.x, &xevent.xconfigure.y,
+ &ChildReturn);
+ }
+
+ if (xevent.xconfigure.x != data->last_xconfigure.x ||
+ xevent.xconfigure.y != data->last_xconfigure.y) {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,
+ xevent.xconfigure.x, xevent.xconfigure.y);
+#ifdef SDL_USE_IME
+ if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
+ /* Update IME candidate list position */
+ SDL_IME_UpdateTextRect(NULL);
+ }
+#endif
+ }
+ if (xevent.xconfigure.width != data->last_xconfigure.width ||
+ xevent.xconfigure.height != data->last_xconfigure.height) {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED,
+ xevent.xconfigure.width,
+ xevent.xconfigure.height);
+ }
+ data->last_xconfigure = xevent.xconfigure;
+ }
+ break;
+
+ /* Have we been requested to quit (or another client message?) */
+ case ClientMessage:{
+
+ static int xdnd_version=0;
+
+ if (xevent.xclient.message_type == videodata->XdndEnter) {
+
+ SDL_bool use_list = xevent.xclient.data.l[1] & 1;
+ data->xdnd_source = xevent.xclient.data.l[0];
+ xdnd_version = (xevent.xclient.data.l[1] >> 24);
+#ifdef DEBUG_XEVENTS
+ printf("XID of source window : %ld\n", data->xdnd_source);
+ printf("Protocol version to use : %d\n", xdnd_version);
+ printf("More then 3 data types : %d\n", (int) use_list);
+#endif
+
+ if (use_list) {
+ /* fetch conversion targets */
+ SDL_x11Prop p;
+ X11_ReadProperty(&p, display, data->xdnd_source, videodata->XdndTypeList);
+ /* pick one */
+ data->xdnd_req = X11_PickTarget(display, (Atom*)p.data, p.count);
+ X11_XFree(p.data);
+ } else {
+ /* pick from list of three */
+ data->xdnd_req = X11_PickTargetFromAtoms(display, xevent.xclient.data.l[2], xevent.xclient.data.l[3], xevent.xclient.data.l[4]);
+ }
+ }
+ else if (xevent.xclient.message_type == videodata->XdndPosition) {
+
+#ifdef DEBUG_XEVENTS
+ Atom act= videodata->XdndActionCopy;
+ if(xdnd_version >= 2) {
+ act = xevent.xclient.data.l[4];
+ }
+ printf("Action requested by user is : %s\n", X11_XGetAtomName(display , act));
+#endif
+
+
+ /* reply with status */
+ memset(&m, 0, sizeof(XClientMessageEvent));
+ m.type = ClientMessage;
+ m.display = xevent.xclient.display;
+ m.window = xevent.xclient.data.l[0];
+ m.message_type = videodata->XdndStatus;
+ m.format=32;
+ m.data.l[0] = data->xwindow;
+ m.data.l[1] = (data->xdnd_req != None);
+ m.data.l[2] = 0; /* specify an empty rectangle */
+ m.data.l[3] = 0;
+ m.data.l[4] = videodata->XdndActionCopy; /* we only accept copying anyway */
+
+ X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
+ X11_XFlush(display);
+ }
+ else if(xevent.xclient.message_type == videodata->XdndDrop) {
+ if (data->xdnd_req == None) {
+ /* say again - not interested! */
+ memset(&m, 0, sizeof(XClientMessageEvent));
+ m.type = ClientMessage;
+ m.display = xevent.xclient.display;
+ m.window = xevent.xclient.data.l[0];
+ m.message_type = videodata->XdndFinished;
+ m.format=32;
+ m.data.l[0] = data->xwindow;
+ m.data.l[1] = 0;
+ m.data.l[2] = None; /* fail! */
+ X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m);
+ } else {
+ /* convert */
+ if(xdnd_version >= 1) {
+ X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent.xclient.data.l[2]);
+ } else {
+ X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, CurrentTime);
+ }
+ }
+ }
+ else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
+ (xevent.xclient.format == 32) &&
+ (xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) {
+ Window root = DefaultRootWindow(display);
+
+#ifdef DEBUG_XEVENTS
+ printf("window %p: _NET_WM_PING\n", data);
+#endif
+ xevent.xclient.window = root;
+ X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
+ break;
+ }
+
+ else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
+ (xevent.xclient.format == 32) &&
+ (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
+
+#ifdef DEBUG_XEVENTS
+ printf("window %p: WM_DELETE_WINDOW\n", data);
+#endif
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
+ break;
+ }
+ else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
+ (xevent.xclient.format == 32) &&
+ (xevent.xclient.data.l[0] == videodata->WM_TAKE_FOCUS)) {
+
+#ifdef DEBUG_XEVENTS
+ printf("window %p: WM_TAKE_FOCUS\n", data);
+#endif
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_TAKE_FOCUS, 0, 0);
+ break;
+ }
+ }
+ break;
+
+ /* Do we need to refresh ourselves? */
+ case Expose:{
+#ifdef DEBUG_XEVENTS
+ printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count);
+#endif
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0);
+ }
+ break;
+
+ case MotionNotify:{
+ SDL_Mouse *mouse = SDL_GetMouse();
+ if(!mouse->relative_mode || mouse->relative_mode_warp) {
+#ifdef DEBUG_MOTION
+ printf("window %p: X11 motion: %d,%d\n", data, xevent.xmotion.x, xevent.xmotion.y);
+#endif
+
+ SDL_SendMouseMotion(data->window, 0, 0, xevent.xmotion.x, xevent.xmotion.y);
+ }
+ }
+ break;
+
+ case ButtonPress:{
+ int xticks = 0, yticks = 0;
+#ifdef DEBUG_XEVENTS
+ printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent.xbutton.button);
+#endif
+ if (X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
+ SDL_SendMouseWheel(data->window, 0, (float) xticks, (float) yticks, SDL_MOUSEWHEEL_NORMAL);
+ } else {
+ SDL_bool ignore_click = SDL_FALSE;
+ int button = xevent.xbutton.button;
+ if(button == Button1) {
+ if (ProcessHitTest(_this, data, &xevent)) {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
+ break; /* don't pass this event on to app. */
+ }
+ }
+ else if(button > 7) {
+ /* X button values 4-7 are used for scrolling, so X1 is 8, X2 is 9, ...
+ => subtract (8-SDL_BUTTON_X1) to get value SDL expects */
+ button -= (8-SDL_BUTTON_X1);
+ }
+ if (data->last_focus_event_time) {
+ const int X11_FOCUS_CLICK_TIMEOUT = 10;
+ if (!SDL_TICKS_PASSED(SDL_GetTicks(), data->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) {
+ ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
+ }
+ data->last_focus_event_time = 0;
+ }
+ if (!ignore_click) {
+ SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
+ }
+ }
+ X11_UpdateUserTime(data, xevent.xbutton.time);
+ }
+ break;
+
+ case ButtonRelease:{
+ int button = xevent.xbutton.button;
+ /* The X server sends a Release event for each Press for wheels. Ignore them. */
+ int xticks = 0, yticks = 0;
+#ifdef DEBUG_XEVENTS
+ printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent.xbutton.button);
+#endif
+ if (!X11_IsWheelEvent(display, &xevent, &xticks, &yticks)) {
+ if (button > 7) {
+ /* see explanation at case ButtonPress */
+ button -= (8-SDL_BUTTON_X1);
+ }
+ SDL_SendMouseButton(data->window, 0, SDL_RELEASED, button);
+ }
+ }
+ break;
+
+ case PropertyNotify:{
+#ifdef DEBUG_XEVENTS
+ unsigned char *propdata;
+ int status, real_format;
+ Atom real_type;
+ unsigned long items_read, items_left;
+
+ char *name = X11_XGetAtomName(display, xevent.xproperty.atom);
+ if (name) {
+ printf("window %p: PropertyNotify: %s %s time=%lu\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed", xevent.xproperty.time);
+ X11_XFree(name);
+ }
+
+ status = X11_XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata);
+ if (status == Success && items_read > 0) {
+ if (real_type == XA_INTEGER) {
+ int *values = (int *)propdata;
+
+ printf("{");
+ for (i = 0; i < items_read; i++) {
+ printf(" %d", values[i]);
+ }
+ printf(" }\n");
+ } else if (real_type == XA_CARDINAL) {
+ if (real_format == 32) {
+ Uint32 *values = (Uint32 *)propdata;
+
+ printf("{");
+ for (i = 0; i < items_read; i++) {
+ printf(" %d", values[i]);
+ }
+ printf(" }\n");
+ } else if (real_format == 16) {
+ Uint16 *values = (Uint16 *)propdata;
+
+ printf("{");
+ for (i = 0; i < items_read; i++) {
+ printf(" %d", values[i]);
+ }
+ printf(" }\n");
+ } else if (real_format == 8) {
+ Uint8 *values = (Uint8 *)propdata;
+
+ printf("{");
+ for (i = 0; i < items_read; i++) {
+ printf(" %d", values[i]);
+ }
+ printf(" }\n");
+ }
+ } else if (real_type == XA_STRING ||
+ real_type == videodata->UTF8_STRING) {
+ printf("{ \"%s\" }\n", propdata);
+ } else if (real_type == XA_ATOM) {
+ Atom *atoms = (Atom *)propdata;
+
+ printf("{");
+ for (i = 0; i < items_read; i++) {
+ char *atomname = X11_XGetAtomName(display, atoms[i]);
+ if (atomname) {
+ printf(" %s", atomname);
+ X11_XFree(atomname);
+ }
+ }
+ printf(" }\n");
+ } else {
+ char *atomname = X11_XGetAtomName(display, real_type);
+ printf("Unknown type: %ld (%s)\n", real_type, atomname ? atomname : "UNKNOWN");
+ if (atomname) {
+ X11_XFree(atomname);
+ }
+ }
+ }
+ if (status == Success) {
+ X11_XFree(propdata);
+ }
+#endif /* DEBUG_XEVENTS */
+
+ /* Take advantage of this moment to make sure user_time has a
+ valid timestamp from the X server, so if we later try to
+ raise/restore this window, _NET_ACTIVE_WINDOW can have a
+ non-zero timestamp, even if there's never been a mouse or
+ key press to this window so far. Note that we don't try to
+ set _NET_WM_USER_TIME here, though. That's only for legit
+ user interaction with the window. */
+ if (!data->user_time) {
+ data->user_time = xevent.xproperty.time;
+ }
+
+ if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
+ /* Get the new state from the window manager.
+ Compositing window managers can alter visibility of windows
+ without ever mapping / unmapping them, so we handle that here,
+ because they use the NETWM protocol to notify us of changes.
+ */
+ const Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
+ const Uint32 changed = flags ^ data->window->flags;
+
+ if ((changed & SDL_WINDOW_HIDDEN) || (changed & SDL_WINDOW_FULLSCREEN)) {
+ if (flags & SDL_WINDOW_HIDDEN) {
+ X11_DispatchUnmapNotify(data);
+ } else {
+ X11_DispatchMapNotify(data);
+ }
+ }
+
+ if (changed & SDL_WINDOW_MAXIMIZED) {
+ if (flags & SDL_WINDOW_MAXIMIZED) {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
+ } else {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
+ }
+ }
+ } else if (xevent.xproperty.atom == videodata->XKLAVIER_STATE) {
+ /* Hack for Ubuntu 12.04 (etc) that doesn't send MappingNotify
+ events when the keyboard layout changes (for example,
+ changing from English to French on the menubar's keyboard
+ icon). Since it changes the XKLAVIER_STATE property, we
+ notice and reinit our keymap here. This might not be the
+ right approach, but it seems to work. */
+ X11_UpdateKeymap(_this);
+ SDL_SendKeymapChangedEvent();
+ } else if (xevent.xproperty.atom == videodata->_NET_FRAME_EXTENTS) {
+ Atom type;
+ int format;
+ unsigned long nitems, bytes_after;
+ unsigned char *property;
+ if (X11_XGetWindowProperty(display, data->xwindow, videodata->_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &property) == Success) {
+ if (type != None && nitems == 4) {
+ data->border_left = (int) ((long*)property)[0];
+ data->border_right = (int) ((long*)property)[1];
+ data->border_top = (int) ((long*)property)[2];
+ data->border_bottom = (int) ((long*)property)[3];
+ }
+ X11_XFree(property);
+
+ #ifdef DEBUG_XEVENTS
+ printf("New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d\n", data->border_left, data->border_right, data->border_top, data->border_bottom);
+ #endif
+ }
+ }
+ }
+ break;
+
+ case SelectionNotify: {
+ Atom target = xevent.xselection.target;
+#ifdef DEBUG_XEVENTS
+ printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data,
+ xevent.xselection.requestor, xevent.xselection.target);
+#endif
+ if (target == data->xdnd_req) {
+ /* read data */
+ SDL_x11Prop p;
+ X11_ReadProperty(&p, display, data->xwindow, videodata->PRIMARY);
+
+ if (p.format == 8) {
+ /* !!! FIXME: don't use strtok here. It's not reentrant and not in SDL_stdinc. */
+ char* name = X11_XGetAtomName(display, target);
+ char *token = strtok((char *) p.data, "\r\n");
+ while (token != NULL) {
+ if (SDL_strcmp("text/plain", name)==0) {
+ SDL_SendDropText(data->window, token);
+ } else if (SDL_strcmp("text/uri-list", name)==0) {
+ char *fn = X11_URIToLocal(token);
+ if (fn) {
+ SDL_SendDropFile(data->window, fn);
+ }
+ }
+ token = strtok(NULL, "\r\n");
+ }
+ SDL_SendDropComplete(data->window);
+ }
+ X11_XFree(p.data);
+
+ /* send reply */
+ SDL_memset(&m, 0, sizeof(XClientMessageEvent));
+ m.type = ClientMessage;
+ m.display = display;
+ m.window = data->xdnd_source;
+ m.message_type = videodata->XdndFinished;
+ m.format = 32;
+ m.data.l[0] = data->xwindow;
+ m.data.l[1] = 1;
+ m.data.l[2] = videodata->XdndActionCopy;
+ X11_XSendEvent(display, data->xdnd_source, False, NoEventMask, (XEvent*)&m);
+
+ X11_XSync(display, False);
+ }
+ }
+ break;
+
+ default:{
+#ifdef DEBUG_XEVENTS
+ printf("window %p: Unhandled event %d\n", data, xevent.type);
+#endif
+ }
+ break;
+ }
+}
+
+static void
+X11_HandleFocusChanges(_THIS)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ int i;
+
+ if (videodata && videodata->windowlist) {
+ for (i = 0; i < videodata->numwindows; ++i) {
+ SDL_WindowData *data = videodata->windowlist[i];
+ if (data && data->pending_focus != PENDING_FOCUS_NONE) {
+ Uint32 now = SDL_GetTicks();
+ if (SDL_TICKS_PASSED(now, data->pending_focus_time)) {
+ if (data->pending_focus == PENDING_FOCUS_IN) {
+ X11_DispatchFocusIn(_this, data);
+ } else {
+ X11_DispatchFocusOut(_this, data);
+ }
+ data->pending_focus = PENDING_FOCUS_NONE;
+ }
+ }
+ }
+ }
+}
+/* Ack! X11_XPending() actually performs a blocking read if no events available */
+static int
+X11_Pending(Display * display)
+{
+ /* Flush the display connection and look to see if events are queued */
+ X11_XFlush(display);
+ if (X11_XEventsQueued(display, QueuedAlready)) {
+ return (1);
+ }
+
+ /* More drastic measures are required -- see if X is ready to talk */
+ if (SDL_IOReady(ConnectionNumber(display), SDL_FALSE, 0)) {
+ return (X11_XPending(display));
+ }
+
+ /* Oh well, nothing is ready .. */
+ return (0);
+}
+
+void
+X11_PumpEvents(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ if (data->last_mode_change_deadline) {
+ if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) {
+ data->last_mode_change_deadline = 0; /* assume we're done. */
+ }
+ }
+
+ /* Update activity every 30 seconds to prevent screensaver */
+ if (_this->suspend_screensaver) {
+ const Uint32 now = SDL_GetTicks();
+ if (!data->screensaver_activity ||
+ SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
+ X11_XResetScreenSaver(data->display);
+
+#if SDL_USE_LIBDBUS
+ SDL_DBus_ScreensaverTickle();
+#endif
+
+ data->screensaver_activity = now;
+ }
+ }
+
+ /* Keep processing pending events */
+ while (X11_Pending(data->display)) {
+ X11_DispatchEvent(_this);
+ }
+
+#ifdef SDL_USE_IME
+ if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
+ SDL_IME_PumpEvents();
+ }
+#endif
+
+ /* FIXME: Only need to do this when there are pending focus changes */
+ X11_HandleFocusChanges(_this);
+}
+
+
+void
+X11_SuspendScreenSaver(_THIS)
+{
+#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ int dummy;
+ int major_version, minor_version;
+#endif /* SDL_VIDEO_DRIVER_X11_XSCRNSAVER */
+
+#if SDL_USE_LIBDBUS
+ if (SDL_DBus_ScreensaverInhibit(_this->suspend_screensaver)) {
+ return;
+ }
+
+ if (_this->suspend_screensaver) {
+ SDL_DBus_ScreensaverTickle();
+ }
+#endif
+
+#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
+ if (SDL_X11_HAVE_XSS) {
+ /* X11_XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */
+ if (!X11_XScreenSaverQueryExtension(data->display, &dummy, &dummy) ||
+ !X11_XScreenSaverQueryVersion(data->display,
+ &major_version, &minor_version) ||
+ major_version < 1 || (major_version == 1 && minor_version < 1)) {
+ return;
+ }
+
+ X11_XScreenSaverSuspend(data->display, _this->suspend_screensaver);
+ X11_XResetScreenSaver(data->display);
+ }
+#endif
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11events.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11events.h
new file mode 100644
index 0000000..53c69a5
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11events.h
@@ -0,0 +1,31 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11events_h_
+#define SDL_x11events_h_
+
+extern void X11_PumpEvents(_THIS);
+extern void X11_SuspendScreenSaver(_THIS);
+
+#endif /* SDL_x11events_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11framebuffer.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11framebuffer.c
new file mode 100644
index 0000000..ad58170
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11framebuffer.c
@@ -0,0 +1,257 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL_x11video.h"
+#include "SDL_x11framebuffer.h"
+
+
+#ifndef NO_SHARED_MEMORY
+
+/* Shared memory error handler routine */
+static int shm_error;
+static int (*X_handler)(Display *, XErrorEvent *) = NULL;
+static int shm_errhandler(Display *d, XErrorEvent *e)
+{
+ if ( e->error_code == BadAccess ) {
+ shm_error = True;
+ return(0);
+ } else
+ return(X_handler(d,e));
+}
+
+static SDL_bool have_mitshm(void)
+{
+ /* Only use shared memory on local X servers */
+ if ( (SDL_strncmp(X11_XDisplayName(NULL), ":", 1) == 0) ||
+ (SDL_strncmp(X11_XDisplayName(NULL), "unix:", 5) == 0) ) {
+ return SDL_X11_HAVE_SHM;
+ }
+ return SDL_FALSE;
+}
+
+#endif /* !NO_SHARED_MEMORY */
+
+int
+X11_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format,
+ void ** pixels, int *pitch)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ XGCValues gcv;
+ XVisualInfo vinfo;
+
+ /* Free the old framebuffer surface */
+ X11_DestroyWindowFramebuffer(_this, window);
+
+ /* Create the graphics context for drawing */
+ gcv.graphics_exposures = False;
+ data->gc = X11_XCreateGC(display, data->xwindow, GCGraphicsExposures, &gcv);
+ if (!data->gc) {
+ return SDL_SetError("Couldn't create graphics context");
+ }
+
+ /* Find out the pixel format and depth */
+ if (X11_GetVisualInfoFromVisual(display, data->visual, &vinfo) < 0) {
+ return SDL_SetError("Couldn't get window visual information");
+ }
+
+ *format = X11_GetPixelFormatFromVisualInfo(display, &vinfo);
+ if (*format == SDL_PIXELFORMAT_UNKNOWN) {
+ return SDL_SetError("Unknown window pixel format");
+ }
+
+ /* Calculate pitch */
+ *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
+
+ /* Create the actual image */
+#ifndef NO_SHARED_MEMORY
+ if (have_mitshm()) {
+ XShmSegmentInfo *shminfo = &data->shminfo;
+
+ shminfo->shmid = shmget(IPC_PRIVATE, window->h*(*pitch), IPC_CREAT | 0777);
+ if ( shminfo->shmid >= 0 ) {
+ shminfo->shmaddr = (char *)shmat(shminfo->shmid, 0, 0);
+ shminfo->readOnly = False;
+ if ( shminfo->shmaddr != (char *)-1 ) {
+ shm_error = False;
+ X_handler = X11_XSetErrorHandler(shm_errhandler);
+ X11_XShmAttach(display, shminfo);
+ X11_XSync(display, False);
+ X11_XSetErrorHandler(X_handler);
+ if ( shm_error )
+ shmdt(shminfo->shmaddr);
+ } else {
+ shm_error = True;
+ }
+ shmctl(shminfo->shmid, IPC_RMID, NULL);
+ } else {
+ shm_error = True;
+ }
+ if (!shm_error) {
+ data->ximage = X11_XShmCreateImage(display, data->visual,
+ vinfo.depth, ZPixmap,
+ shminfo->shmaddr, shminfo,
+ window->w, window->h);
+ if (!data->ximage) {
+ X11_XShmDetach(display, shminfo);
+ X11_XSync(display, False);
+ shmdt(shminfo->shmaddr);
+ } else {
+ /* Done! */
+ data->use_mitshm = SDL_TRUE;
+ *pixels = shminfo->shmaddr;
+ return 0;
+ }
+ }
+ }
+#endif /* not NO_SHARED_MEMORY */
+
+ *pixels = SDL_malloc(window->h*(*pitch));
+ if (*pixels == NULL) {
+ return SDL_OutOfMemory();
+ }
+
+ data->ximage = X11_XCreateImage(display, data->visual,
+ vinfo.depth, ZPixmap, 0, (char *)(*pixels),
+ window->w, window->h, 32, 0);
+ if (!data->ximage) {
+ SDL_free(*pixels);
+ return SDL_SetError("Couldn't create XImage");
+ }
+ return 0;
+}
+
+int
+X11_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects,
+ int numrects)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ int i;
+ int x, y, w ,h;
+#ifndef NO_SHARED_MEMORY
+ if (data->use_mitshm) {
+ for (i = 0; i < numrects; ++i) {
+ x = rects[i].x;
+ y = rects[i].y;
+ w = rects[i].w;
+ h = rects[i].h;
+
+ if (w <= 0 || h <= 0 || (x + w) <= 0 || (y + h) <= 0) {
+ /* Clipped? */
+ continue;
+ }
+ if (x < 0)
+ {
+ x += w;
+ w += rects[i].x;
+ }
+ if (y < 0)
+ {
+ y += h;
+ h += rects[i].y;
+ }
+ if (x + w > window->w)
+ w = window->w - x;
+ if (y + h > window->h)
+ h = window->h - y;
+
+ X11_XShmPutImage(display, data->xwindow, data->gc, data->ximage,
+ x, y, x, y, w, h, False);
+ }
+ }
+ else
+#endif /* !NO_SHARED_MEMORY */
+ {
+ for (i = 0; i < numrects; ++i) {
+ x = rects[i].x;
+ y = rects[i].y;
+ w = rects[i].w;
+ h = rects[i].h;
+
+ if (w <= 0 || h <= 0 || (x + w) <= 0 || (y + h) <= 0) {
+ /* Clipped? */
+ continue;
+ }
+ if (x < 0)
+ {
+ x += w;
+ w += rects[i].x;
+ }
+ if (y < 0)
+ {
+ y += h;
+ h += rects[i].y;
+ }
+ if (x + w > window->w)
+ w = window->w - x;
+ if (y + h > window->h)
+ h = window->h - y;
+
+ X11_XPutImage(display, data->xwindow, data->gc, data->ximage,
+ x, y, x, y, w, h);
+ }
+ }
+
+ X11_XSync(display, False);
+
+ return 0;
+}
+
+void
+X11_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display;
+
+ if (!data) {
+ /* The window wasn't fully initialized */
+ return;
+ }
+
+ display = data->videodata->display;
+
+ if (data->ximage) {
+ XDestroyImage(data->ximage);
+
+#ifndef NO_SHARED_MEMORY
+ if (data->use_mitshm) {
+ X11_XShmDetach(display, &data->shminfo);
+ X11_XSync(display, False);
+ shmdt(data->shminfo.shmaddr);
+ data->use_mitshm = SDL_FALSE;
+ }
+#endif /* !NO_SHARED_MEMORY */
+
+ data->ximage = NULL;
+ }
+ if (data->gc) {
+ X11_XFreeGC(display, data->gc);
+ data->gc = NULL;
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11framebuffer.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11framebuffer.h
new file mode 100644
index 0000000..6a31788
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11framebuffer.h
@@ -0,0 +1,37 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_x11framebuffer_h_
+#define SDL_x11framebuffer_h_
+
+#include "../../SDL_internal.h"
+
+
+extern int X11_CreateWindowFramebuffer(_THIS, SDL_Window * window,
+ Uint32 * format,
+ void ** pixels, int *pitch);
+extern int X11_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
+ const SDL_Rect * rects, int numrects);
+extern void X11_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
+
+#endif /* SDL_x11framebuffer_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11keyboard.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11keyboard.c
new file mode 100644
index 0000000..a57adf9
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11keyboard.c
@@ -0,0 +1,543 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL_x11video.h"
+
+#include "../../events/SDL_keyboard_c.h"
+#include "../../events/scancodes_darwin.h"
+#include "../../events/scancodes_xfree86.h"
+
+#include <X11/keysym.h>
+#include <X11/XKBlib.h>
+
+#include "imKStoUCS.h"
+
+#ifdef X_HAVE_UTF8_STRING
+#include <locale.h>
+#endif
+
+/* *INDENT-OFF* */
+static const struct {
+ KeySym keysym;
+ SDL_Scancode scancode;
+} KeySymToSDLScancode[] = {
+ { XK_Return, SDL_SCANCODE_RETURN },
+ { XK_Escape, SDL_SCANCODE_ESCAPE },
+ { XK_BackSpace, SDL_SCANCODE_BACKSPACE },
+ { XK_Tab, SDL_SCANCODE_TAB },
+ { XK_Caps_Lock, SDL_SCANCODE_CAPSLOCK },
+ { XK_F1, SDL_SCANCODE_F1 },
+ { XK_F2, SDL_SCANCODE_F2 },
+ { XK_F3, SDL_SCANCODE_F3 },
+ { XK_F4, SDL_SCANCODE_F4 },
+ { XK_F5, SDL_SCANCODE_F5 },
+ { XK_F6, SDL_SCANCODE_F6 },
+ { XK_F7, SDL_SCANCODE_F7 },
+ { XK_F8, SDL_SCANCODE_F8 },
+ { XK_F9, SDL_SCANCODE_F9 },
+ { XK_F10, SDL_SCANCODE_F10 },
+ { XK_F11, SDL_SCANCODE_F11 },
+ { XK_F12, SDL_SCANCODE_F12 },
+ { XK_Print, SDL_SCANCODE_PRINTSCREEN },
+ { XK_Scroll_Lock, SDL_SCANCODE_SCROLLLOCK },
+ { XK_Pause, SDL_SCANCODE_PAUSE },
+ { XK_Insert, SDL_SCANCODE_INSERT },
+ { XK_Home, SDL_SCANCODE_HOME },
+ { XK_Prior, SDL_SCANCODE_PAGEUP },
+ { XK_Delete, SDL_SCANCODE_DELETE },
+ { XK_End, SDL_SCANCODE_END },
+ { XK_Next, SDL_SCANCODE_PAGEDOWN },
+ { XK_Right, SDL_SCANCODE_RIGHT },
+ { XK_Left, SDL_SCANCODE_LEFT },
+ { XK_Down, SDL_SCANCODE_DOWN },
+ { XK_Up, SDL_SCANCODE_UP },
+ { XK_Num_Lock, SDL_SCANCODE_NUMLOCKCLEAR },
+ { XK_KP_Divide, SDL_SCANCODE_KP_DIVIDE },
+ { XK_KP_Multiply, SDL_SCANCODE_KP_MULTIPLY },
+ { XK_KP_Subtract, SDL_SCANCODE_KP_MINUS },
+ { XK_KP_Add, SDL_SCANCODE_KP_PLUS },
+ { XK_KP_Enter, SDL_SCANCODE_KP_ENTER },
+ { XK_KP_Delete, SDL_SCANCODE_KP_PERIOD },
+ { XK_KP_End, SDL_SCANCODE_KP_1 },
+ { XK_KP_Down, SDL_SCANCODE_KP_2 },
+ { XK_KP_Next, SDL_SCANCODE_KP_3 },
+ { XK_KP_Left, SDL_SCANCODE_KP_4 },
+ { XK_KP_Begin, SDL_SCANCODE_KP_5 },
+ { XK_KP_Right, SDL_SCANCODE_KP_6 },
+ { XK_KP_Home, SDL_SCANCODE_KP_7 },
+ { XK_KP_Up, SDL_SCANCODE_KP_8 },
+ { XK_KP_Prior, SDL_SCANCODE_KP_9 },
+ { XK_KP_Insert, SDL_SCANCODE_KP_0 },
+ { XK_KP_Decimal, SDL_SCANCODE_KP_PERIOD },
+ { XK_KP_1, SDL_SCANCODE_KP_1 },
+ { XK_KP_2, SDL_SCANCODE_KP_2 },
+ { XK_KP_3, SDL_SCANCODE_KP_3 },
+ { XK_KP_4, SDL_SCANCODE_KP_4 },
+ { XK_KP_5, SDL_SCANCODE_KP_5 },
+ { XK_KP_6, SDL_SCANCODE_KP_6 },
+ { XK_KP_7, SDL_SCANCODE_KP_7 },
+ { XK_KP_8, SDL_SCANCODE_KP_8 },
+ { XK_KP_9, SDL_SCANCODE_KP_9 },
+ { XK_KP_0, SDL_SCANCODE_KP_0 },
+ { XK_KP_Decimal, SDL_SCANCODE_KP_PERIOD },
+ { XK_Hyper_R, SDL_SCANCODE_APPLICATION },
+ { XK_KP_Equal, SDL_SCANCODE_KP_EQUALS },
+ { XK_F13, SDL_SCANCODE_F13 },
+ { XK_F14, SDL_SCANCODE_F14 },
+ { XK_F15, SDL_SCANCODE_F15 },
+ { XK_F16, SDL_SCANCODE_F16 },
+ { XK_F17, SDL_SCANCODE_F17 },
+ { XK_F18, SDL_SCANCODE_F18 },
+ { XK_F19, SDL_SCANCODE_F19 },
+ { XK_F20, SDL_SCANCODE_F20 },
+ { XK_F21, SDL_SCANCODE_F21 },
+ { XK_F22, SDL_SCANCODE_F22 },
+ { XK_F23, SDL_SCANCODE_F23 },
+ { XK_F24, SDL_SCANCODE_F24 },
+ { XK_Execute, SDL_SCANCODE_EXECUTE },
+ { XK_Help, SDL_SCANCODE_HELP },
+ { XK_Menu, SDL_SCANCODE_MENU },
+ { XK_Select, SDL_SCANCODE_SELECT },
+ { XK_Cancel, SDL_SCANCODE_STOP },
+ { XK_Redo, SDL_SCANCODE_AGAIN },
+ { XK_Undo, SDL_SCANCODE_UNDO },
+ { XK_Find, SDL_SCANCODE_FIND },
+ { XK_KP_Separator, SDL_SCANCODE_KP_COMMA },
+ { XK_Sys_Req, SDL_SCANCODE_SYSREQ },
+ { XK_Control_L, SDL_SCANCODE_LCTRL },
+ { XK_Shift_L, SDL_SCANCODE_LSHIFT },
+ { XK_Alt_L, SDL_SCANCODE_LALT },
+ { XK_Meta_L, SDL_SCANCODE_LGUI },
+ { XK_Super_L, SDL_SCANCODE_LGUI },
+ { XK_Control_R, SDL_SCANCODE_RCTRL },
+ { XK_Shift_R, SDL_SCANCODE_RSHIFT },
+ { XK_Alt_R, SDL_SCANCODE_RALT },
+ { XK_ISO_Level3_Shift, SDL_SCANCODE_RALT },
+ { XK_Meta_R, SDL_SCANCODE_RGUI },
+ { XK_Super_R, SDL_SCANCODE_RGUI },
+ { XK_Mode_switch, SDL_SCANCODE_MODE },
+ { XK_period, SDL_SCANCODE_PERIOD },
+ { XK_comma, SDL_SCANCODE_COMMA },
+ { XK_slash, SDL_SCANCODE_SLASH },
+ { XK_backslash, SDL_SCANCODE_BACKSLASH },
+ { XK_minus, SDL_SCANCODE_MINUS },
+ { XK_equal, SDL_SCANCODE_EQUALS },
+ { XK_space, SDL_SCANCODE_SPACE },
+ { XK_grave, SDL_SCANCODE_GRAVE },
+ { XK_apostrophe, SDL_SCANCODE_APOSTROPHE },
+ { XK_bracketleft, SDL_SCANCODE_LEFTBRACKET },
+ { XK_bracketright, SDL_SCANCODE_RIGHTBRACKET },
+};
+
+static const struct
+{
+ SDL_Scancode const *table;
+ int table_size;
+} scancode_set[] = {
+ { darwin_scancode_table, SDL_arraysize(darwin_scancode_table) },
+ { xfree86_scancode_table, SDL_arraysize(xfree86_scancode_table) },
+ { xfree86_scancode_table2, SDL_arraysize(xfree86_scancode_table2) },
+ { xvnc_scancode_table, SDL_arraysize(xvnc_scancode_table) },
+};
+/* *INDENT-OFF* */
+
+/* This function only works for keyboards in US QWERTY layout */
+static SDL_Scancode
+X11_KeyCodeToSDLScancode(_THIS, KeyCode keycode)
+{
+ KeySym keysym;
+ int i;
+
+ keysym = X11_KeyCodeToSym(_this, keycode, 0);
+ if (keysym == NoSymbol) {
+ return SDL_SCANCODE_UNKNOWN;
+ }
+
+ if (keysym >= XK_a && keysym <= XK_z) {
+ return SDL_SCANCODE_A + (keysym - XK_a);
+ }
+ if (keysym >= XK_A && keysym <= XK_Z) {
+ return SDL_SCANCODE_A + (keysym - XK_A);
+ }
+
+ if (keysym == XK_0) {
+ return SDL_SCANCODE_0;
+ }
+ if (keysym >= XK_1 && keysym <= XK_9) {
+ return SDL_SCANCODE_1 + (keysym - XK_1);
+ }
+
+ for (i = 0; i < SDL_arraysize(KeySymToSDLScancode); ++i) {
+ if (keysym == KeySymToSDLScancode[i].keysym) {
+ return KeySymToSDLScancode[i].scancode;
+ }
+ }
+ return SDL_SCANCODE_UNKNOWN;
+}
+
+static Uint32
+X11_KeyCodeToUcs4(_THIS, KeyCode keycode, unsigned char group)
+{
+ KeySym keysym = X11_KeyCodeToSym(_this, keycode, group);
+
+ if (keysym == NoSymbol) {
+ return 0;
+ }
+
+ return X11_KeySymToUcs4(keysym);
+}
+
+KeySym
+X11_KeyCodeToSym(_THIS, KeyCode keycode, unsigned char group)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ KeySym keysym;
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+ if (data->xkb) {
+ int num_groups = XkbKeyNumGroups(data->xkb, keycode);
+ unsigned char info = XkbKeyGroupInfo(data->xkb, keycode);
+
+ if (num_groups && group >= num_groups) {
+
+ int action = XkbOutOfRangeGroupAction(info);
+
+ if (action == XkbRedirectIntoRange) {
+ if ((group = XkbOutOfRangeGroupNumber(info)) >= num_groups) {
+ group = 0;
+ }
+ } else if (action == XkbClampIntoRange) {
+ group = num_groups - 1;
+ } else {
+ group %= num_groups;
+ }
+ }
+ keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0);
+ } else {
+ keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
+ }
+#else
+ keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
+#endif
+
+ return keysym;
+}
+
+int
+X11_InitKeyboard(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ int i = 0;
+ int j = 0;
+ int min_keycode, max_keycode;
+ struct {
+ SDL_Scancode scancode;
+ KeySym keysym;
+ int value;
+ } fingerprint[] = {
+ { SDL_SCANCODE_HOME, XK_Home, 0 },
+ { SDL_SCANCODE_PAGEUP, XK_Prior, 0 },
+ { SDL_SCANCODE_UP, XK_Up, 0 },
+ { SDL_SCANCODE_LEFT, XK_Left, 0 },
+ { SDL_SCANCODE_DELETE, XK_Delete, 0 },
+ { SDL_SCANCODE_KP_ENTER, XK_KP_Enter, 0 },
+ };
+ int best_distance;
+ int best_index;
+ int distance;
+ Bool xkb_repeat = 0;
+
+ X11_XAutoRepeatOn(data->display);
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+ {
+ int xkb_major = XkbMajorVersion;
+ int xkb_minor = XkbMinorVersion;
+
+ if (X11_XkbQueryExtension(data->display, NULL, NULL, NULL, &xkb_major, &xkb_minor)) {
+ data->xkb = X11_XkbGetMap(data->display, XkbAllClientInfoMask, XkbUseCoreKbd);
+ }
+
+ /* This will remove KeyRelease events for held keys */
+ X11_XkbSetDetectableAutoRepeat(data->display, True, &xkb_repeat);
+ }
+#endif
+
+ /* Open a connection to the X input manager */
+#ifdef X_HAVE_UTF8_STRING
+ if (SDL_X11_HAVE_UTF8) {
+ /* Set the locale, and call XSetLocaleModifiers before XOpenIM so that
+ Compose keys will work correctly. */
+ char *prev_locale = setlocale(LC_ALL, NULL);
+ char *prev_xmods = X11_XSetLocaleModifiers(NULL);
+ const char *new_xmods = "";
+ const char *env_xmods = SDL_getenv("XMODIFIERS");
+ SDL_bool has_dbus_ime_support = SDL_FALSE;
+
+ if (prev_locale) {
+ prev_locale = SDL_strdup(prev_locale);
+ }
+
+ if (prev_xmods) {
+ prev_xmods = SDL_strdup(prev_xmods);
+ }
+
+ /* IBus resends some key events that were filtered by XFilterEvents
+ when it is used via XIM which causes issues. Prevent this by forcing
+ @im=none if XMODIFIERS contains @im=ibus. IBus can still be used via
+ the DBus implementation, which also has support for pre-editing. */
+ if (env_xmods && SDL_strstr(env_xmods, "@im=ibus") != NULL) {
+ has_dbus_ime_support = SDL_TRUE;
+ }
+ if (env_xmods && SDL_strstr(env_xmods, "@im=fcitx") != NULL) {
+ has_dbus_ime_support = SDL_TRUE;
+ }
+ if (has_dbus_ime_support || !xkb_repeat) {
+ new_xmods = "@im=none";
+ }
+
+ setlocale(LC_ALL, "");
+ X11_XSetLocaleModifiers(new_xmods);
+
+ data->im = X11_XOpenIM(data->display, NULL, data->classname, data->classname);
+
+ /* Reset the locale + X locale modifiers back to how they were,
+ locale first because the X locale modifiers depend on it. */
+ setlocale(LC_ALL, prev_locale);
+ X11_XSetLocaleModifiers(prev_xmods);
+
+ if (prev_locale) {
+ SDL_free(prev_locale);
+ }
+
+ if (prev_xmods) {
+ SDL_free(prev_xmods);
+ }
+ }
+#endif
+ /* Try to determine which scancodes are being used based on fingerprint */
+ best_distance = SDL_arraysize(fingerprint) + 1;
+ best_index = -1;
+ X11_XDisplayKeycodes(data->display, &min_keycode, &max_keycode);
+ for (i = 0; i < SDL_arraysize(fingerprint); ++i) {
+ fingerprint[i].value =
+ X11_XKeysymToKeycode(data->display, fingerprint[i].keysym) -
+ min_keycode;
+ }
+ for (i = 0; i < SDL_arraysize(scancode_set); ++i) {
+ /* Make sure the scancode set isn't too big */
+ if ((max_keycode - min_keycode + 1) <= scancode_set[i].table_size) {
+ continue;
+ }
+ distance = 0;
+ for (j = 0; j < SDL_arraysize(fingerprint); ++j) {
+ if (fingerprint[j].value < 0
+ || fingerprint[j].value >= scancode_set[i].table_size) {
+ distance += 1;
+ } else if (scancode_set[i].table[fingerprint[j].value] != fingerprint[j].scancode) {
+ distance += 1;
+ }
+ }
+ if (distance < best_distance) {
+ best_distance = distance;
+ best_index = i;
+ }
+ }
+ if (best_index >= 0 && best_distance <= 2) {
+#ifdef DEBUG_KEYBOARD
+ printf("Using scancode set %d, min_keycode = %d, max_keycode = %d, table_size = %d\n", best_index, min_keycode, max_keycode, scancode_set[best_index].table_size);
+#endif
+ SDL_memcpy(&data->key_layout[min_keycode], scancode_set[best_index].table,
+ sizeof(SDL_Scancode) * scancode_set[best_index].table_size);
+ } else {
+ SDL_Keycode keymap[SDL_NUM_SCANCODES];
+
+ printf
+ ("Keyboard layout unknown, please report the following to the SDL forums/mailing list (https://discourse.libsdl.org/):\n");
+
+ /* Determine key_layout - only works on US QWERTY layout */
+ SDL_GetDefaultKeymap(keymap);
+ for (i = min_keycode; i <= max_keycode; ++i) {
+ KeySym sym;
+ sym = X11_KeyCodeToSym(_this, (KeyCode) i, 0);
+ if (sym != NoSymbol) {
+ SDL_Scancode scancode;
+ printf("code = %d, sym = 0x%X (%s) ", i - min_keycode,
+ (unsigned int) sym, X11_XKeysymToString(sym));
+ scancode = X11_KeyCodeToSDLScancode(_this, i);
+ data->key_layout[i] = scancode;
+ if (scancode == SDL_SCANCODE_UNKNOWN) {
+ printf("scancode not found\n");
+ } else {
+ printf("scancode = %d (%s)\n", scancode, SDL_GetScancodeName(scancode));
+ }
+ }
+ }
+ }
+
+ X11_UpdateKeymap(_this);
+
+ SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu");
+
+#ifdef SDL_USE_IME
+ SDL_IME_Init();
+#endif
+
+ return 0;
+}
+
+void
+X11_UpdateKeymap(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ int i;
+ SDL_Scancode scancode;
+ SDL_Keycode keymap[SDL_NUM_SCANCODES];
+ unsigned char group = 0;
+
+ SDL_GetDefaultKeymap(keymap);
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+ if (data->xkb) {
+ XkbStateRec state;
+ X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb);
+
+ if (X11_XkbGetState(data->display, XkbUseCoreKbd, &state) == Success) {
+ group = state.group;
+ }
+ }
+#endif
+
+
+ for (i = 0; i < SDL_arraysize(data->key_layout); i++) {
+ Uint32 key;
+
+ /* Make sure this is a valid scancode */
+ scancode = data->key_layout[i];
+ if (scancode == SDL_SCANCODE_UNKNOWN) {
+ continue;
+ }
+
+ /* See if there is a UCS keycode for this scancode */
+ key = X11_KeyCodeToUcs4(_this, (KeyCode)i, group);
+ if (key) {
+ keymap[scancode] = key;
+ } else {
+ SDL_Scancode keyScancode = X11_KeyCodeToSDLScancode(_this, (KeyCode)i);
+
+ switch (keyScancode) {
+ case SDL_SCANCODE_RETURN:
+ keymap[scancode] = SDLK_RETURN;
+ break;
+ case SDL_SCANCODE_ESCAPE:
+ keymap[scancode] = SDLK_ESCAPE;
+ break;
+ case SDL_SCANCODE_BACKSPACE:
+ keymap[scancode] = SDLK_BACKSPACE;
+ break;
+ case SDL_SCANCODE_TAB:
+ keymap[scancode] = SDLK_TAB;
+ break;
+ case SDL_SCANCODE_DELETE:
+ keymap[scancode] = SDLK_DELETE;
+ break;
+ default:
+ keymap[scancode] = SDL_SCANCODE_TO_KEYCODE(keyScancode);
+ break;
+ }
+ }
+ }
+ SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
+}
+
+void
+X11_QuitKeyboard(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+ if (data->xkb) {
+ X11_XkbFreeKeyboard(data->xkb, 0, True);
+ data->xkb = NULL;
+ }
+#endif
+
+#ifdef SDL_USE_IME
+ SDL_IME_Quit();
+#endif
+}
+
+static void
+X11_ResetXIM(_THIS)
+{
+#ifdef X_HAVE_UTF8_STRING
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ int i;
+
+ if (videodata && videodata->windowlist) {
+ for (i = 0; i < videodata->numwindows; ++i) {
+ SDL_WindowData *data = videodata->windowlist[i];
+ if (data && data->ic) {
+ /* Clear any partially entered dead keys */
+ char *contents = X11_Xutf8ResetIC(data->ic);
+ if (contents) {
+ X11_XFree(contents);
+ }
+ }
+ }
+ }
+#endif
+}
+
+void
+X11_StartTextInput(_THIS)
+{
+ X11_ResetXIM(_this);
+}
+
+void
+X11_StopTextInput(_THIS)
+{
+ X11_ResetXIM(_this);
+#ifdef SDL_USE_IME
+ SDL_IME_Reset();
+#endif
+}
+
+void
+X11_SetTextInputRect(_THIS, SDL_Rect *rect)
+{
+ if (!rect) {
+ SDL_InvalidParamError("rect");
+ return;
+ }
+
+#ifdef SDL_USE_IME
+ SDL_IME_UpdateTextRect(rect);
+#endif
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11keyboard.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11keyboard.h
new file mode 100644
index 0000000..c1cc69c
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11keyboard.h
@@ -0,0 +1,36 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11keyboard_h_
+#define SDL_x11keyboard_h_
+
+extern int X11_InitKeyboard(_THIS);
+extern void X11_UpdateKeymap(_THIS);
+extern void X11_QuitKeyboard(_THIS);
+extern void X11_StartTextInput(_THIS);
+extern void X11_StopTextInput(_THIS);
+extern void X11_SetTextInputRect(_THIS, SDL_Rect *rect);
+extern KeySym X11_KeyCodeToSym(_THIS, KeyCode, unsigned char group);
+
+#endif /* SDL_x11keyboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11messagebox.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11messagebox.c
new file mode 100644
index 0000000..70a472a
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11messagebox.c
@@ -0,0 +1,872 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL.h"
+#include "SDL_x11video.h"
+#include "SDL_x11dyn.h"
+#include "SDL_assert.h"
+#include "SDL_x11messagebox.h"
+
+#include <X11/keysym.h>
+#include <locale.h>
+
+
+#define SDL_FORK_MESSAGEBOX 1
+#define SDL_SET_LOCALE 1
+
+#if SDL_FORK_MESSAGEBOX
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+#endif
+
+#define MAX_BUTTONS 8 /* Maximum number of buttons supported */
+#define MIN_BUTTON_WIDTH 64 /* Minimum button width */
+#define MIN_DIALOG_WIDTH 200 /* Minimum dialog width */
+#define MIN_DIALOG_HEIGHT 100 /* Minimum dialog height */
+
+static const char g_MessageBoxFontLatin1[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1";
+static const char g_MessageBoxFont[] = "-*-*-medium-r-normal--*-120-*-*-*-*-*-*";
+
+static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] = {
+ { 56, 54, 53 }, /* SDL_MESSAGEBOX_COLOR_BACKGROUND, */
+ { 209, 207, 205 }, /* SDL_MESSAGEBOX_COLOR_TEXT, */
+ { 140, 135, 129 }, /* SDL_MESSAGEBOX_COLOR_BUTTON_BORDER, */
+ { 105, 102, 99 }, /* SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND, */
+ { 205, 202, 53 }, /* SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED, */
+};
+
+#define SDL_MAKE_RGB( _r, _g, _b ) ( ( ( Uint32 )( _r ) << 16 ) | \
+ ( ( Uint32 )( _g ) << 8 ) | \
+ ( ( Uint32 )( _b ) ) )
+
+typedef struct SDL_MessageBoxButtonDataX11 {
+ int x, y; /* Text position */
+ int length; /* Text length */
+ int text_width; /* Text width */
+
+ SDL_Rect rect; /* Rectangle for entire button */
+
+ const SDL_MessageBoxButtonData *buttondata; /* Button data from caller */
+} SDL_MessageBoxButtonDataX11;
+
+typedef struct TextLineData {
+ int width; /* Width of this text line */
+ int length; /* String length of this text line */
+ const char *text; /* Text for this line */
+} TextLineData;
+
+typedef struct SDL_MessageBoxDataX11
+{
+ Display *display;
+ int screen;
+ Window window;
+#if SDL_VIDEO_DRIVER_X11_XDBE
+ XdbeBackBuffer buf;
+ SDL_bool xdbe; /* Whether Xdbe is present or not */
+#endif
+ long event_mask;
+ Atom wm_protocols;
+ Atom wm_delete_message;
+
+ int dialog_width; /* Dialog box width. */
+ int dialog_height; /* Dialog box height. */
+
+ XFontSet font_set; /* for UTF-8 systems */
+ XFontStruct *font_struct; /* Latin1 (ASCII) fallback. */
+ int xtext, ytext; /* Text position to start drawing at. */
+ int numlines; /* Count of Text lines. */
+ int text_height; /* Height for text lines. */
+ TextLineData *linedata;
+
+ int *pbuttonid; /* Pointer to user return buttonid value. */
+
+ int button_press_index; /* Index into buttondata/buttonpos for button which is pressed (or -1). */
+ int mouse_over_index; /* Index into buttondata/buttonpos for button mouse is over (or -1). */
+
+ int numbuttons; /* Count of buttons. */
+ const SDL_MessageBoxButtonData *buttondata;
+ SDL_MessageBoxButtonDataX11 buttonpos[ MAX_BUTTONS ];
+
+ Uint32 color[ SDL_MESSAGEBOX_COLOR_MAX ];
+
+ const SDL_MessageBoxData *messageboxdata;
+} SDL_MessageBoxDataX11;
+
+/* Maximum helper for ints. */
+static SDL_INLINE int
+IntMax( int a, int b )
+{
+ return ( a > b ) ? a : b;
+}
+
+/* Return width and height for a string. */
+static void
+GetTextWidthHeight( SDL_MessageBoxDataX11 *data, const char *str, int nbytes, int *pwidth, int *pheight )
+{
+ if (SDL_X11_HAVE_UTF8) {
+ XRectangle overall_ink, overall_logical;
+ X11_Xutf8TextExtents(data->font_set, str, nbytes, &overall_ink, &overall_logical);
+ *pwidth = overall_logical.width;
+ *pheight = overall_logical.height;
+ } else {
+ XCharStruct text_structure;
+ int font_direction, font_ascent, font_descent;
+ X11_XTextExtents( data->font_struct, str, nbytes,
+ &font_direction, &font_ascent, &font_descent,
+ &text_structure );
+ *pwidth = text_structure.width;
+ *pheight = text_structure.ascent + text_structure.descent;
+ }
+}
+
+/* Return index of button if position x,y is contained therein. */
+static int
+GetHitButtonIndex( SDL_MessageBoxDataX11 *data, int x, int y )
+{
+ int i;
+ int numbuttons = data->numbuttons;
+ SDL_MessageBoxButtonDataX11 *buttonpos = data->buttonpos;
+
+ for ( i = 0; i < numbuttons; i++ ) {
+ SDL_Rect *rect = &buttonpos[ i ].rect;
+
+ if ( ( x >= rect->x ) &&
+ ( x <= ( rect->x + rect->w ) ) &&
+ ( y >= rect->y ) &&
+ ( y <= ( rect->y + rect->h ) ) ) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* Initialize SDL_MessageBoxData structure and Display, etc. */
+static int
+X11_MessageBoxInit( SDL_MessageBoxDataX11 *data, const SDL_MessageBoxData * messageboxdata, int * pbuttonid )
+{
+ int i;
+ int numbuttons = messageboxdata->numbuttons;
+ const SDL_MessageBoxButtonData *buttondata = messageboxdata->buttons;
+ const SDL_MessageBoxColor *colorhints;
+
+ if ( numbuttons > MAX_BUTTONS ) {
+ return SDL_SetError("Too many buttons (%d max allowed)", MAX_BUTTONS);
+ }
+
+ data->dialog_width = MIN_DIALOG_WIDTH;
+ data->dialog_height = MIN_DIALOG_HEIGHT;
+ data->messageboxdata = messageboxdata;
+ data->buttondata = buttondata;
+ data->numbuttons = numbuttons;
+ data->pbuttonid = pbuttonid;
+
+ data->display = X11_XOpenDisplay( NULL );
+ if ( !data->display ) {
+ return SDL_SetError("Couldn't open X11 display");
+ }
+
+ if (SDL_X11_HAVE_UTF8) {
+ char **missing = NULL;
+ int num_missing = 0;
+ data->font_set = X11_XCreateFontSet(data->display, g_MessageBoxFont,
+ &missing, &num_missing, NULL);
+ if ( missing != NULL ) {
+ X11_XFreeStringList(missing);
+ }
+ if ( data->font_set == NULL ) {
+ return SDL_SetError("Couldn't load font %s", g_MessageBoxFont);
+ }
+ } else {
+ data->font_struct = X11_XLoadQueryFont( data->display, g_MessageBoxFontLatin1 );
+ if ( data->font_struct == NULL ) {
+ return SDL_SetError("Couldn't load font %s", g_MessageBoxFontLatin1);
+ }
+ }
+
+ if ( messageboxdata->colorScheme ) {
+ colorhints = messageboxdata->colorScheme->colors;
+ } else {
+ colorhints = g_default_colors;
+ }
+
+ /* Convert our SDL_MessageBoxColor r,g,b values to packed RGB format. */
+ for ( i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; i++ ) {
+ data->color[ i ] = SDL_MAKE_RGB( colorhints[ i ].r, colorhints[ i ].g, colorhints[ i ].b );
+ }
+
+ return 0;
+}
+
+static int
+CountLinesOfText(const char *text)
+{
+ int retval = 0;
+ while (text && *text) {
+ const char *lf = SDL_strchr(text, '\n');
+ retval++; /* even without an endline, this counts as a line. */
+ text = lf ? lf + 1 : NULL;
+ }
+ return retval;
+}
+
+/* Calculate and initialize text and button locations. */
+static int
+X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data )
+{
+ int i;
+ int ybuttons;
+ int text_width_max = 0;
+ int button_text_height = 0;
+ int button_width = MIN_BUTTON_WIDTH;
+ const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
+
+ /* Go over text and break linefeeds into separate lines. */
+ if ( messageboxdata->message && messageboxdata->message[ 0 ] ) {
+ const char *text = messageboxdata->message;
+ const int linecount = CountLinesOfText(text);
+ TextLineData *plinedata = (TextLineData *) SDL_malloc(sizeof (TextLineData) * linecount);
+
+ if (!plinedata) {
+ return SDL_OutOfMemory();
+ }
+
+ data->linedata = plinedata;
+ data->numlines = linecount;
+
+ for ( i = 0; i < linecount; i++, plinedata++ ) {
+ const char *lf = SDL_strchr( text, '\n' );
+ const int length = lf ? ( lf - text ) : SDL_strlen( text );
+ int height;
+
+ plinedata->text = text;
+
+ GetTextWidthHeight( data, text, length, &plinedata->width, &height );
+
+ /* Text and widths are the largest we've ever seen. */
+ data->text_height = IntMax( data->text_height, height );
+ text_width_max = IntMax( text_width_max, plinedata->width );
+
+ plinedata->length = length;
+ if (lf && (lf > text) && (lf[-1] == '\r')) {
+ plinedata->length--;
+ }
+
+ text += length + 1;
+
+ /* Break if there are no more linefeeds. */
+ if ( !lf )
+ break;
+ }
+
+ /* Bump up the text height slightly. */
+ data->text_height += 2;
+ }
+
+ /* Loop through all buttons and calculate the button widths and height. */
+ for ( i = 0; i < data->numbuttons; i++ ) {
+ int height;
+
+ data->buttonpos[ i ].buttondata = &data->buttondata[ i ];
+ data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text );
+
+ GetTextWidthHeight( data, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ),
+ &data->buttonpos[ i ].text_width, &height );
+
+ button_width = IntMax( button_width, data->buttonpos[ i ].text_width );
+ button_text_height = IntMax( button_text_height, height );
+ }
+
+ if ( data->numlines ) {
+ /* x,y for this line of text. */
+ data->xtext = data->text_height;
+ data->ytext = data->text_height + data->text_height;
+
+ /* Bump button y down to bottom of text. */
+ ybuttons = 3 * data->ytext / 2 + ( data->numlines - 1 ) * data->text_height;
+
+ /* Bump the dialog box width and height up if needed. */
+ data->dialog_width = IntMax( data->dialog_width, 2 * data->xtext + text_width_max );
+ data->dialog_height = IntMax( data->dialog_height, ybuttons );
+ } else {
+ /* Button y starts at height of button text. */
+ ybuttons = button_text_height;
+ }
+
+ if ( data->numbuttons ) {
+ int x, y;
+ int width_of_buttons;
+ int button_spacing = button_text_height;
+ int button_height = 2 * button_text_height;
+
+ /* Bump button width up a bit. */
+ button_width += button_text_height;
+
+ /* Get width of all buttons lined up. */
+ width_of_buttons = data->numbuttons * button_width + ( data->numbuttons - 1 ) * button_spacing;
+
+ /* Bump up dialog width and height if buttons are wider than text. */
+ data->dialog_width = IntMax( data->dialog_width, width_of_buttons + 2 * button_spacing );
+ data->dialog_height = IntMax( data->dialog_height, ybuttons + 2 * button_height );
+
+ /* Location for first button. */
+ x = ( data->dialog_width - width_of_buttons ) / 2;
+ y = ybuttons + ( data->dialog_height - ybuttons - button_height ) / 2;
+
+ for ( i = 0; i < data->numbuttons; i++ ) {
+ /* Button coordinates. */
+ data->buttonpos[ i ].rect.x = x;
+ data->buttonpos[ i ].rect.y = y;
+ data->buttonpos[ i ].rect.w = button_width;
+ data->buttonpos[ i ].rect.h = button_height;
+
+ /* Button text coordinates. */
+ data->buttonpos[ i ].x = x + ( button_width - data->buttonpos[ i ].text_width ) / 2;
+ data->buttonpos[ i ].y = y + ( button_height - button_text_height - 1 ) / 2 + button_text_height;
+
+ /* Scoot over for next button. */
+ x += button_width + button_spacing;
+ }
+ }
+
+ return 0;
+}
+
+/* Free SDL_MessageBoxData data. */
+static void
+X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data )
+{
+ if ( data->font_set != NULL ) {
+ X11_XFreeFontSet( data->display, data->font_set );
+ data->font_set = NULL;
+ }
+
+ if ( data->font_struct != NULL ) {
+ X11_XFreeFont( data->display, data->font_struct );
+ data->font_struct = NULL;
+ }
+
+#if SDL_VIDEO_DRIVER_X11_XDBE
+ if ( SDL_X11_HAVE_XDBE && data->xdbe ) {
+ X11_XdbeDeallocateBackBufferName(data->display, data->buf);
+ }
+#endif
+
+ if ( data->display ) {
+ if ( data->window != None ) {
+ X11_XWithdrawWindow( data->display, data->window, data->screen );
+ X11_XDestroyWindow( data->display, data->window );
+ data->window = None;
+ }
+
+ X11_XCloseDisplay( data->display );
+ data->display = NULL;
+ }
+
+ SDL_free(data->linedata);
+}
+
+/* Create and set up our X11 dialog box indow. */
+static int
+X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data )
+{
+ int x, y;
+ XSizeHints *sizehints;
+ XSetWindowAttributes wnd_attr;
+ Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG, _NET_WM_NAME;
+ Display *display = data->display;
+ SDL_WindowData *windowdata = NULL;
+ const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
+ char *title_locale = NULL;
+
+ if ( messageboxdata->window ) {
+ SDL_DisplayData *displaydata =
+ (SDL_DisplayData *) SDL_GetDisplayForWindow(messageboxdata->window)->driverdata;
+ windowdata = (SDL_WindowData *)messageboxdata->window->driverdata;
+ data->screen = displaydata->screen;
+ } else {
+ data->screen = DefaultScreen( display );
+ }
+
+ data->event_mask = ExposureMask |
+ ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask |
+ StructureNotifyMask | FocusChangeMask | PointerMotionMask;
+ wnd_attr.event_mask = data->event_mask;
+
+ data->window = X11_XCreateWindow(
+ display, RootWindow(display, data->screen),
+ 0, 0,
+ data->dialog_width, data->dialog_height,
+ 0, CopyFromParent, InputOutput, CopyFromParent,
+ CWEventMask, &wnd_attr );
+ if ( data->window == None ) {
+ return SDL_SetError("Couldn't create X window");
+ }
+
+ if ( windowdata ) {
+ /* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */
+ X11_XSetTransientForHint( display, data->window, windowdata->xwindow );
+ }
+
+ X11_XStoreName( display, data->window, messageboxdata->title );
+ _NET_WM_NAME = X11_XInternAtom(display, "_NET_WM_NAME", False);
+
+ title_locale = SDL_iconv_utf8_locale(messageboxdata->title);
+ if (title_locale) {
+ XTextProperty titleprop;
+ Status status = X11_XStringListToTextProperty(&title_locale, 1, &titleprop);
+ SDL_free(title_locale);
+ if (status) {
+ X11_XSetTextProperty(display, data->window, &titleprop, XA_WM_NAME);
+ X11_XFree(titleprop.value);
+ }
+ }
+
+#ifdef X_HAVE_UTF8_STRING
+ if (SDL_X11_HAVE_UTF8) {
+ XTextProperty titleprop;
+ Status status = X11_Xutf8TextListToTextProperty(display, (char **) &messageboxdata->title, 1,
+ XUTF8StringStyle, &titleprop);
+ if (status == Success) {
+ X11_XSetTextProperty(display, data->window, &titleprop,
+ _NET_WM_NAME);
+ X11_XFree(titleprop.value);
+ }
+ }
+#endif
+
+ /* Let the window manager know this is a dialog box */
+ _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
+ _NET_WM_WINDOW_TYPE_DIALOG = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+ X11_XChangeProperty(display, data->window, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
+ PropModeReplace,
+ (unsigned char *)&_NET_WM_WINDOW_TYPE_DIALOG, 1);
+
+ /* Allow the window to be deleted by the window manager */
+ data->wm_protocols = X11_XInternAtom( display, "WM_PROTOCOLS", False );
+ data->wm_delete_message = X11_XInternAtom( display, "WM_DELETE_WINDOW", False );
+ X11_XSetWMProtocols( display, data->window, &data->wm_delete_message, 1 );
+
+ if ( windowdata ) {
+ XWindowAttributes attrib;
+ Window dummy;
+
+ X11_XGetWindowAttributes(display, windowdata->xwindow, &attrib);
+ x = attrib.x + ( attrib.width - data->dialog_width ) / 2;
+ y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ;
+ X11_XTranslateCoordinates(display, windowdata->xwindow, RootWindow(display, data->screen), x, y, &x, &y, &dummy);
+ } else {
+ const SDL_VideoDevice *dev = SDL_GetVideoDevice();
+ if ((dev) && (dev->displays) && (dev->num_displays > 0)) {
+ const SDL_VideoDisplay *dpy = &dev->displays[0];
+ const SDL_DisplayData *dpydata = (SDL_DisplayData *) dpy->driverdata;
+ x = dpydata->x + (( dpy->current_mode.w - data->dialog_width ) / 2);
+ y = dpydata->y + (( dpy->current_mode.h - data->dialog_height ) / 3);
+ } else { /* oh well. This will misposition on a multi-head setup. Init first next time. */
+ x = ( DisplayWidth( display, data->screen ) - data->dialog_width ) / 2;
+ y = ( DisplayHeight( display, data->screen ) - data->dialog_height ) / 3 ;
+ }
+ }
+ X11_XMoveWindow( display, data->window, x, y );
+
+ sizehints = X11_XAllocSizeHints();
+ if ( sizehints ) {
+ sizehints->flags = USPosition | USSize | PMaxSize | PMinSize;
+ sizehints->x = x;
+ sizehints->y = y;
+ sizehints->width = data->dialog_width;
+ sizehints->height = data->dialog_height;
+
+ sizehints->min_width = sizehints->max_width = data->dialog_width;
+ sizehints->min_height = sizehints->max_height = data->dialog_height;
+
+ X11_XSetWMNormalHints( display, data->window, sizehints );
+
+ X11_XFree( sizehints );
+ }
+
+ X11_XMapRaised( display, data->window );
+
+#if SDL_VIDEO_DRIVER_X11_XDBE
+ /* Initialise a back buffer for double buffering */
+ if (SDL_X11_HAVE_XDBE) {
+ int xdbe_major, xdbe_minor;
+ if (X11_XdbeQueryExtension(display, &xdbe_major, &xdbe_minor) != 0) {
+ data->xdbe = SDL_TRUE;
+ data->buf = X11_XdbeAllocateBackBufferName(display, data->window, XdbeUndefined);
+ } else {
+ data->xdbe = SDL_FALSE;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+/* Draw our message box. */
+static void
+X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx )
+{
+ int i;
+ Drawable window = data->window;
+ Display *display = data->display;
+
+#if SDL_VIDEO_DRIVER_X11_XDBE
+ if (SDL_X11_HAVE_XDBE && data->xdbe) {
+ window = data->buf;
+ X11_XdbeBeginIdiom(data->display);
+ }
+#endif
+
+ X11_XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ] );
+ X11_XFillRectangle( display, window, ctx, 0, 0, data->dialog_width, data->dialog_height );
+
+ X11_XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
+ for ( i = 0; i < data->numlines; i++ ) {
+ TextLineData *plinedata = &data->linedata[ i ];
+
+ if (SDL_X11_HAVE_UTF8) {
+ X11_Xutf8DrawString( display, window, data->font_set, ctx,
+ data->xtext, data->ytext + i * data->text_height,
+ plinedata->text, plinedata->length );
+ } else {
+ X11_XDrawString( display, window, ctx,
+ data->xtext, data->ytext + i * data->text_height,
+ plinedata->text, plinedata->length );
+ }
+ }
+
+ for ( i = 0; i < data->numbuttons; i++ ) {
+ SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
+ const SDL_MessageBoxButtonData *buttondata = buttondatax11->buttondata;
+ int border = ( buttondata->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT ) ? 2 : 0;
+ int offset = ( ( data->mouse_over_index == i ) && ( data->button_press_index == data->mouse_over_index ) ) ? 1 : 0;
+
+ X11_XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND ] );
+ X11_XFillRectangle( display, window, ctx,
+ buttondatax11->rect.x - border, buttondatax11->rect.y - border,
+ buttondatax11->rect.w + 2 * border, buttondatax11->rect.h + 2 * border );
+
+ X11_XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BORDER ] );
+ X11_XDrawRectangle( display, window, ctx,
+ buttondatax11->rect.x, buttondatax11->rect.y,
+ buttondatax11->rect.w, buttondatax11->rect.h );
+
+ X11_XSetForeground( display, ctx, ( data->mouse_over_index == i ) ?
+ data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] :
+ data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] );
+
+ if (SDL_X11_HAVE_UTF8) {
+ X11_Xutf8DrawString( display, window, data->font_set, ctx,
+ buttondatax11->x + offset,
+ buttondatax11->y + offset,
+ buttondata->text, buttondatax11->length );
+ } else {
+ X11_XDrawString( display, window, ctx,
+ buttondatax11->x + offset, buttondatax11->y + offset,
+ buttondata->text, buttondatax11->length );
+ }
+ }
+
+#if SDL_VIDEO_DRIVER_X11_XDBE
+ if (SDL_X11_HAVE_XDBE && data->xdbe) {
+ XdbeSwapInfo swap_info;
+ swap_info.swap_window = data->window;
+ swap_info.swap_action = XdbeUndefined;
+ X11_XdbeSwapBuffers(data->display, &swap_info, 1);
+ X11_XdbeEndIdiom(data->display);
+ }
+#endif
+}
+
+static Bool
+X11_MessageBoxEventTest(Display *display, XEvent *event, XPointer arg)
+{
+ const SDL_MessageBoxDataX11 *data = (const SDL_MessageBoxDataX11 *) arg;
+ return ((event->xany.display == data->display) && (event->xany.window == data->window)) ? True : False;
+}
+
+/* Loop and handle message box event messages until something kills it. */
+static int
+X11_MessageBoxLoop( SDL_MessageBoxDataX11 *data )
+{
+ GC ctx;
+ XGCValues ctx_vals;
+ SDL_bool close_dialog = SDL_FALSE;
+ SDL_bool has_focus = SDL_TRUE;
+ KeySym last_key_pressed = XK_VoidSymbol;
+ unsigned long gcflags = GCForeground | GCBackground;
+
+ SDL_zero(ctx_vals);
+ ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
+ ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ];
+
+ if (!SDL_X11_HAVE_UTF8) {
+ gcflags |= GCFont;
+ ctx_vals.font = data->font_struct->fid;
+ }
+
+ ctx = X11_XCreateGC( data->display, data->window, gcflags, &ctx_vals );
+ if ( ctx == None ) {
+ return SDL_SetError("Couldn't create graphics context");
+ }
+
+ data->button_press_index = -1; /* Reset what button is currently depressed. */
+ data->mouse_over_index = -1; /* Reset what button the mouse is over. */
+
+ while( !close_dialog ) {
+ XEvent e;
+ SDL_bool draw = SDL_TRUE;
+
+ /* can't use XWindowEvent() because it can't handle ClientMessage events. */
+ /* can't use XNextEvent() because we only want events for this window. */
+ X11_XIfEvent( data->display, &e, X11_MessageBoxEventTest, (XPointer) data );
+
+ /* If X11_XFilterEvent returns True, then some input method has filtered the
+ event, and the client should discard the event. */
+ if ( ( e.type != Expose ) && X11_XFilterEvent( &e, None ) )
+ continue;
+
+ switch( e.type ) {
+ case Expose:
+ if ( e.xexpose.count > 0 ) {
+ draw = SDL_FALSE;
+ }
+ break;
+
+ case FocusIn:
+ /* Got focus. */
+ has_focus = SDL_TRUE;
+ break;
+
+ case FocusOut:
+ /* lost focus. Reset button and mouse info. */
+ has_focus = SDL_FALSE;
+ data->button_press_index = -1;
+ data->mouse_over_index = -1;
+ break;
+
+ case MotionNotify:
+ if ( has_focus ) {
+ /* Mouse moved... */
+ const int previndex = data->mouse_over_index;
+ data->mouse_over_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
+ if (data->mouse_over_index == previndex) {
+ draw = SDL_FALSE;
+ }
+ }
+ break;
+
+ case ClientMessage:
+ if ( e.xclient.message_type == data->wm_protocols &&
+ e.xclient.format == 32 &&
+ e.xclient.data.l[ 0 ] == data->wm_delete_message ) {
+ close_dialog = SDL_TRUE;
+ }
+ break;
+
+ case KeyPress:
+ /* Store key press - we make sure in key release that we got both. */
+ last_key_pressed = X11_XLookupKeysym( &e.xkey, 0 );
+ break;
+
+ case KeyRelease: {
+ Uint32 mask = 0;
+ KeySym key = X11_XLookupKeysym( &e.xkey, 0 );
+
+ /* If this is a key release for something we didn't get the key down for, then bail. */
+ if ( key != last_key_pressed )
+ break;
+
+ if ( key == XK_Escape )
+ mask = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
+ else if ( ( key == XK_Return ) || ( key == XK_KP_Enter ) )
+ mask = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT;
+
+ if ( mask ) {
+ int i;
+
+ /* Look for first button with this mask set, and return it if found. */
+ for ( i = 0; i < data->numbuttons; i++ ) {
+ SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ];
+
+ if ( buttondatax11->buttondata->flags & mask ) {
+ *data->pbuttonid = buttondatax11->buttondata->buttonid;
+ close_dialog = SDL_TRUE;
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case ButtonPress:
+ data->button_press_index = -1;
+ if ( e.xbutton.button == Button1 ) {
+ /* Find index of button they clicked on. */
+ data->button_press_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
+ }
+ break;
+
+ case ButtonRelease:
+ /* If button is released over the same button that was clicked down on, then return it. */
+ if ( ( e.xbutton.button == Button1 ) && ( data->button_press_index >= 0 ) ) {
+ int button = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y );
+
+ if ( data->button_press_index == button ) {
+ SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ button ];
+
+ *data->pbuttonid = buttondatax11->buttondata->buttonid;
+ close_dialog = SDL_TRUE;
+ }
+ }
+ data->button_press_index = -1;
+ break;
+ }
+
+ if ( draw ) {
+ /* Draw our dialog box. */
+ X11_MessageBoxDraw( data, ctx );
+ }
+ }
+
+ X11_XFreeGC( data->display, ctx );
+ return 0;
+}
+
+static int
+X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{
+ int ret;
+ SDL_MessageBoxDataX11 data;
+#if SDL_SET_LOCALE
+ char *origlocale;
+#endif
+
+ SDL_zero(data);
+
+ if ( !SDL_X11_LoadSymbols() )
+ return -1;
+
+#if SDL_SET_LOCALE
+ origlocale = setlocale(LC_ALL, NULL);
+ if (origlocale != NULL) {
+ origlocale = SDL_strdup(origlocale);
+ if (origlocale == NULL) {
+ return SDL_OutOfMemory();
+ }
+ setlocale(LC_ALL, "");
+ }
+#endif
+
+ /* This code could get called from multiple threads maybe? */
+ X11_XInitThreads();
+
+ /* Initialize the return buttonid value to -1 (for error or dialogbox closed). */
+ *buttonid = -1;
+
+ /* Init and display the message box. */
+ ret = X11_MessageBoxInit( &data, messageboxdata, buttonid );
+ if ( ret != -1 ) {
+ ret = X11_MessageBoxInitPositions( &data );
+ if ( ret != -1 ) {
+ ret = X11_MessageBoxCreateWindow( &data );
+ if ( ret != -1 ) {
+ ret = X11_MessageBoxLoop( &data );
+ }
+ }
+ }
+
+ X11_MessageBoxShutdown( &data );
+
+#if SDL_SET_LOCALE
+ if (origlocale) {
+ setlocale(LC_ALL, origlocale);
+ SDL_free(origlocale);
+ }
+#endif
+
+ return ret;
+}
+
+/* Display an x11 message box. */
+int
+X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{
+#if SDL_FORK_MESSAGEBOX
+ /* Use a child process to protect against setlocale(). Annoying. */
+ pid_t pid;
+ int fds[2];
+ int status = 0;
+
+ if (pipe(fds) == -1) {
+ return X11_ShowMessageBoxImpl(messageboxdata, buttonid); /* oh well. */
+ }
+
+ pid = fork();
+ if (pid == -1) { /* failed */
+ close(fds[0]);
+ close(fds[1]);
+ return X11_ShowMessageBoxImpl(messageboxdata, buttonid); /* oh well. */
+ } else if (pid == 0) { /* we're the child */
+ int exitcode = 0;
+ close(fds[0]);
+ status = X11_ShowMessageBoxImpl(messageboxdata, buttonid);
+ if (write(fds[1], &status, sizeof (int)) != sizeof (int))
+ exitcode = 1;
+ else if (write(fds[1], buttonid, sizeof (int)) != sizeof (int))
+ exitcode = 1;
+ close(fds[1]);
+ _exit(exitcode); /* don't run atexit() stuff, static destructors, etc. */
+ } else { /* we're the parent */
+ pid_t rc;
+ close(fds[1]);
+ do {
+ rc = waitpid(pid, &status, 0);
+ } while ((rc == -1) && (errno == EINTR));
+
+ SDL_assert(rc == pid); /* not sure what to do if this fails. */
+
+ if ((rc == -1) || (!WIFEXITED(status)) || (WEXITSTATUS(status) != 0)) {
+ return SDL_SetError("msgbox child process failed");
+ }
+
+ if (read(fds[0], &status, sizeof (int)) != sizeof (int))
+ status = -1;
+ else if (read(fds[0], buttonid, sizeof (int)) != sizeof (int))
+ status = -1;
+ close(fds[0]);
+
+ return status;
+ }
+#else
+ return X11_ShowMessageBoxImpl(messageboxdata, buttonid);
+#endif
+}
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11messagebox.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11messagebox.h
new file mode 100644
index 0000000..6515983
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11messagebox.h
@@ -0,0 +1,33 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_x11messagebox_h_
+#define SDL_x11messagebox_h_
+
+#if SDL_VIDEO_DRIVER_X11
+
+extern int X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+#endif /* SDL_x11messagebox_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11modes.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11modes.c
new file mode 100644
index 0000000..5eafe73
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11modes.c
@@ -0,0 +1,1112 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL_hints.h"
+#include "SDL_x11video.h"
+#include "SDL_timer.h"
+#include "edid.h"
+
+/* #define X11MODES_DEBUG */
+
+/* I'm becoming more and more convinced that the application should never
+ * use XRandR, and it's the window manager's responsibility to track and
+ * manage display modes for fullscreen windows. Right now XRandR is completely
+ * broken with respect to window manager behavior on every window manager that
+ * I can find. For example, on Unity 3D if you show a fullscreen window while
+ * the resolution is changing (within ~250 ms) your window will retain the
+ * fullscreen state hint but be decorated and windowed.
+ *
+ * However, many people swear by it, so let them swear at it. :)
+*/
+/* #define XRANDR_DISABLED_BY_DEFAULT */
+
+
+static int
+get_visualinfo(Display * display, int screen, XVisualInfo * vinfo)
+{
+ const char *visual_id = SDL_getenv("SDL_VIDEO_X11_VISUALID");
+ int depth;
+
+ /* Look for an exact visual, if requested */
+ if (visual_id) {
+ XVisualInfo *vi, template;
+ int nvis;
+
+ SDL_zero(template);
+ template.visualid = SDL_strtol(visual_id, NULL, 0);
+ vi = X11_XGetVisualInfo(display, VisualIDMask, &template, &nvis);
+ if (vi) {
+ *vinfo = *vi;
+ X11_XFree(vi);
+ return 0;
+ }
+ }
+
+ depth = DefaultDepth(display, screen);
+ if ((X11_UseDirectColorVisuals() &&
+ X11_XMatchVisualInfo(display, screen, depth, DirectColor, vinfo)) ||
+ X11_XMatchVisualInfo(display, screen, depth, TrueColor, vinfo) ||
+ X11_XMatchVisualInfo(display, screen, depth, PseudoColor, vinfo) ||
+ X11_XMatchVisualInfo(display, screen, depth, StaticColor, vinfo)) {
+ return 0;
+ }
+ return -1;
+}
+
+int
+X11_GetVisualInfoFromVisual(Display * display, Visual * visual, XVisualInfo * vinfo)
+{
+ XVisualInfo *vi;
+ int nvis;
+
+ vinfo->visualid = X11_XVisualIDFromVisual(visual);
+ vi = X11_XGetVisualInfo(display, VisualIDMask, vinfo, &nvis);
+ if (vi) {
+ *vinfo = *vi;
+ X11_XFree(vi);
+ return 0;
+ }
+ return -1;
+}
+
+Uint32
+X11_GetPixelFormatFromVisualInfo(Display * display, XVisualInfo * vinfo)
+{
+ if (vinfo->class == DirectColor || vinfo->class == TrueColor) {
+ int bpp;
+ Uint32 Rmask, Gmask, Bmask, Amask;
+
+ Rmask = vinfo->visual->red_mask;
+ Gmask = vinfo->visual->green_mask;
+ Bmask = vinfo->visual->blue_mask;
+ if (vinfo->depth == 32) {
+ Amask = (0xFFFFFFFF & ~(Rmask | Gmask | Bmask));
+ } else {
+ Amask = 0;
+ }
+
+ bpp = vinfo->depth;
+ if (bpp == 24) {
+ int i, n;
+ XPixmapFormatValues *p = X11_XListPixmapFormats(display, &n);
+ if (p) {
+ for (i = 0; i < n; ++i) {
+ if (p[i].depth == 24) {
+ bpp = p[i].bits_per_pixel;
+ break;
+ }
+ }
+ X11_XFree(p);
+ }
+ }
+
+ return SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
+ }
+
+ if (vinfo->class == PseudoColor || vinfo->class == StaticColor) {
+ switch (vinfo->depth) {
+ case 8:
+ return SDL_PIXELTYPE_INDEX8;
+ case 4:
+ if (BitmapBitOrder(display) == LSBFirst) {
+ return SDL_PIXELFORMAT_INDEX4LSB;
+ } else {
+ return SDL_PIXELFORMAT_INDEX4MSB;
+ }
+ /* break; -Wunreachable-code-break */
+ case 1:
+ if (BitmapBitOrder(display) == LSBFirst) {
+ return SDL_PIXELFORMAT_INDEX1LSB;
+ } else {
+ return SDL_PIXELFORMAT_INDEX1MSB;
+ }
+ /* break; -Wunreachable-code-break */
+ }
+ }
+
+ return SDL_PIXELFORMAT_UNKNOWN;
+}
+
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+static SDL_bool
+CheckXinerama(Display * display, int *major, int *minor)
+{
+ int event_base = 0;
+ int error_base = 0;
+
+ /* Default the extension not available */
+ *major = *minor = 0;
+
+ /* Allow environment override */
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XINERAMA, SDL_TRUE)) {
+#ifdef X11MODES_DEBUG
+ printf("Xinerama disabled due to hint\n");
+#endif
+ return SDL_FALSE;
+ }
+
+ if (!SDL_X11_HAVE_XINERAMA) {
+#ifdef X11MODES_DEBUG
+ printf("Xinerama support not available\n");
+#endif
+ return SDL_FALSE;
+ }
+
+ /* Query the extension version */
+ if (!X11_XineramaQueryExtension(display, &event_base, &error_base) ||
+ !X11_XineramaQueryVersion(display, major, minor) ||
+ !X11_XineramaIsActive(display)) {
+#ifdef X11MODES_DEBUG
+ printf("Xinerama not active on the display\n");
+#endif
+ return SDL_FALSE;
+ }
+#ifdef X11MODES_DEBUG
+ printf("Xinerama available at version %d.%d!\n", *major, *minor);
+#endif
+ return SDL_TRUE;
+}
+
+/* !!! FIXME: remove this later. */
+/* we have a weird bug where XineramaQueryScreens() throws an X error, so this
+ is here to help track it down (and not crash, too!). */
+static SDL_bool xinerama_triggered_error = SDL_FALSE;
+static int
+X11_XineramaFailed(Display * d, XErrorEvent * e)
+{
+ xinerama_triggered_error = SDL_TRUE;
+ fprintf(stderr, "XINERAMA X ERROR: type=%d serial=%lu err=%u req=%u minor=%u\n",
+ e->type, e->serial, (unsigned int) e->error_code,
+ (unsigned int) e->request_code, (unsigned int) e->minor_code);
+ fflush(stderr);
+ return 0;
+}
+#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
+
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+static SDL_bool
+CheckXRandR(Display * display, int *major, int *minor)
+{
+ /* Default the extension not available */
+ *major = *minor = 0;
+
+ /* Allow environment override */
+#ifdef XRANDR_DISABLED_BY_DEFAULT
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XRANDR, SDL_FALSE)) {
+#ifdef X11MODES_DEBUG
+ printf("XRandR disabled by default due to window manager issues\n");
+#endif
+ return SDL_FALSE;
+ }
+#else
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XRANDR, SDL_TRUE)) {
+#ifdef X11MODES_DEBUG
+ printf("XRandR disabled due to hint\n");
+#endif
+ return SDL_FALSE;
+ }
+#endif /* XRANDR_ENABLED_BY_DEFAULT */
+
+ if (!SDL_X11_HAVE_XRANDR) {
+#ifdef X11MODES_DEBUG
+ printf("XRandR support not available\n");
+#endif
+ return SDL_FALSE;
+ }
+
+ /* Query the extension version */
+ *major = 1; *minor = 3; /* we want 1.3 */
+ if (!X11_XRRQueryVersion(display, major, minor)) {
+#ifdef X11MODES_DEBUG
+ printf("XRandR not active on the display\n");
+#endif
+ *major = *minor = 0;
+ return SDL_FALSE;
+ }
+#ifdef X11MODES_DEBUG
+ printf("XRandR available at version %d.%d!\n", *major, *minor);
+#endif
+ return SDL_TRUE;
+}
+
+#define XRANDR_ROTATION_LEFT (1 << 1)
+#define XRANDR_ROTATION_RIGHT (1 << 3)
+
+static int
+CalculateXRandRRefreshRate(const XRRModeInfo *info)
+{
+ return (info->hTotal && info->vTotal) ?
+ round(((double)info->dotClock / (double)(info->hTotal * info->vTotal))) : 0;
+}
+
+static SDL_bool
+SetXRandRModeInfo(Display *display, XRRScreenResources *res, RRCrtc crtc,
+ RRMode modeID, SDL_DisplayMode *mode)
+{
+ int i;
+ for (i = 0; i < res->nmode; ++i) {
+ const XRRModeInfo *info = &res->modes[i];
+ if (info->id == modeID) {
+ XRRCrtcInfo *crtcinfo;
+ Rotation rotation = 0;
+
+ crtcinfo = X11_XRRGetCrtcInfo(display, res, crtc);
+ if (crtcinfo) {
+ rotation = crtcinfo->rotation;
+ X11_XRRFreeCrtcInfo(crtcinfo);
+ }
+
+ if (rotation & (XRANDR_ROTATION_LEFT|XRANDR_ROTATION_RIGHT)) {
+ mode->w = info->height;
+ mode->h = info->width;
+ } else {
+ mode->w = info->width;
+ mode->h = info->height;
+ }
+ mode->refresh_rate = CalculateXRandRRefreshRate(info);
+ ((SDL_DisplayModeData*)mode->driverdata)->xrandr_mode = modeID;
+#ifdef X11MODES_DEBUG
+ printf("XRandR mode %d: %dx%d@%dHz\n", (int) modeID, mode->w, mode->h, mode->refresh_rate);
+#endif
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
+static void
+SetXRandRDisplayName(Display *dpy, Atom EDID, char *name, const size_t namelen, RROutput output, const unsigned long widthmm, const unsigned long heightmm)
+{
+ /* See if we can get the EDID data for the real monitor name */
+ int inches;
+ int nprop;
+ Atom *props = X11_XRRListOutputProperties(dpy, output, &nprop);
+ int i;
+
+ for (i = 0; i < nprop; ++i) {
+ unsigned char *prop;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ Atom actual_type;
+
+ if (props[i] == EDID) {
+ if (X11_XRRGetOutputProperty(dpy, output, props[i], 0, 100, False,
+ False, AnyPropertyType, &actual_type,
+ &actual_format, &nitems, &bytes_after,
+ &prop) == Success) {
+ MonitorInfo *info = decode_edid(prop);
+ if (info) {
+#ifdef X11MODES_DEBUG
+ printf("Found EDID data for %s\n", name);
+ dump_monitor_info(info);
+#endif
+ SDL_strlcpy(name, info->dsc_product_name, namelen);
+ free(info);
+ }
+ X11_XFree(prop);
+ }
+ break;
+ }
+ }
+
+ if (props) {
+ X11_XFree(props);
+ }
+
+ inches = (int)((SDL_sqrtf(widthmm * widthmm + heightmm * heightmm) / 25.4f) + 0.5f);
+ if (*name && inches) {
+ const size_t len = SDL_strlen(name);
+ SDL_snprintf(&name[len], namelen-len, " %d\"", inches);
+ }
+
+#ifdef X11MODES_DEBUG
+ printf("Display name: %s\n", name);
+#endif
+}
+
+
+static int
+X11_InitModes_XRandR(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ Display *dpy = data->display;
+ const int screencount = ScreenCount(dpy);
+ const int default_screen = DefaultScreen(dpy);
+ RROutput primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, default_screen));
+ Atom EDID = X11_XInternAtom(dpy, "EDID", False);
+ XRRScreenResources *res = NULL;
+ Uint32 pixelformat;
+ XVisualInfo vinfo;
+ XPixmapFormatValues *pixmapformats;
+ int looking_for_primary;
+ int scanline_pad;
+ int output;
+ int screen, i, n;
+
+ for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
+ for (screen = 0; screen < screencount; screen++) {
+
+ /* we want the primary output first, and then skipped later. */
+ if (looking_for_primary && (screen != default_screen)) {
+ continue;
+ }
+
+ if (get_visualinfo(dpy, screen, &vinfo) < 0) {
+ continue; /* uh, skip this screen? */
+ }
+
+ pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
+ if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
+ continue; /* Palettized video modes are no longer supported */
+ }
+
+ scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
+ pixmapformats = X11_XListPixmapFormats(dpy, &n);
+ if (pixmapformats) {
+ for (i = 0; i < n; ++i) {
+ if (pixmapformats[i].depth == vinfo.depth) {
+ scanline_pad = pixmapformats[i].scanline_pad;
+ break;
+ }
+ }
+ X11_XFree(pixmapformats);
+ }
+
+ res = X11_XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, screen));
+ if (!res || res->noutput == 0) {
+ if (res) {
+ X11_XRRFreeScreenResources(res);
+ }
+
+ res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
+ if (!res) {
+ continue;
+ }
+ }
+
+ for (output = 0; output < res->noutput; output++) {
+ XRROutputInfo *output_info;
+ int display_x, display_y;
+ unsigned long display_mm_width, display_mm_height;
+ SDL_DisplayData *displaydata;
+ char display_name[128];
+ SDL_DisplayMode mode;
+ SDL_DisplayModeData *modedata;
+ SDL_VideoDisplay display;
+ RRMode modeID;
+ RRCrtc output_crtc;
+ XRRCrtcInfo *crtc;
+
+ /* The primary output _should_ always be sorted first, but just in case... */
+ if ((looking_for_primary && (res->outputs[output] != primary)) ||
+ (!looking_for_primary && (screen == default_screen) && (res->outputs[output] == primary))) {
+ continue;
+ }
+
+ output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
+ if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
+ X11_XRRFreeOutputInfo(output_info);
+ continue;
+ }
+
+ SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
+ display_mm_width = output_info->mm_width;
+ display_mm_height = output_info->mm_height;
+ output_crtc = output_info->crtc;
+ X11_XRRFreeOutputInfo(output_info);
+
+ crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
+ if (!crtc) {
+ continue;
+ }
+
+ SDL_zero(mode);
+ modeID = crtc->mode;
+ mode.w = crtc->width;
+ mode.h = crtc->height;
+ mode.format = pixelformat;
+
+ display_x = crtc->x;
+ display_y = crtc->y;
+
+ X11_XRRFreeCrtcInfo(crtc);
+
+ displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
+ if (!displaydata) {
+ return SDL_OutOfMemory();
+ }
+
+ modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
+ if (!modedata) {
+ SDL_free(displaydata);
+ return SDL_OutOfMemory();
+ }
+ modedata->xrandr_mode = modeID;
+ mode.driverdata = modedata;
+
+ displaydata->screen = screen;
+ displaydata->visual = vinfo.visual;
+ displaydata->depth = vinfo.depth;
+ displaydata->hdpi = display_mm_width ? (((float) mode.w) * 25.4f / display_mm_width) : 0.0f;
+ displaydata->vdpi = display_mm_height ? (((float) mode.h) * 25.4f / display_mm_height) : 0.0f;
+ displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
+ displaydata->scanline_pad = scanline_pad;
+ displaydata->x = display_x;
+ displaydata->y = display_y;
+ displaydata->use_xrandr = 1;
+ displaydata->xrandr_output = res->outputs[output];
+
+ SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
+ SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);
+
+ SDL_zero(display);
+ if (*display_name) {
+ display.name = display_name;
+ }
+ display.desktop_mode = mode;
+ display.current_mode = mode;
+ display.driverdata = displaydata;
+ SDL_AddVideoDisplay(&display);
+ }
+
+ X11_XRRFreeScreenResources(res);
+ }
+ }
+
+ if (_this->num_displays == 0) {
+ return SDL_SetError("No available displays");
+ }
+
+ return 0;
+}
+#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
+
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+static SDL_bool
+CheckVidMode(Display * display, int *major, int *minor)
+{
+ int vm_event, vm_error = -1;
+ /* Default the extension not available */
+ *major = *minor = 0;
+
+ /* Allow environment override */
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XVIDMODE, SDL_TRUE)) {
+#ifdef X11MODES_DEBUG
+ printf("XVidMode disabled due to hint\n");
+#endif
+ return SDL_FALSE;
+ }
+
+ if (!SDL_X11_HAVE_XVIDMODE) {
+#ifdef X11MODES_DEBUG
+ printf("XVidMode support not available\n");
+#endif
+ return SDL_FALSE;
+ }
+
+ /* Query the extension version */
+ if (!X11_XF86VidModeQueryExtension(display, &vm_event, &vm_error)
+ || !X11_XF86VidModeQueryVersion(display, major, minor)) {
+#ifdef X11MODES_DEBUG
+ printf("XVidMode not active on the display\n");
+#endif
+ return SDL_FALSE;
+ }
+#ifdef X11MODES_DEBUG
+ printf("XVidMode available at version %d.%d!\n", *major, *minor);
+#endif
+ return SDL_TRUE;
+}
+
+static
+Bool XF86VidModeGetModeInfo(Display * dpy, int scr,
+ XF86VidModeModeInfo* info)
+{
+ Bool retval;
+ int dotclock;
+ XF86VidModeModeLine l;
+ SDL_zerop(info);
+ SDL_zero(l);
+ retval = X11_XF86VidModeGetModeLine(dpy, scr, &dotclock, &l);
+ info->dotclock = dotclock;
+ info->hdisplay = l.hdisplay;
+ info->hsyncstart = l.hsyncstart;
+ info->hsyncend = l.hsyncend;
+ info->htotal = l.htotal;
+ info->hskew = l.hskew;
+ info->vdisplay = l.vdisplay;
+ info->vsyncstart = l.vsyncstart;
+ info->vsyncend = l.vsyncend;
+ info->vtotal = l.vtotal;
+ info->flags = l.flags;
+ info->privsize = l.privsize;
+ info->private = l.private;
+ return retval;
+}
+
+static int
+CalculateXVidModeRefreshRate(const XF86VidModeModeInfo * info)
+{
+ return (info->htotal
+ && info->vtotal) ? (1000 * info->dotclock / (info->htotal *
+ info->vtotal)) : 0;
+}
+
+static SDL_bool
+SetXVidModeModeInfo(const XF86VidModeModeInfo *info, SDL_DisplayMode *mode)
+{
+ mode->w = info->hdisplay;
+ mode->h = info->vdisplay;
+ mode->refresh_rate = CalculateXVidModeRefreshRate(info);
+ ((SDL_DisplayModeData*)mode->driverdata)->vm_mode = *info;
+ return SDL_TRUE;
+}
+#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
+
+int
+X11_InitModes(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ int snum, screen, screencount = 0;
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ int xinerama_major, xinerama_minor;
+ int use_xinerama = 0;
+ XineramaScreenInfo *xinerama = NULL;
+#endif
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+ int xrandr_major, xrandr_minor;
+#endif
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+ int vm_major, vm_minor;
+ int use_vidmode = 0;
+#endif
+
+/* XRandR is the One True Modern Way to do this on X11. If it's enabled and
+ available, don't even look at other ways of doing things. */
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+ /* require at least XRandR v1.3 */
+ if (CheckXRandR(data->display, &xrandr_major, &xrandr_minor) &&
+ (xrandr_major >= 2 || (xrandr_major == 1 && xrandr_minor >= 3))) {
+ if (X11_InitModes_XRandR(_this) == 0)
+ return 0;
+ }
+#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
+
+/* !!! FIXME: eventually remove support for Xinerama and XVidMode (everything below here). */
+
+ /* This is a workaround for some apps (UnrealEngine4, for example) until
+ we sort out the ramifications of removing XVidMode support outright.
+ This block should be removed with the XVidMode support. */
+ {
+ if (SDL_GetHintBoolean("SDL_VIDEO_X11_REQUIRE_XRANDR", SDL_FALSE)) {
+ #if SDL_VIDEO_DRIVER_X11_XRANDR
+ return SDL_SetError("XRandR support is required but not available");
+ #else
+ return SDL_SetError("XRandR support is required but not built into SDL!");
+ #endif
+ }
+ }
+
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ /* Query Xinerama extention
+ * NOTE: This works with Nvidia Twinview correctly, but you need version 302.17 (released on June 2012)
+ * or newer of the Nvidia binary drivers
+ */
+ if (CheckXinerama(data->display, &xinerama_major, &xinerama_minor)) {
+ int (*handler) (Display *, XErrorEvent *);
+ X11_XSync(data->display, False);
+ handler = X11_XSetErrorHandler(X11_XineramaFailed);
+ xinerama = X11_XineramaQueryScreens(data->display, &screencount);
+ X11_XSync(data->display, False);
+ X11_XSetErrorHandler(handler);
+ if (xinerama_triggered_error) {
+ xinerama = 0;
+ }
+ if (xinerama) {
+ use_xinerama = xinerama_major * 100 + xinerama_minor;
+ }
+ }
+ if (!xinerama) {
+ screencount = ScreenCount(data->display);
+ }
+#else
+ screencount = ScreenCount(data->display);
+#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
+
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+ if (CheckVidMode(data->display, &vm_major, &vm_minor)) {
+ use_vidmode = vm_major * 100 + vm_minor;
+ }
+#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
+
+ for (snum = 0; snum < screencount; ++snum) {
+ XVisualInfo vinfo;
+ SDL_VideoDisplay display;
+ SDL_DisplayData *displaydata;
+ SDL_DisplayMode mode;
+ SDL_DisplayModeData *modedata;
+ XPixmapFormatValues *pixmapFormats;
+ char display_name[128];
+ int i, n;
+
+ /* Re-order screens to always put default screen first */
+ if (snum == 0) {
+ screen = DefaultScreen(data->display);
+ } else if (snum == DefaultScreen(data->display)) {
+ screen = 0;
+ } else {
+ screen = snum;
+ }
+
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ if (xinerama) {
+ if (get_visualinfo(data->display, 0, &vinfo) < 0) {
+ continue;
+ }
+ } else {
+ if (get_visualinfo(data->display, screen, &vinfo) < 0) {
+ continue;
+ }
+ }
+#else
+ if (get_visualinfo(data->display, screen, &vinfo) < 0) {
+ continue;
+ }
+#endif
+
+ displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata));
+ if (!displaydata) {
+ continue;
+ }
+ display_name[0] = '\0';
+
+ mode.format = X11_GetPixelFormatFromVisualInfo(data->display, &vinfo);
+ if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
+ /* We don't support palettized modes now */
+ SDL_free(displaydata);
+ continue;
+ }
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ if (xinerama) {
+ mode.w = xinerama[screen].width;
+ mode.h = xinerama[screen].height;
+ } else {
+ mode.w = DisplayWidth(data->display, screen);
+ mode.h = DisplayHeight(data->display, screen);
+ }
+#else
+ mode.w = DisplayWidth(data->display, screen);
+ mode.h = DisplayHeight(data->display, screen);
+#endif
+ mode.refresh_rate = 0;
+
+ modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
+ if (!modedata) {
+ SDL_free(displaydata);
+ continue;
+ }
+ mode.driverdata = modedata;
+
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ /* Most of SDL's calls to X11 are unwaware of Xinerama, and to X11 standard calls, when Xinerama is active,
+ * there's only one screen available. So we force the screen number to zero and
+ * let Xinerama specific code handle specific functionality using displaydata->xinerama_info
+ */
+ if (use_xinerama) {
+ displaydata->screen = 0;
+ displaydata->use_xinerama = use_xinerama;
+ displaydata->xinerama_info = xinerama[screen];
+ displaydata->xinerama_screen = screen;
+ }
+ else displaydata->screen = screen;
+#else
+ displaydata->screen = screen;
+#endif
+ displaydata->visual = vinfo.visual;
+ displaydata->depth = vinfo.depth;
+
+ /* We use the displaydata screen index here so that this works
+ for both the Xinerama case, where we get the overall DPI,
+ and the regular X11 screen info case. */
+ displaydata->hdpi = (float)DisplayWidth(data->display, displaydata->screen) * 25.4f /
+ DisplayWidthMM(data->display, displaydata->screen);
+ displaydata->vdpi = (float)DisplayHeight(data->display, displaydata->screen) * 25.4f /
+ DisplayHeightMM(data->display, displaydata->screen);
+ displaydata->ddpi = SDL_ComputeDiagonalDPI(DisplayWidth(data->display, displaydata->screen),
+ DisplayHeight(data->display, displaydata->screen),
+ (float)DisplayWidthMM(data->display, displaydata->screen) / 25.4f,
+ (float)DisplayHeightMM(data->display, displaydata->screen) / 25.4f);
+
+ displaydata->scanline_pad = SDL_BYTESPERPIXEL(mode.format) * 8;
+ pixmapFormats = X11_XListPixmapFormats(data->display, &n);
+ if (pixmapFormats) {
+ for (i = 0; i < n; ++i) {
+ if (pixmapFormats[i].depth == displaydata->depth) {
+ displaydata->scanline_pad = pixmapFormats[i].scanline_pad;
+ break;
+ }
+ }
+ X11_XFree(pixmapFormats);
+ }
+
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ if (use_xinerama) {
+ displaydata->x = xinerama[screen].x_org;
+ displaydata->y = xinerama[screen].y_org;
+ }
+ else
+#endif
+ {
+ displaydata->x = 0;
+ displaydata->y = 0;
+ }
+
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+ if (!displaydata->use_xrandr &&
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ /* XVidMode only works on the screen at the origin */
+ (!displaydata->use_xinerama ||
+ (displaydata->x == 0 && displaydata->y == 0)) &&
+#endif
+ use_vidmode) {
+ displaydata->use_vidmode = use_vidmode;
+ if (displaydata->use_xinerama) {
+ displaydata->vidmode_screen = 0;
+ } else {
+ displaydata->vidmode_screen = screen;
+ }
+ XF86VidModeGetModeInfo(data->display, displaydata->vidmode_screen, &modedata->vm_mode);
+ }
+#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
+
+ SDL_zero(display);
+ if (*display_name) {
+ display.name = display_name;
+ }
+ display.desktop_mode = mode;
+ display.current_mode = mode;
+ display.driverdata = displaydata;
+ SDL_AddVideoDisplay(&display);
+ }
+
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ if (xinerama) X11_XFree(xinerama);
+#endif
+
+ if (_this->num_displays == 0) {
+ return SDL_SetError("No available displays");
+ }
+ return 0;
+}
+
+void
+X11_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display)
+{
+ Display *display = ((SDL_VideoData *) _this->driverdata)->display;
+ SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+ int nmodes;
+ XF86VidModeModeInfo ** modes;
+#endif
+ SDL_DisplayMode mode;
+
+ /* Unfortunately X11 requires the window to be created with the correct
+ * visual and depth ahead of time, but the SDL API allows you to create
+ * a window before setting the fullscreen display mode. This means that
+ * we have to use the same format for all windows and all display modes.
+ * (or support recreating the window with a new visual behind the scenes)
+ */
+ mode.format = sdl_display->current_mode.format;
+ mode.driverdata = NULL;
+
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ if (data->use_xinerama) {
+ int screen_w;
+ int screen_h;
+
+ screen_w = DisplayWidth(display, data->screen);
+ screen_h = DisplayHeight(display, data->screen);
+
+ if (data->use_vidmode && !data->xinerama_info.x_org && !data->xinerama_info.y_org &&
+ (screen_w > data->xinerama_info.width || screen_h > data->xinerama_info.height)) {
+ SDL_DisplayModeData *modedata;
+ /* Add the full (both screens combined) xinerama mode only on the display that starts at 0,0
+ * if we're using vidmode.
+ */
+ mode.w = screen_w;
+ mode.h = screen_h;
+ mode.refresh_rate = 0;
+ modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
+ if (modedata) {
+ *modedata = *(SDL_DisplayModeData *)sdl_display->desktop_mode.driverdata;
+ }
+ mode.driverdata = modedata;
+ if (!SDL_AddDisplayMode(sdl_display, &mode)) {
+ SDL_free(modedata);
+ }
+ }
+ else if (!data->use_xrandr)
+ {
+ SDL_DisplayModeData *modedata;
+ /* Add the current mode of each monitor otherwise if we can't get them from xrandr */
+ mode.w = data->xinerama_info.width;
+ mode.h = data->xinerama_info.height;
+ mode.refresh_rate = 0;
+ modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
+ if (modedata) {
+ *modedata = *(SDL_DisplayModeData *)sdl_display->desktop_mode.driverdata;
+ }
+ mode.driverdata = modedata;
+ if (!SDL_AddDisplayMode(sdl_display, &mode)) {
+ SDL_free(modedata);
+ }
+ }
+
+ }
+#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
+
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+ if (data->use_xrandr) {
+ XRRScreenResources *res;
+
+ res = X11_XRRGetScreenResources (display, RootWindow(display, data->screen));
+ if (res) {
+ SDL_DisplayModeData *modedata;
+ XRROutputInfo *output_info;
+ int i;
+
+ output_info = X11_XRRGetOutputInfo(display, res, data->xrandr_output);
+ if (output_info && output_info->connection != RR_Disconnected) {
+ for (i = 0; i < output_info->nmode; ++i) {
+ modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
+ if (!modedata) {
+ continue;
+ }
+ mode.driverdata = modedata;
+
+ if (!SetXRandRModeInfo(display, res, output_info->crtc, output_info->modes[i], &mode) ||
+ !SDL_AddDisplayMode(sdl_display, &mode)) {
+ SDL_free(modedata);
+ }
+ }
+ }
+ X11_XRRFreeOutputInfo(output_info);
+ X11_XRRFreeScreenResources(res);
+ }
+ return;
+ }
+#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
+
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+ if (data->use_vidmode &&
+ X11_XF86VidModeGetAllModeLines(display, data->vidmode_screen, &nmodes, &modes)) {
+ int i;
+ SDL_DisplayModeData *modedata;
+
+#ifdef X11MODES_DEBUG
+ printf("VidMode modes: (unsorted)\n");
+ for (i = 0; i < nmodes; ++i) {
+ printf("Mode %d: %d x %d @ %d, flags: 0x%x\n", i,
+ modes[i]->hdisplay, modes[i]->vdisplay,
+ CalculateXVidModeRefreshRate(modes[i]), modes[i]->flags);
+ }
+#endif
+ for (i = 0; i < nmodes; ++i) {
+ modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
+ if (!modedata) {
+ continue;
+ }
+ mode.driverdata = modedata;
+
+ if (!SetXVidModeModeInfo(modes[i], &mode) || !SDL_AddDisplayMode(sdl_display, &mode)) {
+ SDL_free(modedata);
+ }
+ }
+ X11_XFree(modes);
+ return;
+ }
+#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
+
+ if (!data->use_xrandr && !data->use_vidmode) {
+ SDL_DisplayModeData *modedata;
+ /* Add the desktop mode */
+ mode = sdl_display->desktop_mode;
+ modedata = (SDL_DisplayModeData *) SDL_calloc(1, sizeof(SDL_DisplayModeData));
+ if (modedata) {
+ *modedata = *(SDL_DisplayModeData *)sdl_display->desktop_mode.driverdata;
+ }
+ mode.driverdata = modedata;
+ if (!SDL_AddDisplayMode(sdl_display, &mode)) {
+ SDL_free(modedata);
+ }
+ }
+}
+
+int
+X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode)
+{
+ SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+ Display *display = viddata->display;
+ SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
+ SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata;
+
+ viddata->last_mode_change_deadline = SDL_GetTicks() + (PENDING_FOCUS_TIME * 2);
+
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+ if (data->use_xrandr) {
+ XRRScreenResources *res;
+ XRROutputInfo *output_info;
+ XRRCrtcInfo *crtc;
+ Status status;
+
+ res = X11_XRRGetScreenResources (display, RootWindow(display, data->screen));
+ if (!res) {
+ return SDL_SetError("Couldn't get XRandR screen resources");
+ }
+
+ output_info = X11_XRRGetOutputInfo(display, res, data->xrandr_output);
+ if (!output_info || output_info->connection == RR_Disconnected) {
+ X11_XRRFreeScreenResources(res);
+ return SDL_SetError("Couldn't get XRandR output info");
+ }
+
+ crtc = X11_XRRGetCrtcInfo(display, res, output_info->crtc);
+ if (!crtc) {
+ X11_XRRFreeOutputInfo(output_info);
+ X11_XRRFreeScreenResources(res);
+ return SDL_SetError("Couldn't get XRandR crtc info");
+ }
+
+ status = X11_XRRSetCrtcConfig (display, res, output_info->crtc, CurrentTime,
+ crtc->x, crtc->y, modedata->xrandr_mode, crtc->rotation,
+ &data->xrandr_output, 1);
+
+ X11_XRRFreeCrtcInfo(crtc);
+ X11_XRRFreeOutputInfo(output_info);
+ X11_XRRFreeScreenResources(res);
+
+ if (status != Success) {
+ return SDL_SetError("X11_XRRSetCrtcConfig failed");
+ }
+ }
+#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
+
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+ if (data->use_vidmode) {
+ X11_XF86VidModeSwitchToMode(display, data->vidmode_screen, &modedata->vm_mode);
+ }
+#endif /* SDL_VIDEO_DRIVER_X11_XVIDMODE */
+
+ return 0;
+}
+
+void
+X11_QuitModes(_THIS)
+{
+}
+
+int
+X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect)
+{
+ SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
+
+ rect->x = data->x;
+ rect->y = data->y;
+ rect->w = sdl_display->current_mode.w;
+ rect->h = sdl_display->current_mode.h;
+
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ /* Get the real current bounds of the display */
+ if (data->use_xinerama) {
+ Display *display = ((SDL_VideoData *) _this->driverdata)->display;
+ int screencount;
+ XineramaScreenInfo *xinerama = X11_XineramaQueryScreens(display, &screencount);
+ if (xinerama) {
+ rect->x = xinerama[data->xinerama_screen].x_org;
+ rect->y = xinerama[data->xinerama_screen].y_org;
+ X11_XFree(xinerama);
+ }
+ }
+#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
+ return 0;
+}
+
+int
+X11_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * hdpi, float * vdpi)
+{
+ SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
+
+ if (ddpi) {
+ *ddpi = data->ddpi;
+ }
+ if (hdpi) {
+ *hdpi = data->hdpi;
+ }
+ if (vdpi) {
+ *vdpi = data->vdpi;
+ }
+
+ return data->ddpi != 0.0f ? 0 : SDL_SetError("Couldn't get DPI");
+}
+
+int
+X11_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ Display *display = data->display;
+ Atom _NET_WORKAREA;
+ int status, real_format;
+ int retval = -1;
+ Atom real_type;
+ unsigned long items_read = 0, items_left = 0;
+ unsigned char *propdata = NULL;
+
+ if (X11_GetDisplayBounds(_this, sdl_display, rect) < 0) {
+ return -1;
+ }
+
+ _NET_WORKAREA = X11_XInternAtom(display, "_NET_WORKAREA", False);
+ status = X11_XGetWindowProperty(display, DefaultRootWindow(display),
+ _NET_WORKAREA, 0L, 4L, False, XA_CARDINAL,
+ &real_type, &real_format, &items_read,
+ &items_left, &propdata);
+ if ((status == Success) && (items_read >= 4)) {
+ const long *p = (long*) propdata;
+ const SDL_Rect usable = { (int)p[0], (int)p[1], (int)p[2], (int)p[3] };
+ retval = 0;
+ if (!SDL_IntersectRect(rect, &usable, rect)) {
+ SDL_zerop(rect);
+ }
+ }
+
+ if (propdata) {
+ X11_XFree(propdata);
+ }
+
+ return retval;
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11modes.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11modes.h
new file mode 100644
index 0000000..7d3ff3e
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11modes.h
@@ -0,0 +1,85 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11modes_h_
+#define SDL_x11modes_h_
+
+typedef struct
+{
+ int screen;
+ Visual *visual;
+ int depth;
+ int scanline_pad;
+ int x;
+ int y;
+ float ddpi;
+ float hdpi;
+ float vdpi;
+
+ int use_xinerama;
+ int use_xrandr;
+ int use_vidmode;
+
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+ XineramaScreenInfo xinerama_info;
+ int xinerama_screen;
+#endif
+
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+ RROutput xrandr_output;
+#endif
+
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+ int vidmode_screen;
+#endif
+
+} SDL_DisplayData;
+
+typedef struct
+{
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+ RRMode xrandr_mode;
+#endif
+
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+ XF86VidModeModeInfo vm_mode;
+#endif
+
+} SDL_DisplayModeData;
+
+extern int X11_InitModes(_THIS);
+extern void X11_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
+extern int X11_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
+extern void X11_QuitModes(_THIS);
+
+/* Some utility functions for working with visuals */
+extern int X11_GetVisualInfoFromVisual(Display * display, Visual * visual,
+ XVisualInfo * vinfo);
+extern Uint32 X11_GetPixelFormatFromVisualInfo(Display * display,
+ XVisualInfo * vinfo);
+extern int X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect);
+extern int X11_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect);
+extern int X11_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * hdpi, float * vdpi);
+
+#endif /* SDL_x11modes_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11mouse.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11mouse.c
new file mode 100644
index 0000000..3b98726
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11mouse.c
@@ -0,0 +1,448 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include <X11/cursorfont.h>
+#include "SDL_assert.h"
+#include "SDL_x11video.h"
+#include "SDL_x11mouse.h"
+#include "SDL_x11xinput2.h"
+#include "../../events/SDL_mouse_c.h"
+
+
+/* FIXME: Find a better place to put this... */
+static Cursor x11_empty_cursor = None;
+
+static Display *
+GetDisplay(void)
+{
+ return ((SDL_VideoData *)SDL_GetVideoDevice()->driverdata)->display;
+}
+
+static Cursor
+X11_CreateEmptyCursor()
+{
+ if (x11_empty_cursor == None) {
+ Display *display = GetDisplay();
+ char data[1];
+ XColor color;
+ Pixmap pixmap;
+
+ SDL_zero(data);
+ color.red = color.green = color.blue = 0;
+ pixmap = X11_XCreateBitmapFromData(display, DefaultRootWindow(display),
+ data, 1, 1);
+ if (pixmap) {
+ x11_empty_cursor = X11_XCreatePixmapCursor(display, pixmap, pixmap,
+ &color, &color, 0, 0);
+ X11_XFreePixmap(display, pixmap);
+ }
+ }
+ return x11_empty_cursor;
+}
+
+static void
+X11_DestroyEmptyCursor(void)
+{
+ if (x11_empty_cursor != None) {
+ X11_XFreeCursor(GetDisplay(), x11_empty_cursor);
+ x11_empty_cursor = None;
+ }
+}
+
+static SDL_Cursor *
+X11_CreateDefaultCursor()
+{
+ SDL_Cursor *cursor;
+
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (cursor) {
+ /* None is used to indicate the default cursor */
+ cursor->driverdata = (void*)None;
+ } else {
+ SDL_OutOfMemory();
+ }
+
+ return cursor;
+}
+
+#if SDL_VIDEO_DRIVER_X11_XCURSOR
+static Cursor
+X11_CreateXCursorCursor(SDL_Surface * surface, int hot_x, int hot_y)
+{
+ Display *display = GetDisplay();
+ Cursor cursor = None;
+ XcursorImage *image;
+
+ image = X11_XcursorImageCreate(surface->w, surface->h);
+ if (!image) {
+ SDL_OutOfMemory();
+ return None;
+ }
+ image->xhot = hot_x;
+ image->yhot = hot_y;
+ image->delay = 0;
+
+ SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
+ SDL_assert(surface->pitch == surface->w * 4);
+ SDL_memcpy(image->pixels, surface->pixels, surface->h * surface->pitch);
+
+ cursor = X11_XcursorImageLoadCursor(display, image);
+
+ X11_XcursorImageDestroy(image);
+
+ return cursor;
+}
+#endif /* SDL_VIDEO_DRIVER_X11_XCURSOR */
+
+static Cursor
+X11_CreatePixmapCursor(SDL_Surface * surface, int hot_x, int hot_y)
+{
+ Display *display = GetDisplay();
+ XColor fg, bg;
+ Cursor cursor = None;
+ Uint32 *ptr;
+ Uint8 *data_bits, *mask_bits;
+ Pixmap data_pixmap, mask_pixmap;
+ int x, y;
+ unsigned int rfg, gfg, bfg, rbg, gbg, bbg, fgBits, bgBits;
+ unsigned int width_bytes = ((surface->w + 7) & ~7) / 8;
+
+ data_bits = SDL_calloc(1, surface->h * width_bytes);
+ if (!data_bits) {
+ SDL_OutOfMemory();
+ return None;
+ }
+
+ mask_bits = SDL_calloc(1, surface->h * width_bytes);
+ if (!mask_bits) {
+ SDL_free(data_bits);
+ SDL_OutOfMemory();
+ return None;
+ }
+
+ /* Code below assumes ARGB pixel format */
+ SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
+
+ rfg = gfg = bfg = rbg = gbg = bbg = fgBits = bgBits = 0;
+ for (y = 0; y < surface->h; ++y) {
+ ptr = (Uint32 *)((Uint8 *)surface->pixels + y * surface->pitch);
+ for (x = 0; x < surface->w; ++x) {
+ int alpha = (*ptr >> 24) & 0xff;
+ int red = (*ptr >> 16) & 0xff;
+ int green = (*ptr >> 8) & 0xff;
+ int blue = (*ptr >> 0) & 0xff;
+ if (alpha > 25) {
+ mask_bits[y * width_bytes + x / 8] |= (0x01 << (x % 8));
+
+ if ((red + green + blue) > 0x40) {
+ fgBits++;
+ rfg += red;
+ gfg += green;
+ bfg += blue;
+ data_bits[y * width_bytes + x / 8] |= (0x01 << (x % 8));
+ } else {
+ bgBits++;
+ rbg += red;
+ gbg += green;
+ bbg += blue;
+ }
+ }
+ ++ptr;
+ }
+ }
+
+ if (fgBits) {
+ fg.red = rfg * 257 / fgBits;
+ fg.green = gfg * 257 / fgBits;
+ fg.blue = bfg * 257 / fgBits;
+ }
+ else fg.red = fg.green = fg.blue = 0;
+
+ if (bgBits) {
+ bg.red = rbg * 257 / bgBits;
+ bg.green = gbg * 257 / bgBits;
+ bg.blue = bbg * 257 / bgBits;
+ }
+ else bg.red = bg.green = bg.blue = 0;
+
+ data_pixmap = X11_XCreateBitmapFromData(display, DefaultRootWindow(display),
+ (char*)data_bits,
+ surface->w, surface->h);
+ mask_pixmap = X11_XCreateBitmapFromData(display, DefaultRootWindow(display),
+ (char*)mask_bits,
+ surface->w, surface->h);
+ cursor = X11_XCreatePixmapCursor(display, data_pixmap, mask_pixmap,
+ &fg, &bg, hot_x, hot_y);
+ X11_XFreePixmap(display, data_pixmap);
+ X11_XFreePixmap(display, mask_pixmap);
+
+ return cursor;
+}
+
+static SDL_Cursor *
+X11_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
+{
+ SDL_Cursor *cursor;
+
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (cursor) {
+ Cursor x11_cursor = None;
+
+#if SDL_VIDEO_DRIVER_X11_XCURSOR
+ if (SDL_X11_HAVE_XCURSOR) {
+ x11_cursor = X11_CreateXCursorCursor(surface, hot_x, hot_y);
+ }
+#endif
+ if (x11_cursor == None) {
+ x11_cursor = X11_CreatePixmapCursor(surface, hot_x, hot_y);
+ }
+ cursor->driverdata = (void*)x11_cursor;
+ } else {
+ SDL_OutOfMemory();
+ }
+
+ return cursor;
+}
+
+static SDL_Cursor *
+X11_CreateSystemCursor(SDL_SystemCursor id)
+{
+ SDL_Cursor *cursor;
+ unsigned int shape;
+
+ switch(id)
+ {
+ default:
+ SDL_assert(0);
+ return NULL;
+ /* X Font Cursors reference: */
+ /* http://tronche.com/gui/x/xlib/appendix/b/ */
+ case SDL_SYSTEM_CURSOR_ARROW: shape = XC_left_ptr; break;
+ case SDL_SYSTEM_CURSOR_IBEAM: shape = XC_xterm; break;
+ case SDL_SYSTEM_CURSOR_WAIT: shape = XC_watch; break;
+ case SDL_SYSTEM_CURSOR_CROSSHAIR: shape = XC_tcross; break;
+ case SDL_SYSTEM_CURSOR_WAITARROW: shape = XC_watch; break;
+ case SDL_SYSTEM_CURSOR_SIZENWSE: shape = XC_fleur; break;
+ case SDL_SYSTEM_CURSOR_SIZENESW: shape = XC_fleur; break;
+ case SDL_SYSTEM_CURSOR_SIZEWE: shape = XC_sb_h_double_arrow; break;
+ case SDL_SYSTEM_CURSOR_SIZENS: shape = XC_sb_v_double_arrow; break;
+ case SDL_SYSTEM_CURSOR_SIZEALL: shape = XC_fleur; break;
+ case SDL_SYSTEM_CURSOR_NO: shape = XC_pirate; break;
+ case SDL_SYSTEM_CURSOR_HAND: shape = XC_hand2; break;
+ }
+
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (cursor) {
+ Cursor x11_cursor;
+
+ x11_cursor = X11_XCreateFontCursor(GetDisplay(), shape);
+
+ cursor->driverdata = (void*)x11_cursor;
+ } else {
+ SDL_OutOfMemory();
+ }
+
+ return cursor;
+}
+
+static void
+X11_FreeCursor(SDL_Cursor * cursor)
+{
+ Cursor x11_cursor = (Cursor)cursor->driverdata;
+
+ if (x11_cursor != None) {
+ X11_XFreeCursor(GetDisplay(), x11_cursor);
+ }
+ SDL_free(cursor);
+}
+
+static int
+X11_ShowCursor(SDL_Cursor * cursor)
+{
+ Cursor x11_cursor = 0;
+
+ if (cursor) {
+ x11_cursor = (Cursor)cursor->driverdata;
+ } else {
+ x11_cursor = X11_CreateEmptyCursor();
+ }
+
+ /* FIXME: Is there a better way than this? */
+ {
+ SDL_VideoDevice *video = SDL_GetVideoDevice();
+ Display *display = GetDisplay();
+ SDL_Window *window;
+ SDL_WindowData *data;
+
+ for (window = video->windows; window; window = window->next) {
+ data = (SDL_WindowData *)window->driverdata;
+ if (x11_cursor != None) {
+ X11_XDefineCursor(display, data->xwindow, x11_cursor);
+ } else {
+ X11_XUndefineCursor(display, data->xwindow);
+ }
+ }
+ X11_XFlush(display);
+ }
+ return 0;
+}
+
+static void
+WarpMouseInternal(Window xwindow, const int x, const int y)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) SDL_GetVideoDevice()->driverdata;
+ Display *display = videodata->display;
+ X11_XWarpPointer(display, None, xwindow, 0, 0, 0, 0, x, y);
+ X11_XSync(display, False);
+ videodata->global_mouse_changed = SDL_TRUE;
+}
+
+static void
+X11_WarpMouse(SDL_Window * window, int x, int y)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ WarpMouseInternal(data->xwindow, x, y);
+}
+
+static int
+X11_WarpMouseGlobal(int x, int y)
+{
+ WarpMouseInternal(DefaultRootWindow(GetDisplay()), x, y);
+ return 0;
+}
+
+static int
+X11_SetRelativeMouseMode(SDL_bool enabled)
+{
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+ if(X11_Xinput2IsInitialized())
+ return 0;
+#else
+ SDL_Unsupported();
+#endif
+ return -1;
+}
+
+static int
+X11_CaptureMouse(SDL_Window *window)
+{
+ Display *display = GetDisplay();
+
+ if (window) {
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ const unsigned int mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask;
+ const int rc = X11_XGrabPointer(display, data->xwindow, False,
+ mask, GrabModeAsync, GrabModeAsync,
+ None, None, CurrentTime);
+ if (rc != GrabSuccess) {
+ return SDL_SetError("X server refused mouse capture");
+ }
+ } else {
+ X11_XUngrabPointer(display, CurrentTime);
+ }
+
+ X11_XSync(display, False);
+
+ return 0;
+}
+
+static Uint32
+X11_GetGlobalMouseState(int *x, int *y)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) SDL_GetVideoDevice()->driverdata;
+ Display *display = GetDisplay();
+ const int num_screens = SDL_GetNumVideoDisplays();
+ int i;
+
+ /* !!! FIXME: should we XSync() here first? */
+
+#if !SDL_VIDEO_DRIVER_X11_XINPUT2
+ videodata->global_mouse_changed = SDL_TRUE;
+#endif
+
+ /* check if we have this cached since XInput last saw the mouse move. */
+ /* !!! FIXME: can we just calculate this from XInput's events? */
+ if (videodata->global_mouse_changed) {
+ for (i = 0; i < num_screens; i++) {
+ SDL_DisplayData *data = (SDL_DisplayData *) SDL_GetDisplayDriverData(i);
+ if (data != NULL) {
+ Window root, child;
+ int rootx, rooty, winx, winy;
+ unsigned int mask;
+ if (X11_XQueryPointer(display, RootWindow(display, data->screen), &root, &child, &rootx, &rooty, &winx, &winy, &mask)) {
+ XWindowAttributes root_attrs;
+ Uint32 buttons = 0;
+ buttons |= (mask & Button1Mask) ? SDL_BUTTON_LMASK : 0;
+ buttons |= (mask & Button2Mask) ? SDL_BUTTON_MMASK : 0;
+ buttons |= (mask & Button3Mask) ? SDL_BUTTON_RMASK : 0;
+ /* SDL_DisplayData->x,y point to screen origin, and adding them to mouse coordinates relative to root window doesn't do the right thing
+ * (observed on dual monitor setup with primary display being the rightmost one - mouse was offset to the right).
+ *
+ * Adding root position to root-relative coordinates seems to be a better way to get absolute position. */
+ X11_XGetWindowAttributes(display, root, &root_attrs);
+ videodata->global_mouse_position.x = root_attrs.x + rootx;
+ videodata->global_mouse_position.y = root_attrs.y + rooty;
+ videodata->global_mouse_buttons = buttons;
+ videodata->global_mouse_changed = SDL_FALSE;
+ break;
+ }
+ }
+ }
+ }
+
+ SDL_assert(!videodata->global_mouse_changed); /* The pointer wasn't on any X11 screen?! */
+
+ *x = videodata->global_mouse_position.x;
+ *y = videodata->global_mouse_position.y;
+ return videodata->global_mouse_buttons;
+}
+
+
+void
+X11_InitMouse(_THIS)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+
+ mouse->CreateCursor = X11_CreateCursor;
+ mouse->CreateSystemCursor = X11_CreateSystemCursor;
+ mouse->ShowCursor = X11_ShowCursor;
+ mouse->FreeCursor = X11_FreeCursor;
+ mouse->WarpMouse = X11_WarpMouse;
+ mouse->WarpMouseGlobal = X11_WarpMouseGlobal;
+ mouse->SetRelativeMouseMode = X11_SetRelativeMouseMode;
+ mouse->CaptureMouse = X11_CaptureMouse;
+ mouse->GetGlobalMouseState = X11_GetGlobalMouseState;
+
+ SDL_SetDefaultCursor(X11_CreateDefaultCursor());
+}
+
+void
+X11_QuitMouse(_THIS)
+{
+ X11_DestroyEmptyCursor();
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11mouse.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11mouse.h
new file mode 100644
index 0000000..1041858
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11mouse.h
@@ -0,0 +1,31 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11mouse_h_
+#define SDL_x11mouse_h_
+
+extern void X11_InitMouse(_THIS);
+extern void X11_QuitMouse(_THIS);
+
+#endif /* SDL_x11mouse_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11opengl.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11opengl.c
new file mode 100644
index 0000000..7c3cb33
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11opengl.c
@@ -0,0 +1,946 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL_x11video.h"
+#include "SDL_assert.h"
+#include "SDL_hints.h"
+
+/* GLX implementation of SDL OpenGL support */
+
+#if SDL_VIDEO_OPENGL_GLX
+#include "SDL_loadso.h"
+#include "SDL_x11opengles.h"
+
+#if defined(__IRIX__)
+/* IRIX doesn't have a GL library versioning system */
+#define DEFAULT_OPENGL "libGL.so"
+#elif defined(__MACOSX__)
+#define DEFAULT_OPENGL "/usr/X11R6/lib/libGL.1.dylib"
+#elif defined(__QNXNTO__)
+#define DEFAULT_OPENGL "libGL.so.3"
+#else
+#define DEFAULT_OPENGL "libGL.so.1"
+#endif
+
+#ifndef GLX_NONE_EXT
+#define GLX_NONE_EXT 0x8000
+#endif
+
+#ifndef GLX_ARB_multisample
+#define GLX_ARB_multisample
+#define GLX_SAMPLE_BUFFERS_ARB 100000
+#define GLX_SAMPLES_ARB 100001
+#endif
+
+#ifndef GLX_EXT_visual_rating
+#define GLX_EXT_visual_rating
+#define GLX_VISUAL_CAVEAT_EXT 0x20
+#define GLX_NONE_EXT 0x8000
+#define GLX_SLOW_VISUAL_EXT 0x8001
+#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
+#endif
+
+#ifndef GLX_EXT_visual_info
+#define GLX_EXT_visual_info
+#define GLX_X_VISUAL_TYPE_EXT 0x22
+#define GLX_DIRECT_COLOR_EXT 0x8003
+#endif
+
+#ifndef GLX_ARB_create_context
+#define GLX_ARB_create_context
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+
+/* Typedef for the GL 3.0 context creation function */
+typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy,
+ GLXFBConfig config,
+ GLXContext
+ share_context,
+ Bool direct,
+ const int
+ *attrib_list);
+#endif
+
+#ifndef GLX_ARB_create_context_profile
+#define GLX_ARB_create_context_profile
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#endif
+
+#ifndef GLX_ARB_create_context_robustness
+#define GLX_ARB_create_context_robustness
+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
+#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#endif
+
+#ifndef GLX_EXT_create_context_es2_profile
+#define GLX_EXT_create_context_es2_profile
+#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000002
+#endif
+#endif
+
+#ifndef GLX_ARB_framebuffer_sRGB
+#define GLX_ARB_framebuffer_sRGB
+#ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
+#endif
+#endif
+
+#ifndef GLX_ARB_create_context_no_error
+#define GLX_ARB_create_context_no_error
+#ifndef GLX_CONTEXT_OPENGL_NO_ERROR_ARB
+#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
+#endif
+#endif
+
+#ifndef GLX_EXT_swap_control
+#define GLX_SWAP_INTERVAL_EXT 0x20F1
+#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+#endif
+
+#ifndef GLX_EXT_swap_control_tear
+#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
+#endif
+
+#ifndef GLX_ARB_context_flush_control
+#define GLX_ARB_context_flush_control
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#endif
+
+#define OPENGL_REQUIRES_DLOPEN
+#if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
+#include <dlfcn.h>
+#define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
+#define GL_LoadFunction dlsym
+#define GL_UnloadObject dlclose
+#else
+#define GL_LoadObject SDL_LoadObject
+#define GL_LoadFunction SDL_LoadFunction
+#define GL_UnloadObject SDL_UnloadObject
+#endif
+
+static void X11_GL_InitExtensions(_THIS);
+
+int
+X11_GL_LoadLibrary(_THIS, const char *path)
+{
+ Display *display;
+ void *handle;
+
+ if (_this->gl_data) {
+ return SDL_SetError("OpenGL context already created");
+ }
+
+ /* Load the OpenGL library */
+ if (path == NULL) {
+ path = SDL_getenv("SDL_OPENGL_LIBRARY");
+ }
+ if (path == NULL) {
+ path = DEFAULT_OPENGL;
+ }
+ _this->gl_config.dll_handle = GL_LoadObject(path);
+ if (!_this->gl_config.dll_handle) {
+#if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
+ SDL_SetError("Failed loading %s: %s", path, dlerror());
+#endif
+ return -1;
+ }
+ SDL_strlcpy(_this->gl_config.driver_path, path,
+ SDL_arraysize(_this->gl_config.driver_path));
+
+ /* Allocate OpenGL memory */
+ _this->gl_data =
+ (struct SDL_GLDriverData *) SDL_calloc(1,
+ sizeof(struct
+ SDL_GLDriverData));
+ if (!_this->gl_data) {
+ return SDL_OutOfMemory();
+ }
+
+ /* Load function pointers */
+ handle = _this->gl_config.dll_handle;
+ _this->gl_data->glXQueryExtension =
+ (Bool (*)(Display *, int *, int *))
+ GL_LoadFunction(handle, "glXQueryExtension");
+ _this->gl_data->glXGetProcAddress =
+ (void *(*)(const GLubyte *))
+ GL_LoadFunction(handle, "glXGetProcAddressARB");
+ _this->gl_data->glXChooseVisual =
+ (XVisualInfo * (*)(Display *, int, int *))
+ X11_GL_GetProcAddress(_this, "glXChooseVisual");
+ _this->gl_data->glXCreateContext =
+ (GLXContext(*)(Display *, XVisualInfo *, GLXContext, int))
+ X11_GL_GetProcAddress(_this, "glXCreateContext");
+ _this->gl_data->glXDestroyContext =
+ (void (*)(Display *, GLXContext))
+ X11_GL_GetProcAddress(_this, "glXDestroyContext");
+ _this->gl_data->glXMakeCurrent =
+ (int (*)(Display *, GLXDrawable, GLXContext))
+ X11_GL_GetProcAddress(_this, "glXMakeCurrent");
+ _this->gl_data->glXSwapBuffers =
+ (void (*)(Display *, GLXDrawable))
+ X11_GL_GetProcAddress(_this, "glXSwapBuffers");
+ _this->gl_data->glXQueryDrawable =
+ (void (*)(Display*,GLXDrawable,int,unsigned int*))
+ X11_GL_GetProcAddress(_this, "glXQueryDrawable");
+
+ if (!_this->gl_data->glXQueryExtension ||
+ !_this->gl_data->glXChooseVisual ||
+ !_this->gl_data->glXCreateContext ||
+ !_this->gl_data->glXDestroyContext ||
+ !_this->gl_data->glXMakeCurrent ||
+ !_this->gl_data->glXSwapBuffers) {
+ return SDL_SetError("Could not retrieve OpenGL functions");
+ }
+
+ display = ((SDL_VideoData *) _this->driverdata)->display;
+ if (!_this->gl_data->glXQueryExtension(display, &_this->gl_data->errorBase, &_this->gl_data->eventBase)) {
+ return SDL_SetError("GLX is not supported");
+ }
+
+ /* Initialize extensions */
+ /* See lengthy comment about the inc/dec in
+ ../windows/SDL_windowsopengl.c. */
+ ++_this->gl_config.driver_loaded;
+ X11_GL_InitExtensions(_this);
+ --_this->gl_config.driver_loaded;
+
+ /* If we need a GL ES context and there's no
+ * GLX_EXT_create_context_es2_profile extension, switch over to X11_GLES functions
+ */
+ if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES &&
+ X11_GL_UseEGL(_this) ) {
+#if SDL_VIDEO_OPENGL_EGL
+ X11_GL_UnloadLibrary(_this);
+ /* Better avoid conflicts! */
+ if (_this->gl_config.dll_handle != NULL ) {
+ GL_UnloadObject(_this->gl_config.dll_handle);
+ _this->gl_config.dll_handle = NULL;
+ }
+ _this->GL_LoadLibrary = X11_GLES_LoadLibrary;
+ _this->GL_GetProcAddress = X11_GLES_GetProcAddress;
+ _this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
+ _this->GL_CreateContext = X11_GLES_CreateContext;
+ _this->GL_MakeCurrent = X11_GLES_MakeCurrent;
+ _this->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
+ _this->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
+ _this->GL_SwapWindow = X11_GLES_SwapWindow;
+ _this->GL_DeleteContext = X11_GLES_DeleteContext;
+ return X11_GLES_LoadLibrary(_this, NULL);
+#else
+ return SDL_SetError("SDL not configured with EGL support");
+#endif
+ }
+
+ return 0;
+}
+
+void *
+X11_GL_GetProcAddress(_THIS, const char *proc)
+{
+ if (_this->gl_data->glXGetProcAddress) {
+ return _this->gl_data->glXGetProcAddress((const GLubyte *) proc);
+ }
+ return GL_LoadFunction(_this->gl_config.dll_handle, proc);
+}
+
+void
+X11_GL_UnloadLibrary(_THIS)
+{
+ /* Don't actually unload the library, since it may have registered
+ * X11 shutdown hooks, per the notes at:
+ * http://dri.sourceforge.net/doc/DRIuserguide.html
+ */
+#if 0
+ GL_UnloadObject(_this->gl_config.dll_handle);
+ _this->gl_config.dll_handle = NULL;
+#endif
+
+ /* Free OpenGL memory */
+ SDL_free(_this->gl_data);
+ _this->gl_data = NULL;
+}
+
+static SDL_bool
+HasExtension(const char *extension, const char *extensions)
+{
+ const char *start;
+ const char *where, *terminator;
+
+ if (!extensions)
+ return SDL_FALSE;
+
+ /* Extension names should not have spaces. */
+ where = SDL_strchr(extension, ' ');
+ if (where || *extension == '\0')
+ return SDL_FALSE;
+
+ /* It takes a bit of care to be fool-proof about parsing the
+ * OpenGL extensions string. Don't be fooled by sub-strings,
+ * etc. */
+
+ start = extensions;
+
+ for (;;) {
+ where = SDL_strstr(start, extension);
+ if (!where)
+ break;
+
+ terminator = where + SDL_strlen(extension);
+ if (where == start || *(where - 1) == ' ')
+ if (*terminator == ' ' || *terminator == '\0')
+ return SDL_TRUE;
+
+ start = terminator;
+ }
+ return SDL_FALSE;
+}
+
+static void
+X11_GL_InitExtensions(_THIS)
+{
+ Display *display = ((SDL_VideoData *) _this->driverdata)->display;
+ const int screen = DefaultScreen(display);
+ XVisualInfo *vinfo = NULL;
+ Window w = 0;
+ GLXContext prev_ctx = 0;
+ GLXDrawable prev_drawable = 0;
+ GLXContext context = 0;
+ const char *(*glXQueryExtensionsStringFunc) (Display *, int);
+ const char *extensions;
+
+ vinfo = X11_GL_GetVisual(_this, display, screen);
+ if (vinfo) {
+ GLXContext (*glXGetCurrentContextFunc) (void) =
+ (GLXContext(*)(void))
+ X11_GL_GetProcAddress(_this, "glXGetCurrentContext");
+
+ GLXDrawable (*glXGetCurrentDrawableFunc) (void) =
+ (GLXDrawable(*)(void))
+ X11_GL_GetProcAddress(_this, "glXGetCurrentDrawable");
+
+ if (glXGetCurrentContextFunc && glXGetCurrentDrawableFunc) {
+ XSetWindowAttributes xattr;
+ prev_ctx = glXGetCurrentContextFunc();
+ prev_drawable = glXGetCurrentDrawableFunc();
+
+ xattr.background_pixel = 0;
+ xattr.border_pixel = 0;
+ xattr.colormap =
+ X11_XCreateColormap(display, RootWindow(display, screen),
+ vinfo->visual, AllocNone);
+ w = X11_XCreateWindow(display, RootWindow(display, screen), 0, 0,
+ 32, 32, 0, vinfo->depth, InputOutput, vinfo->visual,
+ (CWBackPixel | CWBorderPixel | CWColormap), &xattr);
+
+ context = _this->gl_data->glXCreateContext(display, vinfo,
+ NULL, True);
+ if (context) {
+ _this->gl_data->glXMakeCurrent(display, w, context);
+ }
+ }
+
+ X11_XFree(vinfo);
+ }
+
+ glXQueryExtensionsStringFunc =
+ (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
+ "glXQueryExtensionsString");
+ if (glXQueryExtensionsStringFunc) {
+ extensions = glXQueryExtensionsStringFunc(display, screen);
+ } else {
+ extensions = NULL;
+ }
+
+ /* Check for GLX_EXT_swap_control(_tear) */
+ _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_FALSE;
+ if (HasExtension("GLX_EXT_swap_control", extensions)) {
+ _this->gl_data->glXSwapIntervalEXT =
+ (void (*)(Display*,GLXDrawable,int))
+ X11_GL_GetProcAddress(_this, "glXSwapIntervalEXT");
+ if (HasExtension("GLX_EXT_swap_control_tear", extensions)) {
+ _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_TRUE;
+ }
+ }
+
+ /* Check for GLX_MESA_swap_control */
+ if (HasExtension("GLX_MESA_swap_control", extensions)) {
+ _this->gl_data->glXSwapIntervalMESA =
+ (int(*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalMESA");
+ _this->gl_data->glXGetSwapIntervalMESA =
+ (int(*)(void)) X11_GL_GetProcAddress(_this,
+ "glXGetSwapIntervalMESA");
+ }
+
+ /* Check for GLX_SGI_swap_control */
+ if (HasExtension("GLX_SGI_swap_control", extensions)) {
+ _this->gl_data->glXSwapIntervalSGI =
+ (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
+ }
+
+ /* Check for GLX_ARB_create_context */
+ if (HasExtension("GLX_ARB_create_context", extensions)) {
+ _this->gl_data->glXCreateContextAttribsARB =
+ (GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,const int *))
+ X11_GL_GetProcAddress(_this, "glXCreateContextAttribsARB");
+ _this->gl_data->glXChooseFBConfig =
+ (GLXFBConfig *(*)(Display *, int, const int *, int *))
+ X11_GL_GetProcAddress(_this, "glXChooseFBConfig");
+ }
+
+ /* Check for GLX_EXT_visual_rating */
+ if (HasExtension("GLX_EXT_visual_rating", extensions)) {
+ _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
+ }
+
+ /* Check for GLX_EXT_visual_info */
+ if (HasExtension("GLX_EXT_visual_info", extensions)) {
+ _this->gl_data->HAS_GLX_EXT_visual_info = SDL_TRUE;
+ }
+
+ /* Check for GLX_EXT_create_context_es2_profile */
+ if (HasExtension("GLX_EXT_create_context_es2_profile", extensions)) {
+ /* this wants to call glGetString(), so it needs a context. */
+ /* !!! FIXME: it would be nice not to make a context here though! */
+ if (context) {
+ SDL_GL_DeduceMaxSupportedESProfile(
+ &_this->gl_data->es_profile_max_supported_version.major,
+ &_this->gl_data->es_profile_max_supported_version.minor
+ );
+ }
+ }
+
+ /* Check for GLX_ARB_context_flush_control */
+ if (HasExtension("GLX_ARB_context_flush_control", extensions)) {
+ _this->gl_data->HAS_GLX_ARB_context_flush_control = SDL_TRUE;
+ }
+
+ /* Check for GLX_ARB_create_context_robustness */
+ if (HasExtension("GLX_ARB_create_context_robustness", extensions)) {
+ _this->gl_data->HAS_GLX_ARB_create_context_robustness = SDL_TRUE;
+ }
+
+ /* Check for GLX_ARB_create_context_no_error */
+ if (HasExtension("GLX_ARB_create_context_no_error", extensions)) {
+ _this->gl_data->HAS_GLX_ARB_create_context_no_error = SDL_TRUE;
+ }
+
+ if (context) {
+ _this->gl_data->glXMakeCurrent(display, None, NULL);
+ _this->gl_data->glXDestroyContext(display, context);
+ if (prev_ctx && prev_drawable) {
+ _this->gl_data->glXMakeCurrent(display, prev_drawable, prev_ctx);
+ }
+ }
+
+ if (w) {
+ X11_XDestroyWindow(display, w);
+ }
+ X11_PumpEvents(_this);
+}
+
+/* glXChooseVisual and glXChooseFBConfig have some small differences in
+ * the attribute encoding, it can be chosen with the for_FBConfig parameter.
+ * Some targets fail if you use GLX_X_VISUAL_TYPE_EXT/GLX_DIRECT_COLOR_EXT,
+ * so it gets specified last if used and is pointed to by *_pvistypeattr.
+ * In case of failure, if that pointer is not NULL, set that pointer to None
+ * and try again.
+ */
+static int
+X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig, int **_pvistypeattr)
+{
+ int i = 0;
+ const int MAX_ATTRIBUTES = 64;
+ int *pvistypeattr = NULL;
+
+ /* assert buffer is large enough to hold all SDL attributes. */
+ SDL_assert(size >= MAX_ATTRIBUTES);
+
+ /* Setup our GLX attributes according to the gl_config. */
+ if( for_FBConfig ) {
+ attribs[i++] = GLX_RENDER_TYPE;
+ attribs[i++] = GLX_RGBA_BIT;
+ } else {
+ attribs[i++] = GLX_RGBA;
+ }
+ attribs[i++] = GLX_RED_SIZE;
+ attribs[i++] = _this->gl_config.red_size;
+ attribs[i++] = GLX_GREEN_SIZE;
+ attribs[i++] = _this->gl_config.green_size;
+ attribs[i++] = GLX_BLUE_SIZE;
+ attribs[i++] = _this->gl_config.blue_size;
+
+ if (_this->gl_config.alpha_size) {
+ attribs[i++] = GLX_ALPHA_SIZE;
+ attribs[i++] = _this->gl_config.alpha_size;
+ }
+
+ if (_this->gl_config.double_buffer) {
+ attribs[i++] = GLX_DOUBLEBUFFER;
+ if( for_FBConfig ) {
+ attribs[i++] = True;
+ }
+ }
+
+ attribs[i++] = GLX_DEPTH_SIZE;
+ attribs[i++] = _this->gl_config.depth_size;
+
+ if (_this->gl_config.stencil_size) {
+ attribs[i++] = GLX_STENCIL_SIZE;
+ attribs[i++] = _this->gl_config.stencil_size;
+ }
+
+ if (_this->gl_config.accum_red_size) {
+ attribs[i++] = GLX_ACCUM_RED_SIZE;
+ attribs[i++] = _this->gl_config.accum_red_size;
+ }
+
+ if (_this->gl_config.accum_green_size) {
+ attribs[i++] = GLX_ACCUM_GREEN_SIZE;
+ attribs[i++] = _this->gl_config.accum_green_size;
+ }
+
+ if (_this->gl_config.accum_blue_size) {
+ attribs[i++] = GLX_ACCUM_BLUE_SIZE;
+ attribs[i++] = _this->gl_config.accum_blue_size;
+ }
+
+ if (_this->gl_config.accum_alpha_size) {
+ attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
+ attribs[i++] = _this->gl_config.accum_alpha_size;
+ }
+
+ if (_this->gl_config.stereo) {
+ attribs[i++] = GLX_STEREO;
+ if( for_FBConfig ) {
+ attribs[i++] = True;
+ }
+ }
+
+ if (_this->gl_config.multisamplebuffers) {
+ attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
+ attribs[i++] = _this->gl_config.multisamplebuffers;
+ }
+
+ if (_this->gl_config.multisamplesamples) {
+ attribs[i++] = GLX_SAMPLES_ARB;
+ attribs[i++] = _this->gl_config.multisamplesamples;
+ }
+
+ if (_this->gl_config.framebuffer_srgb_capable) {
+ attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
+ attribs[i++] = True; /* always needed, for_FBConfig or not! */
+ }
+
+ if (_this->gl_config.accelerated >= 0 &&
+ _this->gl_data->HAS_GLX_EXT_visual_rating) {
+ attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
+ attribs[i++] = _this->gl_config.accelerated ? GLX_NONE_EXT :
+ GLX_SLOW_VISUAL_EXT;
+ }
+
+ /* If we're supposed to use DirectColor visuals, and we've got the
+ EXT_visual_info extension, then add GLX_X_VISUAL_TYPE_EXT. */
+ if (X11_UseDirectColorVisuals() &&
+ _this->gl_data->HAS_GLX_EXT_visual_info) {
+ pvistypeattr = &attribs[i];
+ attribs[i++] = GLX_X_VISUAL_TYPE_EXT;
+ attribs[i++] = GLX_DIRECT_COLOR_EXT;
+ }
+
+ attribs[i++] = None;
+
+ SDL_assert(i <= MAX_ATTRIBUTES);
+
+ if (_pvistypeattr) {
+ *_pvistypeattr = pvistypeattr;
+ }
+
+ return i;
+}
+
+XVisualInfo *
+X11_GL_GetVisual(_THIS, Display * display, int screen)
+{
+ /* 64 seems nice. */
+ int attribs[64];
+ XVisualInfo *vinfo;
+ int *pvistypeattr = NULL;
+
+ if (!_this->gl_data) {
+ /* The OpenGL library wasn't loaded, SDL_GetError() should have info */
+ return NULL;
+ }
+
+ X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_FALSE, &pvistypeattr);
+ vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
+
+ if (!vinfo && (pvistypeattr != NULL)) {
+ *pvistypeattr = None;
+ vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
+ }
+
+ if (!vinfo) {
+ SDL_SetError("Couldn't find matching GLX visual");
+ }
+ return vinfo;
+}
+
+static int (*handler) (Display *, XErrorEvent *) = NULL;
+static const char *errorHandlerOperation = NULL;
+static int errorBase = 0;
+static int errorCode = 0;
+static int
+X11_GL_ErrorHandler(Display * d, XErrorEvent * e)
+{
+ char *x11_error = NULL;
+ char x11_error_locale[256];
+
+ errorCode = e->error_code;
+ if (X11_XGetErrorText(d, errorCode, x11_error_locale, sizeof(x11_error_locale)) == Success)
+ {
+ x11_error = SDL_iconv_string("UTF-8", "", x11_error_locale, SDL_strlen(x11_error_locale)+1);
+ }
+
+ if (x11_error)
+ {
+ SDL_SetError("Could not %s: %s", errorHandlerOperation, x11_error);
+ SDL_free(x11_error);
+ }
+ else
+ {
+ SDL_SetError("Could not %s: %i (Base %i)", errorHandlerOperation, errorCode, errorBase);
+ }
+
+ return (0);
+}
+
+SDL_bool
+X11_GL_UseEGL(_THIS)
+{
+ SDL_assert(_this->gl_data != NULL);
+ SDL_assert(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES);
+
+ return (SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, SDL_FALSE)
+ || _this->gl_config.major_version == 1 /* No GLX extension for OpenGL ES 1.x profiles. */
+ || _this->gl_config.major_version > _this->gl_data->es_profile_max_supported_version.major
+ || (_this->gl_config.major_version == _this->gl_data->es_profile_max_supported_version.major
+ && _this->gl_config.minor_version > _this->gl_data->es_profile_max_supported_version.minor));
+}
+
+SDL_GLContext
+X11_GL_CreateContext(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ int screen =
+ ((SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata)->screen;
+ XWindowAttributes xattr;
+ XVisualInfo v, *vinfo;
+ int n;
+ GLXContext context = NULL, share_context;
+
+ if (_this->gl_config.share_with_current_context) {
+ share_context = (GLXContext)SDL_GL_GetCurrentContext();
+ } else {
+ share_context = NULL;
+ }
+
+ /* We do this to create a clean separation between X and GLX errors. */
+ X11_XSync(display, False);
+ errorHandlerOperation = "create GL context";
+ errorBase = _this->gl_data->errorBase;
+ errorCode = Success;
+ handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
+ X11_XGetWindowAttributes(display, data->xwindow, &xattr);
+ v.screen = screen;
+ v.visualid = X11_XVisualIDFromVisual(xattr.visual);
+ vinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
+ if (vinfo) {
+ if (_this->gl_config.major_version < 3 &&
+ _this->gl_config.profile_mask == 0 &&
+ _this->gl_config.flags == 0) {
+ /* Create legacy context */
+ context =
+ _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
+ } else {
+ /* max 14 attributes plus terminator */
+ int attribs[15] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB,
+ _this->gl_config.major_version,
+ GLX_CONTEXT_MINOR_VERSION_ARB,
+ _this->gl_config.minor_version,
+ 0
+ };
+ int iattr = 4;
+
+ /* SDL profile bits match GLX profile bits */
+ if( _this->gl_config.profile_mask != 0 ) {
+ attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
+ attribs[iattr++] = _this->gl_config.profile_mask;
+ }
+
+ /* SDL flags match GLX flags */
+ if( _this->gl_config.flags != 0 ) {
+ attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
+ attribs[iattr++] = _this->gl_config.flags;
+ }
+
+ /* only set if glx extension is available */
+ if( _this->gl_data->HAS_GLX_ARB_context_flush_control ) {
+ attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB;
+ attribs[iattr++] =
+ _this->gl_config.release_behavior ?
+ GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
+ GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
+ }
+
+ /* only set if glx extension is available */
+ if( _this->gl_data->HAS_GLX_ARB_create_context_robustness ) {
+ attribs[iattr++] = GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
+ attribs[iattr++] =
+ _this->gl_config.reset_notification ?
+ GLX_LOSE_CONTEXT_ON_RESET_ARB :
+ GLX_NO_RESET_NOTIFICATION_ARB;
+ }
+
+ /* only set if glx extension is available */
+ if( _this->gl_data->HAS_GLX_ARB_create_context_no_error ) {
+ attribs[iattr++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB;
+ attribs[iattr++] = _this->gl_config.no_error;
+ }
+
+ attribs[iattr++] = 0;
+
+ /* Get a pointer to the context creation function for GL 3.0 */
+ if (!_this->gl_data->glXCreateContextAttribsARB) {
+ SDL_SetError("OpenGL 3.0 and later are not supported by this system");
+ } else {
+ int glxAttribs[64];
+
+ /* Create a GL 3.x context */
+ GLXFBConfig *framebuffer_config = NULL;
+ int fbcount = 0;
+ int *pvistypeattr = NULL;
+
+ X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE,&pvistypeattr);
+
+ if (_this->gl_data->glXChooseFBConfig) {
+ framebuffer_config = _this->gl_data->glXChooseFBConfig(display,
+ DefaultScreen(display), glxAttribs,
+ &fbcount);
+
+ if (!framebuffer_config && (pvistypeattr != NULL)) {
+ *pvistypeattr = None;
+ framebuffer_config = _this->gl_data->glXChooseFBConfig(display,
+ DefaultScreen(display), glxAttribs,
+ &fbcount);
+ }
+
+ if (framebuffer_config) {
+ context = _this->gl_data->glXCreateContextAttribsARB(display,
+ framebuffer_config[0],
+ share_context, True, attribs);
+ X11_XFree(framebuffer_config);
+ }
+ }
+ }
+ }
+ X11_XFree(vinfo);
+ }
+ X11_XSync(display, False);
+ X11_XSetErrorHandler(handler);
+
+ if (!context) {
+ if (errorCode == Success) {
+ SDL_SetError("Could not create GL context");
+ }
+ return NULL;
+ }
+
+ if (X11_GL_MakeCurrent(_this, window, context) < 0) {
+ X11_GL_DeleteContext(_this, context);
+ return NULL;
+ }
+
+ return context;
+}
+
+int
+X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
+{
+ Display *display = ((SDL_VideoData *) _this->driverdata)->display;
+ Window drawable =
+ (context ? ((SDL_WindowData *) window->driverdata)->xwindow : None);
+ GLXContext glx_context = (GLXContext) context;
+ int rc;
+
+ if (!_this->gl_data) {
+ return SDL_SetError("OpenGL not initialized");
+ }
+
+ /* We do this to create a clean separation between X and GLX errors. */
+ X11_XSync(display, False);
+ errorHandlerOperation = "make GL context current";
+ errorBase = _this->gl_data->errorBase;
+ errorCode = Success;
+ handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
+ rc = _this->gl_data->glXMakeCurrent(display, drawable, glx_context);
+ X11_XSetErrorHandler(handler);
+
+ if (errorCode != Success) { /* uhoh, an X error was thrown! */
+ return -1; /* the error handler called SDL_SetError() already. */
+ } else if (!rc) { /* glXMakeCurrent() failed without throwing an X error */
+ return SDL_SetError("Unable to make GL context current");
+ }
+
+ return 0;
+}
+
+/*
+ 0 is a valid argument to glXSwapInterval(MESA|EXT) and setting it to 0
+ will undo the effect of a previous call with a value that is greater
+ than zero (or at least that is what the docs say). OTOH, 0 is an invalid
+ argument to glXSwapIntervalSGI and it returns an error if you call it
+ with 0 as an argument.
+*/
+
+static int swapinterval = 0;
+int
+X11_GL_SetSwapInterval(_THIS, int interval)
+{
+ int status = -1;
+
+ if ((interval < 0) && (!_this->gl_data->HAS_GLX_EXT_swap_control_tear)) {
+ SDL_SetError("Negative swap interval unsupported in this GL");
+ } else if (_this->gl_data->glXSwapIntervalEXT) {
+ Display *display = ((SDL_VideoData *) _this->driverdata)->display;
+ const SDL_WindowData *windowdata = (SDL_WindowData *)
+ SDL_GL_GetCurrentWindow()->driverdata;
+
+ Window drawable = windowdata->xwindow;
+
+ /*
+ * This is a workaround for a bug in NVIDIA drivers. Bug has been reported
+ * and will be fixed in a future release (probably 319.xx).
+ *
+ * There's a bug where glXSetSwapIntervalEXT ignores updates because
+ * it has the wrong value cached. To work around it, we just run a no-op
+ * update to the current value.
+ */
+ int currentInterval = X11_GL_GetSwapInterval(_this);
+ _this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval);
+ _this->gl_data->glXSwapIntervalEXT(display, drawable, interval);
+
+ status = 0;
+ swapinterval = interval;
+ } else if (_this->gl_data->glXSwapIntervalMESA) {
+ status = _this->gl_data->glXSwapIntervalMESA(interval);
+ if (status != 0) {
+ SDL_SetError("glXSwapIntervalMESA failed");
+ } else {
+ swapinterval = interval;
+ }
+ } else if (_this->gl_data->glXSwapIntervalSGI) {
+ status = _this->gl_data->glXSwapIntervalSGI(interval);
+ if (status != 0) {
+ SDL_SetError("glXSwapIntervalSGI failed");
+ } else {
+ swapinterval = interval;
+ }
+ } else {
+ SDL_Unsupported();
+ }
+ return status;
+}
+
+int
+X11_GL_GetSwapInterval(_THIS)
+{
+ if (_this->gl_data->glXSwapIntervalEXT) {
+ Display *display = ((SDL_VideoData *) _this->driverdata)->display;
+ const SDL_WindowData *windowdata = (SDL_WindowData *)
+ SDL_GL_GetCurrentWindow()->driverdata;
+ Window drawable = windowdata->xwindow;
+ unsigned int allow_late_swap_tearing = 0;
+ unsigned int interval = 0;
+
+ if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) {
+ _this->gl_data->glXQueryDrawable(display, drawable,
+ GLX_LATE_SWAPS_TEAR_EXT,
+ &allow_late_swap_tearing);
+ }
+
+ _this->gl_data->glXQueryDrawable(display, drawable,
+ GLX_SWAP_INTERVAL_EXT, &interval);
+
+ if ((allow_late_swap_tearing) && (interval > 0)) {
+ return -((int) interval);
+ }
+
+ return (int) interval;
+ } else if (_this->gl_data->glXGetSwapIntervalMESA) {
+ return _this->gl_data->glXGetSwapIntervalMESA();
+ } else {
+ return swapinterval;
+ }
+}
+
+int
+X11_GL_SwapWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+
+ _this->gl_data->glXSwapBuffers(display, data->xwindow);
+ return 0;
+}
+
+void
+X11_GL_DeleteContext(_THIS, SDL_GLContext context)
+{
+ Display *display = ((SDL_VideoData *) _this->driverdata)->display;
+ GLXContext glx_context = (GLXContext) context;
+
+ if (!_this->gl_data) {
+ return;
+ }
+ _this->gl_data->glXDestroyContext(display, glx_context);
+ X11_XSync(display, False);
+}
+
+#endif /* SDL_VIDEO_OPENGL_GLX */
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11opengl.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11opengl.h
new file mode 100644
index 0000000..7331b71
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11opengl.h
@@ -0,0 +1,84 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11opengl_h_
+#define SDL_x11opengl_h_
+
+#if SDL_VIDEO_OPENGL_GLX
+#include "SDL_opengl.h"
+#include <GL/glx.h>
+
+struct SDL_GLDriverData
+{
+ int errorBase, eventBase;
+
+ SDL_bool HAS_GLX_EXT_visual_rating;
+ SDL_bool HAS_GLX_EXT_visual_info;
+ SDL_bool HAS_GLX_EXT_swap_control_tear;
+ SDL_bool HAS_GLX_ARB_context_flush_control;
+ SDL_bool HAS_GLX_ARB_create_context_robustness;
+ SDL_bool HAS_GLX_ARB_create_context_no_error;
+
+ /* Max version of OpenGL ES context that can be created if the
+ implementation supports GLX_EXT_create_context_es2_profile.
+ major = minor = 0 when unsupported.
+ */
+ struct {
+ int major;
+ int minor;
+ } es_profile_max_supported_version;
+
+ Bool (*glXQueryExtension) (Display*,int*,int*);
+ void *(*glXGetProcAddress) (const GLubyte*);
+ XVisualInfo *(*glXChooseVisual) (Display*,int,int*);
+ GLXContext (*glXCreateContext) (Display*,XVisualInfo*,GLXContext,Bool);
+ GLXContext (*glXCreateContextAttribsARB) (Display*,GLXFBConfig,GLXContext,Bool,const int *);
+ GLXFBConfig *(*glXChooseFBConfig) (Display*,int,const int *,int *);
+ void (*glXDestroyContext) (Display*, GLXContext);
+ Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext);
+ void (*glXSwapBuffers) (Display*, GLXDrawable);
+ void (*glXQueryDrawable) (Display*,GLXDrawable,int,unsigned int*);
+ void (*glXSwapIntervalEXT) (Display*,GLXDrawable,int);
+ int (*glXSwapIntervalSGI) (int);
+ int (*glXSwapIntervalMESA) (int);
+ int (*glXGetSwapIntervalMESA) (void);
+};
+
+/* OpenGL functions */
+extern int X11_GL_LoadLibrary(_THIS, const char *path);
+extern void *X11_GL_GetProcAddress(_THIS, const char *proc);
+extern void X11_GL_UnloadLibrary(_THIS);
+extern SDL_bool X11_GL_UseEGL(_THIS);
+extern XVisualInfo *X11_GL_GetVisual(_THIS, Display * display, int screen);
+extern SDL_GLContext X11_GL_CreateContext(_THIS, SDL_Window * window);
+extern int X11_GL_MakeCurrent(_THIS, SDL_Window * window,
+ SDL_GLContext context);
+extern int X11_GL_SetSwapInterval(_THIS, int interval);
+extern int X11_GL_GetSwapInterval(_THIS);
+extern int X11_GL_SwapWindow(_THIS, SDL_Window * window);
+extern void X11_GL_DeleteContext(_THIS, SDL_GLContext context);
+
+#endif /* SDL_VIDEO_OPENGL_GLX */
+
+#endif /* SDL_x11opengl_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11opengles.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11opengles.c
new file mode 100644
index 0000000..76b6cd7
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11opengles.c
@@ -0,0 +1,109 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_OPENGL_EGL
+
+#include "SDL_x11video.h"
+#include "SDL_x11opengles.h"
+#include "SDL_x11opengl.h"
+
+/* EGL implementation of SDL OpenGL support */
+
+int
+X11_GLES_LoadLibrary(_THIS, const char *path)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ /* If the profile requested is not GL ES, switch over to X11_GL functions */
+ if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
+ #if SDL_VIDEO_OPENGL_GLX
+ X11_GLES_UnloadLibrary(_this);
+ _this->GL_LoadLibrary = X11_GL_LoadLibrary;
+ _this->GL_GetProcAddress = X11_GL_GetProcAddress;
+ _this->GL_UnloadLibrary = X11_GL_UnloadLibrary;
+ _this->GL_CreateContext = X11_GL_CreateContext;
+ _this->GL_MakeCurrent = X11_GL_MakeCurrent;
+ _this->GL_SetSwapInterval = X11_GL_SetSwapInterval;
+ _this->GL_GetSwapInterval = X11_GL_GetSwapInterval;
+ _this->GL_SwapWindow = X11_GL_SwapWindow;
+ _this->GL_DeleteContext = X11_GL_DeleteContext;
+ return X11_GL_LoadLibrary(_this, path);
+ #else
+ return SDL_SetError("SDL not configured with OpenGL/GLX support");
+ #endif
+ }
+
+ return SDL_EGL_LoadLibrary(_this, path, (NativeDisplayType) data->display, 0);
+}
+
+XVisualInfo *
+X11_GLES_GetVisual(_THIS, Display * display, int screen)
+{
+
+ XVisualInfo *egl_visualinfo = NULL;
+ EGLint visual_id;
+ XVisualInfo vi_in;
+ int out_count;
+
+ if (!_this->egl_data) {
+ /* The EGL library wasn't loaded, SDL_GetError() should have info */
+ return NULL;
+ }
+
+ if (_this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display,
+ _this->egl_data->egl_config,
+ EGL_NATIVE_VISUAL_ID,
+ &visual_id) == EGL_FALSE || !visual_id) {
+ /* Use the default visual when all else fails */
+ vi_in.screen = screen;
+ egl_visualinfo = X11_XGetVisualInfo(display,
+ VisualScreenMask,
+ &vi_in, &out_count);
+ } else {
+ vi_in.screen = screen;
+ vi_in.visualid = visual_id;
+ egl_visualinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &vi_in, &out_count);
+ }
+
+ return egl_visualinfo;
+}
+
+SDL_GLContext
+X11_GLES_CreateContext(_THIS, SDL_Window * window)
+{
+ SDL_GLContext context;
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+
+ X11_XSync(display, False);
+ context = SDL_EGL_CreateContext(_this, data->egl_surface);
+ X11_XSync(display, False);
+
+ return context;
+}
+
+SDL_EGL_SwapWindow_impl(X11)
+SDL_EGL_MakeCurrent_impl(X11)
+
+#endif /* SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_OPENGL_EGL */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11opengles.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11opengles.h
new file mode 100644
index 0000000..b189b76
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11opengles.h
@@ -0,0 +1,56 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11opengles_h_
+#define SDL_x11opengles_h_
+
+#if SDL_VIDEO_OPENGL_EGL
+
+#include "../SDL_sysvideo.h"
+#include "../SDL_egl_c.h"
+
+typedef struct SDL_PrivateGLESData
+{
+ /* 1401 If the struct-declaration-list contains no named members, the behavior is undefined. */
+ /* warning: empty struct has size 0 in C, size 1 in C++ [-Wc++-compat] */
+ int dummy;
+} SDL_PrivateGLESData;
+
+/* OpenGLES functions */
+#define X11_GLES_GetAttribute SDL_EGL_GetAttribute
+#define X11_GLES_GetProcAddress SDL_EGL_GetProcAddress
+#define X11_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
+#define X11_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
+#define X11_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
+#define X11_GLES_DeleteContext SDL_EGL_DeleteContext
+
+extern int X11_GLES_LoadLibrary(_THIS, const char *path);
+extern XVisualInfo *X11_GLES_GetVisual(_THIS, Display * display, int screen);
+extern SDL_GLContext X11_GLES_CreateContext(_THIS, SDL_Window * window);
+extern int X11_GLES_SwapWindow(_THIS, SDL_Window * window);
+extern int X11_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
+
+#endif /* SDL_VIDEO_OPENGL_EGL */
+
+#endif /* SDL_x11opengles_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11shape.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11shape.c
new file mode 100644
index 0000000..4d68fe0
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11shape.c
@@ -0,0 +1,115 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL_assert.h"
+#include "SDL_x11video.h"
+#include "SDL_x11shape.h"
+#include "SDL_x11window.h"
+#include "../SDL_shape_internals.h"
+
+SDL_WindowShaper*
+X11_CreateShaper(SDL_Window* window) {
+ SDL_WindowShaper* result = NULL;
+ SDL_ShapeData* data = NULL;
+ int resized_properly;
+
+#if SDL_VIDEO_DRIVER_X11_XSHAPE
+ if (SDL_X11_HAVE_XSHAPE) { /* Make sure X server supports it. */
+ result = malloc(sizeof(SDL_WindowShaper));
+ result->window = window;
+ result->mode.mode = ShapeModeDefault;
+ result->mode.parameters.binarizationCutoff = 1;
+ result->userx = result->usery = 0;
+ data = SDL_malloc(sizeof(SDL_ShapeData));
+ result->driverdata = data;
+ data->bitmapsize = 0;
+ data->bitmap = NULL;
+ window->shaper = result;
+ resized_properly = X11_ResizeWindowShape(window);
+ SDL_assert(resized_properly == 0);
+ }
+#endif
+
+ return result;
+}
+
+int
+X11_ResizeWindowShape(SDL_Window* window) {
+ SDL_ShapeData* data = window->shaper->driverdata;
+ unsigned int bitmapsize = window->w / 8;
+ SDL_assert(data != NULL);
+
+ if(window->w % 8 > 0)
+ bitmapsize += 1;
+ bitmapsize *= window->h;
+ if(data->bitmapsize != bitmapsize || data->bitmap == NULL) {
+ data->bitmapsize = bitmapsize;
+ if(data->bitmap != NULL)
+ free(data->bitmap);
+ data->bitmap = malloc(data->bitmapsize);
+ if(data->bitmap == NULL) {
+ return SDL_SetError("Could not allocate memory for shaped-window bitmap.");
+ }
+ }
+ memset(data->bitmap,0,data->bitmapsize);
+
+ window->shaper->userx = window->x;
+ window->shaper->usery = window->y;
+ SDL_SetWindowPosition(window,-1000,-1000);
+
+ return 0;
+}
+
+int
+X11_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) {
+ SDL_ShapeData *data = NULL;
+ SDL_WindowData *windowdata = NULL;
+ Pixmap shapemask;
+
+ if(shaper == NULL || shape == NULL || shaper->driverdata == NULL)
+ return -1;
+
+#if SDL_VIDEO_DRIVER_X11_XSHAPE
+ if(shape->format->Amask == 0 && SDL_SHAPEMODEALPHA(shape_mode->mode))
+ return -2;
+ if(shape->w != shaper->window->w || shape->h != shaper->window->h)
+ return -3;
+ data = shaper->driverdata;
+
+ /* Assume that shaper->alphacutoff already has a value, because SDL_SetWindowShape() should have given it one. */
+ SDL_CalculateShapeBitmap(shaper->mode,shape,data->bitmap,8);
+
+ windowdata = (SDL_WindowData*)(shaper->window->driverdata);
+ shapemask = X11_XCreateBitmapFromData(windowdata->videodata->display,windowdata->xwindow,data->bitmap,shaper->window->w,shaper->window->h);
+
+ X11_XShapeCombineMask(windowdata->videodata->display,windowdata->xwindow, ShapeBounding, 0, 0,shapemask, ShapeSet);
+ X11_XSync(windowdata->videodata->display,False);
+
+ X11_XFreePixmap(windowdata->videodata->display,shapemask);
+#endif
+
+ return 0;
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11shape.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11shape.h
new file mode 100644
index 0000000..a8c2e2c
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11shape.h
@@ -0,0 +1,39 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11shape_h_
+#define SDL_x11shape_h_
+
+#include "SDL_video.h"
+#include "SDL_shape.h"
+#include "../SDL_sysvideo.h"
+
+typedef struct {
+ void* bitmap;
+ Uint32 bitmapsize;
+} SDL_ShapeData;
+
+extern SDL_WindowShaper* X11_CreateShaper(SDL_Window* window);
+extern int X11_ResizeWindowShape(SDL_Window* window);
+extern int X11_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shapeMode);
+
+#endif /* SDL_x11shape_h_ */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11sym.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11sym.h
new file mode 100644
index 0000000..6709992
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11sym.h
@@ -0,0 +1,337 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* *INDENT-OFF* */
+
+#ifndef SDL_X11_MODULE
+#define SDL_X11_MODULE(modname)
+#endif
+
+#ifndef SDL_X11_SYM
+#define SDL_X11_SYM(rc,fn,params,args,ret)
+#endif
+
+SDL_X11_MODULE(BASEXLIB)
+SDL_X11_SYM(XSizeHints*,XAllocSizeHints,(void),(),return)
+SDL_X11_SYM(XWMHints*,XAllocWMHints,(void),(),return)
+SDL_X11_SYM(XClassHint*,XAllocClassHint,(void),(),return)
+SDL_X11_SYM(int,XAutoRepeatOn,(Display* a),(a),return)
+SDL_X11_SYM(int,XAutoRepeatOff,(Display* a),(a),return)
+SDL_X11_SYM(int,XChangePointerControl,(Display* a,Bool b,Bool c,int d,int e,int f),(a,b,c,d,e,f),return)
+SDL_X11_SYM(int,XChangeProperty,(Display* a,Window b,Atom c,Atom d,int e,int f,_Xconst unsigned char* g,int h),(a,b,c,d,e,f,g,h),return)
+SDL_X11_SYM(Bool,XCheckIfEvent,(Display* a,XEvent *b,Bool (*c)(Display*,XEvent*,XPointer),XPointer d),(a,b,c,d),return)
+SDL_X11_SYM(int,XClearWindow,(Display* a,Window b),(a,b),return)
+SDL_X11_SYM(int,XCloseDisplay,(Display* a),(a),return)
+SDL_X11_SYM(int,XConvertSelection,(Display* a,Atom b,Atom c,Atom d,Window e,Time f),(a,b,c,d,e,f),return)
+SDL_X11_SYM(Pixmap,XCreateBitmapFromData,(Display *dpy,Drawable d,_Xconst char *data,unsigned int width,unsigned int height),(dpy,d,data,width,height),return)
+SDL_X11_SYM(Colormap,XCreateColormap,(Display* a,Window b,Visual* c,int d),(a,b,c,d),return)
+SDL_X11_SYM(Cursor,XCreatePixmapCursor,(Display* a,Pixmap b,Pixmap c,XColor* d,XColor* e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return)
+SDL_X11_SYM(Cursor,XCreateFontCursor,(Display* a,unsigned int b),(a,b),return)
+SDL_X11_SYM(XFontSet,XCreateFontSet,(Display* a, _Xconst char* b, char*** c, int* d, char** e),(a,b,c,d,e),return)
+SDL_X11_SYM(GC,XCreateGC,(Display* a,Drawable b,unsigned long c,XGCValues* d),(a,b,c,d),return)
+SDL_X11_SYM(XImage*,XCreateImage,(Display* a,Visual* b,unsigned int c,int d,int e,char* f,unsigned int g,unsigned int h,int i,int j),(a,b,c,d,e,f,g,h,i,j),return)
+SDL_X11_SYM(Window,XCreateWindow,(Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,int h,unsigned int i,Visual* j,unsigned long k,XSetWindowAttributes* l),(a,b,c,d,e,f,g,h,i,j,k,l),return)
+SDL_X11_SYM(int,XDefineCursor,(Display* a,Window b,Cursor c),(a,b,c),return)
+SDL_X11_SYM(int,XDeleteProperty,(Display* a,Window b,Atom c),(a,b,c),return)
+SDL_X11_SYM(int,XDestroyWindow,(Display* a,Window b),(a,b),return)
+SDL_X11_SYM(int,XDisplayKeycodes,(Display* a,int* b,int* c),(a,b,c),return)
+SDL_X11_SYM(int,XDrawRectangle,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return)
+SDL_X11_SYM(char*,XDisplayName,(_Xconst char* a),(a),return)
+SDL_X11_SYM(int,XDrawString,(Display* a,Drawable b,GC c,int d,int e,_Xconst char* f,int g),(a,b,c,d,e,f,g),return)
+SDL_X11_SYM(int,XEventsQueued,(Display* a,int b),(a,b),return)
+SDL_X11_SYM(int,XFillRectangle,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return)
+SDL_X11_SYM(Bool,XFilterEvent,(XEvent *event,Window w),(event,w),return)
+SDL_X11_SYM(int,XFlush,(Display* a),(a),return)
+SDL_X11_SYM(int,XFree,(void*a),(a),return)
+SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return)
+SDL_X11_SYM(void,XFreeFontSet,(Display* a, XFontSet b),(a,b),)
+SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return)
+SDL_X11_SYM(int,XFreeFont,(Display* a, XFontStruct* b),(a,b),return)
+SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return)
+SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return)
+SDL_X11_SYM(void,XFreeStringList,(char** a),(a),)
+SDL_X11_SYM(char*,XGetAtomName,(Display *a,Atom b),(a,b),return)
+SDL_X11_SYM(int,XGetInputFocus,(Display *a,Window *b,int *c),(a,b,c),return)
+SDL_X11_SYM(int,XGetErrorDatabaseText,(Display* a,_Xconst char* b,_Xconst char* c,_Xconst char* d,char* e,int f),(a,b,c,d,e,f),return)
+SDL_X11_SYM(XModifierKeymap*,XGetModifierMapping,(Display* a),(a),return)
+SDL_X11_SYM(int,XGetPointerControl,(Display* a,int* b,int* c,int* d),(a,b,c,d),return)
+SDL_X11_SYM(Window,XGetSelectionOwner,(Display* a,Atom b),(a,b),return)
+SDL_X11_SYM(XVisualInfo*,XGetVisualInfo,(Display* a,long b,XVisualInfo* c,int* d),(a,b,c,d),return)
+SDL_X11_SYM(Status,XGetWindowAttributes,(Display* a,Window b,XWindowAttributes* c),(a,b,c),return)
+SDL_X11_SYM(int,XGetWindowProperty,(Display* a,Window b,Atom c,long d,long e,Bool f,Atom g,Atom* h,int* i,unsigned long* j,unsigned long *k,unsigned char **l),(a,b,c,d,e,f,g,h,i,j,k,l),return)
+SDL_X11_SYM(XWMHints*,XGetWMHints,(Display* a,Window b),(a,b),return)
+SDL_X11_SYM(Status,XGetWMNormalHints,(Display *a,Window b, XSizeHints *c, long *d),(a,b,c,d),return)
+SDL_X11_SYM(int,XIfEvent,(Display* a,XEvent *b,Bool (*c)(Display*,XEvent*,XPointer),XPointer d),(a,b,c,d),return)
+SDL_X11_SYM(int,XGrabKeyboard,(Display* a,Window b,Bool c,int d,int e,Time f),(a,b,c,d,e,f),return)
+SDL_X11_SYM(int,XGrabPointer,(Display* a,Window b,Bool c,unsigned int d,int e,int f,Window g,Cursor h,Time i),(a,b,c,d,e,f,g,h,i),return)
+SDL_X11_SYM(int,XGrabServer,(Display* a),(a),return)
+SDL_X11_SYM(Status,XIconifyWindow,(Display* a,Window b,int c),(a,b,c),return)
+SDL_X11_SYM(KeyCode,XKeysymToKeycode,(Display* a,KeySym b),(a,b),return)
+SDL_X11_SYM(char*,XKeysymToString,(KeySym a),(a),return)
+SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return)
+SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return)
+SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return)
+SDL_X11_SYM(XFontStruct*,XLoadQueryFont,(Display* a,_Xconst char* b),(a,b),return)
+SDL_X11_SYM(KeySym,XLookupKeysym,(XKeyEvent* a,int b),(a,b),return)
+SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return)
+SDL_X11_SYM(int,XMapRaised,(Display* a,Window b),(a,b),return)
+SDL_X11_SYM(Status,XMatchVisualInfo,(Display* a,int b,int c,int d,XVisualInfo* e),(a,b,c,d,e),return)
+SDL_X11_SYM(int,XMissingExtension,(Display* a,_Xconst char* b),(a,b),return)
+SDL_X11_SYM(int,XMoveWindow,(Display* a,Window b,int c,int d),(a,b,c,d),return)
+SDL_X11_SYM(int,XNextEvent,(Display* a,XEvent* b),(a,b),return)
+SDL_X11_SYM(Display*,XOpenDisplay,(_Xconst char* a),(a),return)
+SDL_X11_SYM(Status,XInitThreads,(void),(),return)
+SDL_X11_SYM(int,XPeekEvent,(Display* a,XEvent* b),(a,b),return)
+SDL_X11_SYM(int,XPending,(Display* a),(a),return)
+SDL_X11_SYM(int,XPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j),(a,b,c,d,e,f,g,h,i,j),return)
+SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return)
+SDL_X11_SYM(Bool,XQueryPointer,(Display* a,Window b,Window* c,Window* d,int* e,int* f,int* g,int* h,unsigned int* i),(a,b,c,d,e,f,g,h,i),return)
+SDL_X11_SYM(int,XRaiseWindow,(Display* a,Window b),(a,b),return)
+SDL_X11_SYM(int,XReparentWindow,(Display* a,Window b,Window c,int d,int e),(a,b,c,d,e),return)
+SDL_X11_SYM(int,XResetScreenSaver,(Display* a),(a),return)
+SDL_X11_SYM(int,XResizeWindow,(Display* a,Window b,unsigned int c,unsigned int d),(a,b,c,d),return)
+SDL_X11_SYM(int,XSelectInput,(Display* a,Window b,long c),(a,b,c),return)
+SDL_X11_SYM(Status,XSendEvent,(Display* a,Window b,Bool c,long d,XEvent* e),(a,b,c,d,e),return)
+SDL_X11_SYM(XErrorHandler,XSetErrorHandler,(XErrorHandler a),(a),return)
+SDL_X11_SYM(int,XSetForeground,(Display* a,GC b,unsigned long c),(a,b,c),return)
+SDL_X11_SYM(XIOErrorHandler,XSetIOErrorHandler,(XIOErrorHandler a),(a),return)
+SDL_X11_SYM(int,XSetInputFocus,(Display *a,Window b,int c,Time d),(a,b,c,d),return)
+SDL_X11_SYM(int,XSetSelectionOwner,(Display* a,Atom b,Window c,Time d),(a,b,c,d),return)
+SDL_X11_SYM(int,XSetTransientForHint,(Display* a,Window b,Window c),(a,b,c),return)
+SDL_X11_SYM(void,XSetTextProperty,(Display* a,Window b,XTextProperty* c,Atom d),(a,b,c,d),)
+SDL_X11_SYM(int,XSetWindowBackground,(Display* a,Window b,unsigned long c),(a,b,c),return)
+SDL_X11_SYM(void,XSetWMProperties,(Display* a,Window b,XTextProperty* c,XTextProperty* d,char** e,int f,XSizeHints* g,XWMHints* h,XClassHint* i),(a,b,c,d,e,f,g,h,i),)
+SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),)
+SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return)
+SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return)
+SDL_X11_SYM(int,XStoreName,(Display* a,Window b,_Xconst char* c),(a,b,c),return)
+SDL_X11_SYM(Status,XStringListToTextProperty,(char** a,int b,XTextProperty* c),(a,b,c),return)
+SDL_X11_SYM(int,XSync,(Display* a,Bool b),(a,b),return)
+SDL_X11_SYM(int,XTextExtents,(XFontStruct* a,_Xconst char* b,int c,int* d,int* e,int* f,XCharStruct* g),(a,b,c,d,e,f,g),return)
+SDL_X11_SYM(Bool,XTranslateCoordinates,(Display *a,Window b,Window c,int d,int e,int* f,int* g,Window* h),(a,b,c,d,e,f,g,h),return)
+SDL_X11_SYM(int,XUndefineCursor,(Display* a,Window b),(a,b),return)
+SDL_X11_SYM(int,XUngrabKeyboard,(Display* a,Time b),(a,b),return)
+SDL_X11_SYM(int,XUngrabPointer,(Display* a,Time b),(a,b),return)
+SDL_X11_SYM(int,XUngrabServer,(Display* a),(a),return)
+SDL_X11_SYM(int,XUninstallColormap,(Display* a,Colormap b),(a,b),return)
+SDL_X11_SYM(int,XUnloadFont,(Display* a,Font b),(a,b),return)
+SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned int f,unsigned int g,int h,int i),(a,b,c,d,e,f,g,h,i),return)
+SDL_X11_SYM(int,XWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return)
+SDL_X11_SYM(Status,XWithdrawWindow,(Display* a,Window b,int c),(a,b,c),return)
+SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return)
+#if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY
+SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,_Xconst char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return)
+#else
+SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return)
+#endif
+SDL_X11_SYM(XExtensionInfo*,XextCreateExtension,(void),(),return)
+SDL_X11_SYM(void,XextDestroyExtension,(XExtensionInfo* a),(a),)
+SDL_X11_SYM(XExtDisplayInfo*,XextFindDisplay,(XExtensionInfo* a,Display* b),(a,b),return)
+SDL_X11_SYM(int,XextRemoveDisplay,(XExtensionInfo* a,Display* b),(a,b),return)
+SDL_X11_SYM(Bool,XQueryExtension,(Display* a,_Xconst char* b,int* c,int* d,int* e),(a,b,c,d,e),return)
+SDL_X11_SYM(char *,XDisplayString,(Display* a),(a),return)
+SDL_X11_SYM(int,XGetErrorText,(Display* a,int b,char* c,int d),(a,b,c,d),return)
+SDL_X11_SYM(void,_XEatData,(Display* a,unsigned long b),(a,b),)
+SDL_X11_SYM(void,_XFlush,(Display* a),(a),)
+SDL_X11_SYM(void,_XFlushGCCache,(Display* a,GC b),(a,b),)
+SDL_X11_SYM(int,_XRead,(Display* a,char* b,long c),(a,b,c),return)
+SDL_X11_SYM(void,_XReadPad,(Display* a,char* b,long c),(a,b,c),)
+SDL_X11_SYM(void,_XSend,(Display* a,_Xconst char* b,long c),(a,b,c),)
+SDL_X11_SYM(Status,_XReply,(Display* a,xReply* b,int c,Bool d),(a,b,c,d),return)
+SDL_X11_SYM(unsigned long,_XSetLastRequestRead,(Display* a,xGenericReply* b),(a,b),return)
+SDL_X11_SYM(SDL_X11_XSynchronizeRetType,XSynchronize,(Display* a,Bool b),(a,b),return)
+SDL_X11_SYM(SDL_X11_XESetWireToEventRetType,XESetWireToEvent,(Display* a,int b,SDL_X11_XESetWireToEventRetType c),(a,b,c),return)
+SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,SDL_X11_XESetEventToWireRetType c),(a,b,c),return)
+SDL_X11_SYM(void,XRefreshKeyboardMapping,(XMappingEvent *a),(a),)
+SDL_X11_SYM(int,XQueryTree,(Display* a,Window b,Window* c,Window* d,Window** e,unsigned int* f),(a,b,c,d,e,f),return)
+
+#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
+SDL_X11_SYM(Bool,XGetEventData,(Display* a,XGenericEventCookie* b),(a,b),return)
+SDL_X11_SYM(void,XFreeEventData,(Display* a,XGenericEventCookie* b),(a,b),)
+#endif
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+SDL_X11_SYM(Bool,XkbQueryExtension,(Display* a,int * b,int * c,int * d,int * e, int *f),(a,b,c,d,e,f),return)
+#if NeedWidePrototypes
+SDL_X11_SYM(KeySym,XkbKeycodeToKeysym,(Display* a,unsigned int b,int c,int d),(a,b,c,d),return)
+#else
+SDL_X11_SYM(KeySym,XkbKeycodeToKeysym,(Display* a,KeyCode b,int c,int d),(a,b,c,d),return)
+#endif
+SDL_X11_SYM(Status,XkbGetState,(Display* a,unsigned int b,XkbStatePtr c),(a,b,c),return)
+SDL_X11_SYM(Status,XkbGetUpdatedMap,(Display* a,unsigned int b,XkbDescPtr c),(a,b,c),return)
+SDL_X11_SYM(XkbDescPtr,XkbGetMap,(Display* a,unsigned int b,unsigned int c),(a,b,c),return)
+SDL_X11_SYM(void,XkbFreeClientMap,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),)
+SDL_X11_SYM(void,XkbFreeKeyboard,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),)
+SDL_X11_SYM(Bool,XkbSetDetectableAutoRepeat,(Display* a, Bool b, Bool* c),(a,b,c),return)
+#endif
+
+#if NeedWidePrototypes
+SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,unsigned int b,int c),(a,b,c),return)
+#else
+SDL_X11_SYM(KeySym,XKeycodeToKeysym,(Display* a,KeyCode b,int c),(a,b,c),return)
+#endif
+
+#ifdef X_HAVE_UTF8_STRING
+SDL_X11_MODULE(UTF8)
+SDL_X11_SYM(int,Xutf8TextListToTextProperty,(Display* a,char** b,int c,XICCEncodingStyle d,XTextProperty* e),(a,b,c,d,e),return)
+SDL_X11_SYM(int,Xutf8LookupString,(XIC a,XKeyPressedEvent* b,char* c,int d,KeySym* e,Status* f),(a,b,c,d,e,f),return)
+/* SDL_X11_SYM(XIC,XCreateIC,(XIM, ...),return) !!! ARGH! */
+SDL_X11_SYM(void,XDestroyIC,(XIC a),(a),)
+/* SDL_X11_SYM(char*,XGetICValues,(XIC, ...),return) !!! ARGH! */
+SDL_X11_SYM(void,XSetICFocus,(XIC a),(a),)
+SDL_X11_SYM(void,XUnsetICFocus,(XIC a),(a),)
+SDL_X11_SYM(XIM,XOpenIM,(Display* a,struct _XrmHashBucketRec* b,char* c,char* d),(a,b,c,d),return)
+SDL_X11_SYM(Status,XCloseIM,(XIM a),(a),return)
+SDL_X11_SYM(void,Xutf8DrawString,(Display *a, Drawable b, XFontSet c, GC d, int e, int f, _Xconst char *g, int h),(a,b,c,d,e,f,g,h),)
+SDL_X11_SYM(int,Xutf8TextExtents,(XFontSet a, _Xconst char* b, int c, XRectangle* d, XRectangle* e),(a,b,c,d,e),return)
+SDL_X11_SYM(char*,XSetLocaleModifiers,(const char *a),(a),return)
+SDL_X11_SYM(char*,Xutf8ResetIC,(XIC a),(a),return)
+#endif
+
+#ifndef NO_SHARED_MEMORY
+SDL_X11_MODULE(SHM)
+SDL_X11_SYM(Status,XShmAttach,(Display* a,XShmSegmentInfo* b),(a,b),return)
+SDL_X11_SYM(Status,XShmDetach,(Display* a,XShmSegmentInfo* b),(a,b),return)
+SDL_X11_SYM(Status,XShmPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j,Bool k),(a,b,c,d,e,f,g,h,i,j,k),return)
+SDL_X11_SYM(XImage*,XShmCreateImage,(Display* a,Visual* b,unsigned int c,int d,char* e,XShmSegmentInfo* f,unsigned int g,unsigned int h),(a,b,c,d,e,f,g,h),return)
+SDL_X11_SYM(Pixmap,XShmCreatePixmap,(Display *a,Drawable b,char* c,XShmSegmentInfo* d, unsigned int e, unsigned int f, unsigned int g),(a,b,c,d,e,f,g),return)
+SDL_X11_SYM(Bool,XShmQueryExtension,(Display* a),(a),return)
+#endif
+
+/*
+ * Not required...these only exist in code in headers on some 64-bit platforms,
+ * and are removed via macros elsewhere, so it's safe for them to be missing.
+ */
+#ifdef LONG64
+SDL_X11_MODULE(IO_32BIT)
+SDL_X11_SYM(int,_XData32,(Display *dpy,register _Xconst long *data,unsigned len),(dpy,data,len),return)
+SDL_X11_SYM(void,_XRead32,(Display *dpy,register long *data,long len),(dpy,data,len),)
+#endif
+
+/*
+ * These only show up on some variants of Unix.
+ */
+#if defined(__osf__)
+SDL_X11_MODULE(OSF_ENTRY_POINTS)
+SDL_X11_SYM(void,_SmtBufferOverflow,(Display *dpy,register smtDisplayPtr p),(dpy,p),)
+SDL_X11_SYM(void,_SmtIpError,(Display *dpy,register smtDisplayPtr p,int i),(dpy,p,i),)
+SDL_X11_SYM(int,ipAllocateData,(ChannelPtr a,IPCard b,IPDataPtr * c),(a,b,c),return)
+SDL_X11_SYM(int,ipUnallocateAndSendData,(ChannelPtr a,IPCard b),(a,b),return)
+#endif
+
+/* XCursor support */
+#if SDL_VIDEO_DRIVER_X11_XCURSOR
+SDL_X11_MODULE(XCURSOR)
+SDL_X11_SYM(XcursorImage*,XcursorImageCreate,(int a,int b),(a,b),return)
+SDL_X11_SYM(void,XcursorImageDestroy,(XcursorImage *a),(a),)
+SDL_X11_SYM(Cursor,XcursorImageLoadCursor,(Display *a,const XcursorImage *b),(a,b),return)
+#endif
+
+/* Xdbe support */
+#if SDL_VIDEO_DRIVER_X11_XDBE
+SDL_X11_MODULE(XDBE)
+SDL_X11_SYM(Status,XdbeQueryExtension,(Display *dpy,int *major_version_return,int *minor_version_return),(dpy,major_version_return,minor_version_return),return)
+SDL_X11_SYM(XdbeBackBuffer,XdbeAllocateBackBufferName,(Display *dpy,Window window,XdbeSwapAction swap_action),(dpy,window,swap_action),return)
+SDL_X11_SYM(Status,XdbeDeallocateBackBufferName,(Display *dpy,XdbeBackBuffer buffer),(dpy,buffer),return)
+SDL_X11_SYM(Status,XdbeSwapBuffers,(Display *dpy,XdbeSwapInfo *swap_info,int num_windows),(dpy,swap_info,num_windows),return)
+SDL_X11_SYM(Status,XdbeBeginIdiom,(Display *dpy),(dpy),return)
+SDL_X11_SYM(Status,XdbeEndIdiom,(Display *dpy),(dpy),return)
+SDL_X11_SYM(XdbeScreenVisualInfo*,XdbeGetVisualInfo,(Display *dpy,Drawable *screen_specifiers,int *num_screens),(dpy,screen_specifiers,num_screens),return)
+SDL_X11_SYM(void,XdbeFreeVisualInfo,(XdbeScreenVisualInfo *visual_info),(visual_info),)
+SDL_X11_SYM(XdbeBackBufferAttributes*,XdbeGetBackBufferAttributes,(Display *dpy,XdbeBackBuffer buffer),(dpy,buffer),return)
+#endif
+
+/* Xinerama support */
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+SDL_X11_MODULE(XINERAMA)
+SDL_X11_SYM(Bool,XineramaIsActive,(Display *a),(a),return)
+SDL_X11_SYM(Bool,XineramaQueryExtension,(Display *a,int *b,int *c),(a,b,c),return)
+SDL_X11_SYM(Status,XineramaQueryVersion,(Display *a,int *b,int *c),(a,b,c),return)
+SDL_X11_SYM(XineramaScreenInfo*,XineramaQueryScreens,(Display *a, int *b),(a,b),return)
+#endif
+
+/* XInput2 support for multiple mice, tablets, etc. */
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+SDL_X11_MODULE(XINPUT2)
+SDL_X11_SYM(XIDeviceInfo*,XIQueryDevice,(Display *a,int b,int *c),(a,b,c),return)
+SDL_X11_SYM(void,XIFreeDeviceInfo,(XIDeviceInfo *a),(a),)
+SDL_X11_SYM(int,XISelectEvents,(Display *a,Window b,XIEventMask *c,int d),(a,b,c,d),return)
+SDL_X11_SYM(Status,XIQueryVersion,(Display *a,int *b,int *c),(a,b,c),return)
+SDL_X11_SYM(XIEventMask*,XIGetSelectedEvents,(Display *a,Window b,int *c),(a,b,c),return)
+#endif
+
+/* XRandR support */
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+SDL_X11_MODULE(XRANDR)
+SDL_X11_SYM(Status,XRRQueryVersion,(Display *dpy,int *major_versionp,int *minor_versionp),(dpy,major_versionp,minor_versionp),return)
+SDL_X11_SYM(XRRScreenConfiguration *,XRRGetScreenInfo,(Display *dpy,Drawable draw),(dpy,draw),return)
+SDL_X11_SYM(SizeID,XRRConfigCurrentConfiguration,(XRRScreenConfiguration *config,Rotation *rotation),(config,rotation),return)
+SDL_X11_SYM(short,XRRConfigCurrentRate,(XRRScreenConfiguration *config),(config),return)
+SDL_X11_SYM(short *,XRRConfigRates,(XRRScreenConfiguration *config,int sizeID,int *nrates),(config,sizeID,nrates),return)
+SDL_X11_SYM(XRRScreenSize *,XRRConfigSizes,(XRRScreenConfiguration *config,int *nsizes),(config,nsizes),return)
+SDL_X11_SYM(Status,XRRSetScreenConfigAndRate,(Display *dpy,XRRScreenConfiguration *config,Drawable draw,int size_index,Rotation rotation,short rate,Time timestamp),(dpy,config,draw,size_index,rotation,rate,timestamp),return)
+SDL_X11_SYM(void,XRRFreeScreenConfigInfo,(XRRScreenConfiguration *config),(config),)
+SDL_X11_SYM(void,XRRSetScreenSize,(Display *dpy, Window window,int width, int height,int mmWidth, int mmHeight),(dpy,window,width,height,mmWidth,mmHeight),)
+SDL_X11_SYM(Status,XRRGetScreenSizeRange,(Display *dpy, Window window,int *minWidth, int *minHeight, int *maxWidth, int *maxHeight),(dpy,window,minWidth,minHeight,maxWidth,maxHeight),return)
+SDL_X11_SYM(XRRScreenResources *,XRRGetScreenResources,(Display *dpy, Window window),(dpy, window),return)
+SDL_X11_SYM(XRRScreenResources *,XRRGetScreenResourcesCurrent,(Display *dpy, Window window),(dpy, window),return)
+SDL_X11_SYM(void,XRRFreeScreenResources,(XRRScreenResources *resources),(resources),)
+SDL_X11_SYM(XRROutputInfo *,XRRGetOutputInfo,(Display *dpy, XRRScreenResources *resources, RROutput output),(dpy,resources,output),return)
+SDL_X11_SYM(void,XRRFreeOutputInfo,(XRROutputInfo *outputInfo),(outputInfo),)
+SDL_X11_SYM(XRRCrtcInfo *,XRRGetCrtcInfo,(Display *dpy, XRRScreenResources *resources, RRCrtc crtc),(dpy,resources,crtc),return)
+SDL_X11_SYM(void,XRRFreeCrtcInfo,(XRRCrtcInfo *crtcInfo),(crtcInfo),)
+SDL_X11_SYM(Status,XRRSetCrtcConfig,(Display *dpy, XRRScreenResources *resources, RRCrtc crtc, Time timestamp, int x, int y, RRMode mode, Rotation rotation, RROutput *outputs, int noutputs),(dpy,resources,crtc,timestamp,x,y,mode,rotation,outputs,noutputs),return)
+SDL_X11_SYM(Atom*,XRRListOutputProperties,(Display *dpy, RROutput output, int *nprop),(dpy,output,nprop),return)
+SDL_X11_SYM(XRRPropertyInfo*,XRRQueryOutputProperty,(Display *dpy,RROutput output, Atom property),(dpy,output,property),return)
+SDL_X11_SYM(int,XRRGetOutputProperty,(Display *dpy,RROutput output, Atom property, long offset, long length, Bool _delete, Bool pending, Atom req_type, Atom *actual_type, int *actual_format, unsigned long *nitems, unsigned long *bytes_after, unsigned char **prop),(dpy,output,property,offset,length, _delete, pending, req_type, actual_type, actual_format, nitems, bytes_after, prop),return)
+SDL_X11_SYM(RROutput,XRRGetOutputPrimary,(Display *dpy,Window window),(dpy,window),return)
+#endif
+
+/* MIT-SCREEN-SAVER support */
+#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
+SDL_X11_MODULE(XSS)
+SDL_X11_SYM(Bool,XScreenSaverQueryExtension,(Display *dpy,int *event_base,int *error_base),(dpy,event_base,error_base),return)
+SDL_X11_SYM(Status,XScreenSaverQueryVersion,(Display *dpy,int *major_versionp,int *minor_versionp),(dpy,major_versionp,minor_versionp),return)
+SDL_X11_SYM(void,XScreenSaverSuspend,(Display *dpy,Bool suspend),(dpy,suspend),return)
+#endif
+
+#if SDL_VIDEO_DRIVER_X11_XSHAPE
+SDL_X11_MODULE(XSHAPE)
+SDL_X11_SYM(void,XShapeCombineMask,(Display *dpy,Window dest,int dest_kind,int x_off,int y_off,Pixmap src,int op),(dpy,dest,dest_kind,x_off,y_off,src,op),)
+#endif
+
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+SDL_X11_MODULE(XVIDMODE)
+SDL_X11_SYM(Bool,XF86VidModeGetAllModeLines,(Display *a,int b,int *c,XF86VidModeModeInfo ***d),(a,b,c,d),return)
+SDL_X11_SYM(Bool,XF86VidModeGetModeLine,(Display *a,int b,int *c,XF86VidModeModeLine *d),(a,b,c,d),return)
+SDL_X11_SYM(Bool,XF86VidModeGetViewPort,(Display *a,int b,int *c,int *d),(a,b,c,d),return)
+SDL_X11_SYM(Bool,XF86VidModeQueryExtension,(Display *a,int *b,int *c),(a,b,c),return)
+SDL_X11_SYM(Bool,XF86VidModeQueryVersion,(Display *a,int *b,int *c),(a,b,c),return)
+SDL_X11_SYM(Bool,XF86VidModeSwitchToMode,(Display *a,int b,XF86VidModeModeInfo *c),(a,b,c),return)
+SDL_X11_SYM(Bool,XF86VidModeLockModeSwitch,(Display *a,int b,int c),(a,b,c),return)
+#endif
+
+#undef SDL_X11_MODULE
+#undef SDL_X11_SYM
+
+/* *INDENT-ON* */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11touch.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11touch.c
new file mode 100644
index 0000000..2d0e73b
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11touch.c
@@ -0,0 +1,54 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL_x11video.h"
+#include "SDL_x11touch.h"
+#include "SDL_x11xinput2.h"
+#include "../../events/SDL_touch_c.h"
+
+
+void
+X11_InitTouch(_THIS)
+{
+ if (X11_Xinput2IsMultitouchSupported()) {
+ X11_InitXinput2Multitouch(_this);
+ }
+}
+
+void
+X11_QuitTouch(_THIS)
+{
+ SDL_TouchQuit();
+}
+
+void
+X11_ResetTouch(_THIS)
+{
+ X11_QuitTouch(_this);
+ X11_InitTouch(_this);
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11touch.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11touch.h
new file mode 100644
index 0000000..5a59af0
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11touch.h
@@ -0,0 +1,32 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11touch_h_
+#define SDL_x11touch_h_
+
+extern void X11_InitTouch(_THIS);
+extern void X11_QuitTouch(_THIS);
+extern void X11_ResetTouch(_THIS);
+
+#endif /* SDL_x11touch_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11video.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11video.c
new file mode 100644
index 0000000..b3b1a70
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11video.c
@@ -0,0 +1,497 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include <unistd.h> /* For getpid() and readlink() */
+
+#include "SDL_video.h"
+#include "SDL_mouse.h"
+#include "SDL_timer.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_pixels_c.h"
+
+#include "SDL_x11video.h"
+#include "SDL_x11framebuffer.h"
+#include "SDL_x11shape.h"
+#include "SDL_x11touch.h"
+#include "SDL_x11xinput2.h"
+
+#if SDL_VIDEO_OPENGL_EGL
+#include "SDL_x11opengles.h"
+#endif
+
+#include "SDL_x11vulkan.h"
+
+/* Initialization/Query functions */
+static int X11_VideoInit(_THIS);
+static void X11_VideoQuit(_THIS);
+
+/* Find out what class name we should use */
+static char *
+get_classname()
+{
+ char *spot;
+#if defined(__LINUX__) || defined(__FREEBSD__)
+ char procfile[1024];
+ char linkfile[1024];
+ int linksize;
+#endif
+
+ /* First allow environment variable override */
+ spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS");
+ if (spot) {
+ return SDL_strdup(spot);
+ }
+
+ /* Next look at the application's executable name */
+#if defined(__LINUX__) || defined(__FREEBSD__)
+#if defined(__LINUX__)
+ SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid());
+#elif defined(__FREEBSD__)
+ SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file",
+ getpid());
+#else
+#error Where can we find the executable name?
+#endif
+ linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
+ if (linksize > 0) {
+ linkfile[linksize] = '\0';
+ spot = SDL_strrchr(linkfile, '/');
+ if (spot) {
+ return SDL_strdup(spot + 1);
+ } else {
+ return SDL_strdup(linkfile);
+ }
+ }
+#endif /* __LINUX__ || __FREEBSD__ */
+
+ /* Finally use the default we've used forever */
+ return SDL_strdup("SDL_App");
+}
+
+/* X11 driver bootstrap functions */
+
+static int
+X11_Available(void)
+{
+ Display *display = NULL;
+ if (SDL_X11_LoadSymbols()) {
+ display = X11_XOpenDisplay(NULL);
+ if (display != NULL) {
+ X11_XCloseDisplay(display);
+ }
+ SDL_X11_UnloadSymbols();
+ }
+ return (display != NULL);
+}
+
+static void
+X11_DeleteDevice(SDL_VideoDevice * device)
+{
+ SDL_VideoData *data = (SDL_VideoData *) device->driverdata;
+ if (device->vulkan_config.loader_handle) {
+ device->Vulkan_UnloadLibrary(device);
+ }
+ if (data->display) {
+ X11_XCloseDisplay(data->display);
+ }
+ SDL_free(data->windowlist);
+ SDL_free(device->driverdata);
+ SDL_free(device);
+
+ SDL_X11_UnloadSymbols();
+}
+
+/* An error handler to reset the vidmode and then call the default handler. */
+static SDL_bool safety_net_triggered = SDL_FALSE;
+static int (*orig_x11_errhandler) (Display *, XErrorEvent *) = NULL;
+static int
+X11_SafetyNetErrHandler(Display * d, XErrorEvent * e)
+{
+ SDL_VideoDevice *device = NULL;
+ /* if we trigger an error in our error handler, don't try again. */
+ if (!safety_net_triggered) {
+ safety_net_triggered = SDL_TRUE;
+ device = SDL_GetVideoDevice();
+ if (device != NULL) {
+ int i;
+ for (i = 0; i < device->num_displays; i++) {
+ SDL_VideoDisplay *display = &device->displays[i];
+ if (SDL_memcmp(&display->current_mode, &display->desktop_mode,
+ sizeof (SDL_DisplayMode)) != 0) {
+ X11_SetDisplayMode(device, display, &display->desktop_mode);
+ }
+ }
+ }
+ }
+
+ if (orig_x11_errhandler != NULL) {
+ return orig_x11_errhandler(d, e); /* probably terminate. */
+ }
+
+ return 0;
+}
+
+static SDL_VideoDevice *
+X11_CreateDevice(int devindex)
+{
+ SDL_VideoDevice *device;
+ SDL_VideoData *data;
+ const char *display = NULL; /* Use the DISPLAY environment variable */
+
+ if (!SDL_X11_LoadSymbols()) {
+ return NULL;
+ }
+
+ /* Need for threading gl calls. This is also required for the proprietary
+ nVidia driver to be threaded. */
+ X11_XInitThreads();
+
+ /* Initialize all variables that we clean on shutdown */
+ device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
+ if (!device) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+ data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
+ if (!data) {
+ SDL_free(device);
+ SDL_OutOfMemory();
+ return NULL;
+ }
+ device->driverdata = data;
+
+ data->global_mouse_changed = SDL_TRUE;
+
+ /* FIXME: Do we need this?
+ if ( (SDL_strncmp(X11_XDisplayName(display), ":", 1) == 0) ||
+ (SDL_strncmp(X11_XDisplayName(display), "unix:", 5) == 0) ) {
+ local_X11 = 1;
+ } else {
+ local_X11 = 0;
+ }
+ */
+ data->display = X11_XOpenDisplay(display);
+#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC
+ /* On some systems if linking without -lX11, it fails and you get following message.
+ * Xlib: connection to ":0.0" refused by server
+ * Xlib: XDM authorization key matches an existing client!
+ *
+ * It succeeds if retrying 1 second later
+ * or if running xhost +localhost on shell.
+ */
+ if (data->display == NULL) {
+ SDL_Delay(1000);
+ data->display = X11_XOpenDisplay(display);
+ }
+#endif
+ if (data->display == NULL) {
+ SDL_free(device->driverdata);
+ SDL_free(device);
+ SDL_SetError("Couldn't open X11 display");
+ return NULL;
+ }
+#ifdef X11_DEBUG
+ X11_XSynchronize(data->display, True);
+#endif
+
+ /* Hook up an X11 error handler to recover the desktop resolution. */
+ safety_net_triggered = SDL_FALSE;
+ orig_x11_errhandler = X11_XSetErrorHandler(X11_SafetyNetErrHandler);
+
+ /* Set the function pointers */
+ device->VideoInit = X11_VideoInit;
+ device->VideoQuit = X11_VideoQuit;
+ device->ResetTouch = X11_ResetTouch;
+ device->GetDisplayModes = X11_GetDisplayModes;
+ device->GetDisplayBounds = X11_GetDisplayBounds;
+ device->GetDisplayUsableBounds = X11_GetDisplayUsableBounds;
+ device->GetDisplayDPI = X11_GetDisplayDPI;
+ device->SetDisplayMode = X11_SetDisplayMode;
+ device->SuspendScreenSaver = X11_SuspendScreenSaver;
+ device->PumpEvents = X11_PumpEvents;
+
+ device->CreateSDLWindow = X11_CreateWindow;
+ device->CreateSDLWindowFrom = X11_CreateWindowFrom;
+ device->SetWindowTitle = X11_SetWindowTitle;
+ device->SetWindowIcon = X11_SetWindowIcon;
+ device->SetWindowPosition = X11_SetWindowPosition;
+ device->SetWindowSize = X11_SetWindowSize;
+ device->SetWindowMinimumSize = X11_SetWindowMinimumSize;
+ device->SetWindowMaximumSize = X11_SetWindowMaximumSize;
+ device->GetWindowBordersSize = X11_GetWindowBordersSize;
+ device->SetWindowOpacity = X11_SetWindowOpacity;
+ device->SetWindowModalFor = X11_SetWindowModalFor;
+ device->SetWindowInputFocus = X11_SetWindowInputFocus;
+ device->ShowWindow = X11_ShowWindow;
+ device->HideWindow = X11_HideWindow;
+ device->RaiseWindow = X11_RaiseWindow;
+ device->MaximizeWindow = X11_MaximizeWindow;
+ device->MinimizeWindow = X11_MinimizeWindow;
+ device->RestoreWindow = X11_RestoreWindow;
+ device->SetWindowBordered = X11_SetWindowBordered;
+ device->SetWindowResizable = X11_SetWindowResizable;
+ device->SetWindowFullscreen = X11_SetWindowFullscreen;
+ device->SetWindowGammaRamp = X11_SetWindowGammaRamp;
+ device->SetWindowGrab = X11_SetWindowGrab;
+ device->DestroyWindow = X11_DestroyWindow;
+ device->CreateWindowFramebuffer = X11_CreateWindowFramebuffer;
+ device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer;
+ device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer;
+ device->GetWindowWMInfo = X11_GetWindowWMInfo;
+ device->SetWindowHitTest = X11_SetWindowHitTest;
+ device->AcceptDragAndDrop = X11_AcceptDragAndDrop;
+
+ device->shape_driver.CreateShaper = X11_CreateShaper;
+ device->shape_driver.SetWindowShape = X11_SetWindowShape;
+ device->shape_driver.ResizeWindowShape = X11_ResizeWindowShape;
+
+#if SDL_VIDEO_OPENGL_GLX
+ device->GL_LoadLibrary = X11_GL_LoadLibrary;
+ device->GL_GetProcAddress = X11_GL_GetProcAddress;
+ device->GL_UnloadLibrary = X11_GL_UnloadLibrary;
+ device->GL_CreateContext = X11_GL_CreateContext;
+ device->GL_MakeCurrent = X11_GL_MakeCurrent;
+ device->GL_SetSwapInterval = X11_GL_SetSwapInterval;
+ device->GL_GetSwapInterval = X11_GL_GetSwapInterval;
+ device->GL_SwapWindow = X11_GL_SwapWindow;
+ device->GL_DeleteContext = X11_GL_DeleteContext;
+#elif SDL_VIDEO_OPENGL_EGL
+ device->GL_LoadLibrary = X11_GLES_LoadLibrary;
+ device->GL_GetProcAddress = X11_GLES_GetProcAddress;
+ device->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
+ device->GL_CreateContext = X11_GLES_CreateContext;
+ device->GL_MakeCurrent = X11_GLES_MakeCurrent;
+ device->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
+ device->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
+ device->GL_SwapWindow = X11_GLES_SwapWindow;
+ device->GL_DeleteContext = X11_GLES_DeleteContext;
+#endif
+
+ device->SetClipboardText = X11_SetClipboardText;
+ device->GetClipboardText = X11_GetClipboardText;
+ device->HasClipboardText = X11_HasClipboardText;
+ device->StartTextInput = X11_StartTextInput;
+ device->StopTextInput = X11_StopTextInput;
+ device->SetTextInputRect = X11_SetTextInputRect;
+
+ device->free = X11_DeleteDevice;
+
+#if SDL_VIDEO_VULKAN
+ device->Vulkan_LoadLibrary = X11_Vulkan_LoadLibrary;
+ device->Vulkan_UnloadLibrary = X11_Vulkan_UnloadLibrary;
+ device->Vulkan_GetInstanceExtensions = X11_Vulkan_GetInstanceExtensions;
+ device->Vulkan_CreateSurface = X11_Vulkan_CreateSurface;
+#endif
+
+ return device;
+}
+
+VideoBootStrap X11_bootstrap = {
+ "x11", "SDL X11 video driver",
+ X11_Available, X11_CreateDevice
+};
+
+static int (*handler) (Display *, XErrorEvent *) = NULL;
+static int
+X11_CheckWindowManagerErrorHandler(Display * d, XErrorEvent * e)
+{
+ if (e->error_code == BadWindow) {
+ return (0);
+ } else {
+ return (handler(d, e));
+ }
+}
+
+static void
+X11_CheckWindowManager(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ Display *display = data->display;
+ Atom _NET_SUPPORTING_WM_CHECK;
+ int status, real_format;
+ Atom real_type;
+ unsigned long items_read = 0, items_left = 0;
+ unsigned char *propdata = NULL;
+ Window wm_window = 0;
+#ifdef DEBUG_WINDOW_MANAGER
+ char *wm_name;
+#endif
+
+ /* Set up a handler to gracefully catch errors */
+ X11_XSync(display, False);
+ handler = X11_XSetErrorHandler(X11_CheckWindowManagerErrorHandler);
+
+ _NET_SUPPORTING_WM_CHECK = X11_XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
+ status = X11_XGetWindowProperty(display, DefaultRootWindow(display), _NET_SUPPORTING_WM_CHECK, 0L, 1L, False, XA_WINDOW, &real_type, &real_format, &items_read, &items_left, &propdata);
+ if (status == Success) {
+ if (items_read) {
+ wm_window = ((Window*)propdata)[0];
+ }
+ if (propdata) {
+ X11_XFree(propdata);
+ propdata = NULL;
+ }
+ }
+
+ if (wm_window) {
+ status = X11_XGetWindowProperty(display, wm_window, _NET_SUPPORTING_WM_CHECK, 0L, 1L, False, XA_WINDOW, &real_type, &real_format, &items_read, &items_left, &propdata);
+ if (status != Success || !items_read || wm_window != ((Window*)propdata)[0]) {
+ wm_window = None;
+ }
+ if (status == Success && propdata) {
+ X11_XFree(propdata);
+ propdata = NULL;
+ }
+ }
+
+ /* Reset the error handler, we're done checking */
+ X11_XSync(display, False);
+ X11_XSetErrorHandler(handler);
+
+ if (!wm_window) {
+#ifdef DEBUG_WINDOW_MANAGER
+ printf("Couldn't get _NET_SUPPORTING_WM_CHECK property\n");
+#endif
+ return;
+ }
+ data->net_wm = SDL_TRUE;
+
+#ifdef DEBUG_WINDOW_MANAGER
+ wm_name = X11_GetWindowTitle(_this, wm_window);
+ printf("Window manager: %s\n", wm_name);
+ SDL_free(wm_name);
+#endif
+}
+
+
+int
+X11_VideoInit(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ /* Get the window class name, usually the name of the application */
+ data->classname = get_classname();
+
+ /* Get the process PID to be associated to the window */
+ data->pid = getpid();
+
+ /* I have no idea how random this actually is, or has to be. */
+ data->window_group = (XID) (((size_t) data->pid) ^ ((size_t) _this));
+
+ /* Look up some useful Atoms */
+#define GET_ATOM(X) data->X = X11_XInternAtom(data->display, #X, False)
+ GET_ATOM(WM_PROTOCOLS);
+ GET_ATOM(WM_DELETE_WINDOW);
+ GET_ATOM(WM_TAKE_FOCUS);
+ GET_ATOM(_NET_WM_STATE);
+ GET_ATOM(_NET_WM_STATE_HIDDEN);
+ GET_ATOM(_NET_WM_STATE_FOCUSED);
+ GET_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
+ GET_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
+ GET_ATOM(_NET_WM_STATE_FULLSCREEN);
+ GET_ATOM(_NET_WM_STATE_ABOVE);
+ GET_ATOM(_NET_WM_STATE_SKIP_TASKBAR);
+ GET_ATOM(_NET_WM_STATE_SKIP_PAGER);
+ GET_ATOM(_NET_WM_ALLOWED_ACTIONS);
+ GET_ATOM(_NET_WM_ACTION_FULLSCREEN);
+ GET_ATOM(_NET_WM_NAME);
+ GET_ATOM(_NET_WM_ICON_NAME);
+ GET_ATOM(_NET_WM_ICON);
+ GET_ATOM(_NET_WM_PING);
+ GET_ATOM(_NET_WM_WINDOW_OPACITY);
+ GET_ATOM(_NET_WM_USER_TIME);
+ GET_ATOM(_NET_ACTIVE_WINDOW);
+ GET_ATOM(_NET_FRAME_EXTENTS);
+ GET_ATOM(UTF8_STRING);
+ GET_ATOM(PRIMARY);
+ GET_ATOM(XdndEnter);
+ GET_ATOM(XdndPosition);
+ GET_ATOM(XdndStatus);
+ GET_ATOM(XdndTypeList);
+ GET_ATOM(XdndActionCopy);
+ GET_ATOM(XdndDrop);
+ GET_ATOM(XdndFinished);
+ GET_ATOM(XdndSelection);
+ GET_ATOM(XKLAVIER_STATE);
+
+ /* Detect the window manager */
+ X11_CheckWindowManager(_this);
+
+ if (X11_InitModes(_this) < 0) {
+ return -1;
+ }
+
+ X11_InitXinput2(_this);
+
+ if (X11_InitKeyboard(_this) != 0) {
+ return -1;
+ }
+ X11_InitMouse(_this);
+
+ X11_InitTouch(_this);
+
+#if SDL_USE_LIBDBUS
+ SDL_DBus_Init();
+#endif
+
+ return 0;
+}
+
+void
+X11_VideoQuit(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ if (data->clipboard_window) {
+ X11_XDestroyWindow(data->display, data->clipboard_window);
+ }
+
+ SDL_free(data->classname);
+#ifdef X_HAVE_UTF8_STRING
+ if (data->im) {
+ X11_XCloseIM(data->im);
+ }
+#endif
+
+ X11_QuitModes(_this);
+ X11_QuitKeyboard(_this);
+ X11_QuitMouse(_this);
+ X11_QuitTouch(_this);
+
+/* !!! FIXME: other subsystems use D-Bus, so we shouldn't quit it here;
+ have SDL.c do this at a higher level, or add refcounting. */
+#if SDL_USE_LIBDBUS
+ SDL_DBus_Quit();
+#endif
+}
+
+SDL_bool
+X11_UseDirectColorVisuals(void)
+{
+ return SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ? SDL_FALSE : SDL_TRUE;
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vim: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11video.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11video.h
new file mode 100644
index 0000000..c0dc08e
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11video.h
@@ -0,0 +1,156 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11video_h_
+#define SDL_x11video_h_
+
+#include "SDL_keycode.h"
+
+#include "../SDL_sysvideo.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#if SDL_VIDEO_DRIVER_X11_XCURSOR
+#include <X11/Xcursor/Xcursor.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XDBE
+#include <X11/extensions/Xdbe.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XINERAMA
+#include <X11/extensions/Xinerama.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+#include <X11/extensions/XInput2.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER
+#include <X11/extensions/scrnsaver.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XSHAPE
+#include <X11/extensions/shape.h>
+#endif
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+#include <X11/extensions/xf86vmode.h>
+#endif
+
+#include "../../core/linux/SDL_dbus.h"
+#include "../../core/linux/SDL_ime.h"
+
+#include "SDL_x11dyn.h"
+
+#include "SDL_x11clipboard.h"
+#include "SDL_x11events.h"
+#include "SDL_x11keyboard.h"
+#include "SDL_x11modes.h"
+#include "SDL_x11mouse.h"
+#include "SDL_x11opengl.h"
+#include "SDL_x11window.h"
+#include "SDL_x11vulkan.h"
+
+/* Private display data */
+
+typedef struct SDL_VideoData
+{
+ Display *display;
+ char *classname;
+ pid_t pid;
+ XIM im;
+ Uint32 screensaver_activity;
+ int numwindows;
+ SDL_WindowData **windowlist;
+ int windowlistlength;
+ XID window_group;
+ Window clipboard_window;
+
+ /* This is true for ICCCM2.0-compliant window managers */
+ SDL_bool net_wm;
+
+ /* Useful atoms */
+ Atom WM_PROTOCOLS;
+ Atom WM_DELETE_WINDOW;
+ Atom WM_TAKE_FOCUS;
+ Atom _NET_WM_STATE;
+ Atom _NET_WM_STATE_HIDDEN;
+ Atom _NET_WM_STATE_FOCUSED;
+ Atom _NET_WM_STATE_MAXIMIZED_VERT;
+ Atom _NET_WM_STATE_MAXIMIZED_HORZ;
+ Atom _NET_WM_STATE_FULLSCREEN;
+ Atom _NET_WM_STATE_ABOVE;
+ Atom _NET_WM_STATE_SKIP_TASKBAR;
+ Atom _NET_WM_STATE_SKIP_PAGER;
+ Atom _NET_WM_ALLOWED_ACTIONS;
+ Atom _NET_WM_ACTION_FULLSCREEN;
+ Atom _NET_WM_NAME;
+ Atom _NET_WM_ICON_NAME;
+ Atom _NET_WM_ICON;
+ Atom _NET_WM_PING;
+ Atom _NET_WM_WINDOW_OPACITY;
+ Atom _NET_WM_USER_TIME;
+ Atom _NET_ACTIVE_WINDOW;
+ Atom _NET_FRAME_EXTENTS;
+ Atom UTF8_STRING;
+ Atom PRIMARY;
+ Atom XdndEnter;
+ Atom XdndPosition;
+ Atom XdndStatus;
+ Atom XdndTypeList;
+ Atom XdndActionCopy;
+ Atom XdndDrop;
+ Atom XdndFinished;
+ Atom XdndSelection;
+ Atom XKLAVIER_STATE;
+
+ SDL_Scancode key_layout[256];
+ SDL_bool selection_waiting;
+
+ SDL_bool broken_pointer_grab; /* true if XGrabPointer seems unreliable. */
+
+ Uint32 last_mode_change_deadline;
+
+ SDL_bool global_mouse_changed;
+ SDL_Point global_mouse_position;
+ Uint32 global_mouse_buttons;
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+ XkbDescPtr xkb;
+#endif
+
+ KeyCode filter_code;
+ Time filter_time;
+
+#if SDL_VIDEO_VULKAN
+ /* Vulkan variables only valid if _this->vulkan_config.loader_handle is not NULL */
+ void *vulkan_xlib_xcb_library;
+ PFN_XGetXCBConnection vulkan_XGetXCBConnection;
+#endif
+
+} SDL_VideoData;
+
+extern SDL_bool X11_UseDirectColorVisuals(void);
+
+#endif /* SDL_x11video_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11vulkan.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11vulkan.c
new file mode 100644
index 0000000..ec43aef
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11vulkan.c
@@ -0,0 +1,243 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_X11
+
+#include "SDL_x11video.h"
+#include "SDL_assert.h"
+
+#include "SDL_loadso.h"
+#include "SDL_x11vulkan.h"
+
+#include <X11/Xlib.h>
+/*#include <xcb/xcb.h>*/
+/*
+typedef uint32_t xcb_window_t;
+typedef uint32_t xcb_visualid_t;
+*/
+
+int X11_Vulkan_LoadLibrary(_THIS, const char *path)
+{
+ SDL_VideoData *videoData = (SDL_VideoData *)_this->driverdata;
+ VkExtensionProperties *extensions = NULL;
+ Uint32 extensionCount = 0;
+ SDL_bool hasSurfaceExtension = SDL_FALSE;
+ SDL_bool hasXlibSurfaceExtension = SDL_FALSE;
+ SDL_bool hasXCBSurfaceExtension = SDL_FALSE;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
+ Uint32 i;
+ if(_this->vulkan_config.loader_handle)
+ return SDL_SetError("Vulkan already loaded");
+
+ /* Load the Vulkan loader library */
+ if(!path)
+ path = SDL_getenv("SDL_VULKAN_LIBRARY");
+ if(!path)
+ path = "libvulkan.so.1";
+ _this->vulkan_config.loader_handle = SDL_LoadObject(path);
+ if(!_this->vulkan_config.loader_handle)
+ return -1;
+ SDL_strlcpy(_this->vulkan_config.loader_path, path, SDL_arraysize(_this->vulkan_config.loader_path));
+ vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
+ _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
+ if(!vkGetInstanceProcAddr)
+ goto fail;
+ _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
+ _this->vulkan_config.vkEnumerateInstanceExtensionProperties =
+ (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
+ VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
+ if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
+ goto fail;
+ extensions = SDL_Vulkan_CreateInstanceExtensionsList(
+ (PFN_vkEnumerateInstanceExtensionProperties)
+ _this->vulkan_config.vkEnumerateInstanceExtensionProperties,
+ &extensionCount);
+ if(!extensions)
+ goto fail;
+ for(i = 0; i < extensionCount; i++)
+ {
+ if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
+ hasSurfaceExtension = SDL_TRUE;
+ else if(SDL_strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
+ hasXCBSurfaceExtension = SDL_TRUE;
+ else if(SDL_strcmp(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
+ hasXlibSurfaceExtension = SDL_TRUE;
+ }
+ SDL_free(extensions);
+ if(!hasSurfaceExtension)
+ {
+ SDL_SetError("Installed Vulkan doesn't implement the "
+ VK_KHR_SURFACE_EXTENSION_NAME " extension");
+ goto fail;
+ }
+ if(hasXlibSurfaceExtension)
+ {
+ videoData->vulkan_xlib_xcb_library = NULL;
+ }
+ else if(!hasXCBSurfaceExtension)
+ {
+ SDL_SetError("Installed Vulkan doesn't implement either the "
+ VK_KHR_XCB_SURFACE_EXTENSION_NAME "extension or the "
+ VK_KHR_XLIB_SURFACE_EXTENSION_NAME " extension");
+ goto fail;
+ }
+ else
+ {
+ const char *libX11XCBLibraryName = SDL_getenv("SDL_X11_XCB_LIBRARY");
+ if(!libX11XCBLibraryName)
+ libX11XCBLibraryName = "libX11-xcb.so";
+ videoData->vulkan_xlib_xcb_library = SDL_LoadObject(libX11XCBLibraryName);
+ if(!videoData->vulkan_xlib_xcb_library)
+ goto fail;
+ videoData->vulkan_XGetXCBConnection =
+ SDL_LoadFunction(videoData->vulkan_xlib_xcb_library, "XGetXCBConnection");
+ if(!videoData->vulkan_XGetXCBConnection)
+ {
+ SDL_UnloadObject(videoData->vulkan_xlib_xcb_library);
+ goto fail;
+ }
+ }
+ return 0;
+
+fail:
+ SDL_UnloadObject(_this->vulkan_config.loader_handle);
+ _this->vulkan_config.loader_handle = NULL;
+ return -1;
+}
+
+void X11_Vulkan_UnloadLibrary(_THIS)
+{
+ SDL_VideoData *videoData = (SDL_VideoData *)_this->driverdata;
+ if(_this->vulkan_config.loader_handle)
+ {
+ if(videoData->vulkan_xlib_xcb_library)
+ SDL_UnloadObject(videoData->vulkan_xlib_xcb_library);
+ SDL_UnloadObject(_this->vulkan_config.loader_handle);
+ _this->vulkan_config.loader_handle = NULL;
+ }
+}
+
+SDL_bool X11_Vulkan_GetInstanceExtensions(_THIS,
+ SDL_Window *window,
+ unsigned *count,
+ const char **names)
+{
+ SDL_VideoData *videoData = (SDL_VideoData *)_this->driverdata;
+ if(!_this->vulkan_config.loader_handle)
+ {
+ SDL_SetError("Vulkan is not loaded");
+ return SDL_FALSE;
+ }
+ if(videoData->vulkan_xlib_xcb_library)
+ {
+ static const char *const extensionsForXCB[] = {
+ VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XCB_SURFACE_EXTENSION_NAME,
+ };
+ return SDL_Vulkan_GetInstanceExtensions_Helper(
+ count, names, SDL_arraysize(extensionsForXCB), extensionsForXCB);
+ }
+ else
+ {
+ static const char *const extensionsForXlib[] = {
+ VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
+ };
+ return SDL_Vulkan_GetInstanceExtensions_Helper(
+ count, names, SDL_arraysize(extensionsForXlib), extensionsForXlib);
+ }
+}
+
+SDL_bool X11_Vulkan_CreateSurface(_THIS,
+ SDL_Window *window,
+ VkInstance instance,
+ VkSurfaceKHR *surface)
+{
+ SDL_VideoData *videoData = (SDL_VideoData *)_this->driverdata;
+ SDL_WindowData *windowData = (SDL_WindowData *)window->driverdata;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+ if(!_this->vulkan_config.loader_handle)
+ {
+ SDL_SetError("Vulkan is not loaded");
+ return SDL_FALSE;
+ }
+ vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
+ if(videoData->vulkan_xlib_xcb_library)
+ {
+ PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR =
+ (PFN_vkCreateXcbSurfaceKHR)vkGetInstanceProcAddr((VkInstance)instance,
+ "vkCreateXcbSurfaceKHR");
+ VkXcbSurfaceCreateInfoKHR createInfo;
+ VkResult result;
+ if(!vkCreateXcbSurfaceKHR)
+ {
+ SDL_SetError(VK_KHR_XCB_SURFACE_EXTENSION_NAME
+ " extension is not enabled in the Vulkan instance.");
+ return SDL_FALSE;
+ }
+ SDL_zero(createInfo);
+ createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+ createInfo.connection = videoData->vulkan_XGetXCBConnection(videoData->display);
+ if(!createInfo.connection)
+ {
+ SDL_SetError("XGetXCBConnection failed");
+ return SDL_FALSE;
+ }
+ createInfo.window = (xcb_window_t)windowData->xwindow;
+ result = vkCreateXcbSurfaceKHR(instance, &createInfo,
+ NULL, surface);
+ if(result != VK_SUCCESS)
+ {
+ SDL_SetError("vkCreateXcbSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result));
+ return SDL_FALSE;
+ }
+ return SDL_TRUE;
+ }
+ else
+ {
+ PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR =
+ (PFN_vkCreateXlibSurfaceKHR)vkGetInstanceProcAddr((VkInstance)instance,
+ "vkCreateXlibSurfaceKHR");
+ VkXlibSurfaceCreateInfoKHR createInfo;
+ VkResult result;
+ if(!vkCreateXlibSurfaceKHR)
+ {
+ SDL_SetError(VK_KHR_XLIB_SURFACE_EXTENSION_NAME
+ " extension is not enabled in the Vulkan instance.");
+ return SDL_FALSE;
+ }
+ SDL_zero(createInfo);
+ createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
+ createInfo.dpy = videoData->display;
+ createInfo.window = (xcb_window_t)windowData->xwindow;
+ result = vkCreateXlibSurfaceKHR(instance, &createInfo,
+ NULL, surface);
+ if(result != VK_SUCCESS)
+ {
+ SDL_SetError("vkCreateXlibSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result));
+ return SDL_FALSE;
+ }
+ return SDL_TRUE;
+ }
+}
+
+#endif
+
+/* vim: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11vulkan.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11vulkan.h
new file mode 100644
index 0000000..152d9d7
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11vulkan.h
@@ -0,0 +1,48 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11vulkan_h_
+#define SDL_x11vulkan_h_
+
+#include "../SDL_vulkan_internal.h"
+
+#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_X11
+
+/*typedef struct xcb_connection_t xcb_connection_t;*/
+typedef xcb_connection_t *(*PFN_XGetXCBConnection)(Display *dpy);
+
+int X11_Vulkan_LoadLibrary(_THIS, const char *path);
+void X11_Vulkan_UnloadLibrary(_THIS);
+SDL_bool X11_Vulkan_GetInstanceExtensions(_THIS,
+ SDL_Window *window,
+ unsigned *count,
+ const char **names);
+SDL_bool X11_Vulkan_CreateSurface(_THIS,
+ SDL_Window *window,
+ VkInstance instance,
+ VkSurfaceKHR *surface);
+
+#endif
+
+#endif /* SDL_x11vulkan_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11window.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11window.c
new file mode 100644
index 0000000..0a254b0
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11window.c
@@ -0,0 +1,1619 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL_assert.h"
+#include "SDL_hints.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_pixels_c.h"
+#include "../../events/SDL_keyboard_c.h"
+#include "../../events/SDL_mouse_c.h"
+
+#include "SDL_x11video.h"
+#include "SDL_x11mouse.h"
+#include "SDL_x11shape.h"
+#include "SDL_x11xinput2.h"
+
+#if SDL_VIDEO_OPENGL_EGL
+#include "SDL_x11opengles.h"
+#endif
+
+#include "SDL_timer.h"
+#include "SDL_syswm.h"
+#include "SDL_log.h"
+
+#define _NET_WM_STATE_REMOVE 0l
+#define _NET_WM_STATE_ADD 1l
+
+static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win)
+{
+ return ev->type == MapNotify && ev->xmap.window == *((Window*)win);
+}
+static Bool isUnmapNotify(Display *dpy, XEvent *ev, XPointer win)
+{
+ return ev->type == UnmapNotify && ev->xunmap.window == *((Window*)win);
+}
+
+/*
+static Bool isConfigureNotify(Display *dpy, XEvent *ev, XPointer win)
+{
+ return ev->type == ConfigureNotify && ev->xconfigure.window == *((Window*)win);
+}
+static Bool
+X11_XIfEventTimeout(Display *display, XEvent *event_return, Bool (*predicate)(), XPointer arg, int timeoutMS)
+{
+ Uint32 start = SDL_GetTicks();
+
+ while (!X11_XCheckIfEvent(display, event_return, predicate, arg)) {
+ if (SDL_TICKS_PASSED(SDL_GetTicks(), start + timeoutMS)) {
+ return False;
+ }
+ }
+ return True;
+}
+*/
+
+static SDL_bool
+X11_IsWindowLegacyFullscreen(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ return (data->fswindow != 0);
+}
+
+static SDL_bool
+X11_IsWindowMapped(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ XWindowAttributes attr;
+
+ X11_XGetWindowAttributes(videodata->display, data->xwindow, &attr);
+ if (attr.map_state != IsUnmapped) {
+ return SDL_TRUE;
+ } else {
+ return SDL_FALSE;
+ }
+}
+
+#if 0
+static SDL_bool
+X11_IsActionAllowed(SDL_Window *window, Atom action)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Atom _NET_WM_ALLOWED_ACTIONS = data->videodata->_NET_WM_ALLOWED_ACTIONS;
+ Atom type;
+ Display *display = data->videodata->display;
+ int form;
+ unsigned long remain;
+ unsigned long len, i;
+ Atom *list;
+ SDL_bool ret = SDL_FALSE;
+
+ if (X11_XGetWindowProperty(display, data->xwindow, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, XA_ATOM, &type, &form, &len, &remain, (unsigned char **)&list) == Success)
+ {
+ for (i=0; i<len; ++i)
+ {
+ if (list[i] == action) {
+ ret = SDL_TRUE;
+ break;
+ }
+ }
+ X11_XFree(list);
+ }
+ return ret;
+}
+#endif /* 0 */
+
+void
+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 _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.
+ If we did, this would indicate to the window manager that we don't
+ actually want to be mapped during X11_XMapRaised(), which would be bad.
+ *
+ if (flags & SDL_WINDOW_HIDDEN) {
+ 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;
+ }
+ if (flags & SDL_WINDOW_MAXIMIZED) {
+ atoms[count++] = _NET_WM_STATE_MAXIMIZED_VERT;
+ atoms[count++] = _NET_WM_STATE_MAXIMIZED_HORZ;
+ }
+ 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);
+ } else {
+ X11_XDeleteProperty(display, xwindow, _NET_WM_STATE);
+ }
+}
+
+Uint32
+X11_GetNetWMState(_THIS, Window xwindow)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ Display *display = videodata->display;
+ 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 actualType;
+ int actualFormat;
+ unsigned long i, numItems, bytesAfter;
+ unsigned char *propertyValue = NULL;
+ long maxLength = 1024;
+ Uint32 flags = 0;
+
+ if (X11_XGetWindowProperty(display, xwindow, _NET_WM_STATE,
+ 0l, maxLength, False, XA_ATOM, &actualType,
+ &actualFormat, &numItems, &bytesAfter,
+ &propertyValue) == Success) {
+ Atom *atoms = (Atom *) propertyValue;
+ int maximized = 0;
+ int fullscreen = 0;
+
+ for (i = 0; i < numItems; ++i) {
+ if (atoms[i] == _NET_WM_STATE_HIDDEN) {
+ flags |= SDL_WINDOW_HIDDEN;
+ } else if (atoms[i] == _NET_WM_STATE_FOCUSED) {
+ flags |= SDL_WINDOW_INPUT_FOCUS;
+ } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_VERT) {
+ maximized |= 1;
+ } else if (atoms[i] == _NET_WM_STATE_MAXIMIZED_HORZ) {
+ maximized |= 2;
+ } else if ( atoms[i] == _NET_WM_STATE_FULLSCREEN) {
+ fullscreen = 1;
+ }
+ }
+ if (maximized == 3) {
+ flags |= SDL_WINDOW_MAXIMIZED;
+ }
+
+ 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);
+ }
+
+ /* FIXME, check the size hints for resizable */
+ /* flags |= SDL_WINDOW_RESIZABLE; */
+
+ return flags;
+}
+
+static int
+SetupWindowData(_THIS, SDL_Window * window, Window w, BOOL created)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ SDL_WindowData *data;
+ int numwindows = videodata->numwindows;
+ int windowlistlength = videodata->windowlistlength;
+ SDL_WindowData **windowlist = videodata->windowlist;
+
+ /* Allocate the window data */
+ data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ return SDL_OutOfMemory();
+ }
+ data->window = window;
+ data->xwindow = w;
+#ifdef X_HAVE_UTF8_STRING
+ if (SDL_X11_HAVE_UTF8 && videodata->im) {
+ data->ic =
+ X11_XCreateIC(videodata->im, XNClientWindow, w, XNFocusWindow, w,
+ XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+ NULL);
+ }
+#endif
+ data->created = created;
+ data->videodata = videodata;
+
+ /* Associate the data with the window */
+
+ if (numwindows < windowlistlength) {
+ windowlist[numwindows] = data;
+ videodata->numwindows++;
+ } else {
+ windowlist =
+ (SDL_WindowData **) SDL_realloc(windowlist,
+ (numwindows +
+ 1) * sizeof(*windowlist));
+ if (!windowlist) {
+ SDL_free(data);
+ return SDL_OutOfMemory();
+ }
+ windowlist[numwindows] = data;
+ videodata->numwindows++;
+ videodata->windowlistlength++;
+ videodata->windowlist = windowlist;
+ }
+
+ /* Fill in the SDL window with the window data */
+ {
+ XWindowAttributes attrib;
+
+ X11_XGetWindowAttributes(data->videodata->display, w, &attrib);
+ window->x = attrib.x;
+ window->y = attrib.y;
+ window->w = attrib.width;
+ window->h = attrib.height;
+ if (attrib.map_state != IsUnmapped) {
+ window->flags |= SDL_WINDOW_SHOWN;
+ } else {
+ window->flags &= ~SDL_WINDOW_SHOWN;
+ }
+ data->visual = attrib.visual;
+ data->colormap = attrib.colormap;
+ }
+
+ window->flags |= X11_GetNetWMState(_this, w);
+
+ {
+ Window FocalWindow;
+ int RevertTo=0;
+ X11_XGetInputFocus(data->videodata->display, &FocalWindow, &RevertTo);
+ if (FocalWindow==w)
+ {
+ window->flags |= SDL_WINDOW_INPUT_FOCUS;
+ }
+
+ if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
+ SDL_SetKeyboardFocus(data->window);
+ }
+
+ if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
+ /* Tell x11 to clip mouse */
+ }
+ }
+
+ /* All done! */
+ window->driverdata = data;
+ return 0;
+}
+
+static void
+SetWindowBordered(Display *display, int screen, Window window, SDL_bool border)
+{
+ /*
+ * this code used to check for KWM_WIN_DECORATION, but KDE hasn't
+ * supported it for years and years. It now respects _MOTIF_WM_HINTS.
+ * Gnome is similar: just use the Motif atom.
+ */
+
+ Atom WM_HINTS = X11_XInternAtom(display, "_MOTIF_WM_HINTS", True);
+ if (WM_HINTS != None) {
+ /* Hints used by Motif compliant window managers */
+ struct
+ {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long input_mode;
+ unsigned long status;
+ } MWMHints = {
+ (1L << 1), 0, border ? 1 : 0, 0, 0
+ };
+
+ X11_XChangeProperty(display, window, WM_HINTS, WM_HINTS, 32,
+ PropModeReplace, (unsigned char *) &MWMHints,
+ sizeof(MWMHints) / sizeof(long));
+ } else { /* set the transient hints instead, if necessary */
+ X11_XSetTransientForHint(display, window, RootWindow(display, screen));
+ }
+}
+
+int
+X11_CreateWindow(_THIS, SDL_Window * window)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ SDL_DisplayData *displaydata =
+ (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
+ SDL_WindowData *windowdata;
+ Display *display = data->display;
+ int screen = displaydata->screen;
+ Visual *visual;
+ int depth;
+ XSetWindowAttributes xattr;
+ Window w;
+ XSizeHints *sizehints;
+ XWMHints *wmhints;
+ XClassHint *classhints;
+ Atom _NET_WM_BYPASS_COMPOSITOR;
+ Atom _NET_WM_WINDOW_TYPE;
+ Atom wintype;
+ const char *wintype_name = NULL;
+ long compositor = 1;
+ Atom _NET_WM_PID;
+ long fevent = 0;
+
+#if SDL_VIDEO_OPENGL_GLX || SDL_VIDEO_OPENGL_EGL
+ if ((window->flags & SDL_WINDOW_OPENGL) &&
+ !SDL_getenv("SDL_VIDEO_X11_VISUALID")) {
+ XVisualInfo *vinfo = NULL;
+
+#if SDL_VIDEO_OPENGL_EGL
+ if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
+#if SDL_VIDEO_OPENGL_GLX
+ && ( !_this->gl_data || X11_GL_UseEGL(_this) )
+#endif
+ ) {
+ vinfo = X11_GLES_GetVisual(_this, display, screen);
+ } else
+#endif
+ {
+#if SDL_VIDEO_OPENGL_GLX
+ vinfo = X11_GL_GetVisual(_this, display, screen);
+#endif
+ }
+
+ if (!vinfo) {
+ return -1;
+ }
+ visual = vinfo->visual;
+ depth = vinfo->depth;
+ X11_XFree(vinfo);
+ } else
+#endif
+ {
+ visual = displaydata->visual;
+ depth = displaydata->depth;
+ }
+
+ xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU)) ? True : False;
+ xattr.background_pixmap = None;
+ xattr.border_pixel = 0;
+
+ if (visual->class == DirectColor) {
+ XColor *colorcells;
+ int i;
+ int ncolors;
+ int rmax, gmax, bmax;
+ int rmask, gmask, bmask;
+ int rshift, gshift, bshift;
+
+ xattr.colormap =
+ X11_XCreateColormap(display, RootWindow(display, screen),
+ visual, AllocAll);
+
+ /* If we can't create a colormap, then we must die */
+ if (!xattr.colormap) {
+ return SDL_SetError("Could not create writable colormap");
+ }
+
+ /* OK, we got a colormap, now fill it in as best as we can */
+ colorcells = SDL_malloc(visual->map_entries * sizeof(XColor));
+ if (!colorcells) {
+ return SDL_OutOfMemory();
+ }
+ ncolors = visual->map_entries;
+ rmax = 0xffff;
+ gmax = 0xffff;
+ bmax = 0xffff;
+
+ rshift = 0;
+ rmask = visual->red_mask;
+ while (0 == (rmask & 1)) {
+ rshift++;
+ rmask >>= 1;
+ }
+
+ gshift = 0;
+ gmask = visual->green_mask;
+ while (0 == (gmask & 1)) {
+ gshift++;
+ gmask >>= 1;
+ }
+
+ bshift = 0;
+ bmask = visual->blue_mask;
+ while (0 == (bmask & 1)) {
+ bshift++;
+ bmask >>= 1;
+ }
+
+ /* build the color table pixel values */
+ for (i = 0; i < ncolors; i++) {
+ Uint32 red = (rmax * i) / (ncolors - 1);
+ Uint32 green = (gmax * i) / (ncolors - 1);
+ Uint32 blue = (bmax * i) / (ncolors - 1);
+
+ Uint32 rbits = (rmask * i) / (ncolors - 1);
+ Uint32 gbits = (gmask * i) / (ncolors - 1);
+ Uint32 bbits = (bmask * i) / (ncolors - 1);
+
+ Uint32 pix =
+ (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
+
+ colorcells[i].pixel = pix;
+
+ colorcells[i].red = red;
+ colorcells[i].green = green;
+ colorcells[i].blue = blue;
+
+ colorcells[i].flags = DoRed | DoGreen | DoBlue;
+ }
+
+ X11_XStoreColors(display, xattr.colormap, colorcells, ncolors);
+
+ SDL_free(colorcells);
+ } else {
+ xattr.colormap =
+ X11_XCreateColormap(display, RootWindow(display, screen),
+ visual, AllocNone);
+ }
+
+ w = X11_XCreateWindow(display, RootWindow(display, screen),
+ window->x, window->y, window->w, window->h,
+ 0, depth, InputOutput, visual,
+ (CWOverrideRedirect | CWBackPixmap | CWBorderPixel |
+ CWColormap), &xattr);
+ if (!w) {
+ return SDL_SetError("Couldn't create window");
+ }
+
+ SetWindowBordered(display, screen, w,
+ (window->flags & SDL_WINDOW_BORDERLESS) == 0);
+
+ sizehints = X11_XAllocSizeHints();
+ /* Setup the normal size hints */
+ sizehints->flags = 0;
+ if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
+ sizehints->min_width = sizehints->max_width = window->w;
+ sizehints->min_height = sizehints->max_height = window->h;
+ sizehints->flags |= (PMaxSize | PMinSize);
+ }
+ sizehints->x = window->x;
+ sizehints->y = window->y;
+ sizehints->flags |= USPosition;
+
+ /* Setup the input hints so we get keyboard input */
+ wmhints = X11_XAllocWMHints();
+ wmhints->input = True;
+ wmhints->window_group = data->window_group;
+ wmhints->flags = InputHint | WindowGroupHint;
+
+ /* Setup the class hints so we can get an icon (AfterStep) */
+ classhints = X11_XAllocClassHint();
+ classhints->res_name = data->classname;
+ classhints->res_class = data->classname;
+
+ /* Set the size, input and class hints, and define WM_CLIENT_MACHINE and WM_LOCALE_NAME */
+ X11_XSetWMProperties(display, w, NULL, NULL, NULL, 0, sizehints, wmhints, classhints);
+
+ X11_XFree(sizehints);
+ X11_XFree(wmhints);
+ 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 *) &pid, 1);
+ }
+
+ /* Set the window manager state */
+ X11_SetNetWMState(_this, w, window->flags);
+
+ 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);
+ wintype = X11_XInternAtom(display, wintype_name, False);
+ X11_XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
+ 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[3];
+ int proto_count = 0;
+
+ 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 (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]));
+
+ X11_XSetWMProtocols(display, w, protocols, proto_count);
+ }
+
+ if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) {
+ X11_XDestroyWindow(display, w);
+ return -1;
+ }
+ windowdata = (SDL_WindowData *) window->driverdata;
+
+#if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
+ if ((window->flags & SDL_WINDOW_OPENGL) &&
+ _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
+#if SDL_VIDEO_OPENGL_GLX
+ && ( !_this->gl_data || X11_GL_UseEGL(_this) )
+#endif
+ ) {
+#if SDL_VIDEO_OPENGL_EGL
+ if (!_this->egl_data) {
+ X11_XDestroyWindow(display, w);
+ return -1;
+ }
+
+ /* Create the GLES window surface */
+ windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) w);
+
+ if (windowdata->egl_surface == EGL_NO_SURFACE) {
+ X11_XDestroyWindow(display, w);
+ return SDL_SetError("Could not create GLES window surface");
+ }
+#else
+ return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
+#endif /* SDL_VIDEO_OPENGL_EGL */
+ }
+#endif
+
+
+#ifdef X_HAVE_UTF8_STRING
+ if (SDL_X11_HAVE_UTF8 && windowdata->ic) {
+ X11_XGetICValues(windowdata->ic, XNFilterEvents, &fevent, NULL);
+ }
+#endif
+
+ X11_Xinput2SelectTouch(_this, window);
+
+ X11_XSelectInput(display, w,
+ (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
+ ExposureMask | ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | KeyPressMask | KeyReleaseMask |
+ PropertyChangeMask | StructureNotifyMask |
+ KeymapStateMask | fevent));
+
+ X11_XFlush(display);
+
+ return 0;
+}
+
+int
+X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
+{
+ Window w = (Window) data;
+
+ window->title = X11_GetWindowTitle(_this, w);
+
+ if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+char *
+X11_GetWindowTitle(_THIS, Window xwindow)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ Display *display = data->display;
+ int status, real_format;
+ Atom real_type;
+ unsigned long items_read, items_left;
+ unsigned char *propdata;
+ char *title = NULL;
+
+ status = X11_XGetWindowProperty(display, xwindow, data->_NET_WM_NAME,
+ 0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
+ &items_read, &items_left, &propdata);
+ if (status == Success && propdata) {
+ title = SDL_strdup(SDL_static_cast(char*, propdata));
+ X11_XFree(propdata);
+ } else {
+ status = X11_XGetWindowProperty(display, xwindow, XA_WM_NAME,
+ 0L, 8192L, False, XA_STRING, &real_type, &real_format,
+ &items_read, &items_left, &propdata);
+ if (status == Success && propdata) {
+ title = SDL_iconv_string("UTF-8", "", SDL_static_cast(char*, propdata), items_read+1);
+ X11_XFree(propdata);
+ } else {
+ title = SDL_strdup("");
+ }
+ }
+ return title;
+}
+
+void
+X11_SetWindowTitle(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ XTextProperty titleprop;
+ Status status;
+ const char *title = window->title ? window->title : "";
+ char *title_locale = NULL;
+
+#ifdef X_HAVE_UTF8_STRING
+ Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME;
+#endif
+
+ title_locale = SDL_iconv_utf8_locale(title);
+ if (!title_locale) {
+ SDL_OutOfMemory();
+ return;
+ }
+
+ status = X11_XStringListToTextProperty(&title_locale, 1, &titleprop);
+ SDL_free(title_locale);
+ if (status) {
+ X11_XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME);
+ X11_XFree(titleprop.value);
+ }
+#ifdef X_HAVE_UTF8_STRING
+ if (SDL_X11_HAVE_UTF8) {
+ status = X11_Xutf8TextListToTextProperty(display, (char **) &title, 1,
+ XUTF8StringStyle, &titleprop);
+ if (status == Success) {
+ X11_XSetTextProperty(display, data->xwindow, &titleprop,
+ _NET_WM_NAME);
+ X11_XFree(titleprop.value);
+ }
+ }
+#endif
+
+ X11_XFlush(display);
+}
+
+void
+X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON;
+
+ if (icon) {
+ int propsize;
+ long *propdata;
+
+ /* Set the _NET_WM_ICON property */
+ SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888);
+ propsize = 2 + (icon->w * icon->h);
+ propdata = SDL_malloc(propsize * sizeof(long));
+ if (propdata) {
+ int x, y;
+ Uint32 *src;
+ long *dst;
+
+ propdata[0] = icon->w;
+ propdata[1] = icon->h;
+ dst = &propdata[2];
+ for (y = 0; y < icon->h; ++y) {
+ src = (Uint32*)((Uint8*)icon->pixels + y * icon->pitch);
+ for (x = 0; x < icon->w; ++x) {
+ *dst++ = *src++;
+ }
+ }
+ X11_XChangeProperty(display, data->xwindow, _NET_WM_ICON, XA_CARDINAL,
+ 32, PropModeReplace, (unsigned char *) propdata,
+ propsize);
+ }
+ SDL_free(propdata);
+ } else {
+ X11_XDeleteProperty(display, data->xwindow, _NET_WM_ICON);
+ }
+ X11_XFlush(display);
+}
+
+void
+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 - data->border_left, window->y - data->border_top);
+ X11_XFlush(display);
+}
+
+void
+X11_SetWindowMinimumSize(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+
+ if (window->flags & SDL_WINDOW_RESIZABLE) {
+ XSizeHints *sizehints = X11_XAllocSizeHints();
+ long userhints;
+
+ X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
+
+ sizehints->min_width = window->min_w;
+ sizehints->min_height = window->min_h;
+ sizehints->flags |= PMinSize;
+
+ 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_SetWindowMaximumSize(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+
+ if (window->flags & SDL_WINDOW_RESIZABLE) {
+ XSizeHints *sizehints = X11_XAllocSizeHints();
+ long userhints;
+
+ X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
+
+ sizehints->max_width = window->max_w;
+ sizehints->max_height = window->max_h;
+ sizehints->flags |= 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_SetWindowSize(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+
+ if (SDL_IsShapedWindow(window)) {
+ X11_ResizeWindowShape(window);
+ }
+ if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
+ /* Apparently, if the X11 Window is set to a 'non-resizable' window, you cannot resize it using the X11_XResizeWindow, thus
+ we must set the size hints to adjust the window size. */
+ XSizeHints *sizehints = X11_XAllocSizeHints();
+ long userhints;
+
+ X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
+
+ sizehints->min_width = sizehints->max_width = window->w;
+ sizehints->min_height = sizehints->max_height = window->h;
+ sizehints->flags |= PMinSize | PMaxSize;
+
+ X11_XSetWMNormalHints(display, data->xwindow, sizehints);
+
+ X11_XFree(sizehints);
+
+ /* From Pierre-Loup:
+ WMs each have their little quirks with that. When you change the
+ size hints, they get a ConfigureNotify event with the
+ WM_NORMAL_SIZE_HINTS Atom. They all save the hints then, but they
+ don't all resize the window right away to enforce the new hints.
+
+ Some of them resize only after:
+ - A user-initiated move or resize
+ - A code-initiated move or resize
+ - Hiding & showing window (Unmap & map)
+
+ The following move & resize seems to help a lot of WMs that didn't
+ properly update after the hints were changed. We don't do a
+ hide/show, because there are supposedly subtle problems with doing so
+ and transitioning from windowed to fullscreen in Unity.
+ */
+ 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);
+ } else {
+ X11_XResizeWindow(display, data->xwindow, window->w, window->h);
+ }
+
+ 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)
+{
+ const SDL_bool focused = ((window->flags & SDL_WINDOW_INPUT_FOCUS) != 0);
+ const SDL_bool visible = ((window->flags & SDL_WINDOW_HIDDEN) == 0);
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_DisplayData *displaydata =
+ (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
+ Display *display = data->videodata->display;
+ XEvent event;
+
+ SetWindowBordered(display, displaydata->screen, data->xwindow, bordered);
+ X11_XFlush(display);
+
+ if (visible) {
+ XWindowAttributes attr;
+ do {
+ X11_XSync(display, False);
+ X11_XGetWindowAttributes(display, data->xwindow, &attr);
+ } while (attr.map_state != IsViewable);
+
+ if (focused) {
+ X11_XSetInputFocus(display, data->xwindow, RevertToParent, CurrentTime);
+ }
+ }
+
+ /* make sure these don't make it to the real event queue if they fired here. */
+ X11_XSync(display, False);
+ X11_XCheckIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
+ X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
+}
+
+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;
+ Display *display = data->videodata->display;
+ XEvent event;
+
+ if (!X11_IsWindowMapped(_this, window)) {
+ X11_XMapRaised(display, data->xwindow);
+ /* Blocking wait for "MapNotify" event.
+ * We use X11_XIfEvent because pXWindowEvent takes a mask rather than a type,
+ * and XCheckTypedWindowEvent doesn't block */
+ if(!(window->flags & SDL_WINDOW_FOREIGN))
+ X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
+ X11_XFlush(display);
+ }
+
+ if (!data->videodata->net_wm) {
+ /* no WM means no FocusIn event, which confuses us. Force it. */
+ X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime);
+ X11_XFlush(display);
+ }
+}
+
+void
+X11_HideWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
+ Display *display = data->videodata->display;
+ XEvent event;
+
+ if (X11_IsWindowMapped(_this, window)) {
+ X11_XWithdrawWindow(display, data->xwindow, displaydata->screen);
+ /* Blocking wait for "UnmapNotify" event */
+ if(!(window->flags & SDL_WINDOW_FOREIGN))
+ X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow);
+ X11_XFlush(display);
+ }
+}
+
+static void
+SetWindowActive(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_DisplayData *displaydata =
+ (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
+ Display *display = data->videodata->display;
+ Atom _NET_ACTIVE_WINDOW = data->videodata->_NET_ACTIVE_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] = data->user_time;
+ e.xclient.data.l[2] = 0;
+
+ X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
+ SubstructureNotifyMask | SubstructureRedirectMask, &e);
+
+ X11_XFlush(display);
+ }
+}
+
+void
+X11_RaiseWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+
+ X11_XRaiseWindow(display, data->xwindow);
+ SetWindowActive(_this, window);
+ X11_XFlush(display);
+}
+
+static void
+SetWindowMaximized(_THIS, SDL_Window * window, SDL_bool maximized)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_DisplayData *displaydata =
+ (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
+ Display *display = data->videodata->display;
+ Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
+ Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
+ Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
+
+ if (maximized) {
+ window->flags |= SDL_WINDOW_MAXIMIZED;
+ } else {
+ window->flags &= ~SDL_WINDOW_MAXIMIZED;
+ }
+
+ if (X11_IsWindowMapped(_this, window)) {
+ XEvent e;
+
+ 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] =
+ maximized ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+ e.xclient.data.l[1] = _NET_WM_STATE_MAXIMIZED_VERT;
+ e.xclient.data.l[2] = _NET_WM_STATE_MAXIMIZED_HORZ;
+ e.xclient.data.l[3] = 0l;
+
+ X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
+ SubstructureNotifyMask | SubstructureRedirectMask, &e);
+ } else {
+ X11_SetNetWMState(_this, data->xwindow, window->flags);
+ }
+ X11_XFlush(display);
+}
+
+void
+X11_MaximizeWindow(_THIS, SDL_Window * window)
+{
+ SetWindowMaximized(_this, window, SDL_TRUE);
+}
+
+void
+X11_MinimizeWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_DisplayData *displaydata =
+ (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
+ Display *display = data->videodata->display;
+
+ X11_XIconifyWindow(display, data->xwindow, displaydata->screen);
+ X11_XFlush(display);
+}
+
+void
+X11_RestoreWindow(_THIS, SDL_Window * window)
+{
+ SetWindowMaximized(_this, window, SDL_FALSE);
+ X11_ShowWindow(_this, window);
+ SetWindowActive(_this, window);
+}
+
+/* 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)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
+ Display *display = data->videodata->display;
+ Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
+ Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
+
+ if (X11_IsWindowMapped(_this, window)) {
+ XEvent e;
+
+ if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
+ /* Compiz refuses fullscreen toggle if we're not resizable, so update the hints so we
+ can be resized to the fullscreen resolution (or reset so we're not resizable again) */
+ XSizeHints *sizehints = X11_XAllocSizeHints();
+ long flags = 0;
+ X11_XGetWMNormalHints(display, data->xwindow, sizehints, &flags);
+ /* set the resize flags on */
+ if (fullscreen) {
+ /* we are going fullscreen so turn the flags off */
+ sizehints->flags &= ~(PMinSize | PMaxSize);
+ } else {
+ /* Reset the min/max width height to make the window non-resizable again */
+ sizehints->flags |= PMinSize | PMaxSize;
+ sizehints->min_width = sizehints->max_width = window->windowed.w;
+ sizehints->min_height = sizehints->max_height = window->windowed.h;
+ }
+ X11_XSetWMNormalHints(display, data->xwindow, sizehints);
+ X11_XFree(sizehints);
+ }
+
+ 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] =
+ fullscreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+ e.xclient.data.l[1] = _NET_WM_STATE_FULLSCREEN;
+ e.xclient.data.l[3] = 0l;
+
+ 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;
+
+ flags = window->flags;
+ if (fullscreen) {
+ flags |= SDL_WINDOW_FULLSCREEN;
+ } else {
+ flags &= ~SDL_WINDOW_FULLSCREEN;
+ }
+ X11_SetNetWMState(_this, data->xwindow, flags);
+ }
+
+ if (data->visual->class == DirectColor) {
+ if ( fullscreen ) {
+ X11_XInstallColormap(display, data->colormap);
+ } else {
+ X11_XUninstallColormap(display, data->colormap);
+ }
+ }
+
+ X11_XFlush(display);
+}
+
+/* This handles fullscreen itself, outside the Window Manager. */
+static void
+X11_BeginWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
+ Visual *visual = data->visual;
+ Display *display = data->videodata->display;
+ const int screen = displaydata->screen;
+ Window root = RootWindow(display, screen);
+ const int def_vis = (visual == DefaultVisual(display, screen));
+ unsigned long xattrmask = 0;
+ XSetWindowAttributes xattr;
+ XEvent ev;
+ SDL_Rect rect;
+
+ if ( data->fswindow ) {
+ return; /* already fullscreen, I hope. */
+ }
+
+ X11_GetDisplayBounds(_this, _display, &rect);
+
+ SDL_zero(xattr);
+ xattr.override_redirect = True;
+ xattrmask |= CWOverrideRedirect;
+ xattr.background_pixel = def_vis ? BlackPixel(display, screen) : 0;
+ xattrmask |= CWBackPixel;
+ xattr.border_pixel = 0;
+ xattrmask |= CWBorderPixel;
+ xattr.colormap = data->colormap;
+ xattrmask |= CWColormap;
+
+ data->fswindow = X11_XCreateWindow(display, root,
+ rect.x, rect.y, rect.w, rect.h, 0,
+ displaydata->depth, InputOutput,
+ visual, xattrmask, &xattr);
+
+ X11_XSelectInput(display, data->fswindow, StructureNotifyMask);
+ X11_XSetWindowBackground(display, data->fswindow, 0);
+ X11_XInstallColormap(display, data->colormap);
+ X11_XClearWindow(display, data->fswindow);
+ X11_XMapRaised(display, data->fswindow);
+
+ /* Make sure the fswindow is in view by warping mouse to the corner */
+ X11_XUngrabPointer(display, CurrentTime);
+ X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
+
+ /* Wait to be mapped, filter Unmap event out if it arrives. */
+ X11_XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->fswindow);
+ X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->fswindow);
+
+#if SDL_VIDEO_DRIVER_X11_XVIDMODE
+ if ( displaydata->use_vidmode ) {
+ X11_XF86VidModeLockModeSwitch(display, screen, True);
+ }
+#endif
+
+ SetWindowBordered(display, displaydata->screen, data->xwindow, SDL_FALSE);
+
+ /* Center actual window within our cover-the-screen window. */
+ X11_XReparentWindow(display, data->xwindow, data->fswindow,
+ (rect.w - window->w) / 2, (rect.h - window->h) / 2);
+
+ /* Move the mouse to the upper left to make sure it's on-screen */
+ X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
+
+ /* Center mouse in the fullscreen window. */
+ rect.x += (rect.w / 2);
+ rect.y += (rect.h / 2);
+ X11_XWarpPointer(display, None, root, 0, 0, 0, 0, rect.x, rect.y);
+
+ /* Wait to be mapped, filter Unmap event out if it arrives. */
+ X11_XIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
+ X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
+
+ SDL_UpdateWindowGrab(window);
+}
+
+static void
+X11_EndWindowFullscreenLegacy(_THIS, SDL_Window * window, SDL_VideoDisplay * _display)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
+ Display *display = data->videodata->display;
+ const int screen = displaydata->screen;
+ Window root = RootWindow(display, screen);
+ Window fswindow = data->fswindow;
+ XEvent ev;
+
+ if (!data->fswindow) {
+ return; /* already not fullscreen, I hope. */
+ }
+
+ data->fswindow = None;
+
+#if SDL_VIDEO_DRIVER_X11_VIDMODE
+ if ( displaydata->use_vidmode ) {
+ X11_XF86VidModeLockModeSwitch(display, screen, False);
+ }
+#endif
+
+ SDL_UpdateWindowGrab(window);
+
+ X11_XReparentWindow(display, data->xwindow, root, window->x, window->y);
+
+ /* flush these events so they don't confuse normal event handling */
+ X11_XSync(display, False);
+ X11_XCheckIfEvent(display, &ev, &isMapNotify, (XPointer)&data->xwindow);
+ X11_XCheckIfEvent(display, &ev, &isUnmapNotify, (XPointer)&data->xwindow);
+
+ SetWindowBordered(display, screen, data->xwindow,
+ (window->flags & SDL_WINDOW_BORDERLESS) == 0);
+
+ X11_XWithdrawWindow(display, fswindow, screen);
+
+ /* Wait to be unmapped. */
+ X11_XIfEvent(display, &ev, &isUnmapNotify, (XPointer)&fswindow);
+ X11_XDestroyWindow(display, fswindow);
+}
+
+
+void
+X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
+{
+ /* !!! FIXME: SDL_Hint? */
+ SDL_bool legacy = SDL_FALSE;
+ const char *env = SDL_getenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN");
+ if (env) {
+ legacy = SDL_atoi(env);
+ } else {
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) _display->driverdata;
+ if ( displaydata->use_vidmode ) {
+ legacy = SDL_TRUE; /* the new stuff only works with XRandR. */
+ } else if ( !videodata->net_wm ) {
+ legacy = SDL_TRUE; /* The window manager doesn't support it */
+ } else {
+ /* !!! FIXME: look at the window manager name, and blacklist certain ones? */
+ /* http://stackoverflow.com/questions/758648/find-the-name-of-the-x-window-manager */
+ legacy = SDL_FALSE; /* try the new way. */
+ }
+ }
+
+ if (legacy) {
+ if (fullscreen) {
+ X11_BeginWindowFullscreenLegacy(_this, window, _display);
+ } else {
+ X11_EndWindowFullscreenLegacy(_this, window, _display);
+ }
+ } else {
+ X11_SetWindowFullscreenViaWM(_this, window, _display, fullscreen);
+ }
+}
+
+
+int
+X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ Visual *visual = data->visual;
+ Colormap colormap = data->colormap;
+ XColor *colorcells;
+ int ncolors;
+ int rmask, gmask, bmask;
+ int rshift, gshift, bshift;
+ int i;
+
+ if (visual->class != DirectColor) {
+ return SDL_SetError("Window doesn't have DirectColor visual");
+ }
+
+ ncolors = visual->map_entries;
+ colorcells = SDL_malloc(ncolors * sizeof(XColor));
+ if (!colorcells) {
+ return SDL_OutOfMemory();
+ }
+
+ rshift = 0;
+ rmask = visual->red_mask;
+ while (0 == (rmask & 1)) {
+ rshift++;
+ rmask >>= 1;
+ }
+
+ gshift = 0;
+ gmask = visual->green_mask;
+ while (0 == (gmask & 1)) {
+ gshift++;
+ gmask >>= 1;
+ }
+
+ bshift = 0;
+ bmask = visual->blue_mask;
+ while (0 == (bmask & 1)) {
+ bshift++;
+ bmask >>= 1;
+ }
+
+ /* build the color table pixel values */
+ for (i = 0; i < ncolors; i++) {
+ Uint32 rbits = (rmask * i) / (ncolors - 1);
+ Uint32 gbits = (gmask * i) / (ncolors - 1);
+ Uint32 bbits = (bmask * i) / (ncolors - 1);
+ Uint32 pix = (rbits << rshift) | (gbits << gshift) | (bbits << bshift);
+
+ colorcells[i].pixel = pix;
+
+ colorcells[i].red = ramp[(0 * 256) + i];
+ colorcells[i].green = ramp[(1 * 256) + i];
+ colorcells[i].blue = ramp[(2 * 256) + i];
+
+ colorcells[i].flags = DoRed | DoGreen | DoBlue;
+ }
+
+ X11_XStoreColors(display, colormap, colorcells, ncolors);
+ X11_XFlush(display);
+ SDL_free(colorcells);
+
+ return 0;
+}
+
+void
+X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ SDL_bool oldstyle_fullscreen;
+ SDL_bool grab_keyboard;
+
+ /* ICCCM2.0-compliant window managers can handle fullscreen windows
+ If we're using XVidMode to change resolution we need to confine
+ the cursor so we don't pan around the virtual desktop.
+ */
+ oldstyle_fullscreen = X11_IsWindowLegacyFullscreen(_this, window);
+
+ if (oldstyle_fullscreen || grabbed) {
+ /* Try to grab the mouse */
+ 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. */
+ }
+ }
+
+ /* Raise the window if we grab the mouse */
+ X11_XRaiseWindow(display, data->xwindow);
+
+ /* Now grab the keyboard */
+ 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
+ fullscreen window otherwise we won't get keyboard focus.
+ */
+ grab_keyboard = oldstyle_fullscreen;
+ }
+ if (grab_keyboard) {
+ X11_XGrabKeyboard(display, data->xwindow, True, GrabModeAsync,
+ GrabModeAsync, CurrentTime);
+ }
+ } else {
+ X11_XUngrabPointer(display, CurrentTime);
+ X11_XUngrabKeyboard(display, CurrentTime);
+ }
+ X11_XSync(display, False);
+}
+
+void
+X11_DestroyWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if (data) {
+ SDL_VideoData *videodata = (SDL_VideoData *) data->videodata;
+ Display *display = videodata->display;
+ int numwindows = videodata->numwindows;
+ SDL_WindowData **windowlist = videodata->windowlist;
+ int i;
+
+ if (windowlist) {
+ for (i = 0; i < numwindows; ++i) {
+ if (windowlist[i] && (windowlist[i]->window == window)) {
+ windowlist[i] = windowlist[numwindows - 1];
+ windowlist[numwindows - 1] = NULL;
+ videodata->numwindows--;
+ break;
+ }
+ }
+ }
+#ifdef X_HAVE_UTF8_STRING
+ if (data->ic) {
+ X11_XDestroyIC(data->ic);
+ }
+#endif
+ if (data->created) {
+ X11_XDestroyWindow(display, data->xwindow);
+ X11_XFlush(display);
+ }
+ SDL_free(data);
+ }
+ window->driverdata = NULL;
+}
+
+SDL_bool
+X11_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+
+ if (info->version.major == SDL_MAJOR_VERSION &&
+ info->version.minor == SDL_MINOR_VERSION) {
+ info->subsystem = SDL_SYSWM_X11;
+ info->info.x11.display = display;
+ info->info.x11.window = data->xwindow;
+ return SDL_TRUE;
+ } else {
+ SDL_SetError("Application not compiled with SDL %d.%d",
+ SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
+ return SDL_FALSE;
+ }
+}
+
+int
+X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
+{
+ return 0; /* just succeed, the real work is done elsewhere. */
+}
+
+void
+X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ Atom XdndAware = X11_XInternAtom(display, "XdndAware", False);
+
+ if (accept) {
+ Atom xdnd_version = 5;
+ X11_XChangeProperty(display, data->xwindow, XdndAware, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)&xdnd_version, 1);
+ } else {
+ X11_XDeleteProperty(display, data->xwindow, XdndAware);
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11window.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11window.h
new file mode 100644
index 0000000..6ee8016
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11window.h
@@ -0,0 +1,111 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11window_h_
+#define SDL_x11window_h_
+
+/* We need to queue the focus in/out changes because they may occur during
+ video mode changes and we can respond to them by triggering more mode
+ changes.
+*/
+#define PENDING_FOCUS_TIME 200
+
+#if SDL_VIDEO_OPENGL_EGL
+#include <EGL/egl.h>
+#endif
+
+typedef enum
+{
+ PENDING_FOCUS_NONE,
+ PENDING_FOCUS_IN,
+ PENDING_FOCUS_OUT
+} PendingFocusEnum;
+
+typedef struct
+{
+ SDL_Window *window;
+ Window xwindow;
+ Window fswindow; /* used if we can't have the WM handle fullscreen. */
+ Visual *visual;
+ Colormap colormap;
+#ifndef NO_SHARED_MEMORY
+ /* MIT shared memory extension information */
+ SDL_bool use_mitshm;
+ XShmSegmentInfo shminfo;
+#endif
+ XImage *ximage;
+ GC gc;
+ XIC ic;
+ SDL_bool created;
+ int border_left;
+ int border_right;
+ int border_top;
+ int border_bottom;
+ Uint32 last_focus_event_time;
+ PendingFocusEnum pending_focus;
+ Uint32 pending_focus_time;
+ XConfigureEvent last_xconfigure;
+ struct SDL_VideoData *videodata;
+ unsigned long user_time;
+ Atom xdnd_req;
+ Window xdnd_source;
+#if SDL_VIDEO_OPENGL_EGL
+ EGLSurface egl_surface;
+#endif
+} SDL_WindowData;
+
+extern void X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags);
+extern Uint32 X11_GetNetWMState(_THIS, Window xwindow);
+
+extern int X11_CreateWindow(_THIS, SDL_Window * window);
+extern int X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data);
+extern char *X11_GetWindowTitle(_THIS, Window xwindow);
+extern void X11_SetWindowTitle(_THIS, SDL_Window * window);
+extern void X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
+extern void X11_SetWindowPosition(_THIS, SDL_Window * window);
+extern void X11_SetWindowMinimumSize(_THIS, SDL_Window * window);
+extern void X11_SetWindowMaximumSize(_THIS, SDL_Window * window);
+extern int X11_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
+extern int X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
+extern int X11_SetWindowModalFor(_THIS, SDL_Window * modal_window, SDL_Window * parent_window);
+extern int X11_SetWindowInputFocus(_THIS, SDL_Window * window);
+extern void X11_SetWindowSize(_THIS, SDL_Window * window);
+extern void X11_ShowWindow(_THIS, SDL_Window * window);
+extern void X11_HideWindow(_THIS, SDL_Window * window);
+extern void X11_RaiseWindow(_THIS, SDL_Window * window);
+extern void X11_MaximizeWindow(_THIS, SDL_Window * window);
+extern void X11_MinimizeWindow(_THIS, SDL_Window * window);
+extern void X11_RestoreWindow(_THIS, SDL_Window * window);
+extern void X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void X11_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
+extern void X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
+extern int X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
+extern void X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
+extern void X11_DestroyWindow(_THIS, SDL_Window * window);
+extern SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window * window,
+ struct SDL_SysWMinfo *info);
+extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
+extern void X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept);
+
+#endif /* SDL_x11window_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11xinput2.c b/source/3rd-party/SDL2/src/video/x11/SDL_x11xinput2.c
new file mode 100644
index 0000000..06a8937
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11xinput2.c
@@ -0,0 +1,313 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+
+#include "SDL_x11video.h"
+#include "SDL_x11xinput2.h"
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_touch_c.h"
+
+#define MAX_AXIS 16
+
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+static int xinput2_initialized = 0;
+
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+static int xinput2_multitouch_supported = 0;
+#endif
+
+/* Opcode returned X11_XQueryExtension
+ * It will be used in event processing
+ * to know that the event came from
+ * this extension */
+static int xinput2_opcode;
+
+static void parse_valuators(const double *input_values,unsigned char *mask,int mask_len,
+ double *output_values,int output_values_len) {
+ int i = 0,z = 0;
+ int top = mask_len * 8;
+ if (top > MAX_AXIS)
+ top = MAX_AXIS;
+
+ SDL_memset(output_values,0,output_values_len * sizeof(double));
+ for (; i < top && z < output_values_len; i++) {
+ if (XIMaskIsSet(mask, i)) {
+ const int value = (int) *input_values;
+ output_values[z] = value;
+ input_values++;
+ }
+ z++;
+ }
+}
+
+static int
+query_xinput2_version(Display *display, int major, int minor)
+{
+ /* We don't care if this fails, so long as it sets major/minor on it's way out the door. */
+ X11_XIQueryVersion(display, &major, &minor);
+ return ((major * 1000) + minor);
+}
+
+static SDL_bool
+xinput2_version_atleast(const int version, const int wantmajor, const int wantminor)
+{
+ return ( version >= ((wantmajor * 1000) + wantminor) );
+}
+
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+static void
+xinput2_normalize_touch_coordinates(SDL_VideoData *videodata, Window window,
+ double in_x, double in_y, float *out_x, float *out_y)
+{
+ int i;
+ for (i = 0; i < videodata->numwindows; i++) {
+ SDL_WindowData *d = videodata->windowlist[i];
+ if (d->xwindow == window) {
+ if (d->window->w == 1) {
+ *out_x = 0.5f;
+ } else {
+ *out_x = in_x / (d->window->w - 1);
+ }
+ if (d->window->h == 1) {
+ *out_y = 0.5f;
+ } else {
+ *out_y = in_y / (d->window->h - 1);
+ }
+ return;
+ }
+ }
+ // couldn't find the window...
+ *out_x = in_x;
+ *out_y = in_y;
+}
+#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH */
+
+#endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */
+
+void
+X11_InitXinput2(_THIS)
+{
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ int version = 0;
+ XIEventMask eventmask;
+ unsigned char mask[3] = { 0,0,0 };
+ int event, err;
+
+ /*
+ * Initialize XInput 2
+ * According to http://who-t.blogspot.com/2009/05/xi2-recipes-part-1.html its better
+ * to inform Xserver what version of Xinput we support.The server will store the version we support.
+ * "As XI2 progresses it becomes important that you use this call as the server may treat the client
+ * differently depending on the supported version".
+ *
+ * FIXME:event and err are not needed but if not passed X11_XQueryExtension returns SegmentationFault
+ */
+ if (!SDL_X11_HAVE_XINPUT2 ||
+ !X11_XQueryExtension(data->display, "XInputExtension", &xinput2_opcode, &event, &err)) {
+ return; /* X server does not have XInput at all */
+ }
+
+ /* We need at least 2.2 for Multitouch, 2.0 otherwise. */
+ version = query_xinput2_version(data->display, 2, 2);
+ if (!xinput2_version_atleast(version, 2, 0)) {
+ return; /* X server does not support the version we want at all. */
+ }
+
+ xinput2_initialized = 1;
+
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH /* Multitouch needs XInput 2.2 */
+ xinput2_multitouch_supported = xinput2_version_atleast(version, 2, 2);
+#endif
+
+ /* Enable Raw motion events for this display */
+ eventmask.deviceid = XIAllMasterDevices;
+ eventmask.mask_len = sizeof(mask);
+ eventmask.mask = mask;
+
+ XISetMask(mask, XI_RawMotion);
+ XISetMask(mask, XI_RawButtonPress);
+ XISetMask(mask, XI_RawButtonRelease);
+
+ if (X11_XISelectEvents(data->display,DefaultRootWindow(data->display),&eventmask,1) != Success) {
+ return;
+ }
+#endif
+}
+
+int
+X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie)
+{
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+ if(cookie->extension != xinput2_opcode) {
+ return 0;
+ }
+ switch(cookie->evtype) {
+ case XI_RawMotion: {
+ const XIRawEvent *rawev = (const XIRawEvent*)cookie->data;
+ SDL_Mouse *mouse = SDL_GetMouse();
+ double relative_coords[2];
+ static Time prev_time = 0;
+ static double prev_rel_coords[2];
+
+ videodata->global_mouse_changed = SDL_TRUE;
+
+ if (!mouse->relative_mode || mouse->relative_mode_warp) {
+ return 0;
+ }
+
+ parse_valuators(rawev->raw_values,rawev->valuators.mask,
+ rawev->valuators.mask_len,relative_coords,2);
+
+ if ((rawev->time == prev_time) && (relative_coords[0] == prev_rel_coords[0]) && (relative_coords[1] == prev_rel_coords[1])) {
+ return 0; /* duplicate event, drop it. */
+ }
+
+ SDL_SendMouseMotion(mouse->focus,mouse->mouseID,1,(int)relative_coords[0],(int)relative_coords[1]);
+ prev_rel_coords[0] = relative_coords[0];
+ prev_rel_coords[1] = relative_coords[1];
+ prev_time = rawev->time;
+ return 1;
+ }
+ break;
+
+ case XI_RawButtonPress:
+ case XI_RawButtonRelease:
+ videodata->global_mouse_changed = SDL_TRUE;
+ break;
+
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+ case XI_TouchBegin: {
+ const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
+ float x, y;
+ xinput2_normalize_touch_coordinates(videodata, xev->event,
+ xev->event_x, xev->event_y, &x, &y);
+ SDL_SendTouch(xev->sourceid,xev->detail, SDL_TRUE, x, y, 1.0);
+ return 1;
+ }
+ break;
+ case XI_TouchEnd: {
+ const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
+ float x, y;
+ xinput2_normalize_touch_coordinates(videodata, xev->event,
+ xev->event_x, xev->event_y, &x, &y);
+ SDL_SendTouch(xev->sourceid,xev->detail, SDL_FALSE, x, y, 1.0);
+ return 1;
+ }
+ break;
+ case XI_TouchUpdate: {
+ const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
+ float x, y;
+ xinput2_normalize_touch_coordinates(videodata, xev->event,
+ xev->event_x, xev->event_y, &x, &y);
+ SDL_SendTouchMotion(xev->sourceid,xev->detail, x, y, 1.0);
+ return 1;
+ }
+ break;
+#endif
+ }
+#endif
+ return 0;
+}
+
+void
+X11_InitXinput2Multitouch(_THIS)
+{
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ XIDeviceInfo *info;
+ int ndevices,i,j;
+ info = X11_XIQueryDevice(data->display, XIAllDevices, &ndevices);
+
+ for (i = 0; i < ndevices; i++) {
+ XIDeviceInfo *dev = &info[i];
+ for (j = 0; j < dev->num_classes; j++) {
+ SDL_TouchID touchId;
+ XIAnyClassInfo *class = dev->classes[j];
+ XITouchClassInfo *t = (XITouchClassInfo*)class;
+
+ /* Only touch devices */
+ if (class->type != XITouchClass)
+ continue;
+
+ touchId = t->sourceid;
+ SDL_AddTouch(touchId, dev->name);
+ }
+ }
+ X11_XIFreeDeviceInfo(info);
+#endif
+}
+
+void
+X11_Xinput2SelectTouch(_THIS, SDL_Window *window)
+{
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+ SDL_VideoData *data = NULL;
+ XIEventMask eventmask;
+ unsigned char mask[3] = { 0,0,0 };
+ SDL_WindowData *window_data = NULL;
+
+ if (!X11_Xinput2IsMultitouchSupported()) {
+ return;
+ }
+
+ data = (SDL_VideoData *) _this->driverdata;
+ window_data = (SDL_WindowData*)window->driverdata;
+
+ eventmask.deviceid = XIAllMasterDevices;
+ eventmask.mask_len = sizeof(mask);
+ eventmask.mask = mask;
+
+ XISetMask(mask, XI_TouchBegin);
+ XISetMask(mask, XI_TouchUpdate);
+ XISetMask(mask, XI_TouchEnd);
+
+ X11_XISelectEvents(data->display,window_data->xwindow,&eventmask,1);
+#endif
+}
+
+
+int
+X11_Xinput2IsInitialized()
+{
+#if SDL_VIDEO_DRIVER_X11_XINPUT2
+ return xinput2_initialized;
+#else
+ return 0;
+#endif
+}
+
+int
+X11_Xinput2IsMultitouchSupported()
+{
+#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
+ return xinput2_initialized && xinput2_multitouch_supported;
+#else
+ return 0;
+#endif
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/SDL_x11xinput2.h b/source/3rd-party/SDL2/src/video/x11/SDL_x11xinput2.h
new file mode 100644
index 0000000..4780fbb
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/SDL_x11xinput2.h
@@ -0,0 +1,42 @@
+/*
+ Simple DirectMedia Layer
+ 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
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_x11xinput2_h_
+#define SDL_x11xinput2_h_
+
+#ifndef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
+/* Define XGenericEventCookie as forward declaration when
+ *xinput2 is not available in order to compile */
+struct XGenericEventCookie;
+typedef struct XGenericEventCookie XGenericEventCookie;
+#endif
+
+extern void X11_InitXinput2(_THIS);
+extern void X11_InitXinput2Multitouch(_THIS);
+extern int X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie);
+extern int X11_Xinput2IsInitialized(void);
+extern int X11_Xinput2IsMultitouchSupported(void);
+extern void X11_Xinput2SelectTouch(_THIS, SDL_Window *window);
+
+#endif /* SDL_x11xinput2_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/x11/edid-parse.c b/source/3rd-party/SDL2/src/video/x11/edid-parse.c
new file mode 100644
index 0000000..e22324f
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/edid-parse.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright 2007 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* Author: Soren Sandmann <sandmann@redhat.com> */
+#include "../../SDL_internal.h"
+#include "SDL_stdinc.h"
+
+#include "edid.h"
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+
+#define TRUE 1
+#define FALSE 0
+
+static int
+get_bit (int in, int bit)
+{
+ return (in & (1 << bit)) >> bit;
+}
+
+static int
+get_bits (int in, int begin, int end)
+{
+ int mask = (1 << (end - begin + 1)) - 1;
+
+ return (in >> begin) & mask;
+}
+
+static int
+decode_header (const uchar *edid)
+{
+ if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
+ return TRUE;
+ return FALSE;
+}
+
+static int
+decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
+{
+ int is_model_year;
+
+ /* Manufacturer Code */
+ info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6);
+ info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3;
+ info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
+ info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4);
+ info->manufacturer_code[3] = '\0';
+
+ info->manufacturer_code[0] += 'A' - 1;
+ info->manufacturer_code[1] += 'A' - 1;
+ info->manufacturer_code[2] += 'A' - 1;
+
+ /* Product Code */
+ info->product_code = edid[0x0b] << 8 | edid[0x0a];
+
+ /* Serial Number */
+ info->serial_number =
+ edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
+
+ /* Week and Year */
+ is_model_year = FALSE;
+ switch (edid[0x10])
+ {
+ case 0x00:
+ info->production_week = -1;
+ break;
+
+ case 0xff:
+ info->production_week = -1;
+ is_model_year = TRUE;
+ break;
+
+ default:
+ info->production_week = edid[0x10];
+ break;
+ }
+
+ if (is_model_year)
+ {
+ info->production_year = -1;
+ info->model_year = 1990 + edid[0x11];
+ }
+ else
+ {
+ info->production_year = 1990 + edid[0x11];
+ info->model_year = -1;
+ }
+
+ return TRUE;
+}
+
+static int
+decode_edid_version (const uchar *edid, MonitorInfo *info)
+{
+ info->major_version = edid[0x12];
+ info->minor_version = edid[0x13];
+
+ return TRUE;
+}
+
+static int
+decode_display_parameters (const uchar *edid, MonitorInfo *info)
+{
+ /* Digital vs Analog */
+ info->is_digital = get_bit (edid[0x14], 7);
+
+ if (info->is_digital)
+ {
+ int bits;
+
+ static const int bit_depth[8] =
+ {
+ -1, 6, 8, 10, 12, 14, 16, -1
+ };
+
+ static const Interface interfaces[6] =
+ {
+ UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
+ };
+
+ bits = get_bits (edid[0x14], 4, 6);
+ info->ad.digital.bits_per_primary = bit_depth[bits];
+
+ bits = get_bits (edid[0x14], 0, 3);
+
+ if (bits <= 5)
+ info->ad.digital.interface = interfaces[bits];
+ else
+ info->ad.digital.interface = UNDEFINED;
+ }
+ else
+ {
+ int bits = get_bits (edid[0x14], 5, 6);
+
+ static const double levels[][3] =
+ {
+ { 0.7, 0.3, 1.0 },
+ { 0.714, 0.286, 1.0 },
+ { 1.0, 0.4, 1.4 },
+ { 0.7, 0.0, 0.7 },
+ };
+
+ info->ad.analog.video_signal_level = levels[bits][0];
+ info->ad.analog.sync_signal_level = levels[bits][1];
+ info->ad.analog.total_signal_level = levels[bits][2];
+
+ info->ad.analog.blank_to_black = get_bit (edid[0x14], 4);
+
+ info->ad.analog.separate_hv_sync = get_bit (edid[0x14], 3);
+ info->ad.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
+ info->ad.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
+
+ info->ad.analog.serration_on_vsync = get_bit (edid[0x14], 0);
+ }
+
+ /* Screen Size / Aspect Ratio */
+ if (edid[0x15] == 0 && edid[0x16] == 0)
+ {
+ info->width_mm = -1;
+ info->height_mm = -1;
+ info->aspect_ratio = -1.0;
+ }
+ else if (edid[0x16] == 0)
+ {
+ info->width_mm = -1;
+ info->height_mm = -1;
+ info->aspect_ratio = 100.0 / (edid[0x15] + 99);
+ }
+ else if (edid[0x15] == 0)
+ {
+ info->width_mm = -1;
+ info->height_mm = -1;
+ info->aspect_ratio = 100.0 / (edid[0x16] + 99);
+ info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
+ }
+ else
+ {
+ info->width_mm = 10 * edid[0x15];
+ info->height_mm = 10 * edid[0x16];
+ }
+
+ /* Gamma */
+ if (edid[0x17] == 0xFF)
+ info->gamma = -1.0;
+ else
+ info->gamma = (edid[0x17] + 100.0) / 100.0;
+
+ /* Features */
+ info->standby = get_bit (edid[0x18], 7);
+ info->suspend = get_bit (edid[0x18], 6);
+ info->active_off = get_bit (edid[0x18], 5);
+
+ if (info->is_digital)
+ {
+ info->ad.digital.rgb444 = TRUE;
+ if (get_bit (edid[0x18], 3))
+ info->ad.digital.ycrcb444 = 1;
+ if (get_bit (edid[0x18], 4))
+ info->ad.digital.ycrcb422 = 1;
+ }
+ else
+ {
+ int bits = get_bits (edid[0x18], 3, 4);
+ ColorType color_type[4] =
+ {
+ MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
+ };
+
+ info->ad.analog.color_type = color_type[bits];
+ }
+
+ info->srgb_is_standard = get_bit (edid[0x18], 2);
+
+ /* In 1.3 this is called "has preferred timing" */
+ info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
+
+ /* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
+ info->continuous_frequency = get_bit (edid[0x18], 0);
+ return TRUE;
+}
+
+static double
+decode_fraction (int high, int low)
+{
+ double result = 0.0;
+ int i;
+
+ high = (high << 2) | low;
+
+ for (i = 0; i < 10; ++i)
+ result += get_bit (high, i) * SDL_pow (2, i - 10);
+
+ return result;
+}
+
+static int
+decode_color_characteristics (const uchar *edid, MonitorInfo *info)
+{
+ info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
+ info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
+ info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
+ info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
+ info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
+ info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
+ info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
+ info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
+
+ return TRUE;
+}
+
+static int
+decode_established_timings (const uchar *edid, MonitorInfo *info)
+{
+ static const Timing established[][8] =
+ {
+ {
+ { 800, 600, 60 },
+ { 800, 600, 56 },
+ { 640, 480, 75 },
+ { 640, 480, 72 },
+ { 640, 480, 67 },
+ { 640, 480, 60 },
+ { 720, 400, 88 },
+ { 720, 400, 70 }
+ },
+ {
+ { 1280, 1024, 75 },
+ { 1024, 768, 75 },
+ { 1024, 768, 70 },
+ { 1024, 768, 60 },
+ { 1024, 768, 87 },
+ { 832, 624, 75 },
+ { 800, 600, 75 },
+ { 800, 600, 72 }
+ },
+ {
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 1152, 870, 75 }
+ },
+ };
+
+ int i, j, idx;
+
+ idx = 0;
+ for (i = 0; i < 3; ++i)
+ {
+ for (j = 0; j < 8; ++j)
+ {
+ int byte = edid[0x23 + i];
+
+ if (get_bit (byte, j) && established[i][j].frequency != 0)
+ info->established[idx++] = established[i][j];
+ }
+ }
+ return TRUE;
+}
+
+static int
+decode_standard_timings (const uchar *edid, MonitorInfo *info)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ int first = edid[0x26 + 2 * i];
+ int second = edid[0x27 + 2 * i];
+
+ if (first != 0x01 && second != 0x01)
+ {
+ int w = 8 * (first + 31);
+ int h = 0;
+
+ switch (get_bits (second, 6, 7))
+ {
+ case 0x00: h = (w / 16) * 10; break;
+ case 0x01: h = (w / 4) * 3; break;
+ case 0x02: h = (w / 5) * 4; break;
+ case 0x03: h = (w / 16) * 9; break;
+ }
+
+ info->standard[i].width = w;
+ info->standard[i].height = h;
+ info->standard[i].frequency = get_bits (second, 0, 5) + 60;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+decode_lf_string (const uchar *s, int n_chars, char *result)
+{
+ int i;
+ for (i = 0; i < n_chars; ++i)
+ {
+ if (s[i] == 0x0a)
+ {
+ *result++ = '\0';
+ break;
+ }
+ else if (s[i] == 0x00)
+ {
+ /* Convert embedded 0's to spaces */
+ *result++ = ' ';
+ }
+ else
+ {
+ *result++ = s[i];
+ }
+ }
+}
+
+static void
+decode_display_descriptor (const uchar *desc,
+ MonitorInfo *info)
+{
+ switch (desc[0x03])
+ {
+ case 0xFC:
+ decode_lf_string (desc + 5, 13, info->dsc_product_name);
+ break;
+ case 0xFF:
+ decode_lf_string (desc + 5, 13, info->dsc_serial_number);
+ break;
+ case 0xFE:
+ decode_lf_string (desc + 5, 13, info->dsc_string);
+ break;
+ case 0xFD:
+ /* Range Limits */
+ break;
+ case 0xFB:
+ /* Color Point */
+ break;
+ case 0xFA:
+ /* Timing Identifications */
+ break;
+ case 0xF9:
+ /* Color Management */
+ break;
+ case 0xF8:
+ /* Timing Codes */
+ break;
+ case 0xF7:
+ /* Established Timings */
+ break;
+ case 0x10:
+ break;
+ }
+}
+
+static void
+decode_detailed_timing (const uchar *timing,
+ DetailedTiming *detailed)
+{
+ int bits;
+ StereoType stereo[] =
+ {
+ NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
+ TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
+ FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
+ };
+
+ detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
+ detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
+ detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
+ detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
+ detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
+ detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
+ detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
+ detailed->v_front_porch =
+ get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
+ detailed->v_sync =
+ get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
+ detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
+ detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
+ detailed->right_border = timing[0x0f];
+ detailed->top_border = timing[0x10];
+
+ detailed->interlaced = get_bit (timing[0x11], 7);
+
+ /* Stereo */
+ bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
+ detailed->stereo = stereo[bits];
+
+ /* Sync */
+ bits = timing[0x11];
+
+ detailed->digital_sync = get_bit (bits, 4);
+ if (detailed->digital_sync)
+ {
+ detailed->ad.digital.composite = !get_bit (bits, 3);
+
+ if (detailed->ad.digital.composite)
+ {
+ detailed->ad.digital.serrations = get_bit (bits, 2);
+ detailed->ad.digital.negative_vsync = FALSE;
+ }
+ else
+ {
+ detailed->ad.digital.serrations = FALSE;
+ detailed->ad.digital.negative_vsync = !get_bit (bits, 2);
+ }
+
+ detailed->ad.digital.negative_hsync = !get_bit (bits, 0);
+ }
+ else
+ {
+ detailed->ad.analog.bipolar = get_bit (bits, 3);
+ detailed->ad.analog.serrations = get_bit (bits, 2);
+ detailed->ad.analog.sync_on_green = !get_bit (bits, 1);
+ }
+}
+
+static int
+decode_descriptors (const uchar *edid, MonitorInfo *info)
+{
+ int i;
+ int timing_idx;
+
+ timing_idx = 0;
+
+ for (i = 0; i < 4; ++i)
+ {
+ int index = 0x36 + i * 18;
+
+ if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
+ {
+ decode_display_descriptor (edid + index, info);
+ }
+ else
+ {
+ decode_detailed_timing (
+ edid + index, &(info->detailed_timings[timing_idx++]));
+ }
+ }
+
+ info->n_detailed_timings = timing_idx;
+
+ return TRUE;
+}
+
+static void
+decode_check_sum (const uchar *edid,
+ MonitorInfo *info)
+{
+ int i;
+ uchar check = 0;
+
+ for (i = 0; i < 128; ++i)
+ check += edid[i];
+
+ info->checksum = check;
+}
+
+MonitorInfo *
+decode_edid (const uchar *edid)
+{
+ MonitorInfo *info = calloc (1, sizeof (MonitorInfo));
+
+ decode_check_sum (edid, info);
+
+ if (!decode_header (edid) ||
+ !decode_vendor_and_product_identification (edid, info) ||
+ !decode_edid_version (edid, info) ||
+ !decode_display_parameters (edid, info) ||
+ !decode_color_characteristics (edid, info) ||
+ !decode_established_timings (edid, info) ||
+ !decode_standard_timings (edid, info) ||
+ !decode_descriptors (edid, info)) {
+ free(info);
+ return NULL;
+ }
+
+ return info;
+}
+
+static const char *
+yesno (int v)
+{
+ return v? "yes" : "no";
+}
+
+void
+dump_monitor_info (MonitorInfo *info)
+{
+ int i;
+
+ printf ("Checksum: %d (%s)\n",
+ info->checksum, info->checksum? "incorrect" : "correct");
+ printf ("Manufacturer Code: %s\n", info->manufacturer_code);
+ printf ("Product Code: 0x%x\n", info->product_code);
+ printf ("Serial Number: %u\n", info->serial_number);
+
+ if (info->production_week != -1)
+ printf ("Production Week: %d\n", info->production_week);
+ else
+ printf ("Production Week: unspecified\n");
+
+ if (info->production_year != -1)
+ printf ("Production Year: %d\n", info->production_year);
+ else
+ printf ("Production Year: unspecified\n");
+
+ if (info->model_year != -1)
+ printf ("Model Year: %d\n", info->model_year);
+ else
+ printf ("Model Year: unspecified\n");
+
+ printf ("EDID revision: %d.%d\n", info->major_version, info->minor_version);
+
+ printf ("Display is %s\n", info->is_digital? "digital" : "analog");
+ if (info->is_digital)
+ {
+ const char *interface;
+ if (info->ad.digital.bits_per_primary != -1)
+ printf ("Bits Per Primary: %d\n", info->ad.digital.bits_per_primary);
+ else
+ printf ("Bits Per Primary: undefined\n");
+
+ switch (info->ad.digital.interface)
+ {
+ case DVI: interface = "DVI"; break;
+ case HDMI_A: interface = "HDMI-a"; break;
+ case HDMI_B: interface = "HDMI-b"; break;
+ case MDDI: interface = "MDDI"; break;
+ case DISPLAY_PORT: interface = "DisplayPort"; break;
+ case UNDEFINED: interface = "undefined"; break;
+ default: interface = "unknown"; break;
+ }
+ printf ("Interface: %s\n", interface);
+
+ printf ("RGB 4:4:4: %s\n", yesno (info->ad.digital.rgb444));
+ printf ("YCrCb 4:4:4: %s\n", yesno (info->ad.digital.ycrcb444));
+ printf ("YCrCb 4:2:2: %s\n", yesno (info->ad.digital.ycrcb422));
+ }
+ else
+ {
+ const char *s;
+ printf ("Video Signal Level: %f\n", info->ad.analog.video_signal_level);
+ printf ("Sync Signal Level: %f\n", info->ad.analog.sync_signal_level);
+ printf ("Total Signal Level: %f\n", info->ad.analog.total_signal_level);
+
+ printf ("Blank to Black: %s\n",
+ yesno (info->ad.analog.blank_to_black));
+ printf ("Separate HV Sync: %s\n",
+ yesno (info->ad.analog.separate_hv_sync));
+ printf ("Composite Sync on H: %s\n",
+ yesno (info->ad.analog.composite_sync_on_h));
+ printf ("Serration on VSync: %s\n",
+ yesno (info->ad.analog.serration_on_vsync));
+
+ switch (info->ad.analog.color_type)
+ {
+ case UNDEFINED_COLOR: s = "undefined"; break;
+ case MONOCHROME: s = "monochrome"; break;
+ case RGB: s = "rgb"; break;
+ case OTHER_COLOR: s = "other color"; break;
+ default: s = "unknown"; break;
+ };
+
+ printf ("Color: %s\n", s);
+ }
+
+ if (info->width_mm == -1)
+ printf ("Width: undefined\n");
+ else
+ printf ("Width: %d mm\n", info->width_mm);
+
+ if (info->height_mm == -1)
+ printf ("Height: undefined\n");
+ else
+ printf ("Height: %d mm\n", info->height_mm);
+
+ if (info->aspect_ratio > 0)
+ printf ("Aspect Ratio: %f\n", info->aspect_ratio);
+ else
+ printf ("Aspect Ratio: undefined\n");
+
+ if (info->gamma >= 0)
+ printf ("Gamma: %f\n", info->gamma);
+ else
+ printf ("Gamma: undefined\n");
+
+ printf ("Standby: %s\n", yesno (info->standby));
+ printf ("Suspend: %s\n", yesno (info->suspend));
+ printf ("Active Off: %s\n", yesno (info->active_off));
+
+ printf ("SRGB is Standard: %s\n", yesno (info->srgb_is_standard));
+ printf ("Preferred Timing Includes Native: %s\n",
+ yesno (info->preferred_timing_includes_native));
+ printf ("Continuous Frequency: %s\n", yesno (info->continuous_frequency));
+
+ printf ("Red X: %f\n", info->red_x);
+ printf ("Red Y: %f\n", info->red_y);
+ printf ("Green X: %f\n", info->green_x);
+ printf ("Green Y: %f\n", info->green_y);
+ printf ("Blue X: %f\n", info->blue_x);
+ printf ("Blue Y: %f\n", info->blue_y);
+ printf ("White X: %f\n", info->white_x);
+ printf ("White Y: %f\n", info->white_y);
+
+ printf ("Established Timings:\n");
+
+ for (i = 0; i < 24; ++i)
+ {
+ Timing *timing = &(info->established[i]);
+
+ if (timing->frequency == 0)
+ break;
+
+ printf (" %d x %d @ %d Hz\n",
+ timing->width, timing->height, timing->frequency);
+
+ }
+
+ printf ("Standard Timings:\n");
+ for (i = 0; i < 8; ++i)
+ {
+ Timing *timing = &(info->standard[i]);
+
+ if (timing->frequency == 0)
+ break;
+
+ printf (" %d x %d @ %d Hz\n",
+ timing->width, timing->height, timing->frequency);
+ }
+
+ for (i = 0; i < info->n_detailed_timings; ++i)
+ {
+ DetailedTiming *timing = &(info->detailed_timings[i]);
+ const char *s;
+
+ printf ("Timing%s: \n",
+ (i == 0 && info->preferred_timing_includes_native)?
+ " (Preferred)" : "");
+ printf (" Pixel Clock: %d\n", timing->pixel_clock);
+ printf (" H Addressable: %d\n", timing->h_addr);
+ printf (" H Blank: %d\n", timing->h_blank);
+ printf (" H Front Porch: %d\n", timing->h_front_porch);
+ printf (" H Sync: %d\n", timing->h_sync);
+ printf (" V Addressable: %d\n", timing->v_addr);
+ printf (" V Blank: %d\n", timing->v_blank);
+ printf (" V Front Porch: %d\n", timing->v_front_porch);
+ printf (" V Sync: %d\n", timing->v_sync);
+ printf (" Width: %d mm\n", timing->width_mm);
+ printf (" Height: %d mm\n", timing->height_mm);
+ printf (" Right Border: %d\n", timing->right_border);
+ printf (" Top Border: %d\n", timing->top_border);
+ switch (timing->stereo)
+ {
+ default:
+ case NO_STEREO: s = "No Stereo"; break;
+ case FIELD_RIGHT: s = "Field Sequential, Right on Sync"; break;
+ case FIELD_LEFT: s = "Field Sequential, Left on Sync"; break;
+ case TWO_WAY_RIGHT_ON_EVEN: s = "Two-way, Right on Even"; break;
+ case TWO_WAY_LEFT_ON_EVEN: s = "Two-way, Left on Even"; break;
+ case FOUR_WAY_INTERLEAVED: s = "Four-way Interleaved"; break;
+ case SIDE_BY_SIDE: s = "Side-by-Side"; break;
+ }
+ printf (" Stereo: %s\n", s);
+
+ if (timing->digital_sync)
+ {
+ printf (" Digital Sync:\n");
+ printf (" composite: %s\n", yesno (timing->ad.digital.composite));
+ printf (" serrations: %s\n", yesno (timing->ad.digital.serrations));
+ printf (" negative vsync: %s\n",
+ yesno (timing->ad.digital.negative_vsync));
+ printf (" negative hsync: %s\n",
+ yesno (timing->ad.digital.negative_hsync));
+ }
+ else
+ {
+ printf (" Analog Sync:\n");
+ printf (" bipolar: %s\n", yesno (timing->ad.analog.bipolar));
+ printf (" serrations: %s\n", yesno (timing->ad.analog.serrations));
+ printf (" sync on green: %s\n", yesno (
+ timing->ad.analog.sync_on_green));
+ }
+ }
+
+ printf ("Detailed Product information:\n");
+ printf (" Product Name: %s\n", info->dsc_product_name);
+ printf (" Serial Number: %s\n", info->dsc_serial_number);
+ printf (" Unspecified String: %s\n", info->dsc_string);
+}
+
diff --git a/source/3rd-party/SDL2/src/video/x11/edid.h b/source/3rd-party/SDL2/src/video/x11/edid.h
new file mode 100644
index 0000000..cb9f0e8
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/edid.h
@@ -0,0 +1,167 @@
+typedef unsigned char uchar;
+typedef struct MonitorInfo MonitorInfo;
+typedef struct Timing Timing;
+typedef struct DetailedTiming DetailedTiming;
+
+typedef enum
+{
+ UNDEFINED,
+ DVI,
+ HDMI_A,
+ HDMI_B,
+ MDDI,
+ DISPLAY_PORT
+} Interface;
+
+typedef enum
+{
+ UNDEFINED_COLOR,
+ MONOCHROME,
+ RGB,
+ OTHER_COLOR
+} ColorType;
+
+typedef enum
+{
+ NO_STEREO,
+ FIELD_RIGHT,
+ FIELD_LEFT,
+ TWO_WAY_RIGHT_ON_EVEN,
+ TWO_WAY_LEFT_ON_EVEN,
+ FOUR_WAY_INTERLEAVED,
+ SIDE_BY_SIDE
+} StereoType;
+
+struct Timing
+{
+ int width;
+ int height;
+ int frequency;
+};
+
+struct DetailedTiming
+{
+ int pixel_clock;
+ int h_addr;
+ int h_blank;
+ int h_sync;
+ int h_front_porch;
+ int v_addr;
+ int v_blank;
+ int v_sync;
+ int v_front_porch;
+ int width_mm;
+ int height_mm;
+ int right_border;
+ int top_border;
+ int interlaced;
+ StereoType stereo;
+
+ int digital_sync;
+ union
+ {
+ struct
+ {
+ int bipolar;
+ int serrations;
+ int sync_on_green;
+ } analog;
+
+ struct
+ {
+ int composite;
+ int serrations;
+ int negative_vsync;
+ int negative_hsync;
+ } digital;
+ } ad;
+};
+
+struct MonitorInfo
+{
+ int checksum;
+ char manufacturer_code[4];
+ int product_code;
+ unsigned int serial_number;
+
+ int production_week; /* -1 if not specified */
+ int production_year; /* -1 if not specified */
+ int model_year; /* -1 if not specified */
+
+ int major_version;
+ int minor_version;
+
+ int is_digital;
+
+ union
+ {
+ struct
+ {
+ int bits_per_primary;
+ Interface interface;
+ int rgb444;
+ int ycrcb444;
+ int ycrcb422;
+ } digital;
+
+ struct
+ {
+ double video_signal_level;
+ double sync_signal_level;
+ double total_signal_level;
+
+ int blank_to_black;
+
+ int separate_hv_sync;
+ int composite_sync_on_h;
+ int composite_sync_on_green;
+ int serration_on_vsync;
+ ColorType color_type;
+ } analog;
+ } ad;
+
+ int width_mm; /* -1 if not specified */
+ int height_mm; /* -1 if not specified */
+ double aspect_ratio; /* -1.0 if not specififed */
+
+ double gamma; /* -1.0 if not specified */
+
+ int standby;
+ int suspend;
+ int active_off;
+
+ int srgb_is_standard;
+ int preferred_timing_includes_native;
+ int continuous_frequency;
+
+ double red_x;
+ double red_y;
+ double green_x;
+ double green_y;
+ double blue_x;
+ double blue_y;
+ double white_x;
+ double white_y;
+
+ Timing established[24]; /* Terminated by 0x0x0 */
+ Timing standard[8];
+
+ int n_detailed_timings;
+ DetailedTiming detailed_timings[4]; /* If monitor has a preferred
+ * mode, it is the first one
+ * (whether it has, is
+ * determined by the
+ * preferred_timing_includes
+ * bit.
+ */
+
+ /* Optional product description */
+ char dsc_serial_number[14];
+ char dsc_product_name[14];
+ char dsc_string[14]; /* Unspecified ASCII data */
+};
+
+MonitorInfo *decode_edid (const uchar *data);
+void dump_monitor_info (MonitorInfo *info);
+char * make_display_name (const char *output_name,
+ const MonitorInfo *info);
diff --git a/source/3rd-party/SDL2/src/video/x11/imKStoUCS.c b/source/3rd-party/SDL2/src/video/x11/imKStoUCS.c
new file mode 100644
index 0000000..40e2242
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/imKStoUCS.c
@@ -0,0 +1,350 @@
+/*
+Copyright (C) 2003-2006,2008 Jamey Sharp, Josh Triplett
+Copyright © 2009 Red Hat, Inc.
+Copyright 1990-1992,1999,2000,2004,2009,2010 Oracle and/or its affiliates.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_X11
+#include <X11/X.h>
+#include "imKStoUCS.h"
+
+static unsigned short const keysym_to_unicode_1a1_1ff[] = {
+ 0x0104, 0x02d8, 0x0141, 0x0000, 0x013d, 0x015a, 0x0000, /* 0x01a0-0x01a7 */
+ 0x0000, 0x0160, 0x015e, 0x0164, 0x0179, 0x0000, 0x017d, 0x017b, /* 0x01a8-0x01af */
+ 0x0000, 0x0105, 0x02db, 0x0142, 0x0000, 0x013e, 0x015b, 0x02c7, /* 0x01b0-0x01b7 */
+ 0x0000, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* 0x01b8-0x01bf */
+ 0x0154, 0x0000, 0x0000, 0x0102, 0x0000, 0x0139, 0x0106, 0x0000, /* 0x01c0-0x01c7 */
+ 0x010c, 0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x0000, 0x010e, /* 0x01c8-0x01cf */
+ 0x0110, 0x0143, 0x0147, 0x0000, 0x0000, 0x0150, 0x0000, 0x0000, /* 0x01d0-0x01d7 */
+ 0x0158, 0x016e, 0x0000, 0x0170, 0x0000, 0x0000, 0x0162, 0x0000, /* 0x01d8-0x01df */
+ 0x0155, 0x0000, 0x0000, 0x0103, 0x0000, 0x013a, 0x0107, 0x0000, /* 0x01e0-0x01e7 */
+ 0x010d, 0x0000, 0x0119, 0x0000, 0x011b, 0x0000, 0x0000, 0x010f, /* 0x01e8-0x01ef */
+ 0x0111, 0x0144, 0x0148, 0x0000, 0x0000, 0x0151, 0x0000, 0x0000, /* 0x01f0-0x01f7 */
+ 0x0159, 0x016f, 0x0000, 0x0171, 0x0000, 0x0000, 0x0163, 0x02d9 /* 0x01f8-0x01ff */
+};
+
+static unsigned short const keysym_to_unicode_2a1_2fe[] = {
+ 0x0126, 0x0000, 0x0000, 0x0000, 0x0000, 0x0124, 0x0000, /* 0x02a0-0x02a7 */
+ 0x0000, 0x0130, 0x0000, 0x011e, 0x0134, 0x0000, 0x0000, 0x0000, /* 0x02a8-0x02af */
+ 0x0000, 0x0127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0125, 0x0000, /* 0x02b0-0x02b7 */
+ 0x0000, 0x0131, 0x0000, 0x011f, 0x0135, 0x0000, 0x0000, 0x0000, /* 0x02b8-0x02bf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010a, 0x0108, 0x0000, /* 0x02c0-0x02c7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02c8-0x02cf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0120, 0x0000, 0x0000, /* 0x02d0-0x02d7 */
+ 0x011c, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x015c, 0x0000, /* 0x02d8-0x02df */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010b, 0x0109, 0x0000, /* 0x02e0-0x02e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02e8-0x02ef */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0121, 0x0000, 0x0000, /* 0x02f0-0x02f7 */
+ 0x011d, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x015d /* 0x02f8-0x02ff */
+};
+
+static unsigned short const keysym_to_unicode_3a2_3fe[] = {
+ 0x0138, 0x0156, 0x0000, 0x0128, 0x013b, 0x0000, /* 0x03a0-0x03a7 */
+ 0x0000, 0x0000, 0x0112, 0x0122, 0x0166, 0x0000, 0x0000, 0x0000, /* 0x03a8-0x03af */
+ 0x0000, 0x0000, 0x0000, 0x0157, 0x0000, 0x0129, 0x013c, 0x0000, /* 0x03b0-0x03b7 */
+ 0x0000, 0x0000, 0x0113, 0x0123, 0x0167, 0x014a, 0x0000, 0x014b, /* 0x03b8-0x03bf */
+ 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012e, /* 0x03c0-0x03c7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0116, 0x0000, 0x0000, 0x012a, /* 0x03c8-0x03cf */
+ 0x0000, 0x0145, 0x014c, 0x0136, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03d0-0x03d7 */
+ 0x0000, 0x0172, 0x0000, 0x0000, 0x0000, 0x0168, 0x016a, 0x0000, /* 0x03d8-0x03df */
+ 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012f, /* 0x03e0-0x03e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0117, 0x0000, 0x0000, 0x012b, /* 0x03e8-0x03ef */
+ 0x0000, 0x0146, 0x014d, 0x0137, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03f0-0x03f7 */
+ 0x0000, 0x0173, 0x0000, 0x0000, 0x0000, 0x0169, 0x016b /* 0x03f8-0x03ff */
+};
+
+static unsigned short const keysym_to_unicode_4a1_4df[] = {
+ 0x3002, 0x3008, 0x3009, 0x3001, 0x30fb, 0x30f2, 0x30a1, /* 0x04a0-0x04a7 */
+ 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3, /* 0x04a8-0x04af */
+ 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad, /* 0x04b0-0x04b7 */
+ 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd, /* 0x04b8-0x04bf */
+ 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc, /* 0x04c0-0x04c7 */
+ 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, /* 0x04c8-0x04cf */
+ 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, /* 0x04d0-0x04d7 */
+ 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c /* 0x04d8-0x04df */
+};
+
+static unsigned short const keysym_to_unicode_590_5fe[] = {
+ 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06f6, 0x06f7, /* 0x0590-0x0597 */
+ 0x06f8, 0x06f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0598-0x059f */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x066a, 0x0670, 0x0679, /* 0x05a0-0x05a7 */
+
+ 0x067e, 0x0686, 0x0688, 0x0691, 0x060c, 0x0000, 0x06d4, 0x0000, /* 0x05ac-0x05af */
+ 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, /* 0x05b0-0x05b7 */
+ 0x0668, 0x0669, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, /* 0x05b8-0x05bf */
+ 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, /* 0x05c0-0x05c7 */
+ 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, /* 0x05c8-0x05cf */
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, /* 0x05d0-0x05d7 */
+ 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x05d8-0x05df */
+ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, /* 0x05e0-0x05e7 */
+ 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, /* 0x05e8-0x05ef */
+ 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0698, 0x06a4, /* 0x05f0-0x05f7 */
+ 0x06a9, 0x06af, 0x06ba, 0x06be, 0x06cc, 0x06d2, 0x06c1 /* 0x05f8-0x05fe */
+};
+
+static unsigned short keysym_to_unicode_680_6ff[] = {
+ 0x0492, 0x0496, 0x049a, 0x049c, 0x04a2, 0x04ae, 0x04b0, 0x04b2, /* 0x0680-0x0687 */
+ 0x04b6, 0x04b8, 0x04ba, 0x0000, 0x04d8, 0x04e2, 0x04e8, 0x04ee, /* 0x0688-0x068f */
+ 0x0493, 0x0497, 0x049b, 0x049d, 0x04a3, 0x04af, 0x04b1, 0x04b3, /* 0x0690-0x0697 */
+ 0x04b7, 0x04b9, 0x04bb, 0x0000, 0x04d9, 0x04e3, 0x04e9, 0x04ef, /* 0x0698-0x069f */
+ 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, /* 0x06a0-0x06a7 */
+ 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0491, 0x045e, 0x045f, /* 0x06a8-0x06af */
+ 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, /* 0x06b0-0x06b7 */
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0490, 0x040e, 0x040f, /* 0x06b8-0x06bf */
+ 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, /* 0x06c0-0x06c7 */
+ 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0x06c8-0x06cf */
+ 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, /* 0x06d0-0x06d7 */
+ 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0x06d8-0x06df */
+ 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, /* 0x06e0-0x06e7 */
+ 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0x06e8-0x06ef */
+ 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, /* 0x06f0-0x06f7 */
+ 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a /* 0x06f8-0x06ff */
+};
+
+static unsigned short const keysym_to_unicode_7a1_7f9[] = {
+ 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, /* 0x07a0-0x07a7 */
+ 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, /* 0x07a8-0x07af */
+ 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, /* 0x07b0-0x07b7 */
+ 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07b8-0x07bf */
+ 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, /* 0x07c0-0x07c7 */
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, /* 0x07c8-0x07cf */
+ 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, /* 0x07d0-0x07d7 */
+ 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07d8-0x07df */
+ 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, /* 0x07e0-0x07e7 */
+ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, /* 0x07e8-0x07ef */
+ 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, /* 0x07f0-0x07f7 */
+ 0x03c8, 0x03c9 /* 0x07f8-0x07ff */
+};
+
+static unsigned short const keysym_to_unicode_8a4_8fe[] = {
+ 0x2320, 0x2321, 0x0000, 0x231c, /* 0x08a0-0x08a7 */
+ 0x231d, 0x231e, 0x231f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08a8-0x08af */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08b0-0x08b7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222b, /* 0x08b8-0x08bf */
+ 0x2234, 0x0000, 0x221e, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, /* 0x08c0-0x08c7 */
+ 0x2245, 0x2246, 0x0000, 0x0000, 0x0000, 0x0000, 0x21d2, 0x0000, /* 0x08c8-0x08cf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221a, 0x0000, /* 0x08d0-0x08d7 */
+ 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222a, 0x2227, 0x2228, /* 0x08d8-0x08df */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e0-0x08e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202, /* 0x08e8-0x08ef */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, /* 0x08f0-0x08f7 */
+ 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193 /* 0x08f8-0x08ff */
+};
+
+static unsigned short const keysym_to_unicode_9df_9f8[] = {
+ 0x2422, /* 0x09d8-0x09df */
+ 0x2666, 0x25a6, 0x2409, 0x240c, 0x240d, 0x240a, 0x0000, 0x0000, /* 0x09e0-0x09e7 */
+ 0x240a, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x2500, /* 0x09e8-0x09ef */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x251c, 0x2524, 0x2534, 0x252c, /* 0x09f0-0x09f7 */
+ 0x2502 /* 0x09f8-0x09ff */
+};
+
+static unsigned short const keysym_to_unicode_aa1_afe[] = {
+ 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, /* 0x0aa0-0x0aa7 */
+ 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, /* 0x0aa8-0x0aaf */
+ 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, /* 0x0ab0-0x0ab7 */
+ 0x2105, 0x0000, 0x0000, 0x2012, 0x2039, 0x2024, 0x203a, 0x0000, /* 0x0ab8-0x0abf */
+ 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, /* 0x0ac0-0x0ac7 */
+ 0x0000, 0x2122, 0x2120, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25ad, /* 0x0ac8-0x0acf */
+ 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x2030, 0x2032, 0x2033, /* 0x0ad0-0x0ad7 */
+ 0x0000, 0x271d, 0x0000, 0x220e, 0x25c2, 0x2023, 0x25cf, 0x25ac, /* 0x0ad8-0x0adf */
+ 0x25e6, 0x25ab, 0x25ae, 0x25b5, 0x25bf, 0x2606, 0x2022, 0x25aa, /* 0x0ae0-0x0ae7 */
+ 0x25b4, 0x25be, 0x261a, 0x261b, 0x2663, 0x2666, 0x2665, 0x0000, /* 0x0ae8-0x0aef */
+ 0x2720, 0x2020, 0x2021, 0x2713, 0x2612, 0x266f, 0x266d, 0x2642, /* 0x0af0-0x0af7 */
+ 0x2640, 0x2121, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e /* 0x0af8-0x0aff */
+};
+
+/* none of the APL keysyms match the Unicode characters */
+
+static unsigned short const keysym_to_unicode_cdf_cfa[] = {
+ 0x2017, /* 0x0cd8-0x0cdf */
+ 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, /* 0x0ce0-0x0ce7 */
+ 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, /* 0x0ce8-0x0cef */
+ 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, /* 0x0cf0-0x0cf7 */
+ 0x05e8, 0x05e9, 0x05ea /* 0x0cf8-0x0cff */
+};
+
+static unsigned short const keysym_to_unicode_da1_df9[] = {
+ 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, /* 0x0da0-0x0da7 */
+ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, /* 0x0da8-0x0daf */
+ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, /* 0x0db0-0x0db7 */
+ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, /* 0x0db8-0x0dbf */
+ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, /* 0x0dc0-0x0dc7 */
+ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, /* 0x0dc8-0x0dcf */
+ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, /* 0x0dd0-0x0dd7 */
+ 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0e3e, 0x0e3f, /* 0x0dd8-0x0ddf */
+ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, /* 0x0de0-0x0de7 */
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0000, 0x0000, /* 0x0de8-0x0def */
+ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, /* 0x0df0-0x0df7 */
+ 0x0e58, 0x0e59 /* 0x0df8-0x0dff */
+};
+
+static unsigned short const keysym_to_unicode_ea0_eff[] = {
+ 0x0000, 0x1101, 0x1101, 0x11aa, 0x1102, 0x11ac, 0x11ad, 0x1103, /* 0x0ea0-0x0ea7 */
+ 0x1104, 0x1105, 0x11b0, 0x11b1, 0x11b2, 0x11b3, 0x11b4, 0x11b5, /* 0x0ea8-0x0eaf */
+ 0x11b6, 0x1106, 0x1107, 0x1108, 0x11b9, 0x1109, 0x110a, 0x110b, /* 0x0eb0-0x0eb7 */
+ 0x110c, 0x110d, 0x110e, 0x110f, 0x1110, 0x1111, 0x1112, 0x1161, /* 0x0eb8-0x0ebf */
+ 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169, /* 0x0ec0-0x0ec7 */
+ 0x116a, 0x116b, 0x116c, 0x116d, 0x116e, 0x116f, 0x1170, 0x1171, /* 0x0ec8-0x0ecf */
+ 0x1172, 0x1173, 0x1174, 0x1175, 0x11a8, 0x11a9, 0x11aa, 0x11ab, /* 0x0ed0-0x0ed7 */
+ 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, /* 0x0ed8-0x0edf */
+ 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, /* 0x0ee0-0x0ee7 */
+ 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x0000, /* 0x0ee8-0x0eef */
+ 0x0000, 0x0000, 0x1140, 0x0000, 0x0000, 0x1159, 0x119e, 0x0000, /* 0x0ef0-0x0ef7 */
+ 0x11eb, 0x0000, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9, /* 0x0ef8-0x0eff */
+};
+
+static unsigned short keysym_to_unicode_12a1_12fe[] = {
+ 0x1e02, 0x1e03, 0x0000, 0x0000, 0x0000, 0x1e0a, 0x0000, /* 0x12a0-0x12a7 */
+ 0x1e80, 0x0000, 0x1e82, 0x1e0b, 0x1ef2, 0x0000, 0x0000, 0x0000, /* 0x12a8-0x12af */
+ 0x1e1e, 0x1e1f, 0x0000, 0x0000, 0x1e40, 0x1e41, 0x0000, 0x1e56, /* 0x12b0-0x12b7 */
+ 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, /* 0x12b8-0x12bf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c0-0x12c7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c8-0x12cf */
+ 0x0174, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6a, /* 0x12d0-0x12d7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0176, 0x0000, /* 0x12d8-0x12df */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e0-0x12e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e8-0x12ef */
+ 0x0175, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6b, /* 0x12f0-0x12f7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0177 /* 0x12f0-0x12ff */
+};
+
+static unsigned short const keysym_to_unicode_13bc_13be[] = {
+ 0x0152, 0x0153, 0x0178 /* 0x13b8-0x13bf */
+};
+
+static unsigned short keysym_to_unicode_14a1_14ff[] = {
+ 0x2741, 0x00a7, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab, /* 0x14a0-0x14a7 */
+ 0x2014, 0x002e, 0x055d, 0x002c, 0x2013, 0x058a, 0x2026, 0x055c, /* 0x14a8-0x14af */
+ 0x055b, 0x055e, 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563, /* 0x14b0-0x14b7 */
+ 0x0534, 0x0564, 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567, /* 0x14b8-0x14bf */
+ 0x0538, 0x0568, 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b, /* 0x14c0-0x14c7 */
+ 0x053c, 0x056c, 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f, /* 0x14c8-0x14cf */
+ 0x0540, 0x0570, 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573, /* 0x14d0-0x14d7 */
+ 0x0544, 0x0574, 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577, /* 0x14d8-0x14df */
+ 0x0548, 0x0578, 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b, /* 0x14e0-0x14e7 */
+ 0x054c, 0x057c, 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f, /* 0x14e8-0x14ef */
+ 0x0550, 0x0580, 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583, /* 0x14f0-0x14f7 */
+ 0x0554, 0x0584, 0x0555, 0x0585, 0x0556, 0x0586, 0x2019, 0x0027, /* 0x14f8-0x14ff */
+};
+
+static unsigned short keysym_to_unicode_15d0_15f6[] = {
+ 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, /* 0x15d0-0x15d7 */
+ 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, /* 0x15d8-0x15df */
+ 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, /* 0x15e0-0x15e7 */
+ 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, /* 0x15e8-0x15ef */
+ 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6 /* 0x15f0-0x15f7 */
+};
+
+static unsigned short keysym_to_unicode_16a0_16f6[] = {
+ 0x0000, 0x0000, 0xf0a2, 0x1e8a, 0x0000, 0xf0a5, 0x012c, 0xf0a7, /* 0x16a0-0x16a7 */
+ 0xf0a8, 0x01b5, 0x01e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x019f, /* 0x16a8-0x16af */
+ 0x0000, 0x0000, 0xf0b2, 0x1e8b, 0x01d1, 0xf0b5, 0x012d, 0xf0b7, /* 0x16b0-0x16b7 */
+ 0xf0b8, 0x01b6, 0x01e7, 0x0000, 0x0000, 0x01d2, 0x0000, 0x0275, /* 0x16b8-0x16bf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x018f, 0x0000, /* 0x16c0-0x16c7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16c8-0x16cf */
+ 0x0000, 0x1e36, 0xf0d2, 0xf0d3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d0-0x16d7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d8-0x16df */
+ 0x0000, 0x1e37, 0xf0e2, 0xf0e3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e0-0x16e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e8-0x16ef */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0259 /* 0x16f0-0x16f6 */
+};
+
+static unsigned short const keysym_to_unicode_1e9f_1eff[] = {
+ 0x0303,
+ 0x1ea0, 0x1ea1, 0x1ea2, 0x1ea3, 0x1ea4, 0x1ea5, 0x1ea6, 0x1ea7, /* 0x1ea0-0x1ea7 */
+ 0x1ea8, 0x1ea9, 0x1eaa, 0x1eab, 0x1eac, 0x1ead, 0x1eae, 0x1eaf, /* 0x1ea8-0x1eaf */
+ 0x1eb0, 0x1eb1, 0x1eb2, 0x1eb3, 0x1eb4, 0x1eb5, 0x1eb6, 0x1eb7, /* 0x1eb0-0x1eb7 */
+ 0x1eb8, 0x1eb9, 0x1eba, 0x1ebb, 0x1ebc, 0x1ebd, 0x1ebe, 0x1ebf, /* 0x1eb8-0x1ebf */
+ 0x1ec0, 0x1ec1, 0x1ec2, 0x1ec3, 0x1ec4, 0x1ec5, 0x1ec6, 0x1ec7, /* 0x1ec0-0x1ec7 */
+ 0x1ec8, 0x1ec9, 0x1eca, 0x1ecb, 0x1ecc, 0x1ecd, 0x1ece, 0x1ecf, /* 0x1ec8-0x1ecf */
+ 0x1ed0, 0x1ed1, 0x1ed2, 0x1ed3, 0x1ed4, 0x1ed5, 0x1ed6, 0x1ed7, /* 0x1ed0-0x1ed7 */
+ 0x1ed8, 0x1ed9, 0x1eda, 0x1edb, 0x1edc, 0x1edd, 0x1ede, 0x1edf, /* 0x1ed8-0x1edf */
+ 0x1ee0, 0x1ee1, 0x1ee2, 0x1ee3, 0x1ee4, 0x1ee5, 0x1ee6, 0x1ee7, /* 0x1ee0-0x1ee7 */
+ 0x1ee8, 0x1ee9, 0x1eea, 0x1eeb, 0x1eec, 0x1eed, 0x1eee, 0x1eef, /* 0x1ee8-0x1eef */
+ 0x1ef0, 0x1ef1, 0x0300, 0x0301, 0x1ef4, 0x1ef5, 0x1ef6, 0x1ef7, /* 0x1ef0-0x1ef7 */
+ 0x1ef8, 0x1ef9, 0x01a0, 0x01a1, 0x01af, 0x01b0, 0x0309, 0x0323 /* 0x1ef8-0x1eff */
+};
+
+static unsigned short const keysym_to_unicode_20a0_20ac[] = {
+ 0x20a0, 0x20a1, 0x20a2, 0x20a3, 0x20a4, 0x20a5, 0x20a6, 0x20a7, /* 0x20a0-0x20a7 */
+ 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac /* 0x20a8-0x20af */
+};
+
+unsigned int
+X11_KeySymToUcs4(KeySym keysym)
+{
+ /* 'Unicode keysym' */
+ if ((keysym & 0xff000000) == 0x01000000)
+ return (keysym & 0x00ffffff);
+
+ if (keysym > 0 && keysym < 0x100)
+ return keysym;
+ else if (keysym > 0x1a0 && keysym < 0x200)
+ return keysym_to_unicode_1a1_1ff[keysym - 0x1a1];
+ else if (keysym > 0x2a0 && keysym < 0x2ff)
+ return keysym_to_unicode_2a1_2fe[keysym - 0x2a1];
+ else if (keysym > 0x3a1 && keysym < 0x3ff)
+ return keysym_to_unicode_3a2_3fe[keysym - 0x3a2];
+ else if (keysym > 0x4a0 && keysym < 0x4e0)
+ return keysym_to_unicode_4a1_4df[keysym - 0x4a1];
+ else if (keysym > 0x589 && keysym < 0x5ff)
+ return keysym_to_unicode_590_5fe[keysym - 0x590];
+ else if (keysym > 0x67f && keysym < 0x700)
+ return keysym_to_unicode_680_6ff[keysym - 0x680];
+ else if (keysym > 0x7a0 && keysym < 0x7fa)
+ return keysym_to_unicode_7a1_7f9[keysym - 0x7a1];
+ else if (keysym > 0x8a3 && keysym < 0x8ff)
+ return keysym_to_unicode_8a4_8fe[keysym - 0x8a4];
+ else if (keysym > 0x9de && keysym < 0x9f9)
+ return keysym_to_unicode_9df_9f8[keysym - 0x9df];
+ else if (keysym > 0xaa0 && keysym < 0xaff)
+ return keysym_to_unicode_aa1_afe[keysym - 0xaa1];
+ else if (keysym > 0xcde && keysym < 0xcfb)
+ return keysym_to_unicode_cdf_cfa[keysym - 0xcdf];
+ else if (keysym > 0xda0 && keysym < 0xdfa)
+ return keysym_to_unicode_da1_df9[keysym - 0xda1];
+ else if (keysym > 0xe9f && keysym < 0xf00)
+ return keysym_to_unicode_ea0_eff[keysym - 0xea0];
+ else if (keysym > 0x12a0 && keysym < 0x12ff)
+ return keysym_to_unicode_12a1_12fe[keysym - 0x12a1];
+ else if (keysym > 0x13bb && keysym < 0x13bf)
+ return keysym_to_unicode_13bc_13be[keysym - 0x13bc];
+ else if (keysym > 0x14a0 && keysym < 0x1500)
+ return keysym_to_unicode_14a1_14ff[keysym - 0x14a1];
+ else if (keysym > 0x15cf && keysym < 0x15f7)
+ return keysym_to_unicode_15d0_15f6[keysym - 0x15d0];
+ else if (keysym > 0x169f && keysym < 0x16f7)
+ return keysym_to_unicode_16a0_16f6[keysym - 0x16a0];
+ else if (keysym > 0x1e9e && keysym < 0x1f00)
+ return keysym_to_unicode_1e9f_1eff[keysym - 0x1e9f];
+ else if (keysym > 0x209f && keysym < 0x20ad)
+ return keysym_to_unicode_20a0_20ac[keysym - 0x20a0];
+ else
+ return 0;
+}
+
+#endif /* SDL_VIDEO_DRIVER_X11 */
+
diff --git a/source/3rd-party/SDL2/src/video/x11/imKStoUCS.h b/source/3rd-party/SDL2/src/video/x11/imKStoUCS.h
new file mode 100644
index 0000000..fe4381d
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/x11/imKStoUCS.h
@@ -0,0 +1,32 @@
+#ifndef _imKStoUCS_h
+#define _imKStoUCS_h
+
+/*
+Copyright (C) 2003-2006,2008 Jamey Sharp, Josh Triplett
+Copyright © 2009 Red Hat, Inc.
+Copyright 1990-1992,1999,2000,2004,2009,2010 Oracle and/or its affiliates.
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+extern unsigned int X11_KeySymToUcs4(KeySym keysym);
+
+#endif /* _imKStoUCS_h */