From 30f41c02aec763d32e62351452da9ef582bc3472 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 6 Mar 2026 13:30:59 -0800 Subject: Move contrib libraries to contrib repo --- contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.c | 329 --- contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.h | 46 - contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.c | 211 -- contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.h | 113 - contrib/SDL-3.2.8/src/video/x11/SDL_x11events.c | 2205 ------------------- contrib/SDL-3.2.8/src/video/x11/SDL_x11events.h | 40 - .../SDL-3.2.8/src/video/x11/SDL_x11framebuffer.c | 261 --- .../SDL-3.2.8/src/video/x11/SDL_x11framebuffer.h | 34 - contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.c | 789 ------- contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.h | 40 - .../SDL-3.2.8/src/video/x11/SDL_x11messagebox.c | 887 -------- .../SDL-3.2.8/src/video/x11/SDL_x11messagebox.h | 31 - contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.c | 1051 --------- contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.h | 69 - contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.c | 552 ----- contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.h | 40 - contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.c | 1116 ---------- contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.h | 96 - contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.c | 152 -- contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.h | 55 - contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.c | 437 ---- contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.h | 72 - contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.c | 129 -- contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.h | 39 - contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.c | 111 - contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.h | 28 - contrib/SDL-3.2.8/src/video/x11/SDL_x11sym.h | 354 --- contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.c | 46 - contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.h | 30 - contrib/SDL-3.2.8/src/video/x11/SDL_x11video.c | 505 ----- contrib/SDL-3.2.8/src/video/x11/SDL_x11video.h | 177 -- contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.c | 290 --- contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.h | 52 - contrib/SDL-3.2.8/src/video/x11/SDL_x11window.c | 2243 -------------------- contrib/SDL-3.2.8/src/video/x11/SDL_x11window.h | 169 -- contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.c | 214 -- contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.h | 39 - contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.c | 829 -------- contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.h | 44 - contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.c | 148 -- contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.h | 39 - contrib/SDL-3.2.8/src/video/x11/edid-parse.c | 753 ------- contrib/SDL-3.2.8/src/video/x11/edid.h | 191 -- contrib/SDL-3.2.8/src/video/x11/xsettings-client.c | 859 -------- contrib/SDL-3.2.8/src/video/x11/xsettings-client.h | 153 -- 45 files changed, 16068 deletions(-) delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11events.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11events.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11framebuffer.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11framebuffer.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11messagebox.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11messagebox.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11sym.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11video.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11video.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11window.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11window.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/edid-parse.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/edid.h delete mode 100644 contrib/SDL-3.2.8/src/video/x11/xsettings-client.c delete mode 100644 contrib/SDL-3.2.8/src/video/x11/xsettings-client.h (limited to 'contrib/SDL-3.2.8/src/video/x11') diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.c deleted file mode 100644 index 5e33555..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include // For INT_MAX - -#include "SDL_x11video.h" -#include "SDL_x11clipboard.h" -#include "../SDL_clipboard_c.h" -#include "../../events/SDL_events_c.h" - -static const char *text_mime_types[] = { - "UTF8_STRING", - "text/plain;charset=utf-8", - "text/plain", - "TEXT", - "STRING" -}; - -// Get any application owned window handle for clipboard association -Window GetWindow(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - - /* 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_XSelectInput(dpy, data->clipboard_window, PropertyChangeMask); - X11_XFlush(data->display); - } - - return data->clipboard_window; -} - -static bool SetSelectionData(SDL_VideoDevice *_this, Atom selection, SDL_ClipboardDataCallback callback, - void *userdata, const char **mime_types, size_t mime_count, Uint32 sequence) -{ - SDL_VideoData *videodata = _this->internal; - Display *display = videodata->display; - Window window; - SDLX11_ClipboardData *clipboard; - bool clipboard_owner = false; - - window = GetWindow(_this); - if (window == None) { - return SDL_SetError("Couldn't find a window to own the selection"); - } - - if (selection == XA_PRIMARY) { - clipboard = &videodata->primary_selection; - } else { - clipboard = &videodata->clipboard; - } - - clipboard_owner = X11_XGetSelectionOwner(display, selection) == window; - - // If we are canceling our own data we need to clean it up - if (clipboard_owner && clipboard->sequence == 0) { - SDL_free(clipboard->userdata); - } - - clipboard->callback = callback; - clipboard->userdata = userdata; - clipboard->mime_types = mime_types; - clipboard->mime_count = mime_count; - clipboard->sequence = sequence; - - X11_XSetSelectionOwner(display, selection, window, CurrentTime); - return true; -} - -static void *CloneDataBuffer(const void *buffer, const size_t len) -{ - void *clone = NULL; - if (len > 0 && buffer) { - clone = SDL_malloc(len + sizeof(Uint32)); - if (clone) { - SDL_memcpy(clone, buffer, len); - SDL_memset((Uint8 *)clone + len, 0, sizeof(Uint32)); - } - } - return clone; -} - -/* - * original_buffer is considered unusable after the function is called. - */ -static void *AppendDataBuffer(void *original_buffer, const size_t old_len, const void *buffer, const size_t buffer_len) -{ - void *resized_buffer; - - if (buffer_len > 0 && buffer) { - resized_buffer = SDL_realloc(original_buffer, old_len + buffer_len + sizeof(Uint32)); - if (resized_buffer) { - SDL_memcpy((Uint8 *)resized_buffer + old_len, buffer, buffer_len); - SDL_memset((Uint8 *)resized_buffer + old_len + buffer_len, 0, sizeof(Uint32)); - } - - return resized_buffer; - } else { - return original_buffer; - } -} - -static bool WaitForSelection(SDL_VideoDevice *_this, Atom selection_type, bool *flag) -{ - Uint64 waitStart; - Uint64 waitElapsed; - - waitStart = SDL_GetTicks(); - *flag = true; - while (*flag) { - SDL_PumpEvents(); - waitElapsed = SDL_GetTicks() - waitStart; - // Wait one second for a selection response. - if (waitElapsed > 1000) { - *flag = false; - SDL_SetError("Selection timeout"); - /* We need to set the selection text so that next time we won't - timeout, otherwise we will hang on every call to this function. */ - SetSelectionData(_this, selection_type, SDL_ClipboardTextCallback, NULL, - text_mime_types, SDL_arraysize(text_mime_types), 0); - return false; - } - } - - return true; -} - -static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type, - const char *mime_type, size_t *length) -{ - SDL_VideoData *videodata = _this->internal; - Display *display = videodata->display; - Window window; - Window owner; - Atom selection; - Atom seln_type; - int seln_format; - unsigned long count; - unsigned long overflow; - - SDLX11_ClipboardData *clipboard; - void *data = NULL; - unsigned char *src = NULL; - bool incr_success = false; - Atom XA_MIME = X11_XInternAtom(display, mime_type, False); - - *length = 0; - - // Get the window that holds the selection - window = GetWindow(_this); - owner = X11_XGetSelectionOwner(display, selection_type); - if (owner == None) { - // This requires a fallback to ancient X10 cut-buffers. We will just skip those for now - data = NULL; - } else if (owner == window) { - owner = DefaultRootWindow(display); - if (selection_type == XA_PRIMARY) { - clipboard = &videodata->primary_selection; - } else { - clipboard = &videodata->clipboard; - } - - if (clipboard->callback) { - const void *clipboard_data = clipboard->callback(clipboard->userdata, mime_type, length); - data = CloneDataBuffer(clipboard_data, *length); - } - } else { - // Request that the selection owner copy the data to our window - owner = window; - selection = videodata->atoms.SDL_SELECTION; - X11_XConvertSelection(display, selection_type, XA_MIME, selection, owner, - CurrentTime); - - if (WaitForSelection(_this, selection_type, &videodata->selection_waiting) == false) { - data = NULL; - *length = 0; - } - - if (X11_XGetWindowProperty(display, owner, selection, 0, INT_MAX / 4, False, - XA_MIME, &seln_type, &seln_format, &count, &overflow, &src) == Success) { - if (seln_type == XA_MIME) { - *length = (size_t)count; - data = CloneDataBuffer(src, count); - } else if (seln_type == videodata->atoms.INCR) { - while (1) { - // Only delete the property after being done with the previous "chunk". - X11_XDeleteProperty(display, owner, selection); - X11_XFlush(display); - - if (WaitForSelection(_this, selection_type, &videodata->selection_incr_waiting) == false) { - break; - } - - X11_XFree(src); - if (X11_XGetWindowProperty(display, owner, selection, 0, INT_MAX / 4, False, - XA_MIME, &seln_type, &seln_format, &count, &overflow, &src) != Success) { - break; - } - - if (count == 0) { - incr_success = true; - break; - } - - if (*length == 0) { - *length = (size_t)count; - data = CloneDataBuffer(src, count); - } else { - data = AppendDataBuffer(data, *length, src, count); - *length += (size_t)count; - } - - if (data == NULL) { - break; - } - } - - if (incr_success == false) { - SDL_free(data); - data = 0; - *length = 0; - } - } - X11_XFree(src); - } - } - return data; -} - -const char **X11_GetTextMimeTypes(SDL_VideoDevice *_this, size_t *num_mime_types) -{ - *num_mime_types = SDL_arraysize(text_mime_types); - return text_mime_types; -} - -bool X11_SetClipboardData(SDL_VideoDevice *_this) -{ - SDL_VideoData *videodata = _this->internal; - return SetSelectionData(_this, videodata->atoms.CLIPBOARD, _this->clipboard_callback, _this->clipboard_userdata, (const char **)_this->clipboard_mime_types, _this->num_clipboard_mime_types, _this->clipboard_sequence); -} - -void *X11_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *length) -{ - SDL_VideoData *videodata = _this->internal; - return GetSelectionData(_this, videodata->atoms.CLIPBOARD, mime_type, length); -} - -bool X11_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type) -{ - size_t length; - void *data; - data = X11_GetClipboardData(_this, mime_type, &length); - if (data) { - SDL_free(data); - } - return length > 0; -} - -bool X11_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text) -{ - return SetSelectionData(_this, XA_PRIMARY, SDL_ClipboardTextCallback, SDL_strdup(text), text_mime_types, SDL_arraysize(text_mime_types), 0); -} - -char *X11_GetPrimarySelectionText(SDL_VideoDevice *_this) -{ - size_t length; - char *text = GetSelectionData(_this, XA_PRIMARY, text_mime_types[0], &length); - if (!text) { - text = SDL_strdup(""); - } - return text; -} - -bool X11_HasPrimarySelectionText(SDL_VideoDevice *_this) -{ - bool result = false; - char *text = X11_GetPrimarySelectionText(_this); - if (text) { - if (text[0] != '\0') { - result = true; - } - SDL_free(text); - } - return result; -} - -void X11_QuitClipboard(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - if (data->primary_selection.sequence == 0) { - SDL_free(data->primary_selection.userdata); - } - if (data->clipboard.sequence == 0) { - SDL_free(data->clipboard.userdata); - } -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.h deleted file mode 100644 index da5990a..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11clipboard.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_ - -#include - -typedef struct X11_ClipboardData { - SDL_ClipboardDataCallback callback; - void *userdata; - const char **mime_types; - size_t mime_count; - Uint32 sequence; -} SDLX11_ClipboardData; - -extern const char **X11_GetTextMimeTypes(SDL_VideoDevice *_this, size_t *num_mime_types); -extern bool X11_SetClipboardData(SDL_VideoDevice *_this); -extern void *X11_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *length); -extern bool X11_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type); -extern bool X11_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text); -extern char *X11_GetPrimarySelectionText(SDL_VideoDevice *_this); -extern bool X11_HasPrimarySelectionText(SDL_VideoDevice *_this); -extern void X11_QuitClipboard(SDL_VideoDevice *_this); -Window GetWindow(SDL_VideoDevice *_this); - -#endif // SDL_x11clipboard_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.c deleted file mode 100644 index 7c48ed5..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#define DEBUG_DYNAMIC_X11 0 - -#include "SDL_x11dyn.h" - -#if DEBUG_DYNAMIC_X11 -#include -#endif - -#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC - -typedef struct -{ - SDL_SharedObject *lib; - const char *libname; -} x11dynlib; - -#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_XINPUT2 -#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 NULL -#endif -#ifndef SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES -#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES 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 - -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_XINPUT2 }, - { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XFIXES }, - { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR }, - { NULL, SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS } -}; - -static void *X11_GetSym(const char *fnname, int *pHasModule) -{ - int i; - void *fn = NULL; - for (i = 0; i < SDL_arraysize(x11libs); i++) { - if (x11libs[i].lib) { - fn = SDL_LoadFunction(x11libs[i].lib, fnname); - if (fn) { - break; - } - } - } - -#if DEBUG_DYNAMIC_X11 - if (fn) - 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) { - *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; -SDL_DYNX11FN_XSetICValues X11_XSetICValues = NULL; -SDL_DYNX11FN_XVaCreateNestedList X11_XVaCreateNestedList = 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) { -#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC - int i; -#endif - - // 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; - X11_XSetICValues = NULL; - X11_XVaCreateNestedList = NULL; -#endif - -#ifdef SDL_VIDEO_DRIVER_X11_DYNAMIC - for (i = 0; i < SDL_arraysize(x11libs); i++) { - if (x11libs[i].lib) { - SDL_UnloadObject(x11libs[i].lib); - x11libs[i].lib = NULL; - } - } -#endif - } - } -} - -// returns non-zero if all needed symbols were loaded. -bool SDL_X11_LoadSymbols(void) -{ - bool result = true; // 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_arraysize(x11libs); i++) { - if (x11libs[i].libname) { - 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); - X11_XSetICValues = (SDL_DYNX11FN_XSetICValues) - X11_GetSym("XSetICValues", &SDL_X11_HAVE_UTF8); - X11_XVaCreateNestedList = (SDL_DYNX11FN_XVaCreateNestedList) - X11_GetSym("XVaCreateNestedList", &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(); - result = false; - } - -#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; - X11_XSetICValues = XSetICValues; - X11_XVaCreateNestedList = XVaCreateNestedList; -#endif -#endif - } - - return result; -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.h deleted file mode 100644 index e9831fc..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11dyn.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 -#include -#include -#include - -#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM -#include -#endif - -// Apparently some X11 systems can't include this multiple times... -#ifndef SDL_INCLUDED_XLIBINT_H -#define SDL_INCLUDED_XLIBINT_H 1 -#include -#endif - -#include -#include - -#ifndef NO_SHARED_MEMORY -#include -#include -#include -#endif - -#ifdef SDL_VIDEO_DRIVER_X11_XCURSOR -#include -#endif -#ifdef SDL_VIDEO_DRIVER_X11_XDBE -#include -#endif -#if defined(SDL_VIDEO_DRIVER_X11_XINPUT2) || defined(SDL_VIDEO_DRIVER_X11_XFIXES) -#include -#endif -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES -#include -#endif -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC -#include -#endif -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR -#include -#endif -#ifdef SDL_VIDEO_DRIVER_X11_XSCRNSAVER -#include -#endif -#ifdef SDL_VIDEO_DRIVER_X11_XSHAPE -#include -#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 *); - -extern bool SDL_X11_LoadSymbols(void); -extern 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, ...); -typedef char *(*SDL_DYNX11FN_XSetICValues)(XIC, ...); -typedef XVaNestedList (*SDL_DYNX11FN_XVaCreateNestedList)(int, ...); -extern SDL_DYNX11FN_XCreateIC X11_XCreateIC; -extern SDL_DYNX11FN_XGetICValues X11_XGetICValues; -extern SDL_DYNX11FN_XSetICValues X11_XSetICValues; -extern SDL_DYNX11FN_XVaCreateNestedList X11_XVaCreateNestedList; -#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_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11events.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11events.c deleted file mode 100644 index 02c2d90..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11events.c +++ /dev/null @@ -1,2205 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include -#include -#include -#include -#include // For INT_MAX - -#include "SDL_x11video.h" -#include "SDL_x11pen.h" -#include "SDL_x11touch.h" -#include "SDL_x11xinput2.h" -#include "SDL_x11xfixes.h" -#include "SDL_x11settings.h" -#include "../SDL_clipboard_c.h" -#include "SDL_x11xsync.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 "../../core/linux/SDL_system_theme.h" -#include "../SDL_sysvideo.h" - -#include - -#if 0 -#define DEBUG_XEVENTS -#endif - -#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) { - 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]); - // Preferred MIME targets - if ((SDL_strcmp("text/uri-list", name) == 0) || - (SDL_strcmp("text/plain;charset=utf-8", name) == 0) || - (SDL_strcmp("UTF8_STRING", name) == 0)) { - request = list[i]; - } - // Fallback MIME targets - if ((SDL_strcmp("text/plain", name) == 0) || - (SDL_strcmp("TEXT", name) == 0)) { - if (request == None) { - 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; - 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 = true; - } - return False; -} - -/* Check to see if this is a repeated key. - (idea shamelessly lifted from GII -- thanks guys! :) - */ -static bool X11_KeyRepeat(Display *display, XEvent *event) -{ - XEvent dummyev; - struct KeyRepeatCheckData d; - d.event = event; - d.found = false; - if (X11_XPending(display)) { - X11_XCheckIfEvent(display, &dummyev, X11_KeyRepeatCheckIfEvent, (XPointer)&d); - } - return d.found; -} - -static bool X11_IsWheelEvent(Display *display, int button, 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 (button) { - case 4: - *yticks = 1; - return true; - case 5: - *yticks = -1; - return true; - case 6: - *xticks = 1; - return true; - case 7: - *xticks = -1; - return true; - default: - break; - } - return false; -} - -// An X11 event hook -static SDL_X11EventHook g_X11EventHook = NULL; -static void *g_X11EventHookData = NULL; - -void SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata) -{ - g_X11EventHook = callback; - g_X11EventHookData = userdata; -} - -#ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS -static void X11_HandleGenericEvent(SDL_VideoDevice *_this, XEvent *xev) -{ - SDL_VideoData *videodata = _this->internal; - - // event is a union, so cookie == &event, but this is type safe. - XGenericEventCookie *cookie = &xev->xcookie; - if (X11_XGetEventData(videodata->display, cookie)) { - if (!g_X11EventHook || g_X11EventHook(g_X11EventHookData, xev)) { - X11_HandleXinput2Event(_this, cookie); - } - X11_XFreeEventData(videodata->display, cookie); - } -} -#endif // SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS - -static void X11_UpdateSystemKeyModifiers(SDL_VideoData *viddata) -{ - Window junk_window; - int x, y; - - X11_XQueryPointer(viddata->display, DefaultRootWindow(viddata->display), &junk_window, &junk_window, &x, &y, &x, &y, &viddata->xkb.xkb_modifiers); -} - -static void X11_ReconcileModifiers(SDL_VideoData *viddata) -{ - const Uint32 xk_modifiers = viddata->xkb.xkb_modifiers; - - /* If a modifier was activated by a keypress, it will be tied to the - * specific left/right key that initiated it. Otherwise, the ambiguous - * left/right combo is used. - */ - if (xk_modifiers & ShiftMask) { - if (!(viddata->xkb.sdl_modifiers & SDL_KMOD_SHIFT)) { - viddata->xkb.sdl_modifiers |= SDL_KMOD_SHIFT; - } - } else { - viddata->xkb.sdl_modifiers &= ~SDL_KMOD_SHIFT; - } - - if (xk_modifiers & ControlMask) { - if (!(viddata->xkb.sdl_modifiers & SDL_KMOD_CTRL)) { - viddata->xkb.sdl_modifiers |= SDL_KMOD_CTRL; - } - } else { - viddata->xkb.sdl_modifiers &= ~SDL_KMOD_CTRL; - } - - // Mod1 is used for the Alt keys - if (xk_modifiers & Mod1Mask) { - if (!(viddata->xkb.sdl_modifiers & SDL_KMOD_ALT)) { - viddata->xkb.sdl_modifiers |= SDL_KMOD_ALT; - } - } else { - viddata->xkb.sdl_modifiers &= ~SDL_KMOD_ALT; - } - - // Mod4 is used for the Super (aka GUI/Logo) keys. - if (xk_modifiers & Mod4Mask) { - if (!(viddata->xkb.sdl_modifiers & SDL_KMOD_GUI)) { - viddata->xkb.sdl_modifiers |= SDL_KMOD_GUI; - } - } else { - viddata->xkb.sdl_modifiers &= ~SDL_KMOD_GUI; - } - - // Mod3 is typically Level 5 shift. - if (xk_modifiers & Mod3Mask) { - viddata->xkb.sdl_modifiers |= SDL_KMOD_LEVEL5; - } else { - viddata->xkb.sdl_modifiers &= ~SDL_KMOD_LEVEL5; - } - - // Mod5 is typically Level 3 shift (aka AltGr). - if (xk_modifiers & Mod5Mask) { - viddata->xkb.sdl_modifiers |= SDL_KMOD_MODE; - } else { - viddata->xkb.sdl_modifiers &= ~SDL_KMOD_MODE; - } - - if (xk_modifiers & LockMask) { - viddata->xkb.sdl_modifiers |= SDL_KMOD_CAPS; - } else { - viddata->xkb.sdl_modifiers &= ~SDL_KMOD_CAPS; - } - - if (xk_modifiers & viddata->xkb.numlock_mask) { - viddata->xkb.sdl_modifiers |= SDL_KMOD_NUM; - } else { - viddata->xkb.sdl_modifiers &= ~SDL_KMOD_NUM; - } - - if (xk_modifiers & viddata->xkb.scrolllock_mask) { - viddata->xkb.sdl_modifiers |= SDL_KMOD_SCROLL; - } else { - viddata->xkb.sdl_modifiers &= ~SDL_KMOD_SCROLL; - } - - SDL_SetModState(viddata->xkb.sdl_modifiers); -} - -static void X11_HandleModifierKeys(SDL_VideoData *viddata, SDL_Scancode scancode, bool pressed, bool allow_reconciliation) -{ - const SDL_Keycode keycode = SDL_GetKeyFromScancode(scancode, SDL_KMOD_NONE, false); - SDL_Keymod mod = SDL_KMOD_NONE; - bool reconcile = false; - - /* SDL clients expect modifier state to be activated at the same time as the - * source keypress, so we set pressed modifier state with the usual modifier - * keys here, as the explicit modifier event won't arrive until after the - * keypress event. If this is wrong, it will be corrected when the explicit - * modifier state is checked. - */ - switch (keycode) { - case SDLK_LSHIFT: - mod = SDL_KMOD_LSHIFT; - break; - case SDLK_RSHIFT: - mod = SDL_KMOD_RSHIFT; - break; - case SDLK_LCTRL: - mod = SDL_KMOD_LCTRL; - break; - case SDLK_RCTRL: - mod = SDL_KMOD_RCTRL; - break; - case SDLK_LALT: - mod = SDL_KMOD_LALT; - break; - case SDLK_RALT: - mod = SDL_KMOD_RALT; - break; - case SDLK_LGUI: - mod = SDL_KMOD_LGUI; - break; - case SDLK_RGUI: - mod = SDL_KMOD_RGUI; - break; - case SDLK_MODE: - mod = SDL_KMOD_MODE; - break; - case SDLK_LEVEL5_SHIFT: - mod = SDL_KMOD_LEVEL5; - break; - case SDLK_CAPSLOCK: - case SDLK_NUMLOCKCLEAR: - case SDLK_SCROLLLOCK: - { - /* For locking modifier keys, query the lock state directly, or we may have to wait until the next - * key press event to know if a lock was actually activated from the key event. - */ - unsigned int cur_mask = viddata->xkb.xkb_modifiers; - X11_UpdateSystemKeyModifiers(viddata); - - if (viddata->xkb.xkb_modifiers & LockMask) { - cur_mask |= LockMask; - } else { - cur_mask &= ~LockMask; - } - if (viddata->xkb.xkb_modifiers & viddata->xkb.numlock_mask) { - cur_mask |= viddata->xkb.numlock_mask; - } else { - cur_mask &= ~viddata->xkb.numlock_mask; - } - if (viddata->xkb.xkb_modifiers & viddata->xkb.scrolllock_mask) { - cur_mask |= viddata->xkb.scrolllock_mask; - } else { - cur_mask &= ~viddata->xkb.scrolllock_mask; - } - - viddata->xkb.xkb_modifiers = cur_mask; - } SDL_FALLTHROUGH; - default: - reconcile = true; - break; - } - - if (pressed) { - viddata->xkb.sdl_modifiers |= mod; - } else { - viddata->xkb.sdl_modifiers &= ~mod; - } - - if (allow_reconciliation) { - if (reconcile) { - X11_ReconcileModifiers(viddata); - } else { - SDL_SetModState(viddata->xkb.sdl_modifiers); - } - } -} - -void X11_ReconcileKeyboardState(SDL_VideoDevice *_this) -{ - SDL_VideoData *videodata = _this->internal; - Display *display = videodata->display; - char keys[32]; - int keycode; - const bool *keyboardState; - - X11_XQueryKeymap(display, keys); - - keyboardState = SDL_GetKeyboardState(0); - for (keycode = 0; keycode < SDL_arraysize(videodata->key_layout); ++keycode) { - SDL_Scancode scancode = videodata->key_layout[keycode]; - bool x11KeyPressed = (keys[keycode / 8] & (1 << (keycode % 8))) != 0; - bool sdlKeyPressed = keyboardState[scancode]; - - if (x11KeyPressed && !sdlKeyPressed) { - // Only update modifier state for keys that are pressed in another application - switch (SDL_GetKeyFromScancode(scancode, SDL_KMOD_NONE, false)) { - case SDLK_LCTRL: - case SDLK_RCTRL: - case SDLK_LSHIFT: - case SDLK_RSHIFT: - case SDLK_LALT: - case SDLK_RALT: - case SDLK_LGUI: - case SDLK_RGUI: - case SDLK_MODE: - case SDLK_LEVEL5_SHIFT: - X11_HandleModifierKeys(videodata, scancode, true, false); - SDL_SendKeyboardKeyIgnoreModifiers(0, SDL_GLOBAL_KEYBOARD_ID, keycode, scancode, true); - break; - default: - break; - } - } else if (!x11KeyPressed && sdlKeyPressed) { - X11_HandleModifierKeys(videodata, scancode, false, false); - SDL_SendKeyboardKeyIgnoreModifiers(0, SDL_GLOBAL_KEYBOARD_ID, keycode, scancode, false); - } - } - - X11_UpdateSystemKeyModifiers(videodata); - X11_ReconcileModifiers(videodata); -} - -static void X11_DispatchFocusIn(SDL_VideoDevice *_this, SDL_WindowData *data) -{ -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: Dispatching FocusIn", data->xwindow); -#endif - SDL_SetKeyboardFocus(data->window); - X11_ReconcileKeyboardState(_this); -#ifdef X_HAVE_UTF8_STRING - if (data->ic) { - X11_XSetICFocus(data->ic); - } -#endif - if (data->flashing_window) { - X11_FlashWindow(_this, data->window, SDL_FLASH_CANCEL); - } -} - -static void X11_DispatchFocusOut(SDL_VideoDevice *_this, SDL_WindowData *data) -{ -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: Dispatching FocusOut", data->xwindow); -#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 -} - -static void X11_DispatchMapNotify(SDL_WindowData *data) -{ - SDL_Window *window = data->window; - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0); - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0); - if (!(window->flags & SDL_WINDOW_HIDDEN) && (window->flags & SDL_WINDOW_INPUT_FOCUS)) { - SDL_UpdateWindowGrab(window); - } -} - -static void X11_DispatchUnmapNotify(SDL_WindowData *data) -{ - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIDDEN, 0, 0); - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); -} - -static void DispatchWindowMove(SDL_VideoDevice *_this, const SDL_WindowData *data, const SDL_Point *point) -{ - SDL_VideoData *videodata = _this->internal; - SDL_Window *window = data->window; - Display *display = videodata->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 = videodata->atoms._NET_WM_MOVERESIZE; - evt.xclient.format = 32; - evt.xclient.data.l[0] = (size_t)window->x + point->x; - evt.xclient.data.l[1] = (size_t)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 ScheduleWindowMove(SDL_VideoDevice *_this, SDL_WindowData *data, const SDL_Point *point) -{ - data->pending_move = true; - data->pending_move_point = *point; -} - -static void InitiateWindowResize(SDL_VideoDevice *_this, const SDL_WindowData *data, const SDL_Point *point, int direction) -{ - SDL_VideoData *videodata = _this->internal; - SDL_Window *window = data->window; - Display *display = videodata->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 = videodata->atoms._NET_WM_MOVERESIZE; - evt.xclient.format = 32; - evt.xclient.data.l[0] = (size_t)window->x + point->x; - evt.xclient.data.l[1] = (size_t)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); -} - -bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, bool force_new_result) -{ - SDL_Window *window = data->window; - if (!window->hit_test) return false; - const SDL_Point point = { (int)x, (int)y }; - SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data); - if (!force_new_result && rc == data->hit_test_result) { - return true; - } - X11_SetHitTestCursor(rc); - data->hit_test_result = rc; - return true; -} - -bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y) -{ - SDL_Window *window = data->window; - - if (window->hit_test) { - const SDL_Point point = { (int)x, (int)y }; - 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 (data->hit_test_result) { - case SDL_HITTEST_DRAGGABLE: - /* Some window managers get in a bad state when a move event starts while input is transitioning - to the SDL window. This can happen when clicking on a drag region of an unfocused window - where the same mouse down event will trigger a drag event and a window activate. */ - if (data->window->flags & SDL_WINDOW_INPUT_FOCUS) { - DispatchWindowMove(_this, data, &point); - } else { - ScheduleWindowMove(_this, data, &point); - } - return 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[data->hit_test_result - SDL_HITTEST_RESIZE_TOPLEFT]); - return true; - - default: - return false; - } - } - - return 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->atoms._NET_WM_USER_TIME, - XA_CARDINAL, 32, PropModeReplace, - (const unsigned char *)&latest, 1); -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: updating _NET_WM_USER_TIME to %lu", data->xwindow, latest); -#endif - data->user_time = latest; - } -} - -static void X11_HandleClipboardEvent(SDL_VideoDevice *_this, const XEvent *xevent) -{ - int i; - SDL_VideoData *videodata = _this->internal; - 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 mime_formats; - unsigned char *seln_data; - size_t seln_length = 0; - Atom XA_TARGETS = videodata->atoms.TARGETS; - SDLX11_ClipboardData *clipboard; - -#ifdef DEBUG_XEVENTS - char *atom_name; - atom_name = X11_XGetAtomName(display, req->target); - SDL_Log("window CLIPBOARD: SelectionRequest (requestor = 0x%lx, target = 0x%lx, mime_type = %s)", - req->requestor, req->target, atom_name); - if (atom_name) { - X11_XFree(atom_name); - } -#endif - - if (req->selection == XA_PRIMARY) { - clipboard = &videodata->primary_selection; - } else { - clipboard = &videodata->clipboard; - } - - 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 (req->target == XA_TARGETS) { - Atom *supportedFormats; - supportedFormats = SDL_malloc((clipboard->mime_count + 1) * sizeof(Atom)); - supportedFormats[0] = XA_TARGETS; - mime_formats = 1; - for (i = 0; i < clipboard->mime_count; ++i) { - supportedFormats[mime_formats++] = X11_XInternAtom(display, clipboard->mime_types[i], False); - } - X11_XChangeProperty(display, req->requestor, req->property, - XA_ATOM, 32, PropModeReplace, - (unsigned char *)supportedFormats, - mime_formats); - sevent.xselection.property = req->property; - sevent.xselection.target = XA_TARGETS; - SDL_free(supportedFormats); - } else { - if (clipboard->callback) { - for (i = 0; i < clipboard->mime_count; ++i) { - const char *mime_type = clipboard->mime_types[i]; - if (X11_XInternAtom(display, mime_type, False) != req->target) { - continue; - } - - // FIXME: We don't support the X11 INCR protocol for large clipboards. Do we want that? - Yes, yes we do. - // This is a safe cast, XChangeProperty() doesn't take a const value, but it doesn't modify the data - seln_data = (unsigned char *)clipboard->callback(clipboard->userdata, mime_type, &seln_length); - if (seln_data) { - X11_XChangeProperty(display, req->requestor, req->property, - req->target, 8, PropModeReplace, - seln_data, seln_length); - sevent.xselection.property = req->property; - sevent.xselection.target = req->target; - } - break; - } - } - } - X11_XSendEvent(display, req->requestor, False, 0, &sevent); - X11_XSync(display, False); - } break; - - case SelectionNotify: - { - const XSelectionEvent *xsel = &xevent->xselection; -#ifdef DEBUG_XEVENTS - const char *propName = xsel->property ? X11_XGetAtomName(display, xsel->property) : "None"; - const char *targetName = xsel->target ? X11_XGetAtomName(display, xsel->target) : "None"; - - SDL_Log("window CLIPBOARD: SelectionNotify (requestor = 0x%lx, target = %s, property = %s)", - xsel->requestor, targetName, propName); -#endif - if (xsel->target == videodata->atoms.TARGETS && xsel->property == videodata->atoms.SDL_FORMATS) { - /* the new mime formats are the SDL_FORMATS property as an array of Atoms */ - Atom atom = None; - Atom *patom; - unsigned char* data = NULL; - int format_property = 0; - unsigned long length = 0; - unsigned long bytes_left = 0; - int j; - - X11_XGetWindowProperty(display, GetWindow(_this), videodata->atoms.SDL_FORMATS, 0, 200, - 0, XA_ATOM, &atom, &format_property, &length, &bytes_left, &data); - - int allocationsize = (length + 1) * sizeof(char*); - for (j = 0, patom = (Atom*)data; j < length; j++, patom++) { - char *atomStr = X11_XGetAtomName(display, *patom); - allocationsize += SDL_strlen(atomStr) + 1; - X11_XFree(atomStr); - } - - char **new_mime_types = SDL_AllocateTemporaryMemory(allocationsize); - if (new_mime_types) { - char *strPtr = (char *)(new_mime_types + length + 1); - - for (j = 0, patom = (Atom*)data; j < length; j++, patom++) { - char *atomStr = X11_XGetAtomName(display, *patom); - new_mime_types[j] = strPtr; - strPtr = stpcpy(strPtr, atomStr) + 1; - X11_XFree(atomStr); - } - new_mime_types[length] = NULL; - - SDL_SendClipboardUpdate(false, new_mime_types, length); - } - - if (data) { - X11_XFree(data); - } - } - - videodata->selection_waiting = false; - } break; - - case SelectionClear: - { - Atom XA_CLIPBOARD = videodata->atoms.CLIPBOARD; - SDLX11_ClipboardData *clipboard = NULL; - -#ifdef DEBUG_XEVENTS - SDL_Log("window CLIPBOARD: SelectionClear (requestor = 0x%lx, target = 0x%lx)", - xevent->xselection.requestor, xevent->xselection.target); -#endif - - if (xevent->xselectionclear.selection == XA_PRIMARY) { - clipboard = &videodata->primary_selection; - } else if (XA_CLIPBOARD != None && xevent->xselectionclear.selection == XA_CLIPBOARD) { - clipboard = &videodata->clipboard; - } - if (clipboard && clipboard->callback) { - if (clipboard->sequence) { - SDL_CancelClipboardData(clipboard->sequence); - } else { - SDL_free(clipboard->userdata); - } - SDL_zerop(clipboard); - } - } break; - - case PropertyNotify: - { - char *name_of_atom = X11_XGetAtomName(display, xevent->xproperty.atom); - - if (SDL_strncmp(name_of_atom, "SDL_SELECTION", sizeof("SDL_SELECTION") - 1) == 0 && xevent->xproperty.state == PropertyNewValue) { - videodata->selection_incr_waiting = false; - } - - if (name_of_atom) { - X11_XFree(name_of_atom); - } - } break; - } -} - -static void X11_HandleSettingsEvent(SDL_VideoDevice *_this, const XEvent *xevent) -{ - SDL_VideoData *videodata = _this->internal; - - SDL_assert(videodata->xsettings_window != None); - SDL_assert(xevent->xany.window == videodata->xsettings_window); - - X11_HandleXsettings(_this, xevent); -} - -static Bool isMapNotify(Display *display, XEvent *ev, XPointer arg) -{ - XUnmapEvent *unmap; - - unmap = (XUnmapEvent *)arg; - - return ev->type == MapNotify && - ev->xmap.window == unmap->window && - ev->xmap.serial == unmap->serial; -} - -static Bool isReparentNotify(Display *display, XEvent *ev, XPointer arg) -{ - XUnmapEvent *unmap; - - unmap = (XUnmapEvent *)arg; - - return ev->type == ReparentNotify && - ev->xreparent.window == unmap->window && - ev->xreparent.serial == unmap->serial; -} - -static bool IsHighLatin1(const char *string, int length) -{ - while (length-- > 0) { - Uint8 ch = (Uint8)*string; - if (ch >= 0x80) { - return true; - } - ++string; - } - return false; -} - -static int XLookupStringAsUTF8(XKeyEvent *event_struct, char *buffer_return, int bytes_buffer, KeySym *keysym_return, XComposeStatus *status_in_out) -{ - int result = X11_XLookupString(event_struct, buffer_return, bytes_buffer, keysym_return, status_in_out); - if (IsHighLatin1(buffer_return, result)) { - char *utf8_text = SDL_iconv_string("UTF-8", "ISO-8859-1", buffer_return, result + 1); - if (utf8_text) { - SDL_strlcpy(buffer_return, utf8_text, bytes_buffer); - SDL_free(utf8_text); - return SDL_strlen(buffer_return); - } else { - return 0; - } - } - return result; -} - -SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window) -{ - const SDL_VideoData *videodata = _this->internal; - int i; - - if (videodata && videodata->windowlist) { - for (i = 0; i < videodata->numwindows; ++i) { - if ((videodata->windowlist[i] != NULL) && - (videodata->windowlist[i]->xwindow == window)) { - return videodata->windowlist[i]; - } - } - } - return NULL; -} - -Uint64 X11_GetEventTimestamp(unsigned long time) -{ - // FIXME: Get the event time in the SDL tick time base - return SDL_GetTicksNS(); -} - -void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_KeyboardID keyboardID, XEvent *xevent) -{ - SDL_VideoData *videodata = _this->internal; - Display *display = videodata->display; - KeyCode keycode = xevent->xkey.keycode; - KeySym keysym = NoSymbol; - int text_length = 0; - char text[64]; - Status status = 0; - bool handled_by_ime = false; - bool pressed = (xevent->type == KeyPress); - SDL_Scancode scancode = videodata->key_layout[keycode]; - Uint64 timestamp = X11_GetEventTimestamp(xevent->xkey.time); - -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx %s (X11 keycode = 0x%X)", xevent->xany.window, (xevent->type == KeyPress ? "KeyPress" : "KeyRelease"), xevent->xkey.keycode); -#endif -#ifdef DEBUG_SCANCODES - if (scancode == 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); - SDL_Log("The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL forums/mailing list X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).", - keycode, keycode - min_keycode, keysym, - X11_XKeysymToString(keysym)); - } -#endif // DEBUG SCANCODES - - text[0] = '\0'; - videodata->xkb.xkb_modifiers = xevent->xkey.state; - - if (SDL_TextInputActive(windowdata->window)) { - // filter events catches XIM events and sends them to the correct handler - if (X11_XFilterEvent(xevent, None)) { -#ifdef DEBUG_XEVENTS - SDL_Log("Filtered event type = %d display = %p window = 0x%lx", - xevent->type, xevent->xany.display, xevent->xany.window); -#endif - handled_by_ime = true; - } - - if (!handled_by_ime) { -#ifdef X_HAVE_UTF8_STRING - if (windowdata->ic && xevent->type == KeyPress) { - text_length = X11_Xutf8LookupString(windowdata->ic, &xevent->xkey, text, sizeof(text) - 1, - &keysym, &status); - } else { - text_length = XLookupStringAsUTF8(&xevent->xkey, text, sizeof(text) - 1, &keysym, NULL); - } -#else - text_length = XLookupStringAsUTF8(&xevent->xkey, text, sizeof(text) - 1, &keysym, NULL); -#endif - } - } - - if (!handled_by_ime) { - if (pressed) { - X11_HandleModifierKeys(videodata, scancode, true, true); - SDL_SendKeyboardKeyIgnoreModifiers(timestamp, keyboardID, keycode, scancode, true); - - if (*text) { - text[text_length] = '\0'; - X11_ClearComposition(windowdata); - SDL_SendKeyboardText(text); - } - } else { - if (X11_KeyRepeat(display, xevent)) { - // We're about to get a repeated key down, ignore the key up - return; - } - - X11_HandleModifierKeys(videodata, scancode, false, true); - SDL_SendKeyboardKeyIgnoreModifiers(timestamp, keyboardID, keycode, scancode, false); - } - } - - if (pressed) { - X11_UpdateUserTime(windowdata, xevent->xkey.time); - } -} - -void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, float x, float y, unsigned long time) -{ - SDL_Window *window = windowdata->window; - const SDL_VideoData *videodata = _this->internal; - Display *display = videodata->display; - int xticks = 0, yticks = 0; - Uint64 timestamp = X11_GetEventTimestamp(time); - -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: ButtonPress (X11 button = %d)", windowdata->xwindow, button); -#endif - - SDL_Mouse *mouse = SDL_GetMouse(); - if (!mouse->relative_mode && (x != mouse->x || y != mouse->y)) { - X11_ProcessHitTest(_this, windowdata, x, y, false); - SDL_SendMouseMotion(timestamp, window, mouseID, false, x, y); - } - - if (X11_IsWheelEvent(display, button, &xticks, &yticks)) { - SDL_SendMouseWheel(timestamp, window, mouseID, (float)-xticks, (float)yticks, SDL_MOUSEWHEEL_NORMAL); - } else { - bool ignore_click = false; - 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 (button == Button1) { - if (X11_TriggerHitTestAction(_this, windowdata, x, y)) { - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_HIT_TEST, 0, 0); - return; // don't pass this event on to app. - } - } - if (windowdata->last_focus_event_time) { - const int X11_FOCUS_CLICK_TIMEOUT = 10; - if (SDL_GetTicks() < (windowdata->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) { - ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, false); - } - windowdata->last_focus_event_time = 0; - } - if (!ignore_click) { - SDL_SendMouseButton(timestamp, window, mouseID, button, true); - } - } - X11_UpdateUserTime(windowdata, time); -} - -void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, unsigned long time) -{ - SDL_Window *window = windowdata->window; - const SDL_VideoData *videodata = _this->internal; - Display *display = videodata->display; - // The X server sends a Release event for each Press for wheels. Ignore them. - int xticks = 0, yticks = 0; - Uint64 timestamp = X11_GetEventTimestamp(time); - -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: ButtonRelease (X11 button = %d)", windowdata->xwindow, button); -#endif - if (!X11_IsWheelEvent(display, button, &xticks, &yticks)) { - if (button > 7) { - // see explanation at case ButtonPress - button -= (8 - SDL_BUTTON_X1); - } - SDL_SendMouseButton(timestamp, window, mouseID, button, false); - } -} - -void X11_GetBorderValues(SDL_WindowData *data) -{ - SDL_VideoData *videodata = data->videodata; - Display *display = videodata->display; - - Atom type; - int format; - unsigned long nitems, bytes_after; - unsigned char *property; - - // Some compositors will send extents even when the border hint is turned off. Ignore them in this case. - if (!(data->window->flags & SDL_WINDOW_BORDERLESS)) { - if (X11_XGetWindowProperty(display, data->xwindow, videodata->atoms._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 - SDL_Log("New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d", data->border_left, data->border_right, data->border_top, data->border_bottom); -#endif - } - } else { - data->border_left = data->border_top = data->border_right = data->border_bottom = 0; - } -} - -static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) -{ - SDL_VideoData *videodata = _this->internal; - Display *display; - SDL_WindowData *data; - XClientMessageEvent m; - int i; - - SDL_assert(videodata != NULL); - display = videodata->display; - - // filter events catches XIM events and sends them to the correct handler - // Key press/release events are filtered in X11_HandleKeyEvent() - if (xevent->type != KeyPress && xevent->type != KeyRelease) { - if (X11_XFilterEvent(xevent, None)) { -#ifdef DEBUG_XEVENTS - SDL_Log("Filtered event type = %d display = %p window = 0x%lx", - xevent->type, xevent->xany.display, xevent->xany.window); -#endif - return; - } - } - -#ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS - if (xevent->type == GenericEvent) { - X11_HandleGenericEvent(_this, xevent); - return; - } -#endif - - // Calling the event hook for generic events happens in X11_HandleGenericEvent(), where the event data is available - if (g_X11EventHook) { - if (!g_X11EventHook(g_X11EventHookData, xevent)) { - return; - } - } - -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR - if (videodata->xrandr_event_base && (xevent->type == (videodata->xrandr_event_base + RRNotify))) { - X11_HandleXRandREvent(_this, xevent); - } -#endif - -#ifdef DEBUG_XEVENTS - SDL_Log("X11 event type = %d display = %p window = 0x%lx", - xevent->type, xevent->xany.display, xevent->xany.window); -#endif - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - if (SDL_X11_HAVE_XFIXES && - xevent->type == X11_GetXFixesSelectionNotifyEvent()) { - XFixesSelectionNotifyEvent *ev = (XFixesSelectionNotifyEvent *)xevent; - -#ifdef DEBUG_XEVENTS - SDL_Log("window CLIPBOARD: XFixesSelectionNotify (selection = %s)", - X11_XGetAtomName(display, ev->selection)); -#endif - - if (ev->subtype == XFixesSetSelectionOwnerNotify) - { - if (ev->selection != videodata->atoms.CLIPBOARD) - return; - - if (X11_XGetSelectionOwner(display, ev->selection) == videodata->clipboard_window) - return; - - /* when here we're notified that the clipboard had an external change, we request the - * available mime types by asking for a conversion to the TARGETS format. We should get a - * SelectionNotify event later, and when treating these results, we will push a ClipboardUpdated - * event - */ - - X11_XConvertSelection(display, videodata->atoms.CLIPBOARD, videodata->atoms.TARGETS, - videodata->atoms.SDL_FORMATS, GetWindow(_this), CurrentTime); - } - - return; - } -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - - if ((videodata->clipboard_window != None) && - (videodata->clipboard_window == xevent->xany.window)) { - X11_HandleClipboardEvent(_this, xevent); - return; - } - - if ((videodata->xsettings_window != None) && - (videodata->xsettings_window == xevent->xany.window)) { - X11_HandleSettingsEvent(_this, xevent); - return; - } - - data = X11_FindWindow(_this, xevent->xany.window); - - if (!data) { - // The window for KeymapNotify, etc events is 0 - if (xevent->type == KeymapNotify) { -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: KeymapNotify!", xevent->xany.window); -#endif - if (SDL_GetKeyboardFocus() != NULL) { -#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM - if (videodata->xkb.desc_ptr) { - XkbStateRec state; - if (X11_XkbGetState(videodata->display, XkbUseCoreKbd, &state) == Success) { - if (state.group != videodata->xkb.current_group) { - // Only rebuild the keymap if the layout has changed. - videodata->xkb.current_group = state.group; - X11_UpdateKeymap(_this, true); - } - } - } -#endif - X11_ReconcileKeyboardState(_this); - } - } else if (xevent->type == MappingNotify) { - // Has the keyboard layout changed? - const int request = xevent->xmapping.request; - -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: MappingNotify!", xevent->xany.window); -#endif - if ((request == MappingKeyboard) || (request == MappingModifier)) { - X11_XRefreshKeyboardMapping(&xevent->xmapping); - } - - X11_UpdateKeymap(_this, true); - } else if (xevent->type == PropertyNotify && videodata && videodata->windowlist) { - char *name_of_atom = X11_XGetAtomName(display, xevent->xproperty.atom); - - if (SDL_strncmp(name_of_atom, "_ICC_PROFILE", sizeof("_ICC_PROFILE") - 1) == 0) { - XWindowAttributes attrib; - int screennum; - for (i = 0; i < videodata->numwindows; ++i) { - if (videodata->windowlist[i] != NULL) { - data = videodata->windowlist[i]; - X11_XGetWindowAttributes(display, data->xwindow, &attrib); - screennum = X11_XScreenNumberOfScreen(attrib.screen); - if (screennum == 0 && SDL_strcmp(name_of_atom, "_ICC_PROFILE") == 0) { - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ICCPROF_CHANGED, 0, 0); - } else if (SDL_strncmp(name_of_atom, "_ICC_PROFILE_", sizeof("_ICC_PROFILE_") - 1) == 0 && SDL_strlen(name_of_atom) > sizeof("_ICC_PROFILE_") - 1) { - int iccscreennum = SDL_atoi(&name_of_atom[sizeof("_ICC_PROFILE_") - 1]); - - if (screennum == iccscreennum) { - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ICCPROF_CHANGED, 0, 0); - } - } - } - } - } - - if (name_of_atom) { - X11_XFree(name_of_atom); - } - } - return; - } - - switch (xevent->type) { - - // Gaining mouse coverage? - case EnterNotify: - { - SDL_Mouse *mouse = SDL_GetMouse(); -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: EnterNotify! (%d,%d,%d)", xevent->xany.window, - xevent->xcrossing.x, - xevent->xcrossing.y, - xevent->xcrossing.mode); - if (xevent->xcrossing.mode == NotifyGrab) { - SDL_Log("Mode: NotifyGrab"); - } - if (xevent->xcrossing.mode == NotifyUngrab) { - SDL_Log("Mode: NotifyUngrab"); - } -#endif - SDL_SetMouseFocus(data->window); - - mouse->last_x = xevent->xcrossing.x; - mouse->last_y = xevent->xcrossing.y; - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - { - // Only create the barriers if we have input focus - SDL_WindowData *windowdata = data->window->internal; - if ((data->pointer_barrier_active == true) && windowdata->window->flags & SDL_WINDOW_INPUT_FOCUS) { - X11_ConfineCursorWithFlags(_this, windowdata->window, &windowdata->barrier_rect, X11_BARRIER_HANDLED_BY_EVENT); - } - } -#endif - - if (!mouse->relative_mode) { - SDL_SendMouseMotion(0, data->window, SDL_GLOBAL_MOUSE_ID, false, (float)xevent->xcrossing.x, (float)xevent->xcrossing.y); - } - - // We ungrab in LeaveNotify, so we may need to grab again here - SDL_UpdateWindowGrab(data->window); - - X11_ProcessHitTest(_this, data, mouse->last_x, mouse->last_y, true); - } break; - // Losing mouse coverage? - case LeaveNotify: - { -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: LeaveNotify! (%d,%d,%d)", xevent->xany.window, - xevent->xcrossing.x, - xevent->xcrossing.y, - xevent->xcrossing.mode); - if (xevent->xcrossing.mode == NotifyGrab) { - SDL_Log("Mode: NotifyGrab"); - } - if (xevent->xcrossing.mode == NotifyUngrab) { - SDL_Log("Mode: NotifyUngrab"); - } -#endif - if (!SDL_GetMouse()->relative_mode) { - SDL_SendMouseMotion(0, data->window, SDL_GLOBAL_MOUSE_ID, false, (float)xevent->xcrossing.x, (float)xevent->xcrossing.y); - } - - if (xevent->xcrossing.mode != NotifyGrab && - xevent->xcrossing.mode != NotifyUngrab && - xevent->xcrossing.detail != NotifyInferior) { - - /* In order for interaction with the window decorations and menu to work properly - on Mutter, we need to ungrab the keyboard when the the mouse leaves. */ - if (!(data->window->flags & SDL_WINDOW_FULLSCREEN)) { - X11_SetWindowKeyboardGrab(_this, data->window, false); - } - - 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 - SDL_Log("window 0x%lx: FocusIn (NotifyGrab/NotifyUngrab, ignoring)", xevent->xany.window); -#endif - break; - } - - if (xevent->xfocus.detail == NotifyInferior || xevent->xfocus.detail == NotifyPointer) { -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: FocusIn (NotifyInferior/NotifyPointer, ignoring)", xevent->xany.window); -#endif - break; - } -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: FocusIn!", xevent->xany.window); -#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 - SDL_Log("window 0x%lx: FocusOut (NotifyGrab/NotifyUngrab, ignoring)", xevent->xany.window); -#endif - break; - } - if (xevent->xfocus.detail == NotifyInferior || xevent->xfocus.detail == NotifyPointer) { - /* We still have focus if a child gets focus. We also don't - care about the position of the pointer when the keyboard - focus changed. */ -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: FocusOut (NotifyInferior/NotifyPointer, ignoring)", xevent->xany.window); -#endif - break; - } -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: FocusOut!", xevent->xany.window); -#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; - } - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - // Disable confinement if it is activated. - if (data->pointer_barrier_active == true) { - X11_ConfineCursorWithFlags(_this, data->window, NULL, X11_BARRIER_HANDLED_BY_EVENT); - } -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - } break; - - - // Have we been iconified? - case UnmapNotify: - { - XEvent ev; - -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: UnmapNotify!", xevent->xany.window); -#endif - - if (X11_XCheckIfEvent(display, &ev, &isReparentNotify, (XPointer)&xevent->xunmap)) { - X11_XCheckIfEvent(display, &ev, &isMapNotify, (XPointer)&xevent->xunmap); - } else { - X11_DispatchUnmapNotify(data); - } - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - // Disable confinement if the window gets hidden. - if (data->pointer_barrier_active == true) { - X11_ConfineCursorWithFlags(_this, data->window, NULL, X11_BARRIER_HANDLED_BY_EVENT); - } -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - } break; - - // Have we been restored? - case MapNotify: - { -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: MapNotify!", xevent->xany.window); -#endif - X11_DispatchMapNotify(data); - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - // Enable confinement if it was activated. - if (data->pointer_barrier_active == true) { - X11_ConfineCursorWithFlags(_this, data->window, &data->barrier_rect, X11_BARRIER_HANDLED_BY_EVENT); - } -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - } break; - - // Have we been resized or moved? - case ConfigureNotify: - { -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: ConfigureNotify! (position: %d,%d, size: %dx%d)", xevent->xany.window, - 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 coordinates 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) { - if (!data->size_move_event_flags) { - SDL_Window *w; - int x = xevent->xconfigure.x; - int y = xevent->xconfigure.y; - - data->pending_operation &= ~X11_PENDING_OP_MOVE; - SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y); - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); - - for (w = data->window->first_child; w; w = w->next_sibling) { - // Don't update hidden child popup windows, their relative position doesn't change - if (SDL_WINDOW_IS_POPUP(w) && !(w->flags & SDL_WINDOW_HIDDEN)) { - X11_UpdateWindowPosition(w, true); - } - } - } - } - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - X11_HandleConfigure(data->window, &xevent->xconfigure); -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - - if (xevent->xconfigure.width != data->last_xconfigure.width || - xevent->xconfigure.height != data->last_xconfigure.height) { - if (!data->size_move_event_flags) { - data->pending_operation &= ~X11_PENDING_OP_RESIZE; - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_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->atoms.XdndEnter) { - - 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 - SDL_Log("XID of source window : 0x%lx", data->xdnd_source); - SDL_Log("Protocol version to use : %d", xdnd_version); - SDL_Log("More then 3 data types : %d", (int)use_list); -#endif - - if (use_list) { - // fetch conversion targets - SDL_x11Prop p; - X11_ReadProperty(&p, display, data->xdnd_source, videodata->atoms.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->atoms.XdndLeave) { -#ifdef DEBUG_XEVENTS - SDL_Log("XID of source window : 0x%lx", xevent->xclient.data.l[0]); -#endif - SDL_SendDropComplete(data->window); - } else if (xevent->xclient.message_type == videodata->atoms.XdndPosition) { - -#ifdef DEBUG_XEVENTS - Atom act = videodata->atoms.XdndActionCopy; - if (xdnd_version >= 2) { - act = xevent->xclient.data.l[4]; - } - SDL_Log("Action requested by user is : %s", X11_XGetAtomName(display, act)); -#endif - { - // Drag and Drop position - int root_x, root_y, window_x, window_y; - Window ChildReturn; - root_x = xevent->xclient.data.l[2] >> 16; - root_y = xevent->xclient.data.l[2] & 0xffff; - // Translate from root to current window position - X11_XTranslateCoordinates(display, DefaultRootWindow(display), data->xwindow, - root_x, root_y, &window_x, &window_y, &ChildReturn); - - SDL_SendDropPosition(data->window, (float)window_x, (float)window_y); - } - - // reply with status - SDL_memset(&m, 0, sizeof(XClientMessageEvent)); - m.type = ClientMessage; - m.display = xevent->xclient.display; - m.window = xevent->xclient.data.l[0]; - m.message_type = videodata->atoms.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->atoms.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->atoms.XdndDrop) { - if (data->xdnd_req == None) { - // say again - not interested! - SDL_memset(&m, 0, sizeof(XClientMessageEvent)); - m.type = ClientMessage; - m.display = xevent->xclient.display; - m.window = xevent->xclient.data.l[0]; - m.message_type = videodata->atoms.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->atoms.XdndSelection, data->xdnd_req, videodata->atoms.PRIMARY, data->xwindow, xevent->xclient.data.l[2]); - } else { - X11_XConvertSelection(display, videodata->atoms.XdndSelection, data->xdnd_req, videodata->atoms.PRIMARY, data->xwindow, CurrentTime); - } - } - } else if ((xevent->xclient.message_type == videodata->atoms.WM_PROTOCOLS) && - (xevent->xclient.format == 32) && - (xevent->xclient.data.l[0] == videodata->atoms._NET_WM_PING)) { - Window root = DefaultRootWindow(display); - -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: _NET_WM_PING", xevent->xany.window); -#endif - xevent->xclient.window = root; - X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, xevent); - break; - } - - else if ((xevent->xclient.message_type == videodata->atoms.WM_PROTOCOLS) && - (xevent->xclient.format == 32) && - (xevent->xclient.data.l[0] == videodata->atoms.WM_DELETE_WINDOW)) { - -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: WM_DELETE_WINDOW", xevent->xany.window); -#endif - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_CLOSE_REQUESTED, 0, 0); - break; - } else if ((xevent->xclient.message_type == videodata->atoms.WM_PROTOCOLS) && - (xevent->xclient.format == 32) && - (xevent->xclient.data.l[0] == videodata->atoms._NET_WM_SYNC_REQUEST)) { - -#ifdef DEBUG_XEVENTS - printf("window %p: _NET_WM_SYNC_REQUEST\n", data); -#endif -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - X11_HandleSyncRequest(data->window, &xevent->xclient); -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - break; - } - } break; - - // Do we need to refresh ourselves? - case Expose: - { -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: Expose (count = %d)", xevent->xany.window, xevent->xexpose.count); -#endif - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_EXPOSED, 0, 0); - } break; - - /* Use XInput2 instead of the xevents API if possible, for: - - KeyPress - - KeyRelease - - MotionNotify - - ButtonPress - - ButtonRelease - XInput2 has more precise information, e.g., to distinguish different input devices. */ - case KeyPress: - case KeyRelease: - { - if (data->xinput2_keyboard_enabled) { - // This input is being handled by XInput2 - break; - } - - X11_HandleKeyEvent(_this, data, SDL_GLOBAL_KEYBOARD_ID, xevent); - } break; - - case MotionNotify: - { - if (data->xinput2_mouse_enabled && !data->mouse_grabbed) { - // This input is being handled by XInput2 - break; - } - - SDL_Mouse *mouse = SDL_GetMouse(); - if (!mouse->relative_mode) { -#ifdef DEBUG_MOTION - SDL_Log("window 0x%lx: X11 motion: %d,%d", xevent->xany.window, xevent->xmotion.x, xevent->xmotion.y); -#endif - - X11_ProcessHitTest(_this, data, (float)xevent->xmotion.x, (float)xevent->xmotion.y, false); - SDL_SendMouseMotion(0, data->window, SDL_GLOBAL_MOUSE_ID, false, (float)xevent->xmotion.x, (float)xevent->xmotion.y); - } - } break; - - case ButtonPress: - { - if (data->xinput2_mouse_enabled) { - // This input is being handled by XInput2 - break; - } - - X11_HandleButtonPress(_this, data, SDL_GLOBAL_MOUSE_ID, xevent->xbutton.button, - xevent->xbutton.x, xevent->xbutton.y, xevent->xbutton.time); - } break; - - case ButtonRelease: - { - if (data->xinput2_mouse_enabled) { - // This input is being handled by XInput2 - break; - } - - X11_HandleButtonRelease(_this, data, SDL_GLOBAL_MOUSE_ID, xevent->xbutton.button, xevent->xbutton.time); - } 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) { - SDL_Log("window 0x%lx: PropertyNotify: %s %s time=%lu", xevent->xany.window, 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; - - SDL_Log("{"); - for (i = 0; i < items_read; i++) { - SDL_Log(" %d", values[i]); - } - SDL_Log(" }"); - } else if (real_type == XA_CARDINAL) { - if (real_format == 32) { - Uint32 *values = (Uint32 *)propdata; - - SDL_Log("{"); - for (i = 0; i < items_read; i++) { - SDL_Log(" %d", values[i]); - } - SDL_Log(" }"); - } else if (real_format == 16) { - Uint16 *values = (Uint16 *)propdata; - - SDL_Log("{"); - for (i = 0; i < items_read; i++) { - SDL_Log(" %d", values[i]); - } - SDL_Log(" }"); - } else if (real_format == 8) { - Uint8 *values = (Uint8 *)propdata; - - SDL_Log("{"); - for (i = 0; i < items_read; i++) { - SDL_Log(" %d", values[i]); - } - SDL_Log(" }"); - } - } else if (real_type == XA_STRING || - real_type == videodata->atoms.UTF8_STRING) { - SDL_Log("{ \"%s\" }", propdata); - } else if (real_type == XA_ATOM) { - Atom *atoms = (Atom *)propdata; - - SDL_Log("{"); - for (i = 0; i < items_read; i++) { - char *atomname = X11_XGetAtomName(display, atoms[i]); - if (atomname) { - SDL_Log(" %s", atomname); - X11_XFree(atomname); - } - } - SDL_Log(" }"); - } else { - char *atomname = X11_XGetAtomName(display, real_type); - SDL_Log("Unknown type: 0x%lx (%s)", 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->atoms._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 SDL_WindowFlags flags = X11_GetNetWMState(_this, data->window, xevent->xproperty.window); - const SDL_WindowFlags changed = flags ^ data->window->flags; - - if ((changed & (SDL_WINDOW_HIDDEN | SDL_WINDOW_FULLSCREEN)) != 0) { - if (flags & SDL_WINDOW_HIDDEN) { - X11_DispatchUnmapNotify(data); - } else { - X11_DispatchMapNotify(data); - } - } - - if (!SDL_WINDOW_IS_POPUP(data->window)) { - if (changed & SDL_WINDOW_FULLSCREEN) { - data->pending_operation &= ~X11_PENDING_OP_FULLSCREEN; - - if (flags & SDL_WINDOW_FULLSCREEN) { - if (!(flags & SDL_WINDOW_MINIMIZED)) { - const bool commit = SDL_memcmp(&data->window->current_fullscreen_mode, &data->requested_fullscreen_mode, sizeof(SDL_DisplayMode)) != 0; - - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_ENTER_FULLSCREEN, 0, 0); - if (commit) { - /* This was initiated by the compositor, or the mode was changed between the request and the window - * becoming fullscreen. Switch to the application requested mode if necessary. - */ - SDL_copyp(&data->window->current_fullscreen_mode, &data->window->requested_fullscreen_mode); - SDL_UpdateFullscreenMode(data->window, SDL_FULLSCREEN_OP_UPDATE, true); - } else { - SDL_UpdateFullscreenMode(data->window, SDL_FULLSCREEN_OP_ENTER, false); - } - } - } else { - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, 0, 0); - SDL_UpdateFullscreenMode(data->window, false, false); - - SDL_zero(data->requested_fullscreen_mode); - - // Need to restore or update any limits changed while the window was fullscreen. - X11_SetWindowMinMax(data->window, !!(flags & SDL_WINDOW_MAXIMIZED)); - - // Toggle the borders if they were forced on while creating a borderless fullscreen window. - if (data->fullscreen_borders_forced_on) { - data->toggle_borders = true; - data->fullscreen_borders_forced_on = false; - } - } - - if ((flags & SDL_WINDOW_FULLSCREEN) && - (data->border_top || data->border_left || data->border_bottom || data->border_right)) { - /* If the window is entering fullscreen and the borders are - * non-zero sized, turn off size events until the borders are - * shut off to avoid bogus window sizes and positions, and - * note that the old borders were non-zero for restoration. - */ - data->size_move_event_flags |= X11_SIZE_MOVE_EVENTS_WAIT_FOR_BORDERS; - data->previous_borders_nonzero = true; - } else if (!(flags & SDL_WINDOW_FULLSCREEN) && - data->previous_borders_nonzero && - (!data->border_top && !data->border_left && !data->border_bottom && !data->border_right)) { - /* If the window is leaving fullscreen and the current borders - * are zero sized, but weren't when entering fullscreen, turn - * off size events until the borders come back to avoid bogus - * window sizes and positions. - */ - data->size_move_event_flags |= X11_SIZE_MOVE_EVENTS_WAIT_FOR_BORDERS; - data->previous_borders_nonzero = false; - } else { - data->size_move_event_flags = 0; - data->previous_borders_nonzero = false; - - if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) { - data->toggle_borders = false; - X11_SetWindowBordered(_this, data->window, !(data->window->flags & SDL_WINDOW_BORDERLESS)); - } - } - } - if ((changed & SDL_WINDOW_MAXIMIZED) && ((flags & SDL_WINDOW_MAXIMIZED) && !(flags & SDL_WINDOW_MINIMIZED))) { - data->pending_operation &= ~X11_PENDING_OP_MAXIMIZE; - if ((changed & SDL_WINDOW_MINIMIZED)) { - data->pending_operation &= ~X11_PENDING_OP_RESTORE; - // If coming out of minimized, send a restore event before sending maximized. - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0); - } - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); - } - if ((changed & SDL_WINDOW_MINIMIZED) && (flags & SDL_WINDOW_MINIMIZED)) { - data->pending_operation &= ~X11_PENDING_OP_MINIMIZE; - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); - } - if (!(flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED))) { - data->pending_operation &= ~X11_PENDING_OP_RESTORE; - SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0); - - // Apply any pending state if restored. - if (!(flags & SDL_WINDOW_FULLSCREEN)) { - if (data->pending_position) { - data->pending_position = false; - data->pending_operation |= X11_PENDING_OP_MOVE; - data->expected.x = data->window->pending.x - data->border_left; - data->expected.y = data->window->pending.y - data->border_top; - X11_XMoveWindow(display, data->xwindow, data->expected.x, data->expected.y); - } - if (data->pending_size) { - data->pending_size = false; - data->pending_operation |= X11_PENDING_OP_RESIZE; - data->expected.w = data->window->pending.w; - data->expected.h = data->window->pending.h; - X11_XResizeWindow(display, data->xwindow, data->window->pending.w, data->window->pending.h); - } - } - } - if ((flags & SDL_WINDOW_INPUT_FOCUS)) { - if (data->pending_move) { - DispatchWindowMove(_this, data, &data->pending_move_point); - data->pending_move = false; - } - } - } - if (changed & SDL_WINDOW_OCCLUDED) { - SDL_SendWindowEvent(data->window, (flags & SDL_WINDOW_OCCLUDED) ? SDL_EVENT_WINDOW_OCCLUDED : SDL_EVENT_WINDOW_EXPOSED, 0, 0); - } - } else if (xevent->xproperty.atom == videodata->atoms.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, true); - } else if (xevent->xproperty.atom == videodata->atoms._NET_FRAME_EXTENTS) { - /* Events are disabled when leaving fullscreen until the borders appear to avoid - * incorrect size/position events. - */ - if (data->size_move_event_flags) { - data->size_move_event_flags &= ~X11_SIZE_MOVE_EVENTS_WAIT_FOR_BORDERS; - X11_GetBorderValues(data); - - } - if (!(data->window->flags & SDL_WINDOW_FULLSCREEN) && data->toggle_borders) { - data->toggle_borders = false; - X11_SetWindowBordered(_this, data->window, !(data->window->flags & SDL_WINDOW_BORDERLESS)); - } - } - } break; - - case SelectionNotify: - { - Atom target = xevent->xselection.target; -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: SelectionNotify (requestor = 0x%lx, target = 0x%lx)", xevent->xany.window, - xevent->xselection.requestor, xevent->xselection.target); -#endif - if (target == data->xdnd_req) { - // read data - SDL_x11Prop p; - X11_ReadProperty(&p, display, data->xwindow, videodata->atoms.PRIMARY); - - if (p.format == 8) { - char *saveptr = NULL; - char *name = X11_XGetAtomName(display, target); - if (name) { - char *token = SDL_strtok_r((char *)p.data, "\r\n", &saveptr); - while (token) { - if ((SDL_strcmp("text/plain;charset=utf-8", name) == 0) || - (SDL_strcmp("UTF8_STRING", name) == 0) || - (SDL_strcmp("text/plain", name) == 0) || - (SDL_strcmp("TEXT", name) == 0)) { - SDL_SendDropText(data->window, token); - } else if (SDL_strcmp("text/uri-list", name) == 0) { - if (SDL_URIToLocal(token, token) >= 0) { - SDL_SendDropFile(data->window, NULL, token); - } - } - token = SDL_strtok_r(NULL, "\r\n", &saveptr); - } - X11_XFree(name); - } - 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->atoms.XdndFinished; - m.format = 32; - m.data.l[0] = data->xwindow; - m.data.l[1] = 1; - m.data.l[2] = videodata->atoms.XdndActionCopy; - X11_XSendEvent(display, data->xdnd_source, False, NoEventMask, (XEvent *)&m); - - X11_XSync(display, False); - } - } break; - - default: - { -#ifdef DEBUG_XEVENTS - SDL_Log("window 0x%lx: Unhandled event %d", xevent->xany.window, xevent->type); -#endif - } break; - } -} - -static void X11_HandleFocusChanges(SDL_VideoDevice *_this) -{ - SDL_VideoData *videodata = _this->internal; - 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) { - Uint64 now = SDL_GetTicks(); - if (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; - } - } - } - } -} - -static Bool isAnyEvent(Display *display, XEvent *ev, XPointer arg) -{ - return True; -} - -static bool X11_PollEvent(Display *display, XEvent *event) -{ - if (!X11_XCheckIfEvent(display, event, isAnyEvent, NULL)) { - return false; - } - - return true; -} - -void X11_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_VideoData *data = _this->internal; - Display *req_display = data->request_display; - Window xwindow = window->internal->xwindow; - XClientMessageEvent event; - - SDL_memset(&event, 0, sizeof(XClientMessageEvent)); - event.type = ClientMessage; - event.display = req_display; - event.send_event = True; - event.message_type = data->atoms._SDL_WAKEUP; - event.format = 8; - - X11_XSendEvent(req_display, xwindow, False, NoEventMask, (XEvent *)&event); - /* XSendEvent returns a status and it could be BadValue or BadWindow. If an - error happens it is an SDL's internal error and there is nothing we can do here. */ - X11_XFlush(req_display); -} - -int X11_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS) -{ - SDL_VideoData *videodata = _this->internal; - Display *display; - XEvent xevent; - display = videodata->display; - - SDL_zero(xevent); - - // Flush and poll to grab any events already read and queued - X11_XFlush(display); - if (X11_PollEvent(display, &xevent)) { - // Fall through - } else if (timeoutNS == 0) { - return 0; - } else { - // Use SDL_IOR_NO_RETRY to ensure SIGINT will break us out of our wait - int err = SDL_IOReady(ConnectionNumber(display), SDL_IOR_READ | SDL_IOR_NO_RETRY, timeoutNS); - if (err > 0) { - if (!X11_PollEvent(display, &xevent)) { - /* Someone may have beat us to reading the fd. Return 1 here to - * trigger the normal spurious wakeup logic in the event core. */ - return 1; - } - } else if (err == 0) { - // Timeout - return 0; - } else { - // Error returned from poll()/select() - - if (errno == EINTR) { - /* If the wait was interrupted by a signal, we may have generated a - * SDL_EVENT_QUIT event. Let the caller know to call SDL_PumpEvents(). */ - return 1; - } else { - return err; - } - } - } - - X11_DispatchEvent(_this, &xevent); - -#ifdef SDL_USE_LIBDBUS - SDL_DBus_PumpEvents(); -#endif - return 1; -} - -void X11_PumpEvents(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - XEvent xevent; - int i; - - /* Check if a display had the mode changed and is waiting for a window to asynchronously become - * fullscreen. If there is no fullscreen window past the elapsed timeout, revert the mode switch. - */ - for (i = 0; i < _this->num_displays; ++i) { - if (_this->displays[i]->internal->mode_switch_deadline_ns) { - if (_this->displays[i]->fullscreen_window) { - _this->displays[i]->internal->mode_switch_deadline_ns = 0; - } else if (SDL_GetTicksNS() >= _this->displays[i]->internal->mode_switch_deadline_ns) { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, - "Time out elapsed after mode switch on display %" SDL_PRIu32 " with no window becoming fullscreen; reverting", _this->displays[i]->id); - SDL_SetDisplayModeForDisplay(_this->displays[i], NULL); - } - } - } - - if (data->last_mode_change_deadline) { - if (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) { - Uint64 now = SDL_GetTicks(); - if (!data->screensaver_activity || now >= (data->screensaver_activity + 30000)) { - X11_XResetScreenSaver(data->display); - -#ifdef SDL_USE_LIBDBUS - SDL_DBus_ScreensaverTickle(); -#endif - - data->screensaver_activity = now; - } - } - - SDL_zero(xevent); - - // Keep processing pending events - while (X11_PollEvent(data->display, &xevent)) { - X11_DispatchEvent(_this, &xevent); - } - -#ifdef SDL_USE_LIBDBUS - SDL_DBus_PumpEvents(); -#endif - - // FIXME: Only need to do this when there are pending focus changes - X11_HandleFocusChanges(_this); - - // FIXME: Only need to do this when there are flashing windows - for (i = 0; i < data->numwindows; ++i) { - if (data->windowlist[i] != NULL && - data->windowlist[i]->flash_cancel_time && - SDL_GetTicks() >= data->windowlist[i]->flash_cancel_time) { - X11_FlashWindow(_this, data->windowlist[i]->window, SDL_FLASH_CANCEL); - } - } - - if (data->xinput_hierarchy_changed) { - X11_Xinput2UpdateDevices(_this, false); - data->xinput_hierarchy_changed = false; - } -} - -bool X11_SuspendScreenSaver(SDL_VideoDevice *_this) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XSCRNSAVER - SDL_VideoData *data = _this->internal; - int dummy; - int major_version, minor_version; -#endif // SDL_VIDEO_DRIVER_X11_XSCRNSAVER - -#ifdef SDL_USE_LIBDBUS - if (SDL_DBus_ScreensaverInhibit(_this->suspend_screensaver)) { - return true; - } - - if (_this->suspend_screensaver) { - SDL_DBus_ScreensaverTickle(); - } -#endif - -#ifdef 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 SDL_Unsupported(); - } - - X11_XScreenSaverSuspend(data->display, _this->suspend_screensaver); - X11_XResetScreenSaver(data->display); - return true; - } -#endif - return SDL_Unsupported(); -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11events.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11events.h deleted file mode 100644 index bb76f83..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11events.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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(SDL_VideoDevice *_this); -extern int X11_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS); -extern void X11_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_SuspendScreenSaver(SDL_VideoDevice *_this); -extern void X11_ReconcileKeyboardState(SDL_VideoDevice *_this); -extern void X11_GetBorderValues(SDL_WindowData *data); -extern Uint64 X11_GetEventTimestamp(unsigned long time); -extern void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_KeyboardID keyboardID, XEvent *xevent); -extern void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, float x, float y, unsigned long time); -extern void X11_HandleButtonRelease(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_MouseID mouseID, int button, unsigned long time); -extern SDL_WindowData *X11_FindWindow(SDL_VideoDevice *_this, Window window); -extern bool X11_ProcessHitTest(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y, bool force_new_result); -extern bool X11_TriggerHitTestAction(SDL_VideoDevice *_this, SDL_WindowData *data, const float x, const float y); - -#endif // SDL_x11events_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11framebuffer.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11framebuffer.c deleted file mode 100644 index 12642cc..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11framebuffer.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "SDL_x11video.h" -#include "SDL_x11framebuffer.h" -#include "SDL_x11xsync.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; - } - return X_handler(d, e); -} - -static bool have_mitshm(Display *dpy) -{ - // Only use shared memory on local X servers - return X11_XShmQueryExtension(dpy) ? SDL_X11_HAVE_SHM : false; -} - -#endif // !NO_SHARED_MEMORY - -bool X11_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, SDL_PixelFormat *format, - void **pixels, int *pitch) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - XGCValues gcv; - XVisualInfo vinfo; - int w, h; - - SDL_GetWindowSizeInPixels(window, &w, &h); - - // 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)) { - 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 = (((w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3); - - // Create the actual image -#ifndef NO_SHARED_MEMORY - if (have_mitshm(display)) { - XShmSegmentInfo *shminfo = &data->shminfo; - - shminfo->shmid = shmget(IPC_PRIVATE, (size_t)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, - w, h); - if (!data->ximage) { - X11_XShmDetach(display, shminfo); - X11_XSync(display, False); - shmdt(shminfo->shmaddr); - } else { - // Done! - data->ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? MSBFirst : LSBFirst; - data->use_mitshm = true; - *pixels = shminfo->shmaddr; - return true; - } - } - } -#endif // not NO_SHARED_MEMORY - - *pixels = SDL_malloc((size_t)h * (*pitch)); - if (!*pixels) { - return false; - } - - data->ximage = X11_XCreateImage(display, data->visual, - vinfo.depth, ZPixmap, 0, (char *)(*pixels), - w, h, 32, 0); - if (!data->ximage) { - SDL_free(*pixels); - return SDL_SetError("Couldn't create XImage"); - } - data->ximage->byte_order = (SDL_BYTEORDER == SDL_BIG_ENDIAN) ? MSBFirst : LSBFirst; - return true; -} - -bool X11_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects, - int numrects) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - int i; - int x, y, w, h; - int window_w, window_h; - - SDL_GetWindowSizeInPixels(window, &window_w, &window_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); - } - } - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - X11_HandlePresent(data->window); -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - - X11_XSync(display, False); - - return true; -} - -void X11_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - 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 = false; - } -#endif // !NO_SHARED_MEMORY - - data->ximage = NULL; - } - if (data->gc) { - X11_XFreeGC(display, data->gc); - data->gc = NULL; - } -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11framebuffer.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11framebuffer.h deleted file mode 100644 index 08feda4..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11framebuffer.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 bool X11_CreateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, - SDL_PixelFormat *format, - void **pixels, int *pitch); -extern bool X11_UpdateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, - const SDL_Rect *rects, int numrects); -extern void X11_DestroyWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window); - -#endif // SDL_x11framebuffer_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.c deleted file mode 100644 index c48e829..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.c +++ /dev/null @@ -1,789 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "SDL_x11video.h" - -#include "../../events/SDL_keyboard_c.h" -#include "../../events/SDL_scancode_tables_c.h" - -#include -#include - -#include "../../events/imKStoUCS.h" -#include "../../events/SDL_keysym_to_scancode_c.h" -#include "../../events/SDL_keysym_to_keycode_c.h" - -#ifdef X_HAVE_UTF8_STRING -#include -#endif - -static SDL_ScancodeTable scancode_set[] = { - SDL_SCANCODE_TABLE_DARWIN, - SDL_SCANCODE_TABLE_XFREE86_1, - SDL_SCANCODE_TABLE_XFREE86_2, - SDL_SCANCODE_TABLE_XVNC, -}; - -static bool X11_ScancodeIsRemappable(SDL_Scancode scancode) -{ - /* - * XKB remappings can assign different keysyms for these scancodes, but - * as these keys are in fixed positions, the scancodes themselves shouldn't - * be switched. Mark them as not being remappable. - */ - switch (scancode) { - case SDL_SCANCODE_ESCAPE: - case SDL_SCANCODE_CAPSLOCK: - case SDL_SCANCODE_NUMLOCKCLEAR: - case SDL_SCANCODE_LSHIFT: - case SDL_SCANCODE_RSHIFT: - case SDL_SCANCODE_LCTRL: - case SDL_SCANCODE_RCTRL: - case SDL_SCANCODE_LALT: - case SDL_SCANCODE_RALT: - case SDL_SCANCODE_LGUI: - case SDL_SCANCODE_RGUI: - return false; - default: - return true; - } -} - -// This function only correctly maps letters and numbers for keyboards in US QWERTY layout -static SDL_Scancode X11_KeyCodeToSDLScancode(SDL_VideoDevice *_this, KeyCode keycode) -{ - const KeySym keysym = X11_KeyCodeToSym(_this, keycode, 0, 0); - - if (keysym == NoSymbol) { - return SDL_SCANCODE_UNKNOWN; - } - - return SDL_GetScancodeFromKeySym(keysym, keycode); -} - -KeySym X11_KeyCodeToSym(SDL_VideoDevice *_this, KeyCode keycode, unsigned char group, unsigned int mod_mask) -{ - SDL_VideoData *data = _this->internal; - KeySym keysym; - unsigned int mods_ret[16]; - - SDL_zero(mods_ret); - -#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM - if (data->xkb.desc_ptr) { - int num_groups = XkbKeyNumGroups(data->xkb.desc_ptr, keycode); - unsigned char info = XkbKeyGroupInfo(data->xkb.desc_ptr, keycode); - - if (num_groups && group >= num_groups) { - - int action = XkbOutOfRangeGroupAction(info); - - if (action == XkbRedirectIntoRange) { - group = XkbOutOfRangeGroupNumber(info); - if (group >= num_groups) { - group = 0; - } - } else if (action == XkbClampIntoRange) { - group = num_groups - 1; - } else { - group %= num_groups; - } - } - - if (X11_XkbLookupKeySym(data->display, keycode, XkbBuildCoreState(mod_mask, group), mods_ret, &keysym) == NoSymbol) { - keysym = NoSymbol; - } - } else -#endif - { - // TODO: Handle groups and modifiers on the legacy path. - keysym = X11_XKeycodeToKeysym(data->display, keycode, 0); - } - - return keysym; -} - -bool X11_InitKeyboard(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - 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; - -#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM - { - int xkb_major = XkbMajorVersion; - int xkb_minor = XkbMinorVersion; - - if (X11_XkbQueryExtension(data->display, NULL, &data->xkb.event, NULL, &xkb_major, &xkb_minor)) { - data->xkb.desc_ptr = 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); - - if (prev_locale) { - prev_locale = SDL_strdup(prev_locale); - } - - if (prev_xmods) { - prev_xmods = SDL_strdup(prev_xmods); - } - - (void)setlocale(LC_ALL, ""); - X11_XSetLocaleModifiers(""); - - data->im = X11_XOpenIM(data->display, NULL, NULL, NULL); - - /* Reset the locale + X locale modifiers back to how they were, - locale first because the X locale modifiers depend on it. */ - (void)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) { - int table_size; - const SDL_Scancode *table = SDL_GetScancodeTable(scancode_set[i], &table_size); - - distance = 0; - for (j = 0; j < SDL_arraysize(fingerprint); ++j) { - if (fingerprint[j].value < 0 || fingerprint[j].value >= table_size) { - distance += 1; - } else if (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) { - // This is likely to be SDL_SCANCODE_TABLE_XFREE86_2 with remapped keys, double check a rarely remapped value - int fingerprint_value = X11_XKeysymToKeycode(data->display, 0x1008FF5B /* XF86Documents */) - min_keycode; - if (fingerprint_value == 235) { - for (i = 0; i < SDL_arraysize(scancode_set); ++i) { - if (scancode_set[i] == SDL_SCANCODE_TABLE_XFREE86_2) { - best_index = i; - best_distance = 0; - break; - } - } - } - } - if (best_index >= 0 && best_distance <= 2) { - int table_size; - const SDL_Scancode *table = SDL_GetScancodeTable(scancode_set[best_index], &table_size); - -#ifdef DEBUG_KEYBOARD - SDL_Log("Using scancode set %d, min_keycode = %d, max_keycode = %d, table_size = %d", best_index, min_keycode, max_keycode, table_size); -#endif - // This should never happen, but just in case... - if (table_size > (SDL_arraysize(data->key_layout) - min_keycode)) { - table_size = (SDL_arraysize(data->key_layout) - min_keycode); - } - SDL_memcpy(&data->key_layout[min_keycode], table, sizeof(SDL_Scancode) * table_size); - - /* Scancodes represent physical locations on the keyboard, unaffected by keyboard mapping. - However, there are a number of extended scancodes that have no standard location, so use - the X11 mapping for all non-character keys. - */ - for (i = min_keycode; i <= max_keycode; ++i) { - SDL_Scancode scancode = X11_KeyCodeToSDLScancode(_this, i); -#ifdef DEBUG_KEYBOARD - { - KeySym sym; - sym = X11_KeyCodeToSym(_this, (KeyCode)i, 0); - SDL_Log("code = %d, sym = 0x%X (%s) ", i - min_keycode, - (unsigned int)sym, sym == NoSymbol ? "NoSymbol" : X11_XKeysymToString(sym)); - } -#endif - if (scancode == data->key_layout[i]) { - continue; - } - if ((SDL_GetKeymapKeycode(NULL, scancode, SDL_KMOD_NONE) & (SDLK_SCANCODE_MASK | SDLK_EXTENDED_MASK)) && X11_ScancodeIsRemappable(scancode)) { - // Not a character key and the scancode is safe to remap -#ifdef DEBUG_KEYBOARD - SDL_Log("Changing scancode, was %d (%s), now %d (%s)", data->key_layout[i], SDL_GetScancodeName(data->key_layout[i]), scancode, SDL_GetScancodeName(scancode)); -#endif - data->key_layout[i] = scancode; - } - } - } else { -#ifdef DEBUG_SCANCODES - SDL_Log("Keyboard layout unknown, please report the following to the SDL forums/mailing list (https://discourse.libsdl.org/):"); -#endif - - // Determine key_layout - only works on US QWERTY layout - for (i = min_keycode; i <= max_keycode; ++i) { - SDL_Scancode scancode = X11_KeyCodeToSDLScancode(_this, i); -#ifdef DEBUG_SCANCODES - { - KeySym sym; - sym = X11_KeyCodeToSym(_this, (KeyCode)i, 0); - SDL_Log("code = %d, sym = 0x%X (%s) ", i - min_keycode, - (unsigned int)sym, sym == NoSymbol ? "NoSymbol" : X11_XKeysymToString(sym)); - } - if (scancode == SDL_SCANCODE_UNKNOWN) { - SDL_Log("scancode not found"); - } else { - SDL_Log("scancode = %d (%s)", scancode, SDL_GetScancodeName(scancode)); - } -#endif - data->key_layout[i] = scancode; - } - } - - X11_UpdateKeymap(_this, false); - - SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu"); - - X11_ReconcileKeyboardState(_this); - - return true; -} - -static unsigned X11_GetNumLockModifierMask(SDL_VideoDevice *_this) -{ - SDL_VideoData *videodata = _this->internal; - Display *display = videodata->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 (videodata->key_layout[kc] == SDL_SCANCODE_NUMLOCKCLEAR) { - num_mask = 1 << i; - break; - } - } - } - X11_XFreeModifiermap(xmods); - - return num_mask; -} - -static unsigned X11_GetScrollLockModifierMask(SDL_VideoDevice *_this) -{ - SDL_VideoData *videodata = _this->internal; - Display *display = videodata->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 (videodata->key_layout[kc] == SDL_SCANCODE_SCROLLLOCK) { - num_mask = 1 << i; - break; - } - } - } - X11_XFreeModifiermap(xmods); - - return num_mask; -} - -void X11_UpdateKeymap(SDL_VideoDevice *_this, bool send_event) -{ - struct Keymod_masks - { - SDL_Keymod sdl_mask; - unsigned int xkb_mask; - } const keymod_masks[] = { - { SDL_KMOD_NONE, 0 }, - { SDL_KMOD_SHIFT, ShiftMask }, - { SDL_KMOD_CAPS, LockMask }, - { SDL_KMOD_SHIFT | SDL_KMOD_CAPS, ShiftMask | LockMask }, - { SDL_KMOD_MODE, Mod5Mask }, - { SDL_KMOD_MODE | SDL_KMOD_SHIFT, Mod5Mask | ShiftMask }, - { SDL_KMOD_MODE | SDL_KMOD_CAPS, Mod5Mask | LockMask }, - { SDL_KMOD_MODE | SDL_KMOD_SHIFT | SDL_KMOD_CAPS, Mod5Mask | ShiftMask | LockMask }, - { SDL_KMOD_LEVEL5, Mod3Mask }, - { SDL_KMOD_LEVEL5 | SDL_KMOD_SHIFT, Mod3Mask | ShiftMask }, - { SDL_KMOD_LEVEL5 | SDL_KMOD_CAPS, Mod3Mask | LockMask }, - { SDL_KMOD_LEVEL5 | SDL_KMOD_SHIFT | SDL_KMOD_CAPS, Mod3Mask | ShiftMask | LockMask }, - { SDL_KMOD_LEVEL5 | SDL_KMOD_MODE, Mod5Mask | Mod3Mask }, - { SDL_KMOD_LEVEL5 | SDL_KMOD_MODE | SDL_KMOD_SHIFT, Mod3Mask | Mod5Mask | ShiftMask }, - { SDL_KMOD_LEVEL5 | SDL_KMOD_MODE | SDL_KMOD_CAPS, Mod3Mask | Mod5Mask | LockMask }, - { SDL_KMOD_LEVEL5 | SDL_KMOD_MODE | SDL_KMOD_SHIFT | SDL_KMOD_CAPS, Mod3Mask | Mod5Mask | ShiftMask | LockMask } - }; - - SDL_VideoData *data = _this->internal; - SDL_Scancode scancode; - SDL_Keymap *keymap = SDL_CreateKeymap(); - -#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM - if (data->xkb.desc_ptr) { - XkbStateRec state; - X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb.desc_ptr); - - if (X11_XkbGetState(data->display, XkbUseCoreKbd, &state) == Success) { - data->xkb.current_group = state.group; - } - } -#endif - - for (int m = 0; m < SDL_arraysize(keymod_masks); ++m) { - for (int i = 0; i < SDL_arraysize(data->key_layout); ++i) { - // Make sure this is a valid scancode - scancode = data->key_layout[i]; - if (scancode == SDL_SCANCODE_UNKNOWN) { - continue; - } - - const KeySym keysym = X11_KeyCodeToSym(_this, i, data->xkb.current_group, keymod_masks[m].xkb_mask); - - if (keysym != NoSymbol) { - SDL_Keycode keycode = SDL_GetKeyCodeFromKeySym(keysym, i, keymod_masks[m].sdl_mask); - - if (!keycode) { - switch (scancode) { - case SDL_SCANCODE_RETURN: - keycode = SDLK_RETURN; - break; - case SDL_SCANCODE_ESCAPE: - keycode = SDLK_ESCAPE; - break; - case SDL_SCANCODE_BACKSPACE: - keycode = SDLK_BACKSPACE; - break; - case SDL_SCANCODE_DELETE: - keycode = SDLK_DELETE; - break; - default: - keycode = SDL_SCANCODE_TO_KEYCODE(scancode); - break; - } - } - - SDL_SetKeymapEntry(keymap, scancode, keymod_masks[m].sdl_mask, keycode); - } - } - } - - data->xkb.numlock_mask = X11_GetNumLockModifierMask(_this); - data->xkb.scrolllock_mask = X11_GetScrollLockModifierMask(_this); - SDL_SetKeymap(keymap, send_event); -} - -void X11_QuitKeyboard(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - -#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM - if (data->xkb.desc_ptr) { - X11_XkbFreeKeyboard(data->xkb.desc_ptr, 0, True); - data->xkb.desc_ptr = NULL; - } -#endif -} - -void X11_ClearComposition(SDL_WindowData *data) -{ - if (data->preedit_length > 0) { - data->preedit_text[0] = '\0'; - data->preedit_length = 0; - } - - if (data->ime_needs_clear_composition) { - SDL_SendEditingText("", 0, 0); - data->ime_needs_clear_composition = false; - } -} - -static void X11_SendEditingEvent(SDL_WindowData *data) -{ - if (data->preedit_length == 0) { - X11_ClearComposition(data); - return; - } - - bool in_highlight = false; - int start = -1, length = 0, i; - for (i = 0; i < data->preedit_length; ++i) { - if (data->preedit_feedback[i] & (XIMReverse | XIMHighlight)) { - if (start < 0) { - start = i; - in_highlight = true; - } - } else if (in_highlight) { - // Found the end of the highlight - break; - } - } - if (in_highlight) { - length = (i - start); - } else { - start = SDL_clamp(data->preedit_cursor, 0, data->preedit_length); - } - SDL_SendEditingText(data->preedit_text, start, length); - - data->ime_needs_clear_composition = true; -} - -static int preedit_start_callback(XIC xic, XPointer client_data, XPointer call_data) -{ - // No limit on preedit text length - return -1; -} - -static void preedit_done_callback(XIC xic, XPointer client_data, XPointer call_data) -{ -} - -static void preedit_draw_callback(XIC xic, XPointer client_data, XIMPreeditDrawCallbackStruct *call_data) -{ - SDL_WindowData *data = (SDL_WindowData *)client_data; - int chg_first = SDL_clamp(call_data->chg_first, 0, data->preedit_length); - int chg_length = SDL_clamp(call_data->chg_length, 0, data->preedit_length - chg_first); - - const char *start = data->preedit_text; - if (chg_length > 0) { - // Delete text in range - for (int i = 0; start && *start && i < chg_first; ++i) { - SDL_StepUTF8(&start, NULL); - } - - const char *end = start; - for (int i = 0; end && *end && i < chg_length; ++i) { - SDL_StepUTF8(&end, NULL); - } - - if (end > start) { - SDL_memmove((char *)start, end, SDL_strlen(end) + 1); - if ((chg_first + chg_length) > data->preedit_length) { - SDL_memmove(&data->preedit_feedback[chg_first], &data->preedit_feedback[chg_first + chg_length], (data->preedit_length - chg_first - chg_length) * sizeof(*data->preedit_feedback)); - } - } - data->preedit_length -= chg_length; - } - - XIMText *text = call_data->text; - if (text) { - // Insert text in range - SDL_assert(!text->encoding_is_wchar); - - // The text length isn't calculated as directed by the spec, recalculate it now - if (text->string.multi_byte) { - text->length = SDL_utf8strlen(text->string.multi_byte); - } - - size_t string_size = SDL_strlen(text->string.multi_byte); - size_t size = string_size + 1; - if (data->preedit_text) { - size += SDL_strlen(data->preedit_text); - } - char *preedit_text = (char *)SDL_malloc(size * sizeof(*preedit_text)); - if (preedit_text) { - size_t pre_size = (start - data->preedit_text); - size_t post_size = start ? SDL_strlen(start) : 0; - if (pre_size > 0) { - SDL_memcpy(&preedit_text[0], data->preedit_text, pre_size); - } - SDL_memcpy(&preedit_text[pre_size], text->string.multi_byte, string_size); - if (post_size > 0) { - SDL_memcpy(&preedit_text[pre_size + string_size], start, post_size); - } - preedit_text[size - 1] = '\0'; - } - - size_t feedback_size = data->preedit_length + text->length; - XIMFeedback *feedback = (XIMFeedback *)SDL_malloc(feedback_size * sizeof(*feedback)); - if (feedback) { - size_t pre_size = (size_t)chg_first; - size_t post_size = (size_t)data->preedit_length - pre_size; - if (pre_size > 0) { - SDL_memcpy(&feedback[0], data->preedit_feedback, pre_size * sizeof(*feedback)); - } - SDL_memcpy(&feedback[pre_size], text->feedback, text->length * sizeof(*feedback)); - if (post_size > 0) { - SDL_memcpy(&feedback[pre_size + text->length], &data->preedit_feedback[pre_size], post_size * sizeof(*feedback)); - } - } - - if (preedit_text && feedback) { - SDL_free(data->preedit_text); - data->preedit_text = preedit_text; - - SDL_free(data->preedit_feedback); - data->preedit_feedback = feedback; - - data->preedit_length += text->length; - } else { - SDL_free(preedit_text); - SDL_free(feedback); - } - } - - data->preedit_cursor = call_data->caret; - -#ifdef DEBUG_XIM - if (call_data->chg_length > 0) { - SDL_Log("Draw callback deleted %d characters at %d", call_data->chg_length, call_data->chg_first); - } - if (text) { - SDL_Log("Draw callback inserted %s at %d, caret: %d", text->string.multi_byte, call_data->chg_first, call_data->caret); - } - SDL_Log("Pre-edit text: %s", data->preedit_text); -#endif - - X11_SendEditingEvent(data); -} - -static void preedit_caret_callback(XIC xic, XPointer client_data, XIMPreeditCaretCallbackStruct *call_data) -{ - SDL_WindowData *data = (SDL_WindowData *)client_data; - - switch (call_data->direction) { - case XIMAbsolutePosition: - if (call_data->position != data->preedit_cursor) { - data->preedit_cursor = call_data->position; - X11_SendEditingEvent(data); - } - break; - case XIMDontChange: - break; - default: - // Not currently supported - break; - } -} - -void X11_CreateInputContext(SDL_WindowData *data) -{ -#ifdef X_HAVE_UTF8_STRING - SDL_VideoData *videodata = data->videodata; - - if (SDL_X11_HAVE_UTF8 && videodata->im) { - const char *hint = SDL_GetHint(SDL_HINT_IME_IMPLEMENTED_UI); - if (hint && SDL_strstr(hint, "composition")) { - XIMCallback draw_callback; - draw_callback.client_data = (XPointer)data; - draw_callback.callback = (XIMProc)preedit_draw_callback; - - XIMCallback start_callback; - start_callback.client_data = (XPointer)data; - start_callback.callback = (XIMProc)preedit_start_callback; - - XIMCallback done_callback; - done_callback.client_data = (XPointer)data; - done_callback.callback = (XIMProc)preedit_done_callback; - - XIMCallback caret_callback; - caret_callback.client_data = (XPointer)data; - caret_callback.callback = (XIMProc)preedit_caret_callback; - - XVaNestedList attr = X11_XVaCreateNestedList(0, - XNPreeditStartCallback, &start_callback, - XNPreeditDoneCallback, &done_callback, - XNPreeditDrawCallback, &draw_callback, - XNPreeditCaretCallback, &caret_callback, - NULL); - if (attr) { - data->ic = X11_XCreateIC(videodata->im, - XNInputStyle, XIMPreeditCallbacks | XIMStatusCallbacks, - XNPreeditAttributes, attr, - XNClientWindow, data->xwindow, - NULL); - X11_XFree(attr); - } - } - if (!data->ic) { - data->ic = X11_XCreateIC(videodata->im, - XNInputStyle, XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, data->xwindow, - NULL); - } - data->xim_spot.x = -1; - data->xim_spot.y = -1; - } -#endif // X_HAVE_UTF8_STRING -} - -static void X11_ResetXIM(SDL_VideoDevice *_this, SDL_Window *window) -{ -#ifdef X_HAVE_UTF8_STRING - SDL_WindowData *data = window->internal; - - if (data && data->ic) { - // Clear any partially entered dead keys - char *contents = X11_Xutf8ResetIC(data->ic); - if (contents) { - X11_XFree(contents); - } - } -#endif // X_HAVE_UTF8_STRING -} - -bool X11_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) -{ - X11_ResetXIM(_this, window); - - return X11_UpdateTextInputArea(_this, window); -} - -bool X11_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) -{ - X11_ResetXIM(_this, window); - return true; -} - -bool X11_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window) -{ -#ifdef X_HAVE_UTF8_STRING - SDL_WindowData *data = window->internal; - - if (data && data->ic) { - XPoint spot; - spot.x = window->text_input_rect.x + window->text_input_cursor; - spot.y = window->text_input_rect.y + window->text_input_rect.h; - if (spot.x != data->xim_spot.x || spot.y != data->xim_spot.y) { - XVaNestedList attr = X11_XVaCreateNestedList(0, XNSpotLocation, &spot, NULL); - if (attr) { - X11_XSetICValues(data->ic, XNPreeditAttributes, attr, NULL); - X11_XFree(attr); - } - SDL_copyp(&data->xim_spot, &spot); - } - } -#endif - return true; -} - -bool X11_HasScreenKeyboardSupport(SDL_VideoDevice *_this) -{ - SDL_VideoData *videodata = _this->internal; - return videodata->is_steam_deck; -} - -void X11_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props) -{ - SDL_VideoData *videodata = _this->internal; - - if (videodata->is_steam_deck) { - /* For more documentation of the URL parameters, see: - * https://partner.steamgames.com/doc/api/ISteamUtils#ShowFloatingGamepadTextInput - */ - const int k_EFloatingGamepadTextInputModeModeSingleLine = 0; // Enter dismisses the keyboard - const int k_EFloatingGamepadTextInputModeModeMultipleLines = 1; // User needs to explicitly dismiss the keyboard - const int k_EFloatingGamepadTextInputModeModeEmail = 2; // Keyboard is displayed in a special mode that makes it easier to enter emails - const int k_EFloatingGamepadTextInputModeModeNumeric = 3; // Numeric keypad is shown - char deeplink[128]; - int mode; - - switch (SDL_GetTextInputType(props)) { - case SDL_TEXTINPUT_TYPE_TEXT_EMAIL: - mode = k_EFloatingGamepadTextInputModeModeEmail; - break; - case SDL_TEXTINPUT_TYPE_NUMBER: - case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN: - case SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE: - mode = k_EFloatingGamepadTextInputModeModeNumeric; - break; - default: - if (SDL_GetTextInputMultiline(props)) { - mode = k_EFloatingGamepadTextInputModeModeMultipleLines; - } else { - mode = k_EFloatingGamepadTextInputModeModeSingleLine; - } - break; - } - (void)SDL_snprintf(deeplink, sizeof(deeplink), - "steam://open/keyboard?XPosition=0&YPosition=0&Width=0&Height=0&Mode=%d", - mode); - SDL_OpenURL(deeplink); - videodata->steam_keyboard_open = true; - } -} - -void X11_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_VideoData *videodata = _this->internal; - - if (videodata->is_steam_deck) { - SDL_OpenURL("steam://close/keyboard"); - videodata->steam_keyboard_open = false; - } -} - -bool X11_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_VideoData *videodata = _this->internal; - - return videodata->steam_keyboard_open; -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.h deleted file mode 100644 index a6cd2f7..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11keyboard.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 bool X11_InitKeyboard(SDL_VideoDevice *_this); -extern void X11_UpdateKeymap(SDL_VideoDevice *_this, bool send_event); -extern void X11_QuitKeyboard(SDL_VideoDevice *_this); -extern void X11_CreateInputContext(SDL_WindowData *data); -extern void X11_ClearComposition(SDL_WindowData *data); -extern bool X11_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); -extern bool X11_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_HasScreenKeyboardSupport(SDL_VideoDevice *_this); -extern void X11_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID props); -extern void X11_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window); -extern KeySym X11_KeyCodeToSym(SDL_VideoDevice *_this, KeyCode, unsigned char group, unsigned int mod_mask); - -#endif // SDL_x11keyboard_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11messagebox.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11messagebox.c deleted file mode 100644 index 8aa1c6a..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11messagebox.c +++ /dev/null @@ -1,887 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "SDL_x11video.h" -#include "SDL_x11dyn.h" -#include "SDL_x11messagebox.h" - -#include -#include - -#define SDL_FORK_MESSAGEBOX 1 -#define SDL_SET_LOCALE 1 - -#if SDL_FORK_MESSAGEBOX -#include -#include -#include -#include -#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-*-*-*-*-iso10646-1", // explicitly unicode (iso10646-1) - "-*-*-medium-r-*--*-120-*-*-*-*-iso10646-1", // explicitly unicode (iso10646-1) - "-misc-*-*-*-*--*-*-*-*-*-*-iso10646-1", // misc unicode (fix for some systems) - "-*-*-*-*-*--*-*-*-*-*-*-iso10646-1", // just give me anything Unicode. - "-*-*-medium-r-normal--*-120-*-*-*-*-iso8859-1", // explicitly latin1, in case low-ASCII works out. - "-*-*-medium-r-*--*-120-*-*-*-*-iso8859-1", // explicitly latin1, in case low-ASCII works out. - "-misc-*-*-*-*--*-*-*-*-*-*-iso8859-1", // misc latin1 (fix for some systems) - "-*-*-*-*-*--*-*-*-*-*-*-iso8859-1", // just give me anything latin1. - NULL -}; - -static const SDL_MessageBoxColor g_default_colors[SDL_MESSAGEBOX_COLOR_COUNT] = { - { 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; -#ifdef SDL_VIDEO_DRIVER_X11_XDBE - XdbeBackBuffer buf; - 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_COUNT]; - - 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) -{ -#ifdef X_HAVE_UTF8_STRING - 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 -#endif - { - 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 bool 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"); - } - -#ifdef X_HAVE_UTF8_STRING - if (SDL_X11_HAVE_UTF8) { - char **missing = NULL; - int num_missing = 0; - int i_font; - for (i_font = 0; g_MessageBoxFont[i_font]; ++i_font) { - data->font_set = X11_XCreateFontSet(data->display, g_MessageBoxFont[i_font], - &missing, &num_missing, NULL); - if (missing) { - X11_XFreeStringList(missing); - } - if (data->font_set) { - break; - } - } - if (!data->font_set) { - return SDL_SetError("Couldn't load x11 message box font"); - } - } else -#endif - { - data->font_struct = X11_XLoadQueryFont(data->display, g_MessageBoxFontLatin1); - if (!data->font_struct) { - 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_COUNT; i++) { - data->color[i] = SDL_MAKE_RGB(colorhints[i].r, colorhints[i].g, colorhints[i].b); - } - - return true; -} - -static int CountLinesOfText(const char *text) -{ - int result = 0; - while (text && *text) { - const char *lf = SDL_strchr(text, '\n'); - result++; // even without an endline, this counts as a line. - text = lf ? lf + 1 : NULL; - } - return result; -} - -// Calculate and initialize text and button locations. -static bool 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 && messageboxdata->message[0]) { - const char *text = messageboxdata->message; - const int linecount = CountLinesOfText(text); - TextLineData *plinedata = (TextLineData *)SDL_malloc(sizeof(TextLineData) * linecount); - - if (!plinedata) { - return false; - } - - 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. - if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) { - x = data->dialog_width - (data->dialog_width - width_of_buttons) / 2 - (button_width + button_spacing); - } else { - 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. - if (messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) { - x -= button_width + button_spacing; - } else { - x += button_width + button_spacing; - } - } - } - - return true; -} - -// Free SDL_MessageBoxData data. -static void X11_MessageBoxShutdown(SDL_MessageBoxDataX11 *data) -{ - if (data->font_set) { - X11_XFreeFontSet(data->display, data->font_set); - data->font_set = NULL; - } - - if (data->font_struct) { - X11_XFreeFont(data->display, data->font_struct); - data->font_struct = NULL; - } - -#ifdef 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 bool X11_MessageBoxCreateWindow(SDL_MessageBoxDataX11 *data) -{ - int x, y; - XSizeHints *sizehints; - XSetWindowAttributes wnd_attr; - Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG; - Display *display = data->display; - SDL_WindowData *windowdata = NULL; - const SDL_MessageBoxData *messageboxdata = data->messageboxdata; - - if (messageboxdata->window) { - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(messageboxdata->window); - windowdata = messageboxdata->window->internal; - 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) { - Atom _NET_WM_STATE = X11_XInternAtom(display, "_NET_WM_STATE", False); - Atom stateatoms[16]; - size_t statecount = 0; - // Set some message-boxy window states when attached to a parent window... - // we skip the taskbar since this will pop to the front when the parent window is clicked in the taskbar, etc - stateatoms[statecount++] = X11_XInternAtom(display, "_NET_WM_STATE_SKIP_TASKBAR", False); - stateatoms[statecount++] = X11_XInternAtom(display, "_NET_WM_STATE_SKIP_PAGER", False); - stateatoms[statecount++] = X11_XInternAtom(display, "_NET_WM_STATE_FOCUSED", False); - stateatoms[statecount++] = X11_XInternAtom(display, "_NET_WM_STATE_MODAL", False); - SDL_assert(statecount <= SDL_arraysize(stateatoms)); - X11_XChangeProperty(display, data->window, _NET_WM_STATE, XA_ATOM, 32, - PropModeReplace, (unsigned char *)stateatoms, statecount); - - // http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR - X11_XSetTransientForHint(display, data->window, windowdata->xwindow); - } - - SDL_X11_SetWindowTitle(display, data->window, (char *)messageboxdata->title); - - // 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_delete_message = X11_XInternAtom(display, "WM_DELETE_WINDOW", False); - X11_XSetWMProtocols(display, data->window, &data->wm_delete_message, 1); - - data->wm_protocols = X11_XInternAtom(display, "WM_PROTOCOLS", False); - - 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 = dpy->internal; - 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); - -#ifdef 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 = true; - data->buf = X11_XdbeAllocateBackBufferName(display, data->window, XdbeUndefined); - } else { - data->xdbe = false; - } - } -#endif - - return true; -} - -// Draw our message box. -static void X11_MessageBoxDraw(SDL_MessageBoxDataX11 *data, GC ctx) -{ - int i; - Drawable window = data->window; - Display *display = data->display; - -#ifdef 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]; - -#ifdef X_HAVE_UTF8_STRING - 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 -#endif - { - 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]); - -#ifdef X_HAVE_UTF8_STRING - if (SDL_X11_HAVE_UTF8) { - X11_Xutf8DrawString(display, window, data->font_set, ctx, - buttondatax11->x + offset, - buttondatax11->y + offset, - buttondata->text, buttondatax11->length); - } else -#endif - { - X11_XDrawString(display, window, ctx, - buttondatax11->x + offset, buttondatax11->y + offset, - buttondata->text, buttondatax11->length); - } - } - -#ifdef 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 -} - -// NOLINTNEXTLINE(readability-non-const-parameter): cannot make XPointer a const pointer due to typedef -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 bool X11_MessageBoxLoop(SDL_MessageBoxDataX11 *data) -{ - GC ctx; - XGCValues ctx_vals; - bool close_dialog = false; - bool has_focus = true; - KeySym last_key_pressed = XK_VoidSymbol; - unsigned long gcflags = GCForeground | GCBackground; -#ifdef X_HAVE_UTF8_STRING - const int have_utf8 = SDL_X11_HAVE_UTF8; -#else - const int have_utf8 = 0; -#endif - - SDL_zero(ctx_vals); - ctx_vals.foreground = data->color[SDL_MESSAGEBOX_COLOR_BACKGROUND]; - ctx_vals.background = data->color[SDL_MESSAGEBOX_COLOR_BACKGROUND]; - - if (!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; - bool draw = 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 = false; - } - break; - - case FocusIn: - // Got focus. - has_focus = true; - break; - - case FocusOut: - // lost focus. Reset button and mouse info. - has_focus = 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 = 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 = 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 = 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 = true; - } - } - data->button_press_index = -1; - break; - } - - if (draw) { - // Draw our dialog box. - X11_MessageBoxDraw(data, ctx); - } - } - - X11_XFreeGC(data->display, ctx); - return true; -} - -static bool X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int *buttonID) -{ - bool result = false; - SDL_MessageBoxDataX11 data; -#if SDL_SET_LOCALE - char *origlocale; -#endif - - SDL_zero(data); - - if (!SDL_X11_LoadSymbols()) { - return false; - } - -#if SDL_SET_LOCALE - origlocale = setlocale(LC_ALL, NULL); - if (origlocale) { - origlocale = SDL_strdup(origlocale); - if (!origlocale) { - return false; - } - (void)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. - if (X11_MessageBoxInit(&data, messageboxdata, buttonID) && - X11_MessageBoxInitPositions(&data) && - X11_MessageBoxCreateWindow(&data)) { - result = X11_MessageBoxLoop(&data); - } - - X11_MessageBoxShutdown(&data); - -#if SDL_SET_LOCALE - if (origlocale) { - (void)setlocale(LC_ALL, origlocale); - SDL_free(origlocale); - } -#endif - - return result; -} - -// Display an x11 message box. -bool 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; - bool result = true; - - 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]); - result = X11_ShowMessageBoxImpl(messageboxdata, buttonID); - if (write(fds[1], &result, sizeof(result)) != sizeof(result)) { - exitcode = 1; - } else if (write(fds[1], buttonID, sizeof(*buttonID)) != sizeof(*buttonID)) { - 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)) { - result = SDL_SetError("msgbox child process failed"); - } else if ((read(fds[0], &result, sizeof(result)) != sizeof(result)) || - (read(fds[0], buttonID, sizeof(*buttonID)) != sizeof(*buttonID))) { - result = SDL_SetError("read from msgbox child process failed"); - *buttonID = 0; - } - close(fds[0]); - - return result; - } -#else - return X11_ShowMessageBoxImpl(messageboxdata, buttonID); -#endif -} -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11messagebox.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11messagebox.h deleted file mode 100644 index 9baa875..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11messagebox.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_ - -#ifdef SDL_VIDEO_DRIVER_X11 - -extern bool X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID); - -#endif // SDL_VIDEO_DRIVER_X11 - -#endif // SDL_x11messagebox_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.c deleted file mode 100644 index e17a2d1..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.c +++ /dev/null @@ -1,1051 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "SDL_x11video.h" -#include "SDL_x11settings.h" -#include "edid.h" -#include "../../events/SDL_displayevents_c.h" - -// #define X11MODES_DEBUG - -/* Timeout and revert mode switches if the timespan has elapsed without the window becoming fullscreen. - * 5 seconds seems good from testing. - */ -#define MODE_SWITCH_TIMEOUT_NS SDL_NS_PER_SECOND * 5 - -/* 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 float GetGlobalContentScale(SDL_VideoDevice *_this) -{ - static double scale_factor = 0.0; - - if (scale_factor <= 0.0) { - - // First use the forced scaling factor specified by the app/user - const char *hint = SDL_GetHint(SDL_HINT_VIDEO_X11_SCALING_FACTOR); - if (hint && *hint) { - double value = SDL_atof(hint); - if (value >= 1.0f && value <= 10.0f) { - scale_factor = value; - } - } - - // If that failed, try "Xft.dpi" from the XResourcesDatabase... - if (scale_factor <= 0.0) - { - SDL_VideoData *data = _this->internal; - Display *display = data->display; - char *resource_manager; - XrmDatabase db; - XrmValue value; - char *type; - - X11_XrmInitialize(); - - resource_manager = X11_XResourceManagerString(display); - if (resource_manager) { - db = X11_XrmGetStringDatabase(resource_manager); - - // Get the value of Xft.dpi from the Database - if (X11_XrmGetResource(db, "Xft.dpi", "String", &type, &value)) { - if (value.addr && type && SDL_strcmp(type, "String") == 0) { - int dpi = SDL_atoi(value.addr); - scale_factor = dpi / 96.0; - } - } - X11_XrmDestroyDatabase(db); - } - } - - // If that failed, try the XSETTINGS keys... - if (scale_factor <= 0.0) { - scale_factor = X11_GetXsettingsIntKey(_this, "Gdk/WindowScalingFactor", -1); - - // The Xft/DPI key is stored in increments of 1024th - if (scale_factor <= 0.0) { - int dpi = X11_GetXsettingsIntKey(_this, "Xft/DPI", -1); - if (dpi > 0) { - scale_factor = (double) dpi / 1024.0; - scale_factor /= 96.0; - } - } - } - - // If that failed, try the GDK_SCALE envvar... - if (scale_factor <= 0.0) { - const char *scale_str = SDL_getenv("GDK_SCALE"); - if (scale_str) { - scale_factor = SDL_atoi(scale_str); - } - } - - // Nothing or a bad value, just fall back to 1.0 - if (scale_factor <= 0.0) { - scale_factor = 1.0; - } - } - - return (float)scale_factor; -} - -static bool get_visualinfo(Display *display, int screen, XVisualInfo *vinfo) -{ - const char *visual_id = SDL_GetHint(SDL_HINT_VIDEO_X11_VISUALID); - int depth; - - // Look for an exact visual, if requested - if (visual_id && *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 true; - } - } - - 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 true; - } - return false; -} - -bool 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 true; - } - return false; -} - -SDL_PixelFormat 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_GetPixelFormatForMasks(bpp, Rmask, Gmask, Bmask, Amask); - } - - if (vinfo->class == PseudoColor || vinfo->class == StaticColor) { - switch (vinfo->depth) { - case 8: - return SDL_PIXELFORMAT_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; -} - -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR -static 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, false)) { -#ifdef X11MODES_DEBUG - printf("XRandR disabled by default due to window manager issues\n"); -#endif - return false; - } -#else - if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XRANDR, true)) { -#ifdef X11MODES_DEBUG - printf("XRandR disabled due to hint\n"); -#endif - return false; - } -#endif // XRANDR_DISABLED_BY_DEFAULT - - if (!SDL_X11_HAVE_XRANDR) { -#ifdef X11MODES_DEBUG - printf("XRandR support not available\n"); -#endif - return 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 false; - } -#ifdef X11MODES_DEBUG - printf("XRandR available at version %d.%d!\n", *major, *minor); -#endif - return true; -} - -#define XRANDR_ROTATION_LEFT (1 << 1) -#define XRANDR_ROTATION_RIGHT (1 << 3) - -static void CalculateXRandRRefreshRate(const XRRModeInfo *info, int *numerator, int *denominator) -{ - unsigned int vTotal = info->vTotal; - - if (info->modeFlags & RR_DoubleScan) { - // doublescan doubles the number of lines - vTotal *= 2; - } - - if (info->modeFlags & RR_Interlace) { - // interlace splits the frame into two fields - // the field rate is what is typically reported by monitors - vTotal /= 2; - } - - if (info->hTotal && vTotal) { - *numerator = info->dotClock; - *denominator = (info->hTotal * vTotal); - } else { - *numerator = 0; - *denominator = 0; - } -} - -static 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; - XFixed scale_w = 0x10000, scale_h = 0x10000; - XRRCrtcTransformAttributes *attr; - - crtcinfo = X11_XRRGetCrtcInfo(display, res, crtc); - if (crtcinfo) { - rotation = crtcinfo->rotation; - X11_XRRFreeCrtcInfo(crtcinfo); - } - if (X11_XRRGetCrtcTransform(display, crtc, &attr) && attr) { - scale_w = attr->currentTransform.matrix[0][0]; - scale_h = attr->currentTransform.matrix[1][1]; - X11_XFree(attr); - } - - if (rotation & (XRANDR_ROTATION_LEFT | XRANDR_ROTATION_RIGHT)) { - mode->w = (info->height * scale_w + 0xffff) >> 16; - mode->h = (info->width * scale_h + 0xffff) >> 16; - } else { - mode->w = (info->width * scale_w + 0xffff) >> 16; - mode->h = (info->height * scale_h + 0xffff) >> 16; - } - CalculateXRandRRefreshRate(info, &mode->refresh_rate_numerator, &mode->refresh_rate_denominator); - mode->internal->xrandr_mode = modeID; -#ifdef X11MODES_DEBUG - printf("XRandR mode %d: %dx%d@%d/%dHz\n", (int)modeID, - mode->screen_w, mode->screen_h, mode->refresh_rate_numerator, mode->refresh_rate_denominator); -#endif - return true; - } - } - return 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); - SDL_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); - (void)SDL_snprintf(&name[len], namelen - len, " %d\"", inches); - } - -#ifdef X11MODES_DEBUG - printf("Display name: %s\n", name); -#endif -} - -static bool X11_FillXRandRDisplayInfo(SDL_VideoDevice *_this, Display *dpy, int screen, RROutput outputid, XRRScreenResources *res, SDL_VideoDisplay *display, char *display_name, size_t display_name_size) -{ - Atom EDID = X11_XInternAtom(dpy, "EDID", False); - XRROutputInfo *output_info; - int display_x, display_y; - unsigned long display_mm_width, display_mm_height; - SDL_DisplayData *displaydata; - SDL_DisplayMode mode; - SDL_DisplayModeData *modedata; - RRMode modeID; - RRCrtc output_crtc; - XRRCrtcInfo *crtc; - XVisualInfo vinfo; - Uint32 pixelformat; - XPixmapFormatValues *pixmapformats; - int scanline_pad; - int i, n; - - if (!display || !display_name) { - return false; // invalid parameters - } - - if (!get_visualinfo(dpy, screen, &vinfo)) { - return false; // uh, skip this screen? - } - - pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo); - if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) { - return false; // Palettized video modes are no longer supported, ignore this one. - } - - 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); - } - - output_info = X11_XRRGetOutputInfo(dpy, res, outputid); - if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) { - X11_XRRFreeOutputInfo(output_info); - return false; // ignore this one. - } - - SDL_strlcpy(display_name, output_info->name, display_name_size); - 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) { - return false; // oh well, ignore it. - } - - 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 false; - } - - modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData)); - if (!modedata) { - SDL_free(displaydata); - return false; - } - - modedata->xrandr_mode = modeID; - mode.internal = modedata; - - displaydata->screen = screen; - displaydata->visual = vinfo.visual; - displaydata->depth = vinfo.depth; - displaydata->scanline_pad = scanline_pad; - displaydata->x = display_x; - displaydata->y = display_y; - displaydata->use_xrandr = true; - displaydata->xrandr_output = outputid; - SDL_strlcpy(displaydata->connector_name, display_name, sizeof(displaydata->connector_name)); - - SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode); - SetXRandRDisplayName(dpy, EDID, display_name, display_name_size, outputid, display_mm_width, display_mm_height); - - SDL_zero(*display); - if (*display_name) { - display->name = display_name; - } - display->desktop_mode = mode; - display->content_scale = GetGlobalContentScale(_this); - display->internal = displaydata; - - return true; -} - -static bool X11_AddXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int screen, RROutput outputid, XRRScreenResources *res, bool send_event) -{ - SDL_VideoDisplay display; - char display_name[128]; - - if (!X11_FillXRandRDisplayInfo(_this, dpy, screen, outputid, res, &display, display_name, sizeof(display_name))) { - return true; // failed to query data, skip this display - } - - if (SDL_AddVideoDisplay(&display, send_event) == 0) { - return false; - } - - return true; -} - - -static bool X11_UpdateXRandRDisplay(SDL_VideoDevice *_this, Display *dpy, int screen, RROutput outputid, XRRScreenResources *res, SDL_VideoDisplay *existing_display) -{ - SDL_VideoDisplay display; - char display_name[128]; - - if (!X11_FillXRandRDisplayInfo(_this, dpy, screen, outputid, res, &display, display_name, sizeof(display_name))) { - return false; // failed to query current display state - } - - // update mode - this call takes ownership of display.desktop_mode.internal - SDL_SetDesktopDisplayMode(existing_display, &display.desktop_mode); - - // update bounds - if (existing_display->internal->x != display.internal->x || - existing_display->internal->y != display.internal->y) { - existing_display->internal->x = display.internal->x; - existing_display->internal->y = display.internal->y; - SDL_SendDisplayEvent(existing_display, SDL_EVENT_DISPLAY_MOVED, 0, 0); - } - - // update scale - SDL_SetDisplayContentScale(existing_display, display.content_scale); - - // SDL_DisplayData is updated piece-meal above, free our local copy of this data - SDL_free( display.internal ); - - return true; -} - -static XRRScreenResources *X11_GetScreenResources(Display *dpy, int screen) -{ - XRRScreenResources *res = X11_XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, screen)); - if (!res || res->noutput == 0) { - if (res) { - X11_XRRFreeScreenResources(res); - } - res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen)); - } - return res; -} - -static void X11_CheckDisplaysMoved(SDL_VideoDevice *_this, Display *dpy) -{ - const int screen = DefaultScreen(dpy); - XRRScreenResources *res = X11_GetScreenResources(dpy, screen); - if (!res) { - return; - } - - SDL_DisplayID *displays = SDL_GetDisplays(NULL); - if (displays) { - for (int i = 0; displays[i]; ++i) { - SDL_VideoDisplay *display = SDL_GetVideoDisplay(displays[i]); - const SDL_DisplayData *displaydata = display->internal; - X11_UpdateXRandRDisplay(_this, dpy, screen, displaydata->xrandr_output, res, display); - } - SDL_free(displays); - } - X11_XRRFreeScreenResources(res); -} - -static void X11_HandleXRandROutputChange(SDL_VideoDevice *_this, const XRROutputChangeNotifyEvent *ev) -{ - SDL_DisplayID *displays; - SDL_VideoDisplay *display = NULL; - int i; - -#if 0 - printf("XRROutputChangeNotifyEvent! [output=%u, crtc=%u, mode=%u, rotation=%u, connection=%u]", (unsigned int) ev->output, (unsigned int) ev->crtc, (unsigned int) ev->mode, (unsigned int) ev->rotation, (unsigned int) ev->connection); -#endif - - displays = SDL_GetDisplays(NULL); - if (displays) { - for (i = 0; displays[i]; ++i) { - SDL_VideoDisplay *thisdisplay = SDL_GetVideoDisplay(displays[i]); - const SDL_DisplayData *displaydata = thisdisplay->internal; - if (displaydata->xrandr_output == ev->output) { - display = thisdisplay; - break; - } - } - SDL_free(displays); - } - - if (ev->connection == RR_Disconnected) { // output is going away - if (display) { - SDL_DelVideoDisplay(display->id, true); - } - X11_CheckDisplaysMoved(_this, ev->display); - - } else if (ev->connection == RR_Connected) { // output is coming online - if (!display) { - Display *dpy = ev->display; - const int screen = DefaultScreen(dpy); - XRRScreenResources *res = X11_GetScreenResources(dpy, screen); - if (res) { - X11_AddXRandRDisplay(_this, dpy, screen, ev->output, res, true); - X11_XRRFreeScreenResources(res); - } - } - X11_CheckDisplaysMoved(_this, ev->display); - } -} - -void X11_HandleXRandREvent(SDL_VideoDevice *_this, const XEvent *xevent) -{ - SDL_VideoData *videodata = _this->internal; - SDL_assert(xevent->type == (videodata->xrandr_event_base + RRNotify)); - - switch (((const XRRNotifyEvent *)xevent)->subtype) { - case RRNotify_OutputChange: - X11_HandleXRandROutputChange(_this, (const XRROutputChangeNotifyEvent *)xevent); - break; - default: - break; - } -} - -static void X11_SortOutputsByPriorityHint(SDL_VideoDevice *_this) -{ - const char *name_hint = SDL_GetHint(SDL_HINT_VIDEO_DISPLAY_PRIORITY); - - if (name_hint) { - char *saveptr; - char *str = SDL_strdup(name_hint); - SDL_VideoDisplay **sorted_list = SDL_malloc(sizeof(SDL_VideoDisplay *) * _this->num_displays); - - if (str && sorted_list) { - int sorted_index = 0; - - // Sort the requested displays to the front of the list. - const char *token = SDL_strtok_r(str, ",", &saveptr); - while (token) { - for (int i = 0; i < _this->num_displays; ++i) { - SDL_VideoDisplay *d = _this->displays[i]; - if (d) { - SDL_DisplayData *data = d->internal; - if (SDL_strcmp(token, data->connector_name) == 0) { - sorted_list[sorted_index++] = d; - _this->displays[i] = NULL; - break; - } - } - } - - token = SDL_strtok_r(NULL, ",", &saveptr); - } - - // Append the remaining displays to the end of the list. - for (int i = 0; i < _this->num_displays; ++i) { - if (_this->displays[i]) { - sorted_list[sorted_index++] = _this->displays[i]; - } - } - - // Copy the sorted list back to the display list. - SDL_memcpy(_this->displays, sorted_list, sizeof(SDL_VideoDisplay *) * _this->num_displays); - } - - SDL_free(str); - SDL_free(sorted_list); - } -} - -static bool X11_InitModes_XRandR(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - Display *dpy = data->display; - const int screencount = ScreenCount(dpy); - const int default_screen = DefaultScreen(dpy); - RROutput primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, default_screen)); - int xrandr_error_base = 0; - int looking_for_primary; - int output; - int screen; - - if (!X11_XRRQueryExtension(dpy, &data->xrandr_event_base, &xrandr_error_base)) { - return SDL_SetError("XRRQueryExtension failed"); - } - - 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; - } - - XRRScreenResources *res = X11_GetScreenResources(dpy, screen); - if (!res) { - continue; - } - - for (output = 0; output < res->noutput; output++) { - // 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; - } - if (!X11_AddXRandRDisplay(_this, dpy, screen, res->outputs[output], res, false)) { - break; - } - } - - X11_XRRFreeScreenResources(res); - - // This will generate events for displays that come and go at runtime. - X11_XRRSelectInput(dpy, RootWindow(dpy, screen), RROutputChangeNotifyMask); - } - } - - if (_this->num_displays == 0) { - return SDL_SetError("No available displays"); - } - - X11_SortOutputsByPriorityHint(_this); - - return true; -} -#endif // SDL_VIDEO_DRIVER_X11_XRANDR - -/* This is used if there's no better functionality--like XRandR--to use. - It won't attempt to supply different display modes at all, but it can - enumerate the current displays and their current sizes. */ -static bool X11_InitModes_StdXlib(SDL_VideoDevice *_this) -{ - // !!! FIXME: a lot of copy/paste from X11_InitModes_XRandR in this function. - SDL_VideoData *data = _this->internal; - Display *dpy = data->display; - const int default_screen = DefaultScreen(dpy); - Screen *screen = ScreenOfDisplay(dpy, default_screen); - int scanline_pad, n, i; - SDL_DisplayModeData *modedata; - SDL_DisplayData *displaydata; - SDL_DisplayMode mode; - XPixmapFormatValues *pixmapformats; - Uint32 pixelformat; - XVisualInfo vinfo; - SDL_VideoDisplay display; - - // note that generally even if you have a multiple physical monitors, ScreenCount(dpy) still only reports ONE screen. - - if (!get_visualinfo(dpy, default_screen, &vinfo)) { - return SDL_SetError("Failed to find an X11 visual for the primary display"); - } - - pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo); - if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) { - return SDL_SetError("Palettized video modes are no longer supported"); - } - - SDL_zero(mode); - mode.w = WidthOfScreen(screen); - mode.h = HeightOfScreen(screen); - mode.format = pixelformat; - - displaydata = (SDL_DisplayData *)SDL_calloc(1, sizeof(*displaydata)); - if (!displaydata) { - return false; - } - - modedata = (SDL_DisplayModeData *)SDL_calloc(1, sizeof(SDL_DisplayModeData)); - if (!modedata) { - SDL_free(displaydata); - return false; - } - mode.internal = modedata; - - displaydata->screen = default_screen; - displaydata->visual = vinfo.visual; - displaydata->depth = vinfo.depth; - - 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); - } - - displaydata->scanline_pad = scanline_pad; - displaydata->x = 0; - displaydata->y = 0; - displaydata->use_xrandr = false; - - SDL_zero(display); - display.name = (char *)"Generic X11 Display"; /* this is just copied and thrown away, it's safe to cast to char* here. */ - display.desktop_mode = mode; - display.internal = displaydata; - display.content_scale = GetGlobalContentScale(_this); - if (SDL_AddVideoDisplay(&display, true) == 0) { - return false; - } - return true; -} - -bool X11_InitModes(SDL_VideoDevice *_this) -{ - /* XRandR is the One True Modern Way to do this on X11. If this - fails, we just won't report any display modes except the current - desktop size. */ -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR - { - SDL_VideoData *data = _this->internal; - int xrandr_major, xrandr_minor; - // require at least XRandR v1.3 - if (CheckXRandR(data->display, &xrandr_major, &xrandr_minor) && - (xrandr_major >= 2 || (xrandr_major == 1 && xrandr_minor >= 3)) && - X11_InitModes_XRandR(_this)) { - return true; - } - } -#endif // SDL_VIDEO_DRIVER_X11_XRANDR - - // still here? Just set up an extremely basic display. - return X11_InitModes_StdXlib(_this); -} - -bool X11_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR - SDL_DisplayData *data = sdl_display->internal; - 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) - */ - SDL_zero(mode); - mode.format = sdl_display->desktop_mode.format; - - if (data->use_xrandr) { - Display *display = _this->internal->display; - 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.internal = modedata; - - if (!SetXRandRModeInfo(display, res, output_info->crtc, output_info->modes[i], &mode) || - !SDL_AddFullscreenDisplayMode(sdl_display, &mode)) { - SDL_free(modedata); - } - } - } - X11_XRRFreeOutputInfo(output_info); - X11_XRRFreeScreenResources(res); - } - } -#endif // SDL_VIDEO_DRIVER_X11_XRANDR - return true; -} - -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR -// This catches an error from XRRSetScreenSize, as a workaround for now. -// !!! FIXME: remove this later when we have a better solution. -static int (*PreXRRSetScreenSizeErrorHandler)(Display *, XErrorEvent *) = NULL; -static int SDL_XRRSetScreenSizeErrHandler(Display *d, XErrorEvent *e) -{ - // BadMatch: https://github.com/libsdl-org/SDL/issues/4561 - // BadValue: https://github.com/libsdl-org/SDL/issues/4840 - if ((e->error_code == BadMatch) || (e->error_code == BadValue)) { - return 0; - } - - return PreXRRSetScreenSizeErrorHandler(d, e); -} -#endif - -bool X11_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display, SDL_DisplayMode *mode) -{ - SDL_VideoData *viddata = _this->internal; - SDL_DisplayData *data = sdl_display->internal; - - viddata->last_mode_change_deadline = SDL_GetTicks() + (PENDING_FOCUS_TIME * 2); - - // XWayland mode switches are emulated with viewports and thus instantaneous. - if (!viddata->is_xwayland) { - if (sdl_display->current_mode != mode) { - data->mode_switch_deadline_ns = SDL_GetTicksNS() + MODE_SWITCH_TIMEOUT_NS; - } else { - data->mode_switch_deadline_ns = 0; - } - } - -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR - if (data->use_xrandr) { - Display *display = viddata->display; - SDL_DisplayModeData *modedata = mode->internal; - int mm_width, mm_height; - 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"); - } - - if (crtc->mode == modedata->xrandr_mode) { -#ifdef X11MODES_DEBUG - printf("already in desired mode 0x%lx (%ux%u), nothing to do\n", - crtc->mode, crtc->width, crtc->height); -#endif - status = Success; - goto freeInfo; - } - - X11_XGrabServer(display); - status = X11_XRRSetCrtcConfig(display, res, output_info->crtc, CurrentTime, - 0, 0, None, crtc->rotation, NULL, 0); - if (status != Success) { - goto ungrabServer; - } - - mm_width = mode->w * DisplayWidthMM(display, data->screen) / DisplayWidth(display, data->screen); - mm_height = mode->h * DisplayHeightMM(display, data->screen) / DisplayHeight(display, data->screen); - - /* !!! FIXME: this can get into a problem scenario when a window is - bigger than a physical monitor in a configuration where one screen - spans multiple physical monitors. A detailed reproduction case is - discussed at https://github.com/libsdl-org/SDL/issues/4561 ... - for now we cheat and just catch the X11 error and carry on, which - is likely to cause subtle issues but is better than outright - crashing */ - X11_XSync(display, False); - PreXRRSetScreenSizeErrorHandler = X11_XSetErrorHandler(SDL_XRRSetScreenSizeErrHandler); - X11_XRRSetScreenSize(display, RootWindow(display, data->screen), - mode->w, mode->h, mm_width, mm_height); - X11_XSync(display, False); - X11_XSetErrorHandler(PreXRRSetScreenSizeErrorHandler); - - status = X11_XRRSetCrtcConfig(display, res, output_info->crtc, CurrentTime, - crtc->x, crtc->y, modedata->xrandr_mode, crtc->rotation, - &data->xrandr_output, 1); - - ungrabServer: - X11_XUngrabServer(display); - freeInfo: - X11_XRRFreeCrtcInfo(crtc); - X11_XRRFreeOutputInfo(output_info); - X11_XRRFreeScreenResources(res); - - if (status != Success) { - return SDL_SetError("X11_XRRSetCrtcConfig failed"); - } - } -#else - (void)data; -#endif // SDL_VIDEO_DRIVER_X11_XRANDR - - return true; -} - -void X11_QuitModes(SDL_VideoDevice *_this) -{ -} - -bool X11_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display, SDL_Rect *rect) -{ - SDL_DisplayData *data = sdl_display->internal; - - rect->x = data->x; - rect->y = data->y; - rect->w = sdl_display->current_mode->w; - rect->h = sdl_display->current_mode->h; - return true; -} - -bool X11_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display, SDL_Rect *rect) -{ - SDL_VideoData *data = _this->internal; - Display *display = data->display; - Atom _NET_WORKAREA; - int real_format; - Atom real_type; - unsigned long items_read = 0, items_left = 0; - unsigned char *propdata = NULL; - bool result = false; - - if (!X11_GetDisplayBounds(_this, sdl_display, rect)) { - return false; - } - - _NET_WORKAREA = X11_XInternAtom(display, "_NET_WORKAREA", False); - int 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] }; - result = true; - if (!SDL_GetRectIntersection(rect, &usable, rect)) { - SDL_zerop(rect); - } - } - - if (propdata) { - X11_XFree(propdata); - } - - return result; -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.h deleted file mode 100644 index 35fd866..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11modes.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_ - -struct SDL_DisplayData -{ - int screen; - Visual *visual; - int depth; - int scanline_pad; - int x; - int y; - - Uint64 mode_switch_deadline_ns; - - bool use_xrandr; - -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR - RROutput xrandr_output; - char connector_name[16]; -#endif -}; - -struct SDL_DisplayModeData -{ -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR - RRMode xrandr_mode; -#else - int unused; // just so struct isn't empty. -#endif -}; - -extern bool X11_InitModes(SDL_VideoDevice *_this); -extern bool X11_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); -extern bool X11_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); -extern void X11_QuitModes(SDL_VideoDevice *_this); - -// Some utility functions for working with visuals -extern bool X11_GetVisualInfoFromVisual(Display *display, Visual *visual, XVisualInfo *vinfo); -extern SDL_PixelFormat X11_GetPixelFormatFromVisualInfo(Display *display, XVisualInfo *vinfo); -extern bool X11_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display, SDL_Rect *rect); -extern bool X11_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *sdl_display, SDL_Rect *rect); - -#ifdef SDL_VIDEO_DRIVER_X11_XRANDR -extern void X11_HandleXRandREvent(SDL_VideoDevice *_this, const XEvent *xevent); -#endif - -#endif // SDL_x11modes_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.c deleted file mode 100644 index 5c72dbf..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include -#include "SDL_x11video.h" -#include "SDL_x11mouse.h" -#include "SDL_x11xinput2.h" -#include "../SDL_video_c.h" -#include "../../events/SDL_mouse_c.h" - -struct SDL_CursorData -{ - Cursor cursor; -}; - -// FIXME: Find a better place to put this... -static Cursor x11_empty_cursor = None; -static bool x11_cursor_visible = true; - -static SDL_Cursor *sys_cursors[SDL_HITTEST_RESIZE_LEFT + 1]; - -static Display *GetDisplay(void) -{ - return SDL_GetVideoDevice()->internal->display; -} - -static Cursor X11_CreateEmptyCursor(void) -{ - if (x11_empty_cursor == None) { - Display *display = GetDisplay(); - char data[1]; - XColor color; - Pixmap pixmap; - - SDL_zeroa(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_CreateCursorAndData(Cursor x11_cursor) -{ - SDL_Cursor *cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor)); - if (cursor) { - SDL_CursorData *data = (SDL_CursorData *)SDL_calloc(1, sizeof(*data)); - if (!data) { - SDL_free(cursor); - return NULL; - } - data->cursor = x11_cursor; - cursor->internal = data; - } - return cursor; -} - -#ifdef 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 == SDL_PIXELFORMAT_ARGB8888); - SDL_assert(surface->pitch == surface->w * 4); - SDL_memcpy(image->pixels, surface->pixels, (size_t)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; - size_t width_bytes = ((surface->w + 7) & ~((size_t)7)) / 8; - - data_bits = SDL_calloc(1, surface->h * width_bytes); - if (!data_bits) { - return None; - } - - mask_bits = SDL_calloc(1, surface->h * width_bytes); - if (!mask_bits) { - SDL_free(data_bits); - return None; - } - - // Code below assumes ARGB pixel format - SDL_assert(surface->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); - SDL_free(data_bits); - SDL_free(mask_bits); - - return cursor; -} - -static SDL_Cursor *X11_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) -{ - Cursor x11_cursor = None; - -#ifdef 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); - } - return X11_CreateCursorAndData(x11_cursor); -} - -static unsigned int GetLegacySystemCursorShape(SDL_SystemCursor id) -{ - switch (id) { - // X Font Cursors reference: - // http://tronche.com/gui/x/xlib/appendix/b/ - case SDL_SYSTEM_CURSOR_DEFAULT: return XC_left_ptr; - case SDL_SYSTEM_CURSOR_TEXT: return XC_xterm; - case SDL_SYSTEM_CURSOR_WAIT: return XC_watch; - case SDL_SYSTEM_CURSOR_CROSSHAIR: return XC_tcross; - case SDL_SYSTEM_CURSOR_PROGRESS: return XC_watch; - case SDL_SYSTEM_CURSOR_NWSE_RESIZE: return XC_top_left_corner; - case SDL_SYSTEM_CURSOR_NESW_RESIZE: return XC_top_right_corner; - case SDL_SYSTEM_CURSOR_EW_RESIZE: return XC_sb_h_double_arrow; - case SDL_SYSTEM_CURSOR_NS_RESIZE: return XC_sb_v_double_arrow; - case SDL_SYSTEM_CURSOR_MOVE: return XC_fleur; - case SDL_SYSTEM_CURSOR_NOT_ALLOWED: return XC_pirate; - case SDL_SYSTEM_CURSOR_POINTER: return XC_hand2; - case SDL_SYSTEM_CURSOR_NW_RESIZE: return XC_top_left_corner; - case SDL_SYSTEM_CURSOR_N_RESIZE: return XC_top_side; - case SDL_SYSTEM_CURSOR_NE_RESIZE: return XC_top_right_corner; - case SDL_SYSTEM_CURSOR_E_RESIZE: return XC_right_side; - case SDL_SYSTEM_CURSOR_SE_RESIZE: return XC_bottom_right_corner; - case SDL_SYSTEM_CURSOR_S_RESIZE: return XC_bottom_side; - case SDL_SYSTEM_CURSOR_SW_RESIZE: return XC_bottom_left_corner; - case SDL_SYSTEM_CURSOR_W_RESIZE: return XC_left_side; - case SDL_SYSTEM_CURSOR_COUNT: break; // so the compiler might notice if an enum value is missing here. - } - - SDL_assert(0); - return 0; -} - -static SDL_Cursor *X11_CreateSystemCursor(SDL_SystemCursor id) -{ - SDL_Cursor *cursor = NULL; - Display *dpy = GetDisplay(); - Cursor x11_cursor = None; - -#ifdef SDL_VIDEO_DRIVER_X11_XCURSOR - if (SDL_X11_HAVE_XCURSOR) { - x11_cursor = X11_XcursorLibraryLoadCursor(dpy, SDL_GetCSSCursorName(id, NULL)); - } -#endif - - if (x11_cursor == None) { - x11_cursor = X11_XCreateFontCursor(dpy, GetLegacySystemCursorShape(id)); - } - - if (x11_cursor != None) { - cursor = X11_CreateCursorAndData(x11_cursor); - } - - return cursor; -} - -static SDL_Cursor *X11_CreateDefaultCursor(void) -{ - SDL_SystemCursor id = SDL_GetDefaultSystemCursor(); - return X11_CreateSystemCursor(id); -} - -static void X11_FreeCursor(SDL_Cursor *cursor) -{ - Cursor x11_cursor = cursor->internal->cursor; - - if (x11_cursor != None) { - X11_XFreeCursor(GetDisplay(), x11_cursor); - } - SDL_free(cursor->internal); - SDL_free(cursor); -} - -static bool X11_ShowCursor(SDL_Cursor *cursor) -{ - Cursor x11_cursor = 0; - - if (cursor) { - x11_cursor = cursor->internal->cursor; - } else { - x11_cursor = X11_CreateEmptyCursor(); - } - - // FIXME: Is there a better way than this? - { - SDL_VideoDevice *video = SDL_GetVideoDevice(); - Display *display = GetDisplay(); - SDL_Window *window; - - x11_cursor_visible = !!cursor; - - for (window = video->windows; window; window = window->next) { - SDL_WindowData *data = window->internal; - if (data) { - if (x11_cursor != None) { - X11_XDefineCursor(display, data->xwindow, x11_cursor); - } else { - X11_XUndefineCursor(display, data->xwindow); - } - } - } - X11_XFlush(display); - } - return true; -} - -static void X11_WarpMouseInternal(Window xwindow, float x, float y) -{ - SDL_VideoData *videodata = SDL_GetVideoDevice()->internal; - Display *display = videodata->display; - bool warp_hack = false; - - // XWayland will only warp the cursor if it is hidden, so this workaround is required. - if (videodata->is_xwayland && x11_cursor_visible) { - warp_hack = true; - } - - if (warp_hack) { - X11_ShowCursor(NULL); - } -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - int deviceid = 0; - if (X11_Xinput2IsInitialized()) { - /* It seems XIWarpPointer() doesn't work correctly on multi-head setups: - * https://developer.blender.org/rB165caafb99c6846e53d11c4e966990aaffc06cea - */ - if (ScreenCount(display) == 1) { - X11_XIGetClientPointer(display, None, &deviceid); - } - } - if (deviceid != 0) { - SDL_assert(SDL_X11_HAVE_XINPUT2); - X11_XIWarpPointer(display, deviceid, None, xwindow, 0.0, 0.0, 0, 0, x, y); - } else -#endif - { - X11_XWarpPointer(display, None, xwindow, 0, 0, 0, 0, (int)x, (int)y); - } - - if (warp_hack) { - X11_ShowCursor(SDL_GetCursor()); - } - X11_XSync(display, False); - videodata->global_mouse_changed = true; -} - -static bool X11_WarpMouse(SDL_Window *window, float x, float y) -{ - SDL_WindowData *data = window->internal; - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - // If we have no barrier, we need to warp - if (data->pointer_barrier_active == false) { - X11_WarpMouseInternal(data->xwindow, x, y); - } -#else - X11_WarpMouseInternal(data->xwindow, x, y); -#endif - return true; -} - -static bool X11_WarpMouseGlobal(float x, float y) -{ - X11_WarpMouseInternal(DefaultRootWindow(GetDisplay()), x, y); - return true; -} - -static bool X11_SetRelativeMouseMode(bool enabled) -{ - if (!X11_Xinput2IsInitialized()) { - return SDL_Unsupported(); - } - return true; -} - -static bool X11_CaptureMouse(SDL_Window *window) -{ - Display *display = GetDisplay(); - SDL_Window *mouse_focus = SDL_GetMouseFocus(); - - if (window) { - SDL_WindowData *data = window->internal; - - /* If XInput2 is handling the pointer input, non-confinement grabs will always fail with 'AlreadyGrabbed', - * since the pointer is being grabbed by XInput2. - */ - if (!data->xinput2_mouse_enabled || data->mouse_grabbed) { - const unsigned int mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask; - Window confined = (data->mouse_grabbed ? data->xwindow : None); - const int rc = X11_XGrabPointer(display, data->xwindow, False, - mask, GrabModeAsync, GrabModeAsync, - confined, None, CurrentTime); - if (rc != GrabSuccess) { - return SDL_SetError("X server refused mouse capture"); - } - - if (data->mouse_grabbed) { - // XGrabPointer can warp the cursor when confining, so update the coordinates. - data->videodata->global_mouse_changed = true; - } - } - } else if (mouse_focus) { - SDL_UpdateWindowGrab(mouse_focus); - } else { - X11_XUngrabPointer(display, CurrentTime); - } - - X11_XSync(display, False); - - return true; -} - -static SDL_MouseButtonFlags X11_GetGlobalMouseState(float *x, float *y) -{ - SDL_VideoData *videodata = SDL_GetVideoDevice()->internal; - SDL_DisplayID *displays; - Display *display = GetDisplay(); - int i; - - // !!! FIXME: should we XSync() here first? - - if (!X11_Xinput2IsInitialized()) { - videodata->global_mouse_changed = true; - } - - // 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) { - displays = SDL_GetDisplays(NULL); - if (displays) { - for (i = 0; displays[i]; ++i) { - SDL_DisplayData *data = SDL_GetDisplayDriverData(displays[i]); - if (data) { - 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; - SDL_MouseButtonFlags buttons = 0; - buttons |= (mask & Button1Mask) ? SDL_BUTTON_LMASK : 0; - buttons |= (mask & Button2Mask) ? SDL_BUTTON_MMASK : 0; - buttons |= (mask & Button3Mask) ? SDL_BUTTON_RMASK : 0; - // Use the SDL state for the extended buttons - it's better than nothing - buttons |= (SDL_GetMouseState(NULL, NULL) & (SDL_BUTTON_X1MASK | SDL_BUTTON_X2MASK)); - /* 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 = false; - break; - } - } - } - SDL_free(displays); - } - } - - SDL_assert(!videodata->global_mouse_changed); // The pointer wasn't on any X11 screen?! - - *x = (float)videodata->global_mouse_position.x; - *y = (float)videodata->global_mouse_position.y; - return videodata->global_mouse_buttons; -} - -void X11_InitMouse(SDL_VideoDevice *_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_HitTestResult r = SDL_HITTEST_NORMAL; - while (r <= SDL_HITTEST_RESIZE_LEFT) { - switch (r) { - case SDL_HITTEST_NORMAL: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_DEFAULT); break; - case SDL_HITTEST_DRAGGABLE: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_DEFAULT); break; - case SDL_HITTEST_RESIZE_TOPLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_NW_RESIZE); break; - case SDL_HITTEST_RESIZE_TOP: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_N_RESIZE); break; - case SDL_HITTEST_RESIZE_TOPRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_NE_RESIZE); break; - case SDL_HITTEST_RESIZE_RIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_E_RESIZE); break; - case SDL_HITTEST_RESIZE_BOTTOMRIGHT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SE_RESIZE); break; - case SDL_HITTEST_RESIZE_BOTTOM: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_S_RESIZE); break; - case SDL_HITTEST_RESIZE_BOTTOMLEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_SW_RESIZE); break; - case SDL_HITTEST_RESIZE_LEFT: sys_cursors[r] = X11_CreateSystemCursor(SDL_SYSTEM_CURSOR_W_RESIZE); break; - } - r++; - } - - SDL_SetDefaultCursor(X11_CreateDefaultCursor()); -} - -void X11_QuitMouse(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - SDL_XInput2DeviceInfo *i; - SDL_XInput2DeviceInfo *next; - int j; - - for (j = 0; j < SDL_arraysize(sys_cursors); j++) { - X11_FreeCursor(sys_cursors[j]); - sys_cursors[j] = NULL; - } - - for (i = data->mouse_device_info; i; i = next) { - next = i->next; - SDL_free(i); - } - data->mouse_device_info = NULL; - - X11_DestroyEmptyCursor(); -} - -void X11_SetHitTestCursor(SDL_HitTestResult rc) -{ - if (rc == SDL_HITTEST_NORMAL || rc == SDL_HITTEST_DRAGGABLE) { - SDL_SetCursor(NULL); - } else { - X11_ShowCursor(sys_cursors[rc]); - } -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.h deleted file mode 100644 index 2a2973c..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11mouse.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_ - -typedef struct SDL_XInput2DeviceInfo -{ - int device_id; - bool relative[2]; - double minval[2]; - double maxval[2]; - double prev_coords[2]; - struct SDL_XInput2DeviceInfo *next; -} SDL_XInput2DeviceInfo; - -extern void X11_InitMouse(SDL_VideoDevice *_this); -extern void X11_QuitMouse(SDL_VideoDevice *_this); -extern void X11_SetHitTestCursor(SDL_HitTestResult rc); - -#endif // SDL_x11mouse_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.c deleted file mode 100644 index d46409f..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.c +++ /dev/null @@ -1,1116 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - Copyright (C) 2021 NVIDIA Corporation - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "SDL_x11video.h" -#include "SDL_x11xsync.h" - -// GLX implementation of SDL OpenGL support - -#ifdef SDL_VIDEO_OPENGL_GLX -#include "SDL_x11opengles.h" - -#if defined(SDL_PLATFORM_IRIX) || defined(SDL_PLATFORM_NETBSD) || defined(SDL_PLATFORM_OPENBSD) -/* - * IRIX doesn't have a GL library versioning system. - * NetBSD and OpenBSD have different GL library versions depending on how - * the library was installed. - */ -#define DEFAULT_OPENGL "libGL.so" -#elif defined(SDL_PLATFORM_MACOS) -#define DEFAULT_OPENGL "/opt/X11/lib/libGL.1.dylib" -#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_fbconfig_float -#define GLX_ARB_fbconfig_float -#ifndef GLX_RGBA_FLOAT_TYPE_ARB -#define GLX_RGBA_FLOAT_TYPE_ARB 0x20B9 -#endif -#ifndef GLX_RGBA_FLOAT_BIT_ARB -#define GLX_RGBA_FLOAT_BIT_ARB 0x00000004 -#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(HAVE_DLOPEN) -#include -#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(SDL_VideoDevice *_this); - -bool X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path) -{ - Display *display; - SDL_SharedObject *handle; - - if (_this->gl_data) { - return SDL_SetError("OpenGL context already created"); - } - - // Load the OpenGL library - if (path == NULL) { - path = SDL_GetHint(SDL_HINT_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(HAVE_DLOPEN) - SDL_SetError("Failed loading %s: %s", path, dlerror()); -#endif - return false; - } - 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 false; - } - - // 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 = - (__GLXextFuncPtr (*)(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 = _this->internal->display; - if (!_this->gl_data->glXQueryExtension(display, &_this->gl_data->errorBase, &_this->gl_data->eventBase)) { - return SDL_SetError("GLX is not supported"); - } - - _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNTESTED; - - // 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) || - SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, false)) && - X11_GL_UseEGL(_this)) { -#ifdef SDL_VIDEO_OPENGL_EGL - X11_GL_UnloadLibrary(_this); - _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_DestroyContext = X11_GLES_DestroyContext; - return X11_GLES_LoadLibrary(_this, NULL); -#else - return SDL_SetError("SDL not configured with EGL support"); -#endif - } - - return true; -} - -SDL_FunctionPointer X11_GL_GetProcAddress(SDL_VideoDevice *_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(SDL_VideoDevice *_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 bool HasExtension(const char *extension, const char *extensions) -{ - const char *start; - const char *where, *terminator; - - if (!extensions) { - return false; - } - - // Extension names should not have spaces. - where = SDL_strchr(extension, ' '); - if (where || *extension == '\0') { - return 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 true; - } - } - - start = terminator; - } - return false; -} - -static void X11_GL_InitExtensions(SDL_VideoDevice *_this) -{ - Display *display = _this->internal->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, false); - 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 = 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 = 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"); - _this->gl_data->glXGetVisualFromFBConfig = - (XVisualInfo * (*)(Display *, GLXFBConfig)) - X11_GL_GetProcAddress(_this, "glXGetVisualFromFBConfig"); - } - - // Check for GLX_EXT_visual_rating - if (HasExtension("GLX_EXT_visual_rating", extensions)) { - _this->gl_data->HAS_GLX_EXT_visual_rating = true; - } - - // Check for GLX_EXT_visual_info - if (HasExtension("GLX_EXT_visual_info", extensions)) { - _this->gl_data->HAS_GLX_EXT_visual_info = 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 = 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 = 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 = 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(SDL_VideoDevice *_this, Display *display, int screen, int *attribs, int size, Bool for_FBConfig, int **_pvistypeattr, bool transparent) -{ - 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; - if (_this->gl_config.floatbuffers) { - attribs[i++] = GLX_RGBA_FLOAT_BIT_ARB; - } else { - 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.floatbuffers) { - attribs[i++] = GLX_RENDER_TYPE; - attribs[i++] = GLX_RGBA_FLOAT_TYPE_ARB; - } - - 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; - } - - // Un-wanted when we request a transparent buffer - if (!transparent) { - /* 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; -} - -//get the first transparent Visual -static XVisualInfo* X11_GL_GetTransparentVisualInfo(Display *display, int screen) -{ - XVisualInfo* visualinfo = NULL; - XVisualInfo vi_in; - int out_count = 0; - - vi_in.screen = screen; - visualinfo = X11_XGetVisualInfo(display, VisualScreenMask, &vi_in, &out_count); - if (visualinfo != NULL) { - int i = 0; - for (i = 0; i < out_count; i++) { - XVisualInfo* v = &visualinfo[i]; - Uint32 format = X11_GetPixelFormatFromVisualInfo(display, v); - if (SDL_ISPIXELFORMAT_ALPHA(format)) { - vi_in.screen = screen; - vi_in.visualid = v->visualid; - X11_XFree(visualinfo); - visualinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &vi_in, &out_count); - break; - } - } - } - return visualinfo; -} - -XVisualInfo *X11_GL_GetVisual(SDL_VideoDevice *_this, Display *display, int screen, bool transparent) -{ - // 64 seems nice. - int attribs[64]; - XVisualInfo *vinfo = NULL; - int *pvistypeattr = NULL; - - if (!_this->gl_data) { - // The OpenGL library wasn't loaded, SDL_GetError() should have info - return NULL; - } - - if (_this->gl_data->glXChooseFBConfig && - _this->gl_data->glXGetVisualFromFBConfig) { - GLXFBConfig *framebuffer_config = NULL; - int fbcount = 0; - - X11_GL_GetAttributes(_this, display, screen, attribs, 64, true, &pvistypeattr, transparent); - framebuffer_config = _this->gl_data->glXChooseFBConfig(display, screen, attribs, &fbcount); - if (!framebuffer_config && (pvistypeattr != NULL)) { - *pvistypeattr = None; - framebuffer_config = _this->gl_data->glXChooseFBConfig(display, screen, attribs, &fbcount); - } - - if (transparent) { - // Return the first transparent Visual - int i; - for (i = 0; i < fbcount; i++) { - Uint32 format; - vinfo = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[i]); - format = X11_GetPixelFormatFromVisualInfo(display, vinfo); - if (SDL_ISPIXELFORMAT_ALPHA(format)) { // found! - X11_XFree(framebuffer_config); - framebuffer_config = NULL; - break; - } - X11_XFree(vinfo); - vinfo = NULL; - } - } - - if (framebuffer_config) { - vinfo = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[0]); - } - - X11_XFree(framebuffer_config); - } - - if (!vinfo) { - X11_GL_GetAttributes(_this, display, screen, attribs, 64, false, &pvistypeattr, transparent); - vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs); - - if (!vinfo && (pvistypeattr != NULL)) { - *pvistypeattr = None; - vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs); - } - } - - if (transparent && vinfo) { - Uint32 format = X11_GetPixelFormatFromVisualInfo(display, vinfo); - if (!SDL_ISPIXELFORMAT_ALPHA(format)) { - // not transparent! - XVisualInfo* visualinfo = X11_GL_GetTransparentVisualInfo(display, screen); - if (visualinfo != NULL) { - X11_XFree(vinfo); - vinfo = visualinfo; - } - } - } - - 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; -} - -bool X11_GL_UseEGL(SDL_VideoDevice *_this) -{ - SDL_assert(_this->gl_data != NULL); - if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, false)) { - // use of EGL has been requested, even for desktop GL - return true; - } - - SDL_assert(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES); - return (SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, 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(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - int screen = SDL_GetDisplayDriverDataForWindow(window)->screen; - XWindowAttributes xattr; - XVisualInfo v, *vinfo; - int n; - SDL_GLContext context = NULL; - GLXContext share_context; - const int transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? true : false; - - 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 && !transparent) { - // Create legacy context - context = - (SDL_GLContext)_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 and not the default setting - if ((_this->gl_data->HAS_GLX_ARB_context_flush_control) && (_this->gl_config.release_behavior == 0)) { - 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 and not the default setting - if ((_this->gl_data->HAS_GLX_ARB_create_context_robustness) && (_this->gl_config.reset_notification != 0)) { - 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 and not the default setting - if ((_this->gl_data->HAS_GLX_ARB_create_context_no_error) && (_this->gl_config.no_error != 0)) { - 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, true, &pvistypeattr, transparent); - - 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 (transparent && (framebuffer_config != NULL)) { - int i; - for (i = 0; i < fbcount; i++) { - XVisualInfo* vinfo_temp = _this->gl_data->glXGetVisualFromFBConfig(display, framebuffer_config[i]); - if ( vinfo_temp != NULL) { - Uint32 format = X11_GetPixelFormatFromVisualInfo(display, vinfo_temp); - if (SDL_ISPIXELFORMAT_ALPHA(format)) { - // found! - context = (SDL_GLContext)_this->gl_data->glXCreateContextAttribsARB(display, - framebuffer_config[i], - share_context, True, attribs); - X11_XFree(framebuffer_config); - framebuffer_config = NULL; - X11_XFree(vinfo_temp); - break; - } - X11_XFree(vinfo_temp); - } - } - } - if (framebuffer_config) { - context = (SDL_GLContext)_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)) { - X11_GL_DestroyContext(_this, context); - return NULL; - } - - return context; -} - -bool X11_GL_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context) -{ - Display *display = _this->internal->display; - Window drawable = - (context ? window->internal->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 false; // 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 true; -} - -/* - 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; -bool X11_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval) -{ - bool result = false; - - if ((interval < 0) && (!_this->gl_data->HAS_GLX_EXT_swap_control_tear)) { - return SDL_SetError("Negative swap interval unsupported in this GL"); - } else if (_this->gl_data->glXSwapIntervalEXT) { - Display *display = _this->internal->display; - const SDL_WindowData *windowdata = SDL_GL_GetCurrentWindow()->internal; - - 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 = 0; - X11_GL_GetSwapInterval(_this, ¤tInterval); - _this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval); - _this->gl_data->glXSwapIntervalEXT(display, drawable, interval); - result = true; - swapinterval = interval; - } else if (_this->gl_data->glXSwapIntervalMESA) { - const int rc = _this->gl_data->glXSwapIntervalMESA(interval); - if (rc == 0) { - swapinterval = interval; - result = true; - } else { - result = SDL_SetError("glXSwapIntervalMESA failed"); - } - } else if (_this->gl_data->glXSwapIntervalSGI) { - const int rc = _this->gl_data->glXSwapIntervalSGI(interval); - if (rc == 0) { - swapinterval = interval; - result = true; - } else { - result = SDL_SetError("glXSwapIntervalSGI failed"); - } - } else { - return SDL_Unsupported(); - } - return result; -} - -static SDL_GLSwapIntervalTearBehavior CheckSwapIntervalTearBehavior(SDL_VideoDevice *_this, Window drawable, unsigned int current_val, unsigned int current_allow_late) -{ - /* Mesa and Nvidia interpret GLX_EXT_swap_control_tear differently, as of this writing, so - figure out which behavior we have. - Technical details: https://github.com/libsdl-org/SDL/issues/8004#issuecomment-1819603282 */ - if (_this->gl_data->swap_interval_tear_behavior == SDL_SWAPINTERVALTEAR_UNTESTED) { - if (!_this->gl_data->HAS_GLX_EXT_swap_control_tear) { - _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNKNOWN; - } else { - Display *display = _this->internal->display; - unsigned int allow_late_swap_tearing = 22; - int original_val = (int) current_val; - - /* - * 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. - */ - _this->gl_data->glXSwapIntervalEXT(display, drawable, current_val); - - // set it to no swap interval and see how it affects GLX_LATE_SWAPS_TEAR_EXT... - _this->gl_data->glXSwapIntervalEXT(display, drawable, 0); - _this->gl_data->glXQueryDrawable(display, drawable, GLX_LATE_SWAPS_TEAR_EXT, &allow_late_swap_tearing); - - if (allow_late_swap_tearing == 0) { // GLX_LATE_SWAPS_TEAR_EXT says whether late swapping is currently in use - _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_NVIDIA; - if (current_allow_late) { - original_val = -original_val; - } - } else if (allow_late_swap_tearing == 1) { // GLX_LATE_SWAPS_TEAR_EXT says whether the Drawable can use late swapping at all - _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_MESA; - } else { // unexpected outcome! - _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNKNOWN; - } - - // set us back to what it was originally... - _this->gl_data->glXSwapIntervalEXT(display, drawable, original_val); - } - } - - return _this->gl_data->swap_interval_tear_behavior; -} - - -bool X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval) -{ - if (_this->gl_data->glXSwapIntervalEXT) { - Display *display = _this->internal->display; - const SDL_WindowData *windowdata = SDL_GL_GetCurrentWindow()->internal; - Window drawable = windowdata->xwindow; - unsigned int allow_late_swap_tearing = 0; - unsigned int val = 0; - - if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) { - allow_late_swap_tearing = 22; // set this to nonsense. - _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, &val); - - *interval = (int)val; - - switch (CheckSwapIntervalTearBehavior(_this, drawable, val, allow_late_swap_tearing)) { - case SDL_SWAPINTERVALTEAR_MESA: - *interval = (int)val; // unsigned int cast to signed that generates negative value if necessary. - break; - - case SDL_SWAPINTERVALTEAR_NVIDIA: - default: - if ((allow_late_swap_tearing) && (val > 0)) { - *interval = -((int)val); - } - break; - } - - return true; - } else if (_this->gl_data->glXGetSwapIntervalMESA) { - int val = _this->gl_data->glXGetSwapIntervalMESA(); - if (val == GLX_BAD_CONTEXT) { - return SDL_SetError("GLX_BAD_CONTEXT"); - } - *interval = val; - return true; - } else { - *interval = swapinterval; - return true; - } -} - -bool X11_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - - _this->gl_data->glXSwapBuffers(display, data->xwindow); - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - X11_HandlePresent(data->window); -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - - return true; -} - -bool X11_GL_DestroyContext(SDL_VideoDevice *_this, SDL_GLContext context) -{ - Display *display = _this->internal->display; - GLXContext glx_context = (GLXContext)context; - - if (!_this->gl_data) { - return true; - } - _this->gl_data->glXDestroyContext(display, glx_context); - X11_XSync(display, False); - return true; -} - -#endif // SDL_VIDEO_OPENGL_GLX - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.h deleted file mode 100644 index 24db485..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengl.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_ - -#ifdef SDL_VIDEO_OPENGL_GLX -#include -#include - -typedef void (*__GLXextFuncPtr)(void); - -typedef enum SDL_GLSwapIntervalTearBehavior -{ - SDL_SWAPINTERVALTEAR_UNTESTED, - SDL_SWAPINTERVALTEAR_UNKNOWN, - SDL_SWAPINTERVALTEAR_MESA, - SDL_SWAPINTERVALTEAR_NVIDIA -} SDL_GLSwapIntervalTearBehavior; - -struct SDL_GLDriverData -{ - int errorBase, eventBase; - - bool HAS_GLX_EXT_visual_rating; - bool HAS_GLX_EXT_visual_info; - bool HAS_GLX_EXT_swap_control_tear; - bool HAS_GLX_ARB_context_flush_control; - bool HAS_GLX_ARB_create_context_robustness; - 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; - - SDL_GLSwapIntervalTearBehavior swap_interval_tear_behavior; - - Bool (*glXQueryExtension)(Display *, int *, int *); - __GLXextFuncPtr (*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 *); - XVisualInfo *(*glXGetVisualFromFBConfig)(Display *, GLXFBConfig); - 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 bool X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path); -extern SDL_FunctionPointer X11_GL_GetProcAddress(SDL_VideoDevice *_this, const char *proc); -extern void X11_GL_UnloadLibrary(SDL_VideoDevice *_this); -extern bool X11_GL_UseEGL(SDL_VideoDevice *_this); -extern XVisualInfo *X11_GL_GetVisual(SDL_VideoDevice *_this, Display *display, int screen, bool transparent); -extern SDL_GLContext X11_GL_CreateContext(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_GL_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, - SDL_GLContext context); -extern bool X11_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval); -extern bool X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval); -extern bool X11_GL_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_GL_DestroyContext(SDL_VideoDevice *_this, SDL_GLContext context); - -#endif // SDL_VIDEO_OPENGL_GLX - -#endif // SDL_x11opengl_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.c deleted file mode 100644 index 9c1910f..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 defined(SDL_VIDEO_DRIVER_X11) && defined(SDL_VIDEO_OPENGL_EGL) - -#include "SDL_x11video.h" -#include "SDL_x11opengles.h" -#include "SDL_x11opengl.h" -#include "SDL_x11xsync.h" - -// EGL implementation of SDL OpenGL support - -bool X11_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path) -{ - SDL_VideoData *data = _this->internal; - - // 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) && - !SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, false)) { -#ifdef 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_DestroyContext = X11_GL_DestroyContext; - 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, _this->gl_config.egl_platform); -} - -XVisualInfo *X11_GLES_GetVisual(SDL_VideoDevice *_this, Display *display, int screen, bool transparent) -{ - - XVisualInfo *egl_visualinfo = NULL; - EGLint visual_id = 0; - XVisualInfo vi_in; - int out_count = 0; - - 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 = 0; - } - if (visual_id != 0) { - vi_in.screen = screen; - vi_in.visualid = visual_id; - egl_visualinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &vi_in, &out_count); - if (transparent && egl_visualinfo) { - Uint32 format = X11_GetPixelFormatFromVisualInfo(display, egl_visualinfo); - if (!SDL_ISPIXELFORMAT_ALPHA(format)) { - // not transparent! - X11_XFree(egl_visualinfo); - egl_visualinfo = NULL; - } - } - } - - if(!egl_visualinfo) { - // Use the default visual when all else fails - vi_in.screen = screen; - egl_visualinfo = X11_XGetVisualInfo(display, - VisualScreenMask, - &vi_in, &out_count); - - // Return the first transparent Visual - if (transparent) { - int i; - for (i = 0; i < out_count; i++) { - XVisualInfo *v = &egl_visualinfo[i]; - Uint32 format = X11_GetPixelFormatFromVisualInfo(display, v); - if (SDL_ISPIXELFORMAT_ALPHA(format)) { // found! - // re-request it to have a copy that can be X11_XFree'ed later - vi_in.screen = screen; - vi_in.visualid = v->visualid; - X11_XFree(egl_visualinfo); - egl_visualinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &vi_in, &out_count); - return egl_visualinfo; - } - } - } - } - return egl_visualinfo; -} - -SDL_GLContext X11_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_GLContext context; - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - - X11_XSync(display, False); - context = SDL_EGL_CreateContext(_this, data->egl_surface); - X11_XSync(display, False); - - return context; -} - -SDL_EGLSurface X11_GLES_GetEGLSurface(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - return data->egl_surface; -} - -bool X11_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - const bool ret = SDL_EGL_SwapBuffers(_this, window->internal->egl_surface); \ - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - X11_HandlePresent(window); -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - - return ret; -} - -SDL_EGL_MakeCurrent_impl(X11) - -#endif // SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_OPENGL_EGL - diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.h deleted file mode 100644 index f8e8d3b..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11opengles.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_ - -#ifdef 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_GetProcAddressInternal -#define X11_GLES_UnloadLibrary SDL_EGL_UnloadLibrary -#define X11_GLES_SetSwapInterval SDL_EGL_SetSwapInterval -#define X11_GLES_GetSwapInterval SDL_EGL_GetSwapInterval -#define X11_GLES_DestroyContext SDL_EGL_DestroyContext - -extern bool X11_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path); -extern XVisualInfo *X11_GLES_GetVisual(SDL_VideoDevice *_this, Display *display, int screen, bool transparent); -extern SDL_GLContext X11_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context); -extern SDL_EGLSurface X11_GLES_GetEGLSurface(SDL_VideoDevice *_this, SDL_Window *window); - -#endif // SDL_VIDEO_OPENGL_EGL - -#endif // SDL_x11opengles_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.c deleted file mode 100644 index f16da51..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#include "../../events/SDL_pen_c.h" -#include "../SDL_sysvideo.h" -#include "SDL_x11pen.h" -#include "SDL_x11video.h" -#include "SDL_x11xinput2.h" - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - -// Does this device have a valuator for pressure sensitivity? -static bool X11_XInput2DeviceIsPen(SDL_VideoDevice *_this, const XIDeviceInfo *dev) -{ - const SDL_VideoData *data = _this->internal; - for (int i = 0; i < dev->num_classes; i++) { - const XIAnyClassInfo *classinfo = dev->classes[i]; - if (classinfo->type == XIValuatorClass) { - const XIValuatorClassInfo *val_classinfo = (const XIValuatorClassInfo *)classinfo; - if (val_classinfo->label == data->atoms.pen_atom_abs_pressure) { - return true; - } - } - } - - return false; -} - -// Heuristically determines if device is an eraser -static bool X11_XInput2PenIsEraser(SDL_VideoDevice *_this, int deviceid, char *devicename) -{ - #define PEN_ERASER_NAME_TAG "eraser" // String constant to identify erasers - SDL_VideoData *data = _this->internal; - - if (data->atoms.pen_atom_wacom_tool_type != None) { - Atom type_return; - int format_return; - unsigned long num_items_return; - unsigned long bytes_after_return; - unsigned char *tooltype_name_info = NULL; - - // Try Wacom-specific method - if (Success == X11_XIGetProperty(data->display, deviceid, - data->atoms.pen_atom_wacom_tool_type, - 0, 32, False, - AnyPropertyType, &type_return, &format_return, - &num_items_return, &bytes_after_return, - &tooltype_name_info) && - tooltype_name_info != NULL && num_items_return > 0) { - - bool result = false; - char *tooltype_name = NULL; - - if (type_return == XA_ATOM) { - // Atom instead of string? Un-intern - Atom atom = *((Atom *)tooltype_name_info); - if (atom != None) { - tooltype_name = X11_XGetAtomName(data->display, atom); - } - } else if (type_return == XA_STRING && format_return == 8) { - tooltype_name = (char *)tooltype_name_info; - } - - if (tooltype_name) { - if (SDL_strcasecmp(tooltype_name, PEN_ERASER_NAME_TAG) == 0) { - result = true; - } - if (tooltype_name != (char *)tooltype_name_info) { - X11_XFree(tooltype_name_info); - } - X11_XFree(tooltype_name); - - return result; - } - } - } - - // Non-Wacom device? - - /* We assume that a device is an eraser if its name contains the string "eraser". - * Unfortunately there doesn't seem to be a clean way to distinguish these cases (as of 2022-03). */ - return (SDL_strcasestr(devicename, PEN_ERASER_NAME_TAG)) ? true : false; -} - -// Read out an integer property and store into a preallocated Sint32 array, extending 8 and 16 bit values suitably. -// Returns number of Sint32s written (<= max_words), or 0 on error. -static size_t X11_XInput2PenGetIntProperty(SDL_VideoDevice *_this, int deviceid, Atom property, Sint32 *dest, size_t max_words) -{ - const SDL_VideoData *data = _this->internal; - Atom type_return; - int format_return; - unsigned long num_items_return; - unsigned long bytes_after_return; - unsigned char *output; - - if (property == None) { - return 0; - } - - if (Success != X11_XIGetProperty(data->display, deviceid, - property, - 0, max_words, False, - XA_INTEGER, &type_return, &format_return, - &num_items_return, &bytes_after_return, - &output) || - num_items_return == 0 || output == NULL) { - return 0; - } - - if (type_return == XA_INTEGER) { - int k; - const int to_copy = SDL_min(max_words, num_items_return); - - if (format_return == 8) { - Sint8 *numdata = (Sint8 *)output; - for (k = 0; k < to_copy; ++k) { - dest[k] = numdata[k]; - } - } else if (format_return == 16) { - Sint16 *numdata = (Sint16 *)output; - for (k = 0; k < to_copy; ++k) { - dest[k] = numdata[k]; - } - } else { - SDL_memcpy(dest, output, sizeof(Sint32) * to_copy); - } - X11_XFree(output); - return to_copy; - } - - return 0; // type mismatch -} - -// Identify Wacom devices (if true is returned) and extract their device type and serial IDs -static bool X11_XInput2PenWacomDeviceID(SDL_VideoDevice *_this, int deviceid, Uint32 *wacom_devicetype_id, Uint32 *wacom_serial) -{ - SDL_VideoData *data = _this->internal; - Sint32 serial_id_buf[3]; - int result; - - if ((result = X11_XInput2PenGetIntProperty(_this, deviceid, data->atoms.pen_atom_wacom_serial_ids, serial_id_buf, 3)) == 3) { - *wacom_devicetype_id = serial_id_buf[2]; - *wacom_serial = serial_id_buf[1]; - return true; - } - - *wacom_devicetype_id = *wacom_serial = 0; - return false; -} - - -typedef struct FindPenByDeviceIDData -{ - int x11_deviceid; - void *handle; -} FindPenByDeviceIDData; - -static bool FindPenByDeviceID(void *handle, void *userdata) -{ - const X11_PenHandle *x11_handle = (const X11_PenHandle *) handle; - FindPenByDeviceIDData *data = (FindPenByDeviceIDData *) userdata; - if (x11_handle->x11_deviceid != data->x11_deviceid) { - return false; - } - data->handle = handle; - return true; -} - -X11_PenHandle *X11_FindPenByDeviceID(int deviceid) -{ - FindPenByDeviceIDData data; - data.x11_deviceid = deviceid; - data.handle = NULL; - SDL_FindPenByCallback(FindPenByDeviceID, &data); - return (X11_PenHandle *) data.handle; -} - -static X11_PenHandle *X11_MaybeAddPen(SDL_VideoDevice *_this, const XIDeviceInfo *dev) -{ - SDL_VideoData *data = _this->internal; - SDL_PenCapabilityFlags capabilities = 0; - X11_PenHandle *handle = NULL; - - if ((dev->use != XISlavePointer && (dev->use != XIFloatingSlave)) || dev->enabled == 0 || !X11_XInput2DeviceIsPen(_this, dev)) { - return NULL; // Only track physical devices that are enabled and look like pens - } else if ((handle = X11_FindPenByDeviceID(dev->deviceid)) != 0) { - return handle; // already have this pen, skip it. - } else if ((handle = SDL_calloc(1, sizeof (*handle))) == NULL) { - return NULL; // oh well. - } - - for (int i = 0; i < SDL_arraysize(handle->valuator_for_axis); i++) { - handle->valuator_for_axis[i] = SDL_X11_PEN_AXIS_VALUATOR_MISSING; // until proven otherwise - } - - int total_buttons = 0; - for (int i = 0; i < dev->num_classes; i++) { - const XIAnyClassInfo *classinfo = dev->classes[i]; - if (classinfo->type == XIButtonClass) { - const XIButtonClassInfo *button_classinfo = (const XIButtonClassInfo *)classinfo; - total_buttons += button_classinfo->num_buttons; - } else if (classinfo->type == XIValuatorClass) { - const XIValuatorClassInfo *val_classinfo = (const XIValuatorClassInfo *)classinfo; - const Sint8 valuator_nr = val_classinfo->number; - const Atom vname = val_classinfo->label; - const float min = (float)val_classinfo->min; - const float max = (float)val_classinfo->max; - bool use_this_axis = true; - SDL_PenAxis axis = SDL_PEN_AXIS_COUNT; - - // afaict, SDL_PEN_AXIS_DISTANCE is never reported by XInput2 (Wayland can offer it, though) - if (vname == data->atoms.pen_atom_abs_pressure) { - axis = SDL_PEN_AXIS_PRESSURE; - } else if (vname == data->atoms.pen_atom_abs_tilt_x) { - axis = SDL_PEN_AXIS_XTILT; - } else if (vname == data->atoms.pen_atom_abs_tilt_y) { - axis = SDL_PEN_AXIS_YTILT; - } else { - use_this_axis = false; - } - - // !!! FIXME: there are wacom-specific hacks for getting SDL_PEN_AXIS_(ROTATION|SLIDER) on some devices, but for simplicity, we're skipping all that for now. - - if (use_this_axis) { - capabilities |= SDL_GetPenCapabilityFromAxis(axis); - handle->valuator_for_axis[axis] = valuator_nr; - handle->axis_min[axis] = min; - handle->axis_max[axis] = max; - } - } - } - - // We have a pen if and only if the device measures pressure. - // We checked this in X11_XInput2DeviceIsPen, so just assert it here. - SDL_assert(capabilities & SDL_PEN_CAPABILITY_PRESSURE); - - const bool is_eraser = X11_XInput2PenIsEraser(_this, dev->deviceid, dev->name); - Uint32 wacom_devicetype_id = 0; - Uint32 wacom_serial = 0; - X11_XInput2PenWacomDeviceID(_this, dev->deviceid, &wacom_devicetype_id, &wacom_serial); - - SDL_PenInfo peninfo; - SDL_zero(peninfo); - peninfo.capabilities = capabilities; - peninfo.max_tilt = -1; - peninfo.wacom_id = wacom_devicetype_id; - peninfo.num_buttons = total_buttons; - peninfo.subtype = is_eraser ? SDL_PEN_TYPE_ERASER : SDL_PEN_TYPE_PEN; - if (is_eraser) { - peninfo.capabilities |= SDL_PEN_CAPABILITY_ERASER; - } - - handle->is_eraser = is_eraser; - handle->x11_deviceid = dev->deviceid; - - handle->pen = SDL_AddPenDevice(0, dev->name, &peninfo, handle); - if (!handle->pen) { - SDL_free(handle); - return NULL; - } - - return handle; -} - -X11_PenHandle *X11_MaybeAddPenByDeviceID(SDL_VideoDevice *_this, int deviceid) -{ - SDL_VideoData *data = _this->internal; - int num_device_info = 0; - XIDeviceInfo *device_info = X11_XIQueryDevice(data->display, deviceid, &num_device_info); - if (device_info) { - SDL_assert(num_device_info == 1); - X11_PenHandle *handle = X11_MaybeAddPen(_this, device_info); - X11_XIFreeDeviceInfo(device_info); - return handle; - } - return NULL; -} - -void X11_RemovePenByDeviceID(int deviceid) -{ - X11_PenHandle *handle = X11_FindPenByDeviceID(deviceid); - if (handle) { - SDL_RemovePenDevice(0, handle->pen); - SDL_free(handle); - } -} - -void X11_InitPen(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - - #define LOOKUP_PEN_ATOM(X) X11_XInternAtom(data->display, X, False) - data->atoms.pen_atom_device_product_id = LOOKUP_PEN_ATOM("Device Product ID"); - data->atoms.pen_atom_wacom_serial_ids = LOOKUP_PEN_ATOM("Wacom Serial IDs"); - data->atoms.pen_atom_wacom_tool_type = LOOKUP_PEN_ATOM("Wacom Tool Type"); - data->atoms.pen_atom_abs_pressure = LOOKUP_PEN_ATOM("Abs Pressure"); - data->atoms.pen_atom_abs_tilt_x = LOOKUP_PEN_ATOM("Abs Tilt X"); - data->atoms.pen_atom_abs_tilt_y = LOOKUP_PEN_ATOM("Abs Tilt Y"); - #undef LOOKUP_PEN_ATOM - - // Do an initial check on devices. After this, we'll add/remove individual pens when XI_HierarchyChanged events alert us. - int num_device_info = 0; - XIDeviceInfo *device_info = X11_XIQueryDevice(data->display, XIAllDevices, &num_device_info); - if (device_info) { - for (int i = 0; i < num_device_info; i++) { - X11_MaybeAddPen(_this, &device_info[i]); - } - X11_XIFreeDeviceInfo(device_info); - } -} - -static void X11_FreePenHandle(SDL_PenID instance_id, void *handle, void *userdata) -{ - SDL_free(handle); -} - -void X11_QuitPen(SDL_VideoDevice *_this) -{ - SDL_RemoveAllPenDevices(X11_FreePenHandle, NULL); -} - -static void X11_XInput2NormalizePenAxes(const X11_PenHandle *pen, float *coords) -{ - // Normalise axes - for (int axis = 0; axis < SDL_PEN_AXIS_COUNT; ++axis) { - const int valuator = pen->valuator_for_axis[axis]; - if (valuator == SDL_X11_PEN_AXIS_VALUATOR_MISSING) { - continue; - } - - float value = coords[axis]; - const float min = pen->axis_min[axis]; - const float max = pen->axis_max[axis]; - - if (axis == SDL_PEN_AXIS_SLIDER) { - value += pen->slider_bias; - } - - // min ... 0 ... max - if (min < 0.0) { - // Normalise so that 0 remains 0.0 - if (value < 0) { - value = value / (-min); - } else { - if (max == 0.0f) { - value = 0.0f; - } else { - value = value / max; - } - } - } else { - // 0 ... min ... max - // including 0.0 = min - if (max == 0.0f) { - value = 0.0f; - } else { - value = (value - min) / max; - } - } - - switch (axis) { - case SDL_PEN_AXIS_XTILT: - case SDL_PEN_AXIS_YTILT: - //if (peninfo->info.max_tilt > 0.0f) { - // value *= peninfo->info.max_tilt; // normalize to physical max - //} - break; - - case SDL_PEN_AXIS_ROTATION: - // normalised to -1..1, so let's convert to degrees - value *= 180.0f; - value += pen->rotation_bias; - - // handle simple over/underflow - if (value >= 180.0f) { - value -= 360.0f; - } else if (value < -180.0f) { - value += 360.0f; - } - break; - - default: - break; - } - - coords[axis] = value; - } -} - -void X11_PenAxesFromValuators(const X11_PenHandle *pen, - const double *input_values, const unsigned char *mask, int mask_len, - float axis_values[SDL_PEN_AXIS_COUNT]) -{ - for (int i = 0; i < SDL_PEN_AXIS_COUNT; i++) { - const int valuator = pen->valuator_for_axis[i]; - if ((valuator == SDL_X11_PEN_AXIS_VALUATOR_MISSING) || (valuator >= mask_len * 8) || !(XIMaskIsSet(mask, valuator))) { - axis_values[i] = 0.0f; - } else { - axis_values[i] = (float)input_values[valuator]; - } - } - X11_XInput2NormalizePenAxes(pen, axis_values); -} - -#else - -void X11_InitPen(SDL_VideoDevice *_this) -{ - (void) _this; -} - -void X11_QuitPen(SDL_VideoDevice *_this) -{ - (void) _this; -} - -#endif // SDL_VIDEO_DRIVER_X11_XINPUT2 - diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.h deleted file mode 100644 index de75181..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11pen.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_x11pen_h_ -#define SDL_x11pen_h_ - -// Pressure-sensitive pen support for X11. - -#include "SDL_x11video.h" -#include "../../events/SDL_pen_c.h" - -// Prep pen support (never fails; pens simply won't be added if there's a problem). -extern void X11_InitPen(SDL_VideoDevice *_this); - -// Clean up pen support. -extern void X11_QuitPen(SDL_VideoDevice *_this); - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - -// Forward definition for SDL_x11video.h -struct SDL_VideoData; - -#define SDL_X11_PEN_AXIS_VALUATOR_MISSING -1 - -typedef struct X11_PenHandle -{ - SDL_PenID pen; - bool is_eraser; - int x11_deviceid; - int valuator_for_axis[SDL_PEN_AXIS_COUNT]; - float slider_bias; // shift value to add to PEN_AXIS_SLIDER (before normalisation) - float rotation_bias; // rotation to add to PEN_AXIS_ROTATION (after normalisation) - float axis_min[SDL_PEN_AXIS_COUNT]; - float axis_max[SDL_PEN_AXIS_COUNT]; -} X11_PenHandle; - -// Converts XINPUT2 valuators into pen axis information, including normalisation. -extern void X11_PenAxesFromValuators(const X11_PenHandle *pen, - const double *input_values, const unsigned char *mask, int mask_len, - float axis_values[SDL_PEN_AXIS_COUNT]); - -// Add a pen (if this function's further checks validate it). -extern X11_PenHandle *X11_MaybeAddPenByDeviceID(SDL_VideoDevice *_this, int deviceid); - -// Remove a pen. It's okay if deviceid is bogus or not a pen, we'll check it. -extern void X11_RemovePenByDeviceID(int deviceid); - -// Map X11 device ID to pen ID. -extern X11_PenHandle *X11_FindPenByDeviceID(int deviceid); - -#endif // SDL_VIDEO_DRIVER_X11_XINPUT2 - -#endif // SDL_x11pen_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.c deleted file mode 100644 index 7a7ae01..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright 2024 Igalia S.L. - - 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 defined(SDL_VIDEO_DRIVER_X11) - -#include "SDL_x11video.h" -#include "SDL_x11settings.h" - -#define SDL_XSETTINGS_GDK_WINDOW_SCALING_FACTOR "Gdk/WindowScalingFactor" -#define SDL_XSETTINGS_XFT_DPI "Xft/DPI" - -static void X11_XsettingsNotify(const char *name, XSettingsAction action, XSettingsSetting *setting, void *data) -{ - SDL_VideoDevice *_this = data; - float scale_factor = 1.0; - int i; - - if (SDL_strcmp(name, SDL_XSETTINGS_GDK_WINDOW_SCALING_FACTOR) != 0 || - SDL_strcmp(name, SDL_XSETTINGS_XFT_DPI) != 0) { - return; - } - - if (setting->type != XSETTINGS_TYPE_INT) { - return; - } - - switch (action) { - case XSETTINGS_ACTION_NEW: - SDL_FALLTHROUGH; - case XSETTINGS_ACTION_CHANGED: - scale_factor = setting->data.v_int; - if (SDL_strcmp(name, SDL_XSETTINGS_XFT_DPI) == 0) { - scale_factor = scale_factor / 1024.0f / 96.0f; - } - break; - case XSETTINGS_ACTION_DELETED: - scale_factor = 1.0; - break; - } - - if (_this) { - for (i = 0; i < _this->num_displays; ++i) { - SDL_SetDisplayContentScale(_this->displays[i], scale_factor); - } - } -} - -void X11_InitXsettings(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - SDLX11_SettingsData *xsettings_data = &data->xsettings_data; - - xsettings_data->xsettings = xsettings_client_new(data->display, - DefaultScreen(data->display), X11_XsettingsNotify, NULL, _this); - -} - -void X11_QuitXsettings(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - SDLX11_SettingsData *xsettings_data = &data->xsettings_data; - - if (xsettings_data->xsettings) { - xsettings_client_destroy(xsettings_data->xsettings); - xsettings_data->xsettings = NULL; - } -} - -void X11_HandleXsettings(SDL_VideoDevice *_this, const XEvent *xevent) -{ - SDL_VideoData *data = _this->internal; - SDLX11_SettingsData *xsettings_data = &data->xsettings_data; - - if (xsettings_data->xsettings) { - if (!xsettings_client_process_event(xsettings_data->xsettings, xevent)) { - xsettings_client_destroy(xsettings_data->xsettings); - xsettings_data->xsettings = NULL; - } - } -} - -int X11_GetXsettingsIntKey(SDL_VideoDevice *_this, const char *key, int fallback_value) { - SDL_VideoData *data = _this->internal; - SDLX11_SettingsData *xsettings_data = &data->xsettings_data; - XSettingsSetting *setting = NULL; - int res = fallback_value; - - - if (xsettings_data->xsettings) { - if (xsettings_client_get_setting(xsettings_data->xsettings, key, &setting) != XSETTINGS_SUCCESS) { - goto no_key; - } - - if (setting->type != XSETTINGS_TYPE_INT) { - goto no_key; - } - - res = setting->data.v_int; - } - -no_key: - if (setting) { - xsettings_setting_free(setting); - } - - return res; -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.h deleted file mode 100644 index 5b36884..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11settings.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright 2024 Igalia S.L. - - 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_x11settings_h_ -#define SDL_x11settings_h_ - -#include -#include "xsettings-client.h" - -typedef struct X11_SettingsData { - XSettingsClient *xsettings; -} SDLX11_SettingsData; - -extern void X11_InitXsettings(SDL_VideoDevice *_this); -extern void X11_QuitXsettings(SDL_VideoDevice *_this); -extern void X11_HandleXsettings(SDL_VideoDevice *_this, const XEvent *xevent); -extern int X11_GetXsettingsIntKey(SDL_VideoDevice *_this, const char *key, int fallback_value); - -#endif // SDL_x11settings_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.c deleted file mode 100644 index e433598..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "SDL_x11video.h" -#include "SDL_x11shape.h" - - -#ifdef SDL_VIDEO_DRIVER_X11_XSHAPE -static Uint8 *GenerateShapeMask(SDL_Surface *shape) -{ - int x, y; - const size_t ppb = 8; - const size_t bytes_per_scanline = (shape->w + (ppb - 1)) / ppb; - const Uint8 *a; - Uint8 *mask; - Uint8 *mask_scanline; - Uint8 mask_value; - - mask = (Uint8 *)SDL_calloc(1, shape->h * bytes_per_scanline); - if (mask) { - for (y = 0; y < shape->h; y++) { - a = (const Uint8 *)shape->pixels + y * shape->pitch; - mask_scanline = mask + y * bytes_per_scanline; - for (x = 0; x < shape->w; x++) { - mask_value = (*a == SDL_ALPHA_TRANSPARENT) ? 0 : 1; - mask_scanline[x / ppb] |= mask_value << (x % ppb); - a += 4; - } - } - } - return mask; -} -#endif // SDL_VIDEO_DRIVER_X11_XSHAPE - -bool X11_UpdateWindowShape(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *shape) -{ - bool result = false; - -#ifdef SDL_VIDEO_DRIVER_X11_XSHAPE - SDL_WindowData *windowdata = window->internal; - - // Generate a set of spans for the region - if (shape) { - SDL_Surface *stretched = NULL; - Uint8 *mask; - Pixmap pixmap; - - if (shape->w != window->w || shape->h != window->h) { - stretched = SDL_CreateSurface(window->w, window->h, SDL_PIXELFORMAT_ARGB32); - if (!stretched) { - return false; - } - if (!SDL_StretchSurface(shape, NULL, stretched, NULL, SDL_SCALEMODE_LINEAR)) { - SDL_DestroySurface(stretched); - return false; - } - shape = stretched; - } - - mask = GenerateShapeMask(shape); - if (mask) { - pixmap = X11_XCreateBitmapFromData(windowdata->videodata->display, windowdata->xwindow, (const char *)mask, shape->w, shape->h); - X11_XShapeCombineMask(windowdata->videodata->display, windowdata->xwindow, ShapeInput, 0, 0, pixmap, ShapeSet); - SDL_free(mask); - - result = true; - } - - if (stretched) { - SDL_DestroySurface(stretched); - } - } else { - Region region = X11_XCreateRegion(); - XRectangle rect; - - rect.x = 0; - rect.y = 0; - rect.width = window->w; - rect.height = window->h; - X11_XUnionRectWithRegion(&rect, region, region); - X11_XShapeCombineRegion(windowdata->videodata->display, windowdata->xwindow, ShapeInput, 0, 0, region, ShapeSet); - X11_XDestroyRegion(region); - result = true; - } -#endif // SDL_VIDEO_DRIVER_X11_XSHAPE - - return result; -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.h deleted file mode 100644 index d47d103..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11shape.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_ - -extern bool X11_UpdateWindowShape(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *shape); - -#endif // SDL_x11shape_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11sym.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11sym.h deleted file mode 100644 index 68d70cd..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11sym.h +++ /dev/null @@ -1,354 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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* */ // clang-format 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,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(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[32]),(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,XScreenNumberOfScreen,(Screen* a),(a),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,XSetWMHints,(Display* a,Window b,XWMHints* c),(a,b,c),) -SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),) -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(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) -SDL_X11_SYM(char*,XGetDefault,(Display* a,_Xconst char* b, _Xconst char* c),(a,b,c),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) -SDL_X11_SYM(Bool,XSupportsLocale,(void),(),return) -SDL_X11_SYM(Status,XmbTextListToTextProperty,(Display* a,char** b,int c,XICCEncodingStyle d,XTextProperty* e),(a,b,c,d,e),return) -SDL_X11_SYM(Region,XCreateRegion,(void),(),return) -SDL_X11_SYM(int,XUnionRectWithRegion,(XRectangle *a, Region b, Region c),(a,b,c), return) -SDL_X11_SYM(void,XDestroyRegion,(Region),(a),) -SDL_X11_SYM(void,XrmInitialize,(void),(),) -SDL_X11_SYM(char*,XResourceManagerString,(Display *display),(display),) -SDL_X11_SYM(XrmDatabase,XrmGetStringDatabase,(char *data),(data),) -SDL_X11_SYM(void,XrmDestroyDatabase,(XrmDatabase db),(db),) -SDL_X11_SYM(Bool,XrmGetResource,(XrmDatabase db, char* str_name, char* str_class, char **str_type_return, XrmValue *),(db, str_name, str_class,str_type_return,value_return),) - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES -SDL_X11_MODULE(XFIXES) -SDL_X11_SYM(PointerBarrier, XFixesCreatePointerBarrier, (Display* a, Window b, int c, int d, int e, int f, int g, int h, int *i),(a,b,c,d,e,f,g,h,i),return) -SDL_X11_SYM(void, XFixesDestroyPointerBarrier, (Display* a, PointerBarrier b), (a,b),) -SDL_X11_SYM(int, XIBarrierReleasePointer,(Display* a, int b, PointerBarrier c, BarrierEventID d), (a,b,c,d), return) // this is actually Xinput2 -SDL_X11_SYM(Status, XFixesQueryVersion,(Display* a, int* b, int* c), (a,b,c), return) -SDL_X11_SYM(Status, XFixesSelectSelectionInput, (Display* a, Window b, Atom c, unsigned long d), (a,b,c,d), return) -#endif - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC -SDL_X11_MODULE(XSYNC) -SDL_X11_SYM(Status, XSyncQueryExtension, (Display* a, int* b, int* c), (a, b, c), return) -SDL_X11_SYM(Status, XSyncInitialize, (Display* a, int* b, int* c), (a, b, c), return) -SDL_X11_SYM(XSyncCounter, XSyncCreateCounter, (Display* a, XSyncValue b), (a, b), return) -SDL_X11_SYM(Status, XSyncDestroyCounter, (Display* a, XSyncCounter b), (a, b), return) -SDL_X11_SYM(Status, XSyncSetCounter, (Display* a, XSyncCounter b, XSyncValue c), (a, b, c), return) -#endif - -#ifdef 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 - -#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM -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(Bool,XkbLookupKeySym,(Display* a, unsigned int b, unsigned int c, unsigned int* d, KeySym* e),(a,b,c,d,e),return) -#else -SDL_X11_SYM(Bool,XkbLookupKeySym,(Display* a, KeyCode b, unsigned int c, unsigned int* d, KeySym* e),(a,b,c,d,e),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 - -// XKeycodeToKeysym is a deprecated function -#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#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 HAVE_GCC_DIAGNOSTIC_PRAGMA -#pragma GCC diagnostic pop -#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(char*,XSetICValues,(XIC, ...),return) !!! ARGH! */ -/* SDL_X11_SYM(XVaNestedList,XVaCreateNestedList,(int, ...),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. - */ -#ifdef SDL_PLATFORM_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 -#ifdef 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) -SDL_X11_SYM(Cursor,XcursorLibraryLoadCursor,(Display *a, const char *b),(a,b),return) -#endif - -// Xdbe support -#ifdef 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 - -// XInput2 support for multiple mice, tablets, etc. -#ifdef 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(int,XIGrabTouchBegin,(Display *a,int b,Window c,int d,XIEventMask *e,int f,XIGrabModifiers *g),(a,b,c,d,e,f,g),return) -SDL_X11_SYM(int,XIUngrabTouchBegin, (Display *a,int b,Window c, int d,XIGrabModifiers *e),(a, b, c, d, e),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) -SDL_X11_SYM(Bool,XIGetClientPointer,(Display *a,Window b,int *c),(a,b,c),return) -SDL_X11_SYM(Bool,XIWarpPointer,(Display *a,int b,Window c,Window d,double e,double f,int g,int h,double i,double j),(a,b,c,d,e,f,g,h,i,j),return) -SDL_X11_SYM(Status,XIGetProperty,(Display *a,int 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) -#endif - -// XRandR support -#ifdef 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(Bool,XRRQueryExtension,(Display *dpy,int *event_base_return,int *error_base_return),(dpy,event_base_return,error_base_return),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) -SDL_X11_SYM(void,XRRSelectInput,(Display *dpy, Window window, int mask),(dpy,window,mask),) -SDL_X11_SYM(Status,XRRGetCrtcTransform,(Display *dpy,RRCrtc crtc,XRRCrtcTransformAttributes **attributes),(dpy,crtc,attributes),return) -#endif - -// MIT-SCREEN-SAVER support -#ifdef 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 - -#ifdef 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),) -SDL_X11_SYM(void,XShapeCombineRegion,(Display *a,Window b,int c,int d,int e,Region f,int g),(a,b,c,d,e,f,g),) -#endif - -#undef SDL_X11_MODULE -#undef SDL_X11_SYM - -/* *INDENT-ON* */ // clang-format on diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.c deleted file mode 100644 index 5b42c97..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef 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(SDL_VideoDevice *_this) -{ - X11_InitXinput2Multitouch(_this); -} - -void X11_QuitTouch(SDL_VideoDevice *_this) -{ - SDL_QuitTouch(); -} - -void X11_ResetTouch(SDL_VideoDevice *_this) -{ - X11_QuitTouch(_this); - X11_InitTouch(_this); -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.h deleted file mode 100644 index 548bf07..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11touch.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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(SDL_VideoDevice *_this); -extern void X11_QuitTouch(SDL_VideoDevice *_this); -extern void X11_ResetTouch(SDL_VideoDevice *_this); - -#endif // SDL_x11touch_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11video.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11video.c deleted file mode 100644 index 75862db..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11video.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include // For getpid() and readlink() - -#include "../../core/linux/SDL_system_theme.h" -#include "../../events/SDL_keyboard_c.h" -#include "../../events/SDL_mouse_c.h" -#include "../SDL_pixels_c.h" -#include "../SDL_sysvideo.h" - -#include "SDL_x11framebuffer.h" -#include "SDL_x11pen.h" -#include "SDL_x11touch.h" -#include "SDL_x11video.h" -#include "SDL_x11xfixes.h" -#include "SDL_x11xinput2.h" -#include "SDL_x11messagebox.h" -#include "SDL_x11shape.h" -#include "SDL_x11xsync.h" - -#ifdef SDL_VIDEO_OPENGL_EGL -#include "SDL_x11opengles.h" -#endif - -// Initialization/Query functions -static bool X11_VideoInit(SDL_VideoDevice *_this); -static void X11_VideoQuit(SDL_VideoDevice *_this); - -// X11 driver bootstrap functions - -static void X11_DeleteDevice(SDL_VideoDevice *device) -{ - SDL_VideoData *data = device->internal; - if (device->vulkan_config.loader_handle) { - device->Vulkan_UnloadLibrary(device); - } - if (data->display) { - X11_XCloseDisplay(data->display); - } - if (data->request_display) { - X11_XCloseDisplay(data->request_display); - } - SDL_free(data->windowlist); - if (device->wakeup_lock) { - SDL_DestroyMutex(device->wakeup_lock); - } - SDL_free(device->internal); - SDL_free(device); - - SDL_X11_UnloadSymbols(); -} - -static bool X11_IsXWayland(Display *d) -{ - int opcode, event, error; - return X11_XQueryExtension(d, "XWAYLAND", &opcode, &event, &error) == True; -} - -static bool X11_CheckCurrentDesktop(const char *name) -{ - SDL_Environment *env = SDL_GetEnvironment(); - - const char *desktopVar = SDL_GetEnvironmentVariable(env, "DESKTOP_SESSION"); - if (desktopVar && SDL_strcasecmp(desktopVar, name) == 0) { - return true; - } - - desktopVar = SDL_GetEnvironmentVariable(env, "XDG_CURRENT_DESKTOP"); - if (desktopVar && SDL_strcasestr(desktopVar, name)) { - return true; - } - - return false; -} - -static SDL_VideoDevice *X11_CreateDevice(void) -{ - SDL_VideoDevice *device; - SDL_VideoData *data; - const char *display = NULL; // Use the DISPLAY environment variable - Display *x11_display = NULL; - - 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(); - - // Open the display first to be sure that X11 is available - x11_display = X11_XOpenDisplay(display); - - if (!x11_display) { - SDL_X11_UnloadSymbols(); - return NULL; - } - - // Initialize all variables that we clean on shutdown - device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (!device) { - return NULL; - } - data = (struct SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (!data) { - SDL_free(device); - return NULL; - } - device->internal = data; - - data->global_mouse_changed = true; - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - data->active_cursor_confined_window = NULL; -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - - data->display = x11_display; - data->request_display = X11_XOpenDisplay(display); - if (!data->request_display) { - X11_XCloseDisplay(data->display); - SDL_free(device->internal); - SDL_free(device); - SDL_X11_UnloadSymbols(); - return NULL; - } - - device->wakeup_lock = SDL_CreateMutex(); - -#ifdef X11_DEBUG - X11_XSynchronize(data->display, True); -#endif - - /* Steam Deck will have an on-screen keyboard, so check their environment - * variable so we can make use of SDL_StartTextInput. - */ - data->is_steam_deck = SDL_GetHintBoolean("SteamDeck", false); - - // 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->GetWindowICCProfile = X11_GetWindowICCProfile; - device->SetDisplayMode = X11_SetDisplayMode; - device->SuspendScreenSaver = X11_SuspendScreenSaver; - device->PumpEvents = X11_PumpEvents; - device->WaitEventTimeout = X11_WaitEventTimeout; - device->SendWakeupEvent = X11_SendWakeupEvent; - - device->CreateSDLWindow = X11_CreateWindow; - 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->SetWindowAspectRatio = X11_SetWindowAspectRatio; - device->GetWindowBordersSize = X11_GetWindowBordersSize; - device->SetWindowOpacity = X11_SetWindowOpacity; - device->SetWindowParent = X11_SetWindowParent; - device->SetWindowModal = X11_SetWindowModal; - 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->SetWindowAlwaysOnTop = X11_SetWindowAlwaysOnTop; - device->SetWindowFullscreen = X11_SetWindowFullscreen; - device->SetWindowMouseGrab = X11_SetWindowMouseGrab; - device->SetWindowKeyboardGrab = X11_SetWindowKeyboardGrab; - device->DestroyWindow = X11_DestroyWindow; - device->CreateWindowFramebuffer = X11_CreateWindowFramebuffer; - device->UpdateWindowFramebuffer = X11_UpdateWindowFramebuffer; - device->DestroyWindowFramebuffer = X11_DestroyWindowFramebuffer; - device->SetWindowHitTest = X11_SetWindowHitTest; - device->AcceptDragAndDrop = X11_AcceptDragAndDrop; - device->UpdateWindowShape = X11_UpdateWindowShape; - device->FlashWindow = X11_FlashWindow; - device->ShowWindowSystemMenu = X11_ShowWindowSystemMenu; - device->SetWindowFocusable = X11_SetWindowFocusable; - device->SyncWindow = X11_SyncWindow; - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - device->SetWindowMouseRect = X11_SetWindowMouseRect; -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - -#ifdef 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_DestroyContext = X11_GL_DestroyContext; - device->GL_GetEGLSurface = NULL; -#endif -#ifdef SDL_VIDEO_OPENGL_EGL -#ifdef SDL_VIDEO_OPENGL_GLX - if (SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, false)) { -#endif - 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_DestroyContext = X11_GLES_DestroyContext; - device->GL_GetEGLSurface = X11_GLES_GetEGLSurface; -#ifdef SDL_VIDEO_OPENGL_GLX - } -#endif -#endif - - device->GetTextMimeTypes = X11_GetTextMimeTypes; - device->SetClipboardData = X11_SetClipboardData; - device->GetClipboardData = X11_GetClipboardData; - device->HasClipboardData = X11_HasClipboardData; - device->SetPrimarySelectionText = X11_SetPrimarySelectionText; - device->GetPrimarySelectionText = X11_GetPrimarySelectionText; - device->HasPrimarySelectionText = X11_HasPrimarySelectionText; - device->StartTextInput = X11_StartTextInput; - device->StopTextInput = X11_StopTextInput; - device->UpdateTextInputArea = X11_UpdateTextInputArea; - device->HasScreenKeyboardSupport = X11_HasScreenKeyboardSupport; - device->ShowScreenKeyboard = X11_ShowScreenKeyboard; - device->HideScreenKeyboard = X11_HideScreenKeyboard; - device->IsScreenKeyboardShown = X11_IsScreenKeyboardShown; - - device->free = X11_DeleteDevice; - -#ifdef 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; - device->Vulkan_DestroySurface = X11_Vulkan_DestroySurface; - device->Vulkan_GetPresentationSupport = X11_Vulkan_GetPresentationSupport; -#endif - -#ifdef SDL_USE_LIBDBUS - if (SDL_SystemTheme_Init()) - device->system_theme = SDL_SystemTheme_Get(); -#endif - - device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT; - - /* Openbox doesn't send the new window dimensions when entering fullscreen, so the events must be synthesized. - * This is otherwise not wanted, as it can break fullscreen window positioning on multi-monitor configurations. - */ - if (!X11_CheckCurrentDesktop("openbox")) { - device->device_caps |= VIDEO_DEVICE_CAPS_SENDS_DISPLAY_CHANGES; - } - - data->is_xwayland = X11_IsXWayland(x11_display); - if (data->is_xwayland) { - device->device_caps |= VIDEO_DEVICE_CAPS_MODE_SWITCHING_EMULATED | - VIDEO_DEVICE_CAPS_DISABLE_MOUSE_WARP_ON_FULLSCREEN_TRANSITIONS; - } - - return device; -} - -VideoBootStrap X11_bootstrap = { - "x11", "SDL X11 video driver", - X11_CreateDevice, - X11_ShowMessageBox, - false -}; - -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(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - 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 = true; - -#ifdef DEBUG_WINDOW_MANAGER - wm_name = X11_GetWindowTitle(_this, wm_window); - printf("Window manager: %s\n", wm_name); - SDL_free(wm_name); -#endif -} - -static bool X11_VideoInit(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - - // 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->atoms.X = X11_XInternAtom(data->display, #X, False) - GET_ATOM(WM_PROTOCOLS); - GET_ATOM(WM_DELETE_WINDOW); - GET_ATOM(WM_TAKE_FOCUS); - GET_ATOM(WM_NAME); - GET_ATOM(WM_TRANSIENT_FOR); - 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_MOVERESIZE); - GET_ATOM(_NET_WM_STATE_MODAL); - 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_SYNC_REQUEST); - GET_ATOM(_NET_WM_SYNC_REQUEST_COUNTER); - GET_ATOM(_NET_WM_WINDOW_OPACITY); - GET_ATOM(_NET_WM_USER_TIME); - GET_ATOM(_NET_ACTIVE_WINDOW); - GET_ATOM(_NET_FRAME_EXTENTS); - GET_ATOM(_SDL_WAKEUP); - GET_ATOM(UTF8_STRING); - GET_ATOM(PRIMARY); - GET_ATOM(CLIPBOARD); - GET_ATOM(INCR); - GET_ATOM(SDL_SELECTION); - GET_ATOM(TARGETS); - GET_ATOM(SDL_FORMATS); - GET_ATOM(XdndAware); - GET_ATOM(XdndEnter); - GET_ATOM(XdndLeave); - 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)) { - return false; - } - - if (!X11_InitXinput2(_this)) { - // Assume a mouse and keyboard are attached - SDL_AddKeyboard(SDL_DEFAULT_KEYBOARD_ID, NULL, false); - SDL_AddMouse(SDL_DEFAULT_MOUSE_ID, NULL, false); - } - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - X11_InitXfixes(_this); -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - - X11_InitXsettings(_this); - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - X11_InitXsync(_this); -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - -#ifndef X_HAVE_UTF8_STRING -#warning X server does not support UTF8_STRING, a feature introduced in 2000! This is likely to become a hard error in a future libSDL3. -#endif - - if (!X11_InitKeyboard(_this)) { - return false; - } - X11_InitMouse(_this); - - X11_InitTouch(_this); - - X11_InitPen(_this); - - return true; -} - -void X11_VideoQuit(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - - if (data->clipboard_window) { - X11_XDestroyWindow(data->display, data->clipboard_window); - } - - if (data->xsettings_window) { - X11_XDestroyWindow(data->display, data->xsettings_window); - } - -#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); - X11_QuitPen(_this); - X11_QuitClipboard(_this); - X11_QuitXsettings(_this); -} - -bool X11_UseDirectColorVisuals(void) -{ - if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_NODIRECTCOLOR, false)) { - return false; - } - return true; -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11video.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11video.h deleted file mode 100644 index a336a80..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11video.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_sysvideo.h" - -#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_x11settings.h" -#include "SDL_x11window.h" -#include "SDL_x11vulkan.h" - -// Private display data - -struct SDL_VideoData -{ - Display *display; - Display *request_display; - pid_t pid; - XIM im; - Uint64 screensaver_activity; - int numwindows; - SDL_WindowData **windowlist; - int windowlistlength; - XID window_group; - Window clipboard_window; - SDLX11_ClipboardData clipboard; - SDLX11_ClipboardData primary_selection; -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - SDL_Window *active_cursor_confined_window; -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - Window xsettings_window; - SDLX11_SettingsData xsettings_data; - - // This is true for ICCCM2.0-compliant window managers - bool net_wm; - - // Useful atoms - struct { - Atom WM_PROTOCOLS; - Atom WM_DELETE_WINDOW; - Atom WM_TAKE_FOCUS; - Atom WM_NAME; - Atom WM_TRANSIENT_FOR; - 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_STATE_MODAL; - Atom _NET_WM_MOVERESIZE; - 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_SYNC_REQUEST; - Atom _NET_WM_SYNC_REQUEST_COUNTER; - Atom _NET_WM_WINDOW_OPACITY; - Atom _NET_WM_USER_TIME; - Atom _NET_ACTIVE_WINDOW; - Atom _NET_FRAME_EXTENTS; - Atom _SDL_WAKEUP; - Atom UTF8_STRING; - Atom PRIMARY; - Atom CLIPBOARD; - Atom INCR; - Atom SDL_SELECTION; - Atom TARGETS; - Atom SDL_FORMATS; - Atom XdndAware; - Atom XdndEnter; - Atom XdndLeave; - Atom XdndPosition; - Atom XdndStatus; - Atom XdndTypeList; - Atom XdndActionCopy; - Atom XdndDrop; - Atom XdndFinished; - Atom XdndSelection; - Atom XKLAVIER_STATE; - - // Pen atoms (these have names that don't map well to C symbols) - Atom pen_atom_device_product_id; - Atom pen_atom_abs_pressure; - Atom pen_atom_abs_tilt_x; - Atom pen_atom_abs_tilt_y; - Atom pen_atom_wacom_serial_ids; - Atom pen_atom_wacom_tool_type; - } atoms; - - SDL_Scancode key_layout[256]; - bool selection_waiting; - bool selection_incr_waiting; - - bool broken_pointer_grab; // true if XGrabPointer seems unreliable. - - Uint64 last_mode_change_deadline; - - bool global_mouse_changed; - SDL_Point global_mouse_position; - Uint32 global_mouse_buttons; - - SDL_XInput2DeviceInfo *mouse_device_info; - int xinput_master_pointer_device; - bool xinput_hierarchy_changed; - - int xrandr_event_base; - struct - { -#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM - XkbDescPtr desc_ptr; -#endif - int event; - unsigned int current_group; - unsigned int xkb_modifiers; - - SDL_Keymod sdl_modifiers; - - Uint32 numlock_mask; - Uint32 scrolllock_mask; - } xkb; - - KeyCode filter_code; - Time filter_time; - -#ifdef SDL_VIDEO_VULKAN - // Vulkan variables only valid if _this->vulkan_config.loader_handle is not NULL - SDL_SharedObject *vulkan_xlib_xcb_library; - PFN_XGetXCBConnection vulkan_XGetXCBConnection; -#endif - - // Used to interact with the on-screen keyboard - bool is_steam_deck; - bool steam_keyboard_open; - - bool is_xwayland; -}; - -extern bool X11_UseDirectColorVisuals(void); - -#endif // SDL_x11video_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.c deleted file mode 100644 index 065549b..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_X11) - -#include "../SDL_vulkan_internal.h" - -#include "SDL_x11video.h" - -#include "SDL_x11vulkan.h" - -#include -// #include - -#ifdef SDL_PLATFORM_OPENBSD -#define DEFAULT_VULKAN "libvulkan.so" -#define DEFAULT_X11_XCB "libX11-xcb.so" -#else -#define DEFAULT_VULKAN "libvulkan.so.1" -#define DEFAULT_X11_XCB "libX11-xcb.so.1" -#endif - -/* -typedef uint32_t xcb_window_t; -typedef uint32_t xcb_visualid_t; -*/ - -bool X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) -{ - SDL_VideoData *videoData = _this->internal; - VkExtensionProperties *extensions = NULL; - Uint32 extensionCount = 0; - bool hasSurfaceExtension = false; - bool hasXlibSurfaceExtension = false; - bool hasXCBSurfaceExtension = 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_GetHint(SDL_HINT_VULKAN_LIBRARY); - } - if (!path) { - path = DEFAULT_VULKAN; - } - _this->vulkan_config.loader_handle = SDL_LoadObject(path); - if (!_this->vulkan_config.loader_handle) { - return false; - } - 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 = true; - } else if (SDL_strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { - hasXCBSurfaceExtension = true; - } else if (SDL_strcmp(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { - hasXlibSurfaceExtension = 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_GetHint(SDL_HINT_X11_XCB_LIBRARY); - if (!libX11XCBLibraryName || !*libX11XCBLibraryName) { - libX11XCBLibraryName = DEFAULT_X11_XCB; - } - videoData->vulkan_xlib_xcb_library = SDL_LoadObject(libX11XCBLibraryName); - if (!videoData->vulkan_xlib_xcb_library) { - goto fail; - } - videoData->vulkan_XGetXCBConnection = - (PFN_XGetXCBConnection)SDL_LoadFunction(videoData->vulkan_xlib_xcb_library, "XGetXCBConnection"); - if (!videoData->vulkan_XGetXCBConnection) { - SDL_UnloadObject(videoData->vulkan_xlib_xcb_library); - goto fail; - } - } - return true; - -fail: - SDL_UnloadObject(_this->vulkan_config.loader_handle); - _this->vulkan_config.loader_handle = NULL; - return false; -} - -void X11_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) -{ - SDL_VideoData *videoData = _this->internal; - 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; - } -} - -char const* const* X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - Uint32 *count) -{ - SDL_VideoData *videoData = _this->internal; - if (videoData->vulkan_xlib_xcb_library) { - static const char *const extensionsForXCB[] = { - VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_XCB_SURFACE_EXTENSION_NAME, - }; - if(count) { - *count = SDL_arraysize(extensionsForXCB); - } - return extensionsForXCB; - } else { - static const char *const extensionsForXlib[] = { - VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_XLIB_SURFACE_EXTENSION_NAME, - }; - if(count) { - *count = SDL_arraysize(extensionsForXlib); - } - return extensionsForXlib; - } -} - -bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this, - SDL_Window *window, - VkInstance instance, - const struct VkAllocationCallbacks *allocator, - VkSurfaceKHR *surface) -{ - SDL_VideoData *videoData = _this->internal; - SDL_WindowData *windowData = window->internal; - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; - if (!_this->vulkan_config.loader_handle) { - return SDL_SetError("Vulkan is not loaded"); - } - vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; - if (videoData->vulkan_xlib_xcb_library) { - PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR = - (PFN_vkCreateXcbSurfaceKHR)vkGetInstanceProcAddr(instance, - "vkCreateXcbSurfaceKHR"); - VkXcbSurfaceCreateInfoKHR createInfo; - VkResult result; - if (!vkCreateXcbSurfaceKHR) { - return SDL_SetError(VK_KHR_XCB_SURFACE_EXTENSION_NAME " extension is not enabled in the Vulkan instance."); - } - SDL_zero(createInfo); - createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; - createInfo.connection = videoData->vulkan_XGetXCBConnection(videoData->display); - if (!createInfo.connection) { - return SDL_SetError("XGetXCBConnection failed"); - } - createInfo.window = (xcb_window_t)windowData->xwindow; - result = vkCreateXcbSurfaceKHR(instance, &createInfo, allocator, surface); - if (result != VK_SUCCESS) { - return SDL_SetError("vkCreateXcbSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result)); - } - } else { - PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR = - (PFN_vkCreateXlibSurfaceKHR)vkGetInstanceProcAddr(instance, - "vkCreateXlibSurfaceKHR"); - VkXlibSurfaceCreateInfoKHR createInfo; - VkResult result; - if (!vkCreateXlibSurfaceKHR) { - return SDL_SetError(VK_KHR_XLIB_SURFACE_EXTENSION_NAME " extension is not enabled in the Vulkan instance."); - } - 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, allocator, surface); - if (result != VK_SUCCESS) { - return SDL_SetError("vkCreateXlibSurfaceKHR failed: %s", SDL_Vulkan_GetResultString(result)); - } - } - - return true; // success! -} - -void X11_Vulkan_DestroySurface(SDL_VideoDevice *_this, - VkInstance instance, - VkSurfaceKHR surface, - const struct VkAllocationCallbacks *allocator) -{ - if (_this->vulkan_config.loader_handle) { - SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator); - } -} - -bool X11_Vulkan_GetPresentationSupport(SDL_VideoDevice *_this, - VkInstance instance, - VkPhysicalDevice physicalDevice, - Uint32 queueFamilyIndex) -{ - SDL_VideoData *videoData = _this->internal; - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; - const char *forced_visual_id; - VisualID visualid; - - if (!_this->vulkan_config.loader_handle) { - return SDL_SetError("Vulkan is not loaded"); - } - vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; - - forced_visual_id = SDL_GetHint(SDL_HINT_VIDEO_X11_WINDOW_VISUALID); - if (forced_visual_id) { - visualid = SDL_strtol(forced_visual_id, NULL, 0); - } else { - visualid = X11_XVisualIDFromVisual(DefaultVisual(videoData->display, DefaultScreen(videoData->display))); - } - - if (videoData->vulkan_xlib_xcb_library) { - PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR = - (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)vkGetInstanceProcAddr( - instance, - "vkGetPhysicalDeviceXcbPresentationSupportKHR"); - - if (!vkGetPhysicalDeviceXcbPresentationSupportKHR) { - return SDL_SetError(VK_KHR_XCB_SURFACE_EXTENSION_NAME " extension is not enabled in the Vulkan instance."); - } - - return vkGetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, - queueFamilyIndex, - videoData->vulkan_XGetXCBConnection(videoData->display), - visualid); - } else { - PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR = - (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)vkGetInstanceProcAddr( - instance, - "vkGetPhysicalDeviceXlibPresentationSupportKHR"); - - if (!vkGetPhysicalDeviceXlibPresentationSupportKHR) { - return SDL_SetError(VK_KHR_XLIB_SURFACE_EXTENSION_NAME " extension is not enabled in the Vulkan instance."); - } - - return vkGetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, - queueFamilyIndex, - videoData->display, - visualid); - } -} - -#endif diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.h deleted file mode 100644 index 2a62596..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11vulkan.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 - -#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_X11) - -typedef struct xcb_connection_t xcb_connection_t; -typedef xcb_connection_t *(*PFN_XGetXCBConnection)(Display *dpy); - -extern bool X11_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); -extern void X11_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -extern char const* const* X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count); -extern bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this, - SDL_Window *window, - VkInstance instance, - const struct VkAllocationCallbacks *allocator, - VkSurfaceKHR *surface); -extern void X11_Vulkan_DestroySurface(SDL_VideoDevice *_this, - VkInstance instance, - VkSurfaceKHR surface, - const struct VkAllocationCallbacks *allocator); -extern bool X11_Vulkan_GetPresentationSupport(SDL_VideoDevice *_this, - VkInstance instance, - VkPhysicalDevice physicalDevice, - Uint32 queueFamilyIndex); - -#endif - -#endif // SDL_x11vulkan_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11window.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11window.c deleted file mode 100644 index 5562053..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11window.c +++ /dev/null @@ -1,2243 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "../SDL_sysvideo.h" -#include "../SDL_pixels_c.h" -#include "../../events/SDL_keyboard_c.h" -#include "../../events/SDL_mouse_c.h" -#include "../../events/SDL_events_c.h" -#include "../../core/unix/SDL_appid.h" - -#include "SDL_x11video.h" -#include "SDL_x11mouse.h" -#include "SDL_x11xinput2.h" -#include "SDL_x11xfixes.h" - -#ifdef SDL_VIDEO_OPENGL_EGL -#include "SDL_x11opengles.h" -#endif - -#include "SDL_x11xsync.h" - -#define _NET_WM_STATE_REMOVE 0l -#define _NET_WM_STATE_ADD 1l - -#define CHECK_WINDOW_DATA(window) \ - if (!window) { \ - return SDL_SetError("Invalid window"); \ - } \ - if (!window->internal) { \ - return SDL_SetError("Invalid window driver data"); \ - } - -#define CHECK_DISPLAY_DATA(display) \ - if (!_display) { \ - return SDL_SetError("Invalid display"); \ - } \ - if (!_display->internal) { \ - return SDL_SetError("Invalid display driver data"); \ - } - -static Bool isMapNotify(Display *dpy, XEvent *ev, XPointer win) // NOLINT(readability-non-const-parameter): cannot make XPointer a const pointer due to typedef -{ - return ev->type == MapNotify && ev->xmap.window == *((Window *)win); -} -static Bool isUnmapNotify(Display *dpy, XEvent *ev, XPointer win) // NOLINT(readability-non-const-parameter): cannot make XPointer a const pointer due to typedef -{ - 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) -{ - Uint64 start = SDL_GetTicks(); - - while (!X11_XCheckIfEvent(display, event_return, predicate, arg)) { - if (SDL_GetTicks() >= (start + timeoutMS)) { - return False; - } - } - return True; -} -*/ - -static bool X11_IsWindowMapped(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - SDL_VideoData *videodata = _this->internal; - XWindowAttributes attr; - - X11_XGetWindowAttributes(videodata->display, data->xwindow, &attr); - if (attr.map_state != IsUnmapped) { - return true; - } else { - return false; - } -} - -static bool X11_IsDisplayOk(Display *display) -{ - if (display->flags & XlibDisplayIOError) { - return false; - } - return true; -} - -#if 0 -static bool X11_IsActionAllowed(SDL_Window *window, Atom action) -{ - SDL_WindowData *data = window->internal; - 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; - bool ret = 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; ilast_position_pending; - const bool last_size_pending = window->last_size_pending; - - X11_SyncWindow(_this, window); - - window->last_position_pending = last_position_pending; - window->last_size_pending = last_size_pending; -} - -void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, SDL_WindowFlags flags) -{ - SDL_VideoData *videodata = _this->internal; - Display *display = videodata->display; - // !!! FIXME: just dereference videodata below instead of copying to locals. - Atom _NET_WM_STATE = videodata->atoms._NET_WM_STATE; - // Atom _NET_WM_STATE_HIDDEN = videodata->atoms._NET_WM_STATE_HIDDEN; - Atom _NET_WM_STATE_FOCUSED = videodata->atoms._NET_WM_STATE_FOCUSED; - Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->atoms._NET_WM_STATE_MAXIMIZED_VERT; - Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->atoms._NET_WM_STATE_MAXIMIZED_HORZ; - Atom _NET_WM_STATE_FULLSCREEN = videodata->atoms._NET_WM_STATE_FULLSCREEN; - Atom _NET_WM_STATE_ABOVE = videodata->atoms._NET_WM_STATE_ABOVE; - Atom _NET_WM_STATE_SKIP_TASKBAR = videodata->atoms._NET_WM_STATE_SKIP_TASKBAR; - Atom _NET_WM_STATE_SKIP_PAGER = videodata->atoms._NET_WM_STATE_SKIP_PAGER; - Atom _NET_WM_STATE_MODAL = videodata->atoms._NET_WM_STATE_MODAL; - 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) != 0) { - atoms[count++] = _NET_WM_STATE_HIDDEN; - } - */ - - if (flags & SDL_WINDOW_ALWAYS_ON_TOP) { - atoms[count++] = _NET_WM_STATE_ABOVE; - } - if (flags & SDL_WINDOW_UTILITY) { - 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; - } - if (flags & SDL_WINDOW_MODAL) { - atoms[count++] = _NET_WM_STATE_MODAL; - } - - 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); - } -} - -static void X11_ConstrainPopup(SDL_Window *window, bool output_to_pending) -{ - // Clamp popup windows to the output borders - if (SDL_WINDOW_IS_POPUP(window)) { - SDL_Window *w; - SDL_DisplayID displayID; - SDL_Rect rect; - int abs_x = window->last_position_pending ? window->pending.x : window->floating.x; - int abs_y = window->last_position_pending ? window->pending.y : window->floating.y; - int offset_x = 0, offset_y = 0; - - // Calculate the total offset from the parents - for (w = window->parent; SDL_WINDOW_IS_POPUP(w); w = w->parent) { - offset_x += w->x; - offset_y += w->y; - } - - offset_x += w->x; - offset_y += w->y; - abs_x += offset_x; - abs_y += offset_y; - - displayID = SDL_GetDisplayForWindow(w); - - SDL_GetDisplayBounds(displayID, &rect); - if (abs_x + window->w > rect.x + rect.w) { - abs_x -= (abs_x + window->w) - (rect.x + rect.w); - } - if (abs_y + window->h > rect.y + rect.h) { - abs_y -= (abs_y + window->h) - (rect.y + rect.h); - } - abs_x = SDL_max(abs_x, rect.x); - abs_y = SDL_max(abs_y, rect.y); - - if (output_to_pending) { - window->pending.x = abs_x - offset_x; - window->pending.y = abs_y - offset_y; - } else { - window->floating.x = window->windowed.x = abs_x - offset_x; - window->floating.y = window->windowed.y = abs_y - offset_y; - } - } -} - -static void X11_SetKeyboardFocus(SDL_Window *window, bool set_active_focus) -{ - SDL_Window *toplevel = window; - - // Find the toplevel parent - while (SDL_WINDOW_IS_POPUP(toplevel)) { - toplevel = toplevel->parent; - } - - toplevel->internal->keyboard_focus = window; - - if (set_active_focus && !window->is_hiding && !window->is_destroying) { - SDL_SetKeyboardFocus(window); - } -} - -Uint32 X11_GetNetWMState(SDL_VideoDevice *_this, SDL_Window *window, Window xwindow) -{ - SDL_VideoData *videodata = _this->internal; - Display *display = videodata->display; - Atom _NET_WM_STATE = videodata->atoms._NET_WM_STATE; - Atom _NET_WM_STATE_HIDDEN = videodata->atoms._NET_WM_STATE_HIDDEN; - Atom _NET_WM_STATE_FOCUSED = videodata->atoms._NET_WM_STATE_FOCUSED; - Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->atoms._NET_WM_STATE_MAXIMIZED_VERT; - Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->atoms._NET_WM_STATE_MAXIMIZED_HORZ; - Atom _NET_WM_STATE_FULLSCREEN = videodata->atoms._NET_WM_STATE_FULLSCREEN; - Atom actualType; - int actualFormat; - unsigned long i, numItems, bytesAfter; - unsigned char *propertyValue = NULL; - long maxLength = 1024; - SDL_WindowFlags 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_MINIMIZED | SDL_WINDOW_OCCLUDED; - } 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 (fullscreen == 1) { - if (window->flags & SDL_WINDOW_FULLSCREEN) { - // Pick whatever state the window expects - flags |= (window->flags & SDL_WINDOW_FULLSCREEN); - } else { - // Assume we're fullscreen desktop - flags |= SDL_WINDOW_FULLSCREEN; - } - } - - if (maximized == 3) { - /* Fullscreen windows are maximized on some window managers, - and this is functional behavior - if maximized is removed, - the windows remain floating centered and not covering the - rest of the desktop. So we just won't change the maximize - state for fullscreen windows here, otherwise SDL would think - we're always maximized when fullscreen and not restore the - correct state when leaving fullscreen. - */ - if (fullscreen) { - flags |= (window->flags & SDL_WINDOW_MAXIMIZED); - } else { - flags |= SDL_WINDOW_MAXIMIZED; - } - } - - /* 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 bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, Window w) -{ - SDL_VideoData *videodata = _this->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - 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 false; - } - data->videodata = videodata; - data->window = window; - data->xwindow = w; - data->hit_test_result = SDL_HITTEST_NORMAL; - - X11_CreateInputContext(data); - - // Associate the data with the window - - if (numwindows < windowlistlength) { - windowlist[numwindows] = data; - videodata->numwindows++; - } else { - SDL_WindowData ** new_windowlist = (SDL_WindowData **)SDL_realloc(windowlist, (numwindows + 1) * sizeof(*windowlist)); - if (!new_windowlist) { - SDL_free(data); - return false; - } - windowlist = new_windowlist; - 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); - if (!SDL_WINDOW_IS_POPUP(window)) { - window->x = window->windowed.x = window->floating.x = attrib.x; - window->y = window->windowed.y = window->floating.y = attrib.y - data->border_top; - } - window->w = window->windowed.w = window->floating.w = attrib.width; - window->h = window->windowed.h = window->floating.h = attrib.height; - if (attrib.map_state != IsUnmapped) { - window->flags &= ~SDL_WINDOW_HIDDEN; - } else { - window->flags |= SDL_WINDOW_HIDDEN; - } - data->visual = attrib.visual; - data->colormap = attrib.colormap; - } - - window->flags |= X11_GetNetWMState(_this, window, 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_MOUSE_GRABBED) { - // Tell x11 to clip mouse - } - } - - if (window->flags & SDL_WINDOW_EXTERNAL) { - // Query the title from the existing window - window->title = X11_GetWindowTitle(_this, w); - } - - SDL_PropertiesID props = SDL_GetWindowProperties(window); - int screen = (displaydata ? displaydata->screen : 0); - SDL_SetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, data->videodata->display); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_X11_SCREEN_NUMBER, screen); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, data->xwindow); - - // All done! - window->internal = data; - return true; -} - -static void SetupWindowInput(SDL_VideoDevice *_this, SDL_Window *window) -{ - long fevent = 0; - SDL_WindowData *data = window->internal; - Window xwindow = data->xwindow; - -#ifdef X_HAVE_UTF8_STRING - if (SDL_X11_HAVE_UTF8 && data->ic) { - X11_XGetICValues(data->ic, XNFilterEvents, &fevent, NULL); - } -#endif - - X11_Xinput2SelectTouch(_this, window); - - { - unsigned int x11_keyboard_events = KeyPressMask | KeyReleaseMask; - unsigned int x11_pointer_events = ButtonPressMask | ButtonReleaseMask | PointerMotionMask; - - X11_Xinput2SelectMouseAndKeyboard(_this, window); - - // If XInput2 can handle pointer and keyboard events, we don't track them here - if (data->xinput2_keyboard_enabled) { - x11_keyboard_events = 0; - } - if (data->xinput2_mouse_enabled) { - x11_pointer_events = 0; - } - - X11_XSelectInput(data->videodata->display, xwindow, - (FocusChangeMask | EnterWindowMask | LeaveWindowMask | ExposureMask | - x11_keyboard_events | x11_pointer_events | - PropertyChangeMask | StructureNotifyMask | - KeymapStateMask | fevent)); - } -} - -static void SetWindowBordered(Display *display, int screen, Window window, 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)); - } -} - -bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) -{ - Window w = (Window)SDL_GetNumberProperty(create_props, SDL_PROP_WINDOW_CREATE_X11_WINDOW_NUMBER, - (Window)SDL_GetPointerProperty(create_props, "sdl2-compat.external_window", NULL)); - if (w) { - window->flags |= SDL_WINDOW_EXTERNAL; - - if (!SetupWindowData(_this, window, w)) { - return false; - } - - SetupWindowInput(_this, window); - return true; - } - - SDL_VideoData *data = _this->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - if (!displaydata) { - return SDL_SetError("Could not find display info"); - } - - const bool force_override_redirect = SDL_GetHintBoolean(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, false); - const bool use_resize_sync = (window->flags & SDL_WINDOW_VULKAN); /* doesn't work well with Vulkan */ - SDL_WindowData *windowdata; - Display *display = data->display; - int screen = displaydata->screen; - Visual *visual; - int depth; - XSetWindowAttributes xattr; - 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; - const char *hint = NULL; - int win_x, win_y; - bool undefined_position = false; - -#if defined(SDL_VIDEO_OPENGL_GLX) || defined(SDL_VIDEO_OPENGL_EGL) - const int transparent = (window->flags & SDL_WINDOW_TRANSPARENT) ? true : false; - const char *forced_visual_id = SDL_GetHint(SDL_HINT_VIDEO_X11_WINDOW_VISUALID); - const char *display_visual_id = SDL_GetHint(SDL_HINT_VIDEO_X11_VISUALID); - - if (forced_visual_id && *forced_visual_id) { - XVisualInfo *vi, template; - int nvis; - - SDL_zero(template); - template.visualid = SDL_strtol(forced_visual_id, NULL, 0); - vi = X11_XGetVisualInfo(display, VisualIDMask, &template, &nvis); - if (vi) { - visual = vi->visual; - depth = vi->depth; - X11_XFree(vi); - } else { - return false; - } - } else if ((window->flags & SDL_WINDOW_OPENGL) && - (!display_visual_id || !*display_visual_id)) { - XVisualInfo *vinfo = NULL; - -#ifdef SDL_VIDEO_OPENGL_EGL - if (((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) || - SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, false)) -#ifdef SDL_VIDEO_OPENGL_GLX - && (!_this->gl_data || X11_GL_UseEGL(_this)) -#endif - ) { - vinfo = X11_GLES_GetVisual(_this, display, screen, transparent); - } else -#endif - { -#ifdef SDL_VIDEO_OPENGL_GLX - vinfo = X11_GL_GetVisual(_this, display, screen, transparent); -#endif - } - - if (!vinfo) { - return false; - } - 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) || force_override_redirect) ? True : False; - xattr.backing_store = NotUseful; - 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 false; - } - 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); - } - - if (window->undefined_x && window->undefined_y && - window->last_displayID == SDL_GetPrimaryDisplay()) { - undefined_position = true; - } - - if (SDL_WINDOW_IS_POPUP(window)) { - X11_ConstrainPopup(window, false); - } - SDL_RelativeToGlobalForWindow(window, - window->floating.x, window->floating.y, - &win_x, &win_y); - - /* Always create this with the window->floating.* fields; if we're creating a windowed mode window, - * that's fine. If we're creating a maximized or fullscreen window, the window manager will want to - * know these values so it can use them if we go _back_ to the base floating windowed mode. SDL manages - * migration to fullscreen after CreateSDLWindow returns, which will put all the SDL_Window fields and - * system state as expected. - */ - w = X11_XCreateWindow(display, RootWindow(display, screen), - win_x, win_y, window->floating.w, window->floating.h, - 0, depth, InputOutput, visual, - (CWOverrideRedirect | CWBackPixmap | CWBorderPixel | - CWBackingStore | CWColormap), - &xattr); - if (!w) { - return SDL_SetError("Couldn't create window"); - } - - /* Don't set the borderless flag if we're about to go fullscreen. - * This prevents the window manager from moving a full-screen borderless - * window to a different display before we actually go fullscreen. - */ - if (!(window->pending_flags & SDL_WINDOW_FULLSCREEN)) { - SetWindowBordered(display, screen, w, !(window->flags & SDL_WINDOW_BORDERLESS)); - } - - sizehints = X11_XAllocSizeHints(); - // Setup the normal size hints - sizehints->flags = 0; - if (!(window->flags & SDL_WINDOW_RESIZABLE)) { - sizehints->min_width = sizehints->max_width = window->floating.w; - sizehints->min_height = sizehints->max_height = window->floating.h; - sizehints->flags |= (PMaxSize | PMinSize); - } - if (!undefined_position) { - sizehints->x = win_x; - sizehints->y = win_y; - sizehints->flags |= USPosition; - } - - // Setup the input hints so we get keyboard input - wmhints = X11_XAllocWMHints(); - wmhints->input = !(window->flags & SDL_WINDOW_NOT_FOCUSABLE) ? True : False; - 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 = (char *)SDL_GetExeName(); - classhints->res_class = (char *)SDL_GetAppID(); - - // 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 - hint = SDL_GetHint(SDL_HINT_X11_WINDOW_TYPE); - 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 if (hint && *hint) { - wintype_name = hint; - } 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, 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[4]; - int proto_count = 0; - - protocols[proto_count++] = data->atoms.WM_DELETE_WINDOW; // Allow window to be deleted by the WM - protocols[proto_count++] = data->atoms.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, true)) { - protocols[proto_count++] = data->atoms._NET_WM_PING; // Respond so WM knows we're alive - } - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - if (use_resize_sync) { - protocols[proto_count++] = data->atoms._NET_WM_SYNC_REQUEST; /* Respond after completing resize */ - } -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - - SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0])); - - X11_XSetWMProtocols(display, w, protocols, proto_count); - } - - if (!SetupWindowData(_this, window, w)) { - X11_XDestroyWindow(display, w); - return false; - } - windowdata = window->internal; - - // Set the parent if this is a non-popup window. - if (!SDL_WINDOW_IS_POPUP(window) && window->parent) { - X11_XSetTransientForHint(display, w, window->parent->internal->xwindow); - } - - // Set the flag if the borders were forced on when creating a fullscreen window for later removal. - windowdata->fullscreen_borders_forced_on = !!(window->pending_flags & SDL_WINDOW_FULLSCREEN) && - !!(window->flags & SDL_WINDOW_BORDERLESS); - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - if (use_resize_sync) { - X11_InitResizeSync(window); - } -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - -#if defined(SDL_VIDEO_OPENGL_ES) || defined(SDL_VIDEO_OPENGL_ES2) || defined(SDL_VIDEO_OPENGL_EGL) - if ((window->flags & SDL_WINDOW_OPENGL) && - ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) || - SDL_GetHintBoolean(SDL_HINT_VIDEO_FORCE_EGL, false)) -#ifdef SDL_VIDEO_OPENGL_GLX - && (!_this->gl_data || X11_GL_UseEGL(_this)) -#endif - ) { -#ifdef SDL_VIDEO_OPENGL_EGL - if (!_this->egl_data) { - return false; - } - - // Create the GLES window surface - windowdata->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)w); - - if (windowdata->egl_surface == EGL_NO_SURFACE) { - 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 SDL_VIDEO_DRIVER_X11_XSHAPE - // Tooltips do not receive input - if (window->flags & SDL_WINDOW_TOOLTIP) { - Region region = X11_XCreateRegion(); - X11_XShapeCombineRegion(display, w, ShapeInput, 0, 0, region, ShapeSet); - X11_XDestroyRegion(region); - } -#endif - - SetupWindowInput(_this, window); - - // For _ICC_PROFILE. - X11_XSelectInput(display, RootWindow(display, screen), PropertyChangeMask); - - X11_XFlush(display); - - return true; -} - -char *X11_GetWindowTitle(SDL_VideoDevice *_this, Window xwindow) -{ - SDL_VideoData *data = _this->internal; - 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->atoms._NET_WM_NAME, - 0L, 8192L, False, data->atoms.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); - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Failed to convert WM_NAME title expecting UTF8! Title: %s", title); - X11_XFree(propdata); - } else { - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Could not get any window title response from Xorg, returning empty string!"); - title = SDL_strdup(""); - } - } - return title; -} - -void X11_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - Window xwindow = data->xwindow; - Display *display = data->videodata->display; - char *title = window->title ? window->title : ""; - - SDL_X11_SetWindowTitle(display, xwindow, title); -} - -static bool caught_x11_error = false; -static int X11_CatchAnyError(Display *d, XErrorEvent *e) -{ - /* this may happen during tumultuous times when we are polling anyhow, - so just note we had an error and return control. */ - caught_x11_error = true; - return 0; -} - -/* Wait a brief time, or not, to see if the window manager decided to move/resize the window. - * Send MOVED and RESIZED window events */ -static bool X11_SyncWindowTimeout(SDL_VideoDevice *_this, SDL_Window *window, Uint64 param_timeout) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - int (*prev_handler)(Display *, XErrorEvent *); - Uint64 timeout = 0; - bool force_exit = false; - bool result = true; - - X11_XSync(display, False); - prev_handler = X11_XSetErrorHandler(X11_CatchAnyError); - - if (param_timeout) { - timeout = SDL_GetTicksNS() + param_timeout; - } - - while (true) { - X11_XSync(display, False); - X11_PumpEvents(_this); - - if ((data->pending_operation & X11_PENDING_OP_MOVE) && (window->x == data->expected.x + data->border_left && window->y == data->expected.y + data->border_top)) { - data->pending_operation &= ~X11_PENDING_OP_MOVE; - } - if ((data->pending_operation & X11_PENDING_OP_RESIZE) && (window->w == data->expected.w && window->h == data->expected.h)) { - data->pending_operation &= ~X11_PENDING_OP_RESIZE; - } - - if (data->pending_operation == X11_PENDING_OP_NONE) { - if (force_exit || - (window->x == data->expected.x + data->border_left && window->y == data->expected.y + data->border_top && - window->w == data->expected.w && window->h == data->expected.h)) { - // The window is in the expected state and nothing is pending. Done. - break; - } - - /* No operations are pending, but the window still isn't in the expected state. - * Try one more time before exiting. - */ - force_exit = true; - } - - if (SDL_GetTicksNS() >= timeout) { - // Timed out without the expected values. Update the requested data so future sync calls won't block. - data->expected.x = window->x; - data->expected.y = window->y; - data->expected.w = window->w; - data->expected.h = window->h; - - result = false; - break; - } - - SDL_Delay(10); - } - - data->pending_operation = X11_PENDING_OP_NONE; - - if (!caught_x11_error) { - X11_PumpEvents(_this); - } else { - result = false; - } - - X11_XSetErrorHandler(prev_handler); - caught_x11_error = false; - - return result; -} - -bool X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - Atom _NET_WM_ICON = data->videodata->atoms._NET_WM_ICON; - int (*prevHandler)(Display *, XErrorEvent *) = NULL; - bool result = true; - - if (icon) { - int x, y; - int propsize; - long *propdata; - Uint32 *src; - long *dst; - - // Set the _NET_WM_ICON property - SDL_assert(icon->format == SDL_PIXELFORMAT_ARGB8888); - propsize = 2 + (icon->w * icon->h); - propdata = SDL_malloc(propsize * sizeof(long)); - - if (!propdata) { - return false; - } - - X11_XSync(display, False); - prevHandler = X11_XSetErrorHandler(X11_CatchAnyError); - - 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); - - if (caught_x11_error) { - result = SDL_SetError("An error occurred while trying to set the window's icon"); - } - } - - X11_XFlush(display); - - if (prevHandler) { - X11_XSetErrorHandler(prevHandler); - caught_x11_error = false; - } - - return result; -} - -void X11_UpdateWindowPosition(SDL_Window *window, bool use_current_position) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - const int rel_x = use_current_position ? window->x : window->pending.x; - const int rel_y = use_current_position ? window->y : window->pending.y; - - SDL_RelativeToGlobalForWindow(window, - rel_x - data->border_left, rel_y - data->border_top, - &data->expected.x, &data->expected.y); - - // Attempt to move the window - if (window->flags & SDL_WINDOW_HIDDEN) { - window->internal->pending_position = true; - } else { - data->pending_operation |= X11_PENDING_OP_MOVE; - X11_XMoveWindow(display, data->xwindow, data->expected.x, data->expected.y); - } -} - -bool X11_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) -{ - // Sync any pending fullscreen or maximize events. - if (window->internal->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE)) { - X11_FlushPendingEvents(_this, window); - } - - // Set the position as pending if the window is maximized with a restore pending. - if (window->flags & SDL_WINDOW_MAXIMIZED) { - if (window->internal->pending_operation & X11_PENDING_OP_RESTORE) { - window->internal->pending_position = true; - } - return true; - } - - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - if (SDL_WINDOW_IS_POPUP(window)) { - X11_ConstrainPopup(window, true); - } - X11_UpdateWindowPosition(window, false); - } else { - SDL_UpdateFullscreenMode(window, SDL_FULLSCREEN_OP_UPDATE, true); - } - return true; -} - -void X11_SetWindowMinMax(SDL_Window *window, bool use_current) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - XSizeHints *sizehints = X11_XAllocSizeHints(); - long hint_flags = 0; - - X11_XGetWMNormalHints(display, data->xwindow, sizehints, &hint_flags); - sizehints->flags &= ~(PMinSize | PMaxSize | PAspect); - - if (data->window->flags & SDL_WINDOW_RESIZABLE) { - if (data->window->min_w || data->window->min_h) { - sizehints->flags |= PMinSize; - sizehints->min_width = data->window->min_w; - sizehints->min_height = data->window->min_h; - } - if (data->window->max_w || data->window->max_h) { - sizehints->flags |= PMaxSize; - sizehints->max_width = data->window->max_w; - sizehints->max_height = data->window->max_h; - } - if (data->window->min_aspect > 0.0f || data->window->max_aspect > 0.0f) { - sizehints->flags |= PAspect; - SDL_CalculateFraction(data->window->min_aspect, &sizehints->min_aspect.x, &sizehints->min_aspect.y); - SDL_CalculateFraction(data->window->max_aspect, &sizehints->max_aspect.x, &sizehints->max_aspect.y); - } - } else { - // Set the min/max to the same values to make the window non-resizable - sizehints->flags |= PMinSize | PMaxSize; - sizehints->min_width = sizehints->max_width = use_current ? data->window->floating.w : window->windowed.w; - sizehints->min_height = sizehints->max_height = use_current ? data->window->floating.h : window->windowed.h; - } - - X11_XSetWMNormalHints(display, data->xwindow, sizehints); - X11_XFree(sizehints); -} - -void X11_SetWindowMinimumSize(SDL_VideoDevice *_this, SDL_Window *window) -{ - if (window->internal->pending_operation & X11_PENDING_OP_FULLSCREEN) { - X11_SyncWindow(_this, window); - } - - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - X11_SetWindowMinMax(window, true); - } -} - -void X11_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *window) -{ - if (window->internal->pending_operation & X11_PENDING_OP_FULLSCREEN) { - X11_SyncWindow(_this, window); - } - - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - X11_SetWindowMinMax(window, true); - } -} - -void X11_SetWindowAspectRatio(SDL_VideoDevice *_this, SDL_Window *window) -{ - if (window->internal->pending_operation & X11_PENDING_OP_FULLSCREEN) { - X11_SyncWindow(_this, window); - } - - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - X11_SetWindowMinMax(window, true); - } -} - -void X11_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - - /* Wait for pending maximize and fullscreen operations to complete, as these windows - * don't get size changes. - */ - if (data->pending_operation & (X11_PENDING_OP_MAXIMIZE | X11_PENDING_OP_FULLSCREEN)) { - X11_FlushPendingEvents(_this, window); - } - - // Set the size as pending if the window is being restored. - if (window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN)) { - // New size will be set when the window is restored. - if (data->pending_operation & X11_PENDING_OP_RESTORE) { - data->pending_size = true; - } else { - // Can't resize the window. - window->last_size_pending = false; - } - return; - } - - if (!(window->flags & SDL_WINDOW_RESIZABLE)) { - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - /* 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; - int dest_x, dest_y; - - X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints); - - sizehints->min_width = sizehints->max_width = window->pending.w; - sizehints->min_height = sizehints->max_height = window->pending.h; - sizehints->flags |= PMinSize | PMaxSize; - - X11_XSetWMNormalHints(display, data->xwindow, 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->pending.w, window->pending.h); - const int x = window->last_position_pending ? window->pending.x : window->x; - const int y = window->last_position_pending ? window->pending.y : window->y; - SDL_RelativeToGlobalForWindow(window, - x - data->border_left, - y - data->border_top, - &dest_x, &dest_y); - X11_XMoveWindow(display, data->xwindow, dest_x, dest_y); - X11_XRaiseWindow(display, data->xwindow); - - X11_XFree(sizehints); - } - } else { - data->expected.w = window->pending.w; - data->expected.h = window->pending.h; - data->pending_operation |= X11_PENDING_OP_RESIZE; - X11_XResizeWindow(display, data->xwindow, data->expected.w, data->expected.h); - } -} - -bool X11_GetWindowBordersSize(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right) -{ - SDL_WindowData *data = window->internal; - - *left = data->border_left; - *right = data->border_right; - *top = data->border_top; - *bottom = data->border_bottom; - - return true; -} - -bool X11_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - Atom _NET_WM_WINDOW_OPACITY = data->videodata->atoms._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 true; -} - -bool X11_SetWindowParent(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window *parent) -{ - SDL_WindowData *data = window->internal; - SDL_WindowData *parent_data = parent ? parent->internal : NULL; - SDL_VideoData *video_data = _this->internal; - Display *display = video_data->display; - - if (parent_data) { - X11_XSetTransientForHint(display, data->xwindow, parent_data->xwindow); - } else { - X11_XDeleteProperty(display, data->xwindow, video_data->atoms.WM_TRANSIENT_FOR); - } - - return true; -} - -bool X11_SetWindowModal(SDL_VideoDevice *_this, SDL_Window *window, bool modal) -{ - SDL_WindowData *data = window->internal; - SDL_VideoData *video_data = _this->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - Display *display = video_data->display; - Uint32 flags = window->flags; - Atom _NET_WM_STATE = data->videodata->atoms._NET_WM_STATE; - Atom _NET_WM_STATE_MODAL = data->videodata->atoms._NET_WM_STATE_MODAL; - - if (modal) { - flags |= SDL_WINDOW_MODAL; - } else { - flags &= ~SDL_WINDOW_MODAL; - X11_XDeleteProperty(display, data->xwindow, video_data->atoms.WM_TRANSIENT_FOR); - } - - 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] = modal ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; - e.xclient.data.l[1] = _NET_WM_STATE_MODAL; - e.xclient.data.l[3] = 0l; - - X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0, - SubstructureNotifyMask | SubstructureRedirectMask, &e); - } else { - X11_SetNetWMState(_this, data->xwindow, flags); - } - - X11_XFlush(display); - - return true; -} - -void X11_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, bool bordered) -{ - const bool focused = (window->flags & SDL_WINDOW_INPUT_FOCUS) ? true : false; - const bool visible = (!(window->flags & SDL_WINDOW_HIDDEN)) ? true : false; - SDL_WindowData *data = window->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - Display *display = data->videodata->display; - XEvent event; - - if (data->pending_operation & X11_PENDING_OP_FULLSCREEN) { - X11_SyncWindow(_this, window); - } - - // If the window is fullscreen, the resize capability will be set/cleared when it is returned to windowed mode. - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - 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); - - // Turning the borders off doesn't send an extent event, so they must be cleared here. - X11_GetBorderValues(data); - - // Make sure the window manager didn't resize our window for the difference. - X11_XResizeWindow(display, data->xwindow, window->floating.w, window->floating.h); - X11_XSync(display, False); - } else { - // If fullscreen, set a flag to toggle the borders when returning to windowed mode. - data->toggle_borders = true; - data->fullscreen_borders_forced_on = false; - } -} - -void X11_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, bool resizable) -{ - SDL_WindowData *data = window->internal; - - if (data->pending_operation & X11_PENDING_OP_FULLSCREEN) { - X11_SyncWindow(_this, window); - } - - // If the window is fullscreen, the resize capability will be set/cleared when it is returned to windowed mode. - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - X11_SetWindowMinMax(window, true); - } -} - -void X11_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, bool on_top) -{ - SDL_WindowData *data = window->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - Display *display = data->videodata->display; - Atom _NET_WM_STATE = data->videodata->atoms._NET_WM_STATE; - Atom _NET_WM_STATE_ABOVE = data->videodata->atoms._NET_WM_STATE_ABOVE; - - 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] = - on_top ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; - e.xclient.data.l[1] = _NET_WM_STATE_ABOVE; - 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_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - bool bActivate = SDL_GetHintBoolean(SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN, true); - bool position_is_absolute = false; - bool set_position = false; - XEvent event; - - if (SDL_WINDOW_IS_POPUP(window)) { - // Update the position in case the parent moved while we were hidden - X11_ConstrainPopup(window, true); - data->pending_position = true; - - // Coordinates after X11_ConstrainPopup() are already in the global space. - position_is_absolute = true; - set_position = true; - } - - /* Whether XMapRaised focuses the window is based on the window type and it is - * wm specific. There isn't much we can do here */ - (void)bActivate; - - 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_EXTERNAL) && X11_IsDisplayOk(display)) { - X11_XIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow); - } - X11_XFlush(display); - set_position = data->pending_position || - (!(window->flags & SDL_WINDOW_BORDERLESS) && !window->undefined_x && !window->undefined_y); - } - - if (!data->videodata->net_wm) { - // no WM means no FocusIn event, which confuses us. Force it. - X11_XSync(display, False); - X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime); - X11_XFlush(display); - } - - // Popup menus grab the keyboard - if (window->flags & SDL_WINDOW_POPUP_MENU) { - X11_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus()); - } - - // Get some valid border values, if we haven't received them yet - if (data->border_left == 0 && data->border_right == 0 && data->border_top == 0 && data->border_bottom == 0) { - X11_GetBorderValues(data); - } - - if (set_position) { - // Apply the window position, accounting for offsets due to the borders appearing. - const int tx = data->pending_position ? window->pending.x : window->x; - const int ty = data->pending_position ? window->pending.y : window->y; - int x, y; - if (position_is_absolute) { - x = tx; - y = ty; - } else { - SDL_RelativeToGlobalForWindow(window, - tx - data->border_left, ty - data->border_top, - &x, &y); - } - data->pending_position = false; - X11_XMoveWindow(display, data->xwindow, x, y); - } - - /* Some window managers can send garbage coordinates while mapping the window, so don't emit size and position - * events during the initial configure events. - */ - data->size_move_event_flags = X11_SIZE_MOVE_EVENTS_DISABLE; - X11_XSync(display, False); - X11_PumpEvents(_this); - data->size_move_event_flags = 0; - - // If a configure event was received (type is non-zero), send the final window size and coordinates. - if (data->last_xconfigure.type) { - int x, y; - SDL_GlobalToRelativeForWindow(data->window, data->last_xconfigure.x, data->last_xconfigure.y, &x, &y); - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, data->last_xconfigure.width, data->last_xconfigure.height); - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y); - } -} - -void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - int screen = (displaydata ? displaydata->screen : 0); - Display *display = data->videodata->display; - XEvent event; - - if (X11_IsWindowMapped(_this, window)) { - X11_XWithdrawWindow(display, data->xwindow, screen); - // Blocking wait for "UnmapNotify" event - if (!(window->flags & SDL_WINDOW_EXTERNAL) && X11_IsDisplayOk(display)) { - X11_XIfEvent(display, &event, &isUnmapNotify, (XPointer)&data->xwindow); - } - X11_XFlush(display); - } - - // Transfer keyboard focus back to the parent - if (window->flags & SDL_WINDOW_POPUP_MENU) { - SDL_Window *new_focus = window->parent; - bool set_focus = window == SDL_GetKeyboardFocus(); - - // Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed. - while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) { - new_focus = new_focus->parent; - - // If some window in the chain currently had focus, set it to the new lowest-level window. - if (!set_focus) { - set_focus = new_focus == SDL_GetKeyboardFocus(); - } - } - - X11_SetKeyboardFocus(new_focus, set_focus); - } - - X11_XSync(display, False); - X11_PumpEvents(_this); -} - -static bool X11_SetWindowActive(SDL_VideoDevice *_this, SDL_Window *window) -{ - CHECK_WINDOW_DATA(window); - - SDL_WindowData *data = window->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - Display *display = data->videodata->display; - Atom _NET_ACTIVE_WINDOW = data->videodata->atoms._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); - } - return true; -} - -void X11_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - bool bActivate = SDL_GetHintBoolean(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, true); - - X11_XRaiseWindow(display, data->xwindow); - if (bActivate) { - X11_SetWindowActive(_this, window); - } - X11_XFlush(display); -} - -static bool X11_SetWindowMaximized(SDL_VideoDevice *_this, SDL_Window *window, bool maximized) -{ - CHECK_WINDOW_DATA(window); - - SDL_WindowData *data = window->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - Display *display = data->videodata->display; - Atom _NET_WM_STATE = data->videodata->atoms._NET_WM_STATE; - Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->atoms._NET_WM_STATE_MAXIMIZED_VERT; - Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->atoms._NET_WM_STATE_MAXIMIZED_HORZ; - - if (window->flags & SDL_WINDOW_FULLSCREEN) { - /* Fullscreen windows are maximized on some window managers, - and this is functional behavior, so don't remove that state - now, we'll take care of it when we leave fullscreen mode. - */ - return true; - } - - 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; - - if (maximized) { - SDL_DisplayID displayID = SDL_GetDisplayForWindow(window); - SDL_Rect bounds; - - SDL_zero(bounds); - SDL_GetDisplayUsableBounds(displayID, &bounds); - - data->expected.x = bounds.x + data->border_left; - data->expected.y = bounds.y + data->border_top; - data->expected.w = bounds.w - (data->border_left + data->border_right); - data->expected.h = bounds.h - (data->border_top + data->border_bottom); - } else { - data->expected.x = window->floating.x; - data->expected.y = window->floating.y; - data->expected.w = window->floating.w; - data->expected.h = window->floating.h; - } - - X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0, - SubstructureNotifyMask | SubstructureRedirectMask, &e); - } else { - X11_SetNetWMState(_this, data->xwindow, window->flags); - } - X11_XFlush(display); - - return true; -} - -void X11_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - if (window->internal->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MINIMIZE)) { - SDL_SyncWindow(window); - } - - if (window->flags & SDL_WINDOW_FULLSCREEN) { - // If fullscreen, just toggle the restored state. - window->internal->window_was_maximized = true; - return; - } - - if (!(window->flags & SDL_WINDOW_MINIMIZED)) { - window->internal->pending_operation |= X11_PENDING_OP_MAXIMIZE; - X11_SetWindowMaximized(_this, window, true); - } -} - -void X11_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - Display *display = data->videodata->display; - - if (data->pending_operation & SDL_WINDOW_FULLSCREEN) { - SDL_SyncWindow(window); - } - - data->pending_operation |= X11_PENDING_OP_MINIMIZE; - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - data->window_was_maximized = !!(window->flags & SDL_WINDOW_MAXIMIZED); - } - X11_XIconifyWindow(display, data->xwindow, displaydata->screen); - X11_XFlush(display); -} - -void X11_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - if (window->internal->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE | X11_PENDING_OP_MINIMIZE)) { - SDL_SyncWindow(window); - } - - if ((window->flags & SDL_WINDOW_FULLSCREEN) && !(window->flags & SDL_WINDOW_MINIMIZED)) { - // If fullscreen and not minimized, just toggle the restored state. - window->internal->window_was_maximized = false; - return; - } - - if (window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED) || - (window->internal->pending_operation & X11_PENDING_OP_MINIMIZE)) { - window->internal->pending_operation |= X11_PENDING_OP_RESTORE; - } - - // If the window was minimized while maximized, restore as maximized. - const bool maximize = !!(window->flags & SDL_WINDOW_MINIMIZED) && window->internal->window_was_maximized; - X11_SetWindowMaximized(_this, window, maximize); - X11_ShowWindow(_this, window); - X11_SetWindowActive(_this, window); -} - -// This asks the Window Manager to handle fullscreen for us. This is the modern way. -static SDL_FullscreenResult X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_FullscreenOp fullscreen) -{ - CHECK_WINDOW_DATA(window); - CHECK_DISPLAY_DATA(_display); - - SDL_WindowData *data = window->internal; - SDL_DisplayData *displaydata = _display->internal; - Display *display = data->videodata->display; - Atom _NET_WM_STATE = data->videodata->atoms._NET_WM_STATE; - Atom _NET_WM_STATE_FULLSCREEN = data->videodata->atoms._NET_WM_STATE_FULLSCREEN; - - if (X11_IsWindowMapped(_this, window)) { - XEvent e; - - // Flush any pending fullscreen events. - if (data->pending_operation & (X11_PENDING_OP_FULLSCREEN | X11_PENDING_OP_MAXIMIZE | X11_PENDING_OP_MOVE)) { - X11_SyncWindow(_this, window); - } - - if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - if (fullscreen == SDL_FULLSCREEN_OP_UPDATE) { - // Request was out of date; set -1 to signal the video core to undo a mode switch. - return SDL_FULLSCREEN_FAILED; - } else if (fullscreen == SDL_FULLSCREEN_OP_LEAVE) { - // Nothing to do. - return SDL_FULLSCREEN_SUCCEEDED; - } - } - - if (fullscreen && !(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); - // we are going fullscreen so turn the flags off - sizehints->flags &= ~(PMinSize | PMaxSize | PAspect); - 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); - - if (!!(window->flags & SDL_WINDOW_FULLSCREEN) != fullscreen) { - data->pending_operation |= X11_PENDING_OP_FULLSCREEN; - } - - // Set the position so the window will be on the target display - if (fullscreen) { - SDL_DisplayID current = SDL_GetDisplayForWindowPosition(window); - SDL_copyp(&data->requested_fullscreen_mode, &window->current_fullscreen_mode); - if (fullscreen != !!(window->flags & SDL_WINDOW_FULLSCREEN)) { - data->window_was_maximized = !!(window->flags & SDL_WINDOW_MAXIMIZED); - } - data->expected.x = displaydata->x; - data->expected.y = displaydata->y; - data->expected.w = _display->current_mode->w; - data->expected.h = _display->current_mode->h; - - // Only move the window if it isn't fullscreen or already on the target display. - if (!(window->flags & SDL_WINDOW_FULLSCREEN) || (!current || current != _display->id)) { - X11_XMoveWindow(display, data->xwindow, displaydata->x, displaydata->y); - data->pending_operation |= X11_PENDING_OP_MOVE; - } - } else { - SDL_zero(data->requested_fullscreen_mode); - - /* Fullscreen windows sometimes end up being marked maximized by - * window managers. Force it back to how we expect it to be. - */ - SDL_zero(e); - e.xany.type = ClientMessage; - e.xclient.message_type = _NET_WM_STATE; - e.xclient.format = 32; - e.xclient.window = data->xwindow; - if (data->window_was_maximized) { - e.xclient.data.l[0] = _NET_WM_STATE_ADD; - } else { - e.xclient.data.l[0] = _NET_WM_STATE_REMOVE; - } - e.xclient.data.l[1] = data->videodata->atoms._NET_WM_STATE_MAXIMIZED_VERT; - e.xclient.data.l[2] = data->videodata->atoms._NET_WM_STATE_MAXIMIZED_HORZ; - e.xclient.data.l[3] = 0l; - X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0, - SubstructureNotifyMask | SubstructureRedirectMask, &e); - } - } else { - SDL_WindowFlags 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); - } - } - - return SDL_FULLSCREEN_PENDING; -} - -SDL_FullscreenResult X11_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_FullscreenOp fullscreen) -{ - return X11_SetWindowFullscreenViaWM(_this, window, _display, fullscreen); -} - -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) { - 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; -} - -void *X11_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - XWindowAttributes attributes; - Atom icc_profile_atom; - char icc_atom_string[sizeof("_ICC_PROFILE_") + 12]; - void *ret_icc_profile_data = NULL; - CARD8 *icc_profile_data; - int real_format; - unsigned long real_nitems; - SDL_x11Prop atomProp; - - X11_XGetWindowAttributes(display, data->xwindow, &attributes); - if (X11_XScreenNumberOfScreen(attributes.screen) > 0) { - (void)SDL_snprintf(icc_atom_string, sizeof("_ICC_PROFILE_") + 12, "%s%d", "_ICC_PROFILE_", X11_XScreenNumberOfScreen(attributes.screen)); - } else { - SDL_strlcpy(icc_atom_string, "_ICC_PROFILE", sizeof("_ICC_PROFILE")); - } - X11_XGetWindowAttributes(display, RootWindowOfScreen(attributes.screen), &attributes); - - icc_profile_atom = X11_XInternAtom(display, icc_atom_string, True); - if (icc_profile_atom == None) { - SDL_SetError("Screen is not calibrated."); - return NULL; - } - - X11_ReadProperty(&atomProp, display, RootWindowOfScreen(attributes.screen), icc_profile_atom); - real_format = atomProp.format; - real_nitems = atomProp.count; - icc_profile_data = atomProp.data; - if (real_format == None) { - SDL_SetError("Screen is not calibrated."); - return NULL; - } - - ret_icc_profile_data = SDL_malloc(real_nitems); - if (!ret_icc_profile_data) { - return NULL; - } - - SDL_memcpy(ret_icc_profile_data, icc_profile_data, real_nitems); - *size = real_nitems; - X11_XFree(icc_profile_data); - - return ret_icc_profile_data; -} - -bool X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, bool grabbed) -{ - SDL_WindowData *data = window->internal; - Display *display; - - if (!data) { - return SDL_SetError("Invalid window data"); - } - data->mouse_grabbed = false; - - display = data->videodata->display; - - if (grabbed) { - /* If the window is unmapped, XGrab calls return GrabNotViewable, - so when we get a MapNotify later, we'll try to update the grab as - appropriate. */ - if (window->flags & SDL_WINDOW_HIDDEN) { - return true; - } - - /* If XInput2 is enabled, it will grab the pointer on button presses, - * which results in XGrabPointer returning AlreadyGrabbed. If buttons - * are currently pressed, clear any existing grabs before attempting - * the confinement grab. - */ - if (data->xinput2_mouse_enabled && SDL_GetMouseState(NULL, NULL)) { - X11_XUngrabPointer(display, CurrentTime); - } - - // Try to grab the mouse - if (!data->videodata->broken_pointer_grab) { - const unsigned int mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask | FocusChangeMask; - int attempts; - int result = 0; - - // 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, False, mask, GrabModeAsync, - GrabModeAsync, data->xwindow, None, CurrentTime); - if (result == GrabSuccess) { - data->mouse_grabbed = true; - break; - } - SDL_Delay(50); - } - - if (result != GrabSuccess) { - data->videodata->broken_pointer_grab = true; // don't try again. - } - } - - X11_Xinput2GrabTouch(_this, window); - - // Raise the window if we grab the mouse - X11_XRaiseWindow(display, data->xwindow); - } else { - X11_XUngrabPointer(display, CurrentTime); - - X11_Xinput2UngrabTouch(_this, window); - } - X11_XSync(display, False); - - if (!data->videodata->broken_pointer_grab) { - return true; - } else { - return SDL_SetError("The X server refused to let us grab the mouse. You might experience input bugs."); - } -} - -bool X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, bool grabbed) -{ - SDL_WindowData *data = window->internal; - Display *display; - - if (!data) { - return SDL_SetError("Invalid window data"); - } - - display = data->videodata->display; - - if (grabbed) { - /* If the window is unmapped, XGrab calls return GrabNotViewable, - so when we get a MapNotify later, we'll try to update the grab as - appropriate. */ - if (window->flags & SDL_WINDOW_HIDDEN) { - return true; - } - - X11_XGrabKeyboard(display, data->xwindow, True, GrabModeAsync, - GrabModeAsync, CurrentTime); - } else { - X11_XUngrabKeyboard(display, CurrentTime); - } - X11_XSync(display, False); - - return true; -} - -void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - - if (data) { - SDL_VideoData *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); - SDL_free(data->preedit_text); - SDL_free(data->preedit_feedback); - } -#endif - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - X11_TermResizeSync(window); -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - - if (!(window->flags & SDL_WINDOW_EXTERNAL)) { - X11_XDestroyWindow(display, data->xwindow); - X11_XFlush(display); - } - SDL_free(data); - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - // If the pointer barriers are active for this, deactivate it. - if (videodata->active_cursor_confined_window == window) { - X11_DestroyPointerBarrier(_this, window); - } -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - } - window->internal = NULL; -} - -bool X11_SetWindowHitTest(SDL_Window *window, bool enabled) -{ - return true; // just succeed, the real work is done elsewhere. -} - -void X11_AcceptDragAndDrop(SDL_Window *window, bool accept) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - Atom XdndAware = data->videodata->atoms.XdndAware; - - 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); - } -} - -bool X11_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - XWMHints *wmhints; - - wmhints = X11_XGetWMHints(display, data->xwindow); - if (!wmhints) { - return SDL_SetError("Couldn't get WM hints"); - } - - wmhints->flags &= ~XUrgencyHint; - data->flashing_window = false; - data->flash_cancel_time = 0; - - switch (operation) { - case SDL_FLASH_CANCEL: - // Taken care of above - break; - case SDL_FLASH_BRIEFLY: - if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) { - wmhints->flags |= XUrgencyHint; - data->flashing_window = true; - // On Ubuntu 21.04 this causes a dialog to pop up, so leave it up for a full second so users can see it - data->flash_cancel_time = SDL_GetTicks() + 1000; - } - break; - case SDL_FLASH_UNTIL_FOCUSED: - if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) { - wmhints->flags |= XUrgencyHint; - data->flashing_window = true; - } - break; - default: - break; - } - - X11_XSetWMHints(display, data->xwindow, wmhints); - X11_XFree(wmhints); - return true; -} - -bool SDL_X11_SetWindowTitle(Display *display, Window xwindow, char *title) -{ - Atom _NET_WM_NAME = X11_XInternAtom(display, "_NET_WM_NAME", False); - XTextProperty titleprop; - int conv = X11_XmbTextListToTextProperty(display, &title, 1, XTextStyle, &titleprop); - Status status; - - if (X11_XSupportsLocale() != True) { - return SDL_SetError("Current locale not supported by X server, cannot continue."); - } - - if (conv == 0) { - X11_XSetTextProperty(display, xwindow, &titleprop, XA_WM_NAME); - X11_XFree(titleprop.value); - // we know this can't be a locale error as we checked X locale validity - } else if (conv < 0) { - return SDL_OutOfMemory(); - } else { // conv > 0 - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "%d characters were not convertible to the current locale!", conv); - return true; - } - -#ifdef X_HAVE_UTF8_STRING - status = X11_Xutf8TextListToTextProperty(display, &title, 1, XUTF8StringStyle, &titleprop); - if (status == Success) { - X11_XSetTextProperty(display, xwindow, &titleprop, _NET_WM_NAME); - X11_XFree(titleprop.value); - } else { - return SDL_SetError("Failed to convert title to UTF8! Bad encoding, or bad Xorg encoding? Window title: «%s»", title); - } -#endif - - X11_XFlush(display); - return true; -} - -void X11_ShowWindowSystemMenu(SDL_Window *window, int x, int y) -{ - SDL_WindowData *data = window->internal; - SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window); - Display *display = data->videodata->display; - Window root = RootWindow(display, displaydata->screen); - XClientMessageEvent e; - Window childReturn; - int wx, wy; - - SDL_zero(e); - X11_XTranslateCoordinates(display, data->xwindow, root, x, y, &wx, &wy, &childReturn); - - e.type = ClientMessage; - e.window = data->xwindow; - e.message_type = X11_XInternAtom(display, "_GTK_SHOW_WINDOW_MENU", 0); - e.data.l[0] = 0; // GTK device ID (unused) - e.data.l[1] = wx; // X coordinate relative to root - e.data.l[2] = wy; // Y coordinate relative to root - e.format = 32; - - X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent *)&e); - X11_XFlush(display); -} - -bool X11_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - const Uint64 current_time = SDL_GetTicksNS(); - Uint64 timeout = 0; - - // Allow time for any pending mode switches to complete. - for (int i = 0; i < _this->num_displays; ++i) { - if (_this->displays[i]->internal->mode_switch_deadline_ns && - current_time < _this->displays[i]->internal->mode_switch_deadline_ns) { - timeout = SDL_max(_this->displays[i]->internal->mode_switch_deadline_ns - current_time, timeout); - } - } - - /* 100ms is fine for most cases, but, for some reason, maximizing - * a window can take a very long time. - */ - timeout += window->internal->pending_operation & X11_PENDING_OP_MAXIMIZE ? SDL_MS_TO_NS(1000) : SDL_MS_TO_NS(100); - - return X11_SyncWindowTimeout(_this, window, timeout); -} - -bool X11_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool focusable) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - XWMHints *wmhints; - - wmhints = X11_XGetWMHints(display, data->xwindow); - if (!wmhints) { - return SDL_SetError("Couldn't get WM hints"); - } - - wmhints->input = focusable ? True : False; - wmhints->flags |= InputHint; - - X11_XSetWMHints(display, data->xwindow, wmhints); - X11_XFree(wmhints); - - return true; -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11window.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11window.h deleted file mode 100644 index f1a73ab..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11window.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 - -#ifdef SDL_VIDEO_OPENGL_EGL -#include -#endif - -typedef enum -{ - PENDING_FOCUS_NONE, - PENDING_FOCUS_IN, - PENDING_FOCUS_OUT -} PendingFocusEnum; - -struct SDL_WindowData -{ - SDL_Window *window; - Window xwindow; - Visual *visual; - Colormap colormap; -#ifndef NO_SHARED_MEMORY - // MIT shared memory extension information - bool use_mitshm; - XShmSegmentInfo shminfo; -#endif - XImage *ximage; - GC gc; - XIC ic; - bool created; - int border_left; - int border_right; - int border_top; - int border_bottom; - bool xinput2_mouse_enabled; - bool xinput2_keyboard_enabled; - bool mouse_grabbed; - Uint64 last_focus_event_time; - PendingFocusEnum pending_focus; - Uint64 pending_focus_time; - bool pending_move; - SDL_Point pending_move_point; - XConfigureEvent last_xconfigure; - struct SDL_VideoData *videodata; - unsigned long user_time; - Atom xdnd_req; - Window xdnd_source; - bool flashing_window; - Uint64 flash_cancel_time; - SDL_Window *keyboard_focus; -#ifdef SDL_VIDEO_OPENGL_EGL - EGLSurface egl_surface; -#endif -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - bool pointer_barrier_active; - PointerBarrier barrier[4]; - SDL_Rect barrier_rect; -#endif // SDL_VIDEO_DRIVER_X11_XFIXES -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - XSyncCounter resize_counter; - XSyncValue resize_id; - bool resize_in_progress; -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - - SDL_Rect expected; - SDL_DisplayMode requested_fullscreen_mode; - - enum - { - X11_PENDING_OP_NONE = 0x00, - X11_PENDING_OP_RESTORE = 0x01, - X11_PENDING_OP_MINIMIZE = 0x02, - X11_PENDING_OP_MAXIMIZE = 0x04, - X11_PENDING_OP_FULLSCREEN = 0x08, - X11_PENDING_OP_MOVE = 0x10, - X11_PENDING_OP_RESIZE = 0x20 - } pending_operation; - - enum - { - X11_SIZE_MOVE_EVENTS_DISABLE = 0x01, // Events are completely disabled. - X11_SIZE_MOVE_EVENTS_WAIT_FOR_BORDERS = 0x02, // Events are disabled until a _NET_FRAME_EXTENTS event arrives. - } size_move_event_flags; - - bool pending_size; - bool pending_position; - bool window_was_maximized; - bool previous_borders_nonzero; - bool toggle_borders; - bool fullscreen_borders_forced_on; - SDL_HitTestResult hit_test_result; - - XPoint xim_spot; - char *preedit_text; - XIMFeedback *preedit_feedback; - int preedit_length; - int preedit_cursor; - bool ime_needs_clear_composition; -}; - -extern void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, SDL_WindowFlags flags); -extern Uint32 X11_GetNetWMState(SDL_VideoDevice *_this, SDL_Window *window, Window xwindow); - -extern bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); -extern char *X11_GetWindowTitle(SDL_VideoDevice *_this, Window xwindow); -extern void X11_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *icon); -extern bool X11_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_SetWindowMinimumSize(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_SetWindowAspectRatio(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_GetWindowBordersSize(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right); -extern bool X11_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity); -extern bool X11_SetWindowParent(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window *parent); -extern bool X11_SetWindowModal(SDL_VideoDevice *_this, SDL_Window *window, bool modal); -extern void X11_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_HideWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_SetWindowBordered(SDL_VideoDevice *_this, SDL_Window *window, bool bordered); -extern void X11_SetWindowResizable(SDL_VideoDevice *_this, SDL_Window *window, bool resizable); -extern void X11_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, bool on_top); -extern SDL_FullscreenResult X11_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_FullscreenOp fullscreen); -extern void *X11_GetWindowICCProfile(SDL_VideoDevice *_this, SDL_Window *window, size_t *size); -extern bool X11_SetWindowMouseGrab(SDL_VideoDevice *_this, SDL_Window *window, bool grabbed); -extern bool X11_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, bool grabbed); -extern void X11_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_SetWindowHitTest(SDL_Window *window, bool enabled); -extern void X11_AcceptDragAndDrop(SDL_Window *window, bool accept); -extern bool X11_FlashWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_FlashOperation operation); -extern void X11_ShowWindowSystemMenu(SDL_Window *window, int x, int y); -extern bool X11_SyncWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool focusable); - -extern bool SDL_X11_SetWindowTitle(Display *display, Window xwindow, char *title); -extern void X11_UpdateWindowPosition(SDL_Window *window, bool use_current_position); -extern void X11_SetWindowMinMax(SDL_Window *window, bool use_current); - -#endif // SDL_x11window_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.c deleted file mode 100644 index 517ebc8..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 defined(SDL_VIDEO_DRIVER_X11) && defined(SDL_VIDEO_DRIVER_X11_XFIXES) - -#include "SDL_x11video.h" -#include "SDL_x11xfixes.h" -#include "../../events/SDL_mouse_c.h" -#include "../../events/SDL_touch_c.h" - -static bool xfixes_initialized = true; -static int xfixes_selection_notify_event = 0; - -static int query_xfixes_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_XFixesQueryVersion(display, &major, &minor); - return (major * 1000) + minor; -} - -static bool xfixes_version_atleast(const int version, const int wantmajor, const int wantminor) -{ - return version >= ((wantmajor * 1000) + wantminor); -} - -void X11_InitXfixes(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - - int version = 0; - int event, error; - int fixes_opcode; - - Atom XA_CLIPBOARD = data->atoms.CLIPBOARD; - - if (!SDL_X11_HAVE_XFIXES || - !X11_XQueryExtension(data->display, "XFIXES", &fixes_opcode, &event, &error)) { - return; - } - - // Selection tracking is available in all versions of XFixes - xfixes_selection_notify_event = event + XFixesSelectionNotify; - X11_XFixesSelectSelectionInput(data->display, DefaultRootWindow(data->display), - XA_CLIPBOARD, XFixesSetSelectionOwnerNotifyMask); - X11_XFixesSelectSelectionInput(data->display, DefaultRootWindow(data->display), - XA_PRIMARY, XFixesSetSelectionOwnerNotifyMask); - - // We need at least 5.0 for barriers. - version = query_xfixes_version(data->display, 5, 0); - if (!xfixes_version_atleast(version, 5, 0)) { - return; // X server does not support the version we want at all. - } - - xfixes_initialized = 1; -} - -bool X11_XfixesIsInitialized(void) -{ - return xfixes_initialized; -} - -int X11_GetXFixesSelectionNotifyEvent(void) -{ - return xfixes_selection_notify_event; -} - -bool X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window) -{ - if (SDL_RectEmpty(&window->mouse_rect)) { - X11_ConfineCursorWithFlags(_this, window, NULL, 0); - } else { - if (window->flags & SDL_WINDOW_INPUT_FOCUS) { - X11_ConfineCursorWithFlags(_this, window, &window->mouse_rect, 0); - } else { - // Save the state for when we get focus again - SDL_WindowData *wdata = window->internal; - - SDL_memcpy(&wdata->barrier_rect, &window->mouse_rect, sizeof(wdata->barrier_rect)); - - wdata->pointer_barrier_active = true; - } - } - - return true; -} - -bool X11_ConfineCursorWithFlags(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rect, int flags) -{ - /* Yaakuro: For some reason Xfixes when confining inside a rect where the - * edges exactly match, a rectangle the cursor 'slips' out of the barrier. - * To prevent that the lines for the barriers will span the whole screen. - */ - SDL_VideoData *data = _this->internal; - SDL_WindowData *wdata; - - if (!X11_XfixesIsInitialized()) { - return SDL_Unsupported(); - } - - // If there is already a set of barriers active, disable them. - if (data->active_cursor_confined_window) { - X11_DestroyPointerBarrier(_this, data->active_cursor_confined_window); - } - - SDL_assert(window != NULL); - wdata = window->internal; - - /* If user did not specify an area to confine, destroy the barrier that was/is assigned to - * this window it was assigned */ - if (rect) { - int x1, y1, x2, y2; - SDL_Rect bounds; - SDL_GetWindowPosition(window, &bounds.x, &bounds.y); - SDL_GetWindowSize(window, &bounds.w, &bounds.h); - - /** Negative values are not allowed. Clip values relative to the specified window. */ - x1 = bounds.x + SDL_max(rect->x, 0); - y1 = bounds.y + SDL_max(rect->y, 0); - x2 = SDL_min(bounds.x + rect->x + rect->w, bounds.x + bounds.w); - y2 = SDL_min(bounds.y + rect->y + rect->h, bounds.y + bounds.h); - - if ((wdata->barrier_rect.x != rect->x) || - (wdata->barrier_rect.y != rect->y) || - (wdata->barrier_rect.w != rect->w) || - (wdata->barrier_rect.h != rect->h)) { - wdata->barrier_rect = *rect; - } - - // Use the display bounds to ensure the barriers don't have corner gaps - SDL_GetDisplayBounds(SDL_GetDisplayForWindow(window), &bounds); - - /** Create the left barrier */ - wdata->barrier[0] = X11_XFixesCreatePointerBarrier(data->display, wdata->xwindow, - x1, bounds.y, - x1, bounds.y + bounds.h, - BarrierPositiveX, - 0, NULL); - /** Create the right barrier */ - wdata->barrier[1] = X11_XFixesCreatePointerBarrier(data->display, wdata->xwindow, - x2, bounds.y, - x2, bounds.y + bounds.h, - BarrierNegativeX, - 0, NULL); - /** Create the top barrier */ - wdata->barrier[2] = X11_XFixesCreatePointerBarrier(data->display, wdata->xwindow, - bounds.x, y1, - bounds.x + bounds.w, y1, - BarrierPositiveY, - 0, NULL); - /** Create the bottom barrier */ - wdata->barrier[3] = X11_XFixesCreatePointerBarrier(data->display, wdata->xwindow, - bounds.x, y2, - bounds.x + bounds.w, y2, - BarrierNegativeY, - 0, NULL); - - X11_XFlush(data->display); - - // Lets remember current active confined window. - data->active_cursor_confined_window = window; - - /* User activated the confinement for this window. We use this later to reactivate - * the confinement if it got deactivated by FocusOut or UnmapNotify */ - wdata->pointer_barrier_active = true; - } else { - X11_DestroyPointerBarrier(_this, window); - - // Only set barrier inactive when user specified NULL and not handled by focus out. - if (flags != X11_BARRIER_HANDLED_BY_EVENT) { - wdata->pointer_barrier_active = false; - } - } - return true; -} - -void X11_DestroyPointerBarrier(SDL_VideoDevice *_this, SDL_Window *window) -{ - int i; - SDL_VideoData *data = _this->internal; - if (window) { - SDL_WindowData *wdata = window->internal; - - for (i = 0; i < 4; i++) { - if (wdata->barrier[i] > 0) { - X11_XFixesDestroyPointerBarrier(data->display, wdata->barrier[i]); - wdata->barrier[i] = 0; - } - } - X11_XFlush(data->display); - } - data->active_cursor_confined_window = NULL; -} - -#endif // SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_DRIVER_X11_XFIXES diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.h deleted file mode 100644 index bd8e437..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xfixes.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_x11xfixes_h_ -#define SDL_x11xfixes_h_ - -#ifdef SDL_VIDEO_DRIVER_X11_XFIXES - -#define X11_BARRIER_HANDLED_BY_EVENT 1 - -extern void X11_InitXfixes(SDL_VideoDevice *_this); -extern bool X11_XfixesIsInitialized(void); -extern bool X11_SetWindowMouseRect(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_ConfineCursorWithFlags(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rect, int flags); -extern void X11_DestroyPointerBarrier(SDL_VideoDevice *_this, SDL_Window *window); -extern int X11_GetXFixesSelectionNotifyEvent(void); -#endif // SDL_VIDEO_DRIVER_X11_XFIXES - -#endif // SDL_x11xfixes_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.c deleted file mode 100644 index afe4a7c..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.c +++ /dev/null @@ -1,829 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "SDL_x11pen.h" -#include "SDL_x11video.h" -#include "SDL_x11xinput2.h" -#include "../../events/SDL_events_c.h" -#include "../../events/SDL_mouse_c.h" -#include "../../events/SDL_pen_c.h" -#include "../../events/SDL_touch_c.h" - -#define MAX_AXIS 16 - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 -static bool xinput2_initialized; - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH -static bool xinput2_multitouch_supported; -#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, const 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 bool xinput2_version_atleast(const int version, const int wantmajor, const int wantminor) -{ - return version >= ((wantmajor * 1000) + wantminor); -} - -static SDL_WindowData *xinput2_get_sdlwindowdata(SDL_VideoData *videodata, Window window) -{ - int i; - for (i = 0; i < videodata->numwindows; i++) { - SDL_WindowData *d = videodata->windowlist[i]; - if (d->xwindow == window) { - return d; - } - } - return NULL; -} - -static SDL_Window *xinput2_get_sdlwindow(SDL_VideoData *videodata, Window window) -{ - const SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, window); - return windowdata ? windowdata->window : NULL; -} - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH -static void xinput2_normalize_touch_coordinates(SDL_Window *window, double in_x, double in_y, float *out_x, float *out_y) -{ - if (window) { - if (window->w == 1) { - *out_x = 0.5f; - } else { - *out_x = (float)in_x / (window->w - 1); - } - if (window->h == 1) { - *out_y = 0.5f; - } else { - *out_y = (float)in_y / (window->h - 1); - } - } else { - // couldn't find the window... - *out_x = (float)in_x; - *out_y = (float)in_y; - } -} -#endif // SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - -#endif // SDL_VIDEO_DRIVER_X11_XINPUT2 - -bool X11_InitXinput2(SDL_VideoDevice *_this) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - SDL_VideoData *data = _this->internal; - - int version = 0; - XIEventMask eventmask; - unsigned char mask[4] = { 0, 0, 0, 0 }; - int event, err; - - /* XInput2 is required for relative mouse mode, so you probably want to leave this enabled */ - if (!SDL_GetHintBoolean("SDL_VIDEO_X11_XINPUT2", true)) { - return false; - } - - /* - * 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 false; // 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 false; // X server does not support the version we want at all. - } - - xinput2_initialized = true; - -#ifdef 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 - SDL_zero(eventmask); - SDL_zeroa(mask); - eventmask.deviceid = XIAllMasterDevices; - eventmask.mask_len = sizeof(mask); - eventmask.mask = mask; - - XISetMask(mask, XI_RawMotion); - XISetMask(mask, XI_RawButtonPress); - XISetMask(mask, XI_RawButtonRelease); - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - // Enable raw touch events if supported - if (X11_Xinput2IsMultitouchSupported()) { - XISetMask(mask, XI_RawTouchBegin); - XISetMask(mask, XI_RawTouchUpdate); - XISetMask(mask, XI_RawTouchEnd); - } -#endif - - X11_XISelectEvents(data->display, DefaultRootWindow(data->display), &eventmask, 1); - - SDL_zero(eventmask); - SDL_zeroa(mask); - eventmask.deviceid = XIAllDevices; - eventmask.mask_len = sizeof(mask); - eventmask.mask = mask; - - XISetMask(mask, XI_HierarchyChanged); - X11_XISelectEvents(data->display, DefaultRootWindow(data->display), &eventmask, 1); - - X11_Xinput2UpdateDevices(_this, true); - - return true; -#else - return false; -#endif -} - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 -// xi2 device went away? take it out of the list. -static void xinput2_remove_device_info(SDL_VideoData *videodata, const int device_id) -{ - SDL_XInput2DeviceInfo *prev = NULL; - SDL_XInput2DeviceInfo *devinfo; - - for (devinfo = videodata->mouse_device_info; devinfo; devinfo = devinfo->next) { - if (devinfo->device_id == device_id) { - SDL_assert((devinfo == videodata->mouse_device_info) == (prev == NULL)); - if (!prev) { - videodata->mouse_device_info = devinfo->next; - } else { - prev->next = devinfo->next; - } - SDL_free(devinfo); - return; - } - prev = devinfo; - } -} - -static SDL_XInput2DeviceInfo *xinput2_get_device_info(SDL_VideoData *videodata, const int device_id) -{ - // cache device info as we see new devices. - SDL_XInput2DeviceInfo *prev = NULL; - SDL_XInput2DeviceInfo *devinfo; - XIDeviceInfo *xidevinfo; - int axis = 0; - int i; - - for (devinfo = videodata->mouse_device_info; devinfo; devinfo = devinfo->next) { - if (devinfo->device_id == device_id) { - SDL_assert((devinfo == videodata->mouse_device_info) == (prev == NULL)); - if (prev) { // move this to the front of the list, assuming we'll get more from this one. - prev->next = devinfo->next; - devinfo->next = videodata->mouse_device_info; - videodata->mouse_device_info = devinfo; - } - return devinfo; - } - prev = devinfo; - } - - // don't know about this device yet, query and cache it. - devinfo = (SDL_XInput2DeviceInfo *)SDL_calloc(1, sizeof(SDL_XInput2DeviceInfo)); - if (!devinfo) { - return NULL; - } - - xidevinfo = X11_XIQueryDevice(videodata->display, device_id, &i); - if (!xidevinfo) { - SDL_free(devinfo); - return NULL; - } - - devinfo->device_id = device_id; - - /* !!! FIXME: this is sort of hacky because we only care about the first two axes we see, but any given - !!! FIXME: axis could be relative or absolute, and they might not even be the X and Y axes! - !!! FIXME: But we go on, for now. Maybe we need a more robust mouse API in SDL3... */ - for (i = 0; i < xidevinfo->num_classes; i++) { - const XIValuatorClassInfo *v = (const XIValuatorClassInfo *)xidevinfo->classes[i]; - if (v->type == XIValuatorClass) { - devinfo->relative[axis] = (v->mode == XIModeRelative); - devinfo->minval[axis] = v->min; - devinfo->maxval[axis] = v->max; - if (++axis >= 2) { - break; - } - } - } - - X11_XIFreeDeviceInfo(xidevinfo); - - devinfo->next = videodata->mouse_device_info; - videodata->mouse_device_info = devinfo; - - return devinfo; -} -#endif - -void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - SDL_VideoData *videodata = _this->internal; - - if (cookie->extension != xinput2_opcode) { - return; - } - - switch (cookie->evtype) { - case XI_HierarchyChanged: - { - const XIHierarchyEvent *hierev = (const XIHierarchyEvent *)cookie->data; - int i; - for (i = 0; i < hierev->num_info; i++) { - // pen stuff... - if ((hierev->info[i].flags & (XISlaveRemoved | XIDeviceDisabled)) != 0) { - X11_RemovePenByDeviceID(hierev->info[i].deviceid); // it's okay if this thing isn't actually a pen, it'll handle it. - } else if ((hierev->info[i].flags & (XISlaveAdded | XIDeviceEnabled)) != 0) { - X11_MaybeAddPenByDeviceID(_this, hierev->info[i].deviceid); // this will do more checks to make sure this is valid. - } - - // not pen stuff... - if (hierev->info[i].flags & XISlaveRemoved) { - xinput2_remove_device_info(videodata, hierev->info[i].deviceid); - } - } - videodata->xinput_hierarchy_changed = true; - } break; - - // !!! FIXME: the pen code used to rescan all devices here, but we can do this device-by-device with XI_HierarchyChanged. When do these events fire and why? - //case XI_PropertyEvent: - //case XI_DeviceChanged: - - case XI_RawMotion: - { - const XIRawEvent *rawev = (const XIRawEvent *)cookie->data; - const bool is_pen = X11_FindPenByDeviceID(rawev->sourceid) != NULL; - SDL_Mouse *mouse = SDL_GetMouse(); - SDL_XInput2DeviceInfo *devinfo; - double coords[2]; - double processed_coords[2]; - int i; - Uint64 timestamp = X11_GetEventTimestamp(rawev->time); - - videodata->global_mouse_changed = true; - if (is_pen) { - break; // Pens check for XI_Motion instead - } - - devinfo = xinput2_get_device_info(videodata, rawev->deviceid); - if (!devinfo) { - break; // oh well. - } - - parse_valuators(rawev->raw_values, rawev->valuators.mask, - rawev->valuators.mask_len, coords, 2); - - for (i = 0; i < 2; i++) { - if (devinfo->relative[i]) { - processed_coords[i] = coords[i]; - } else { - processed_coords[i] = devinfo->prev_coords[i] - coords[i]; // convert absolute to relative - } - } - - // Relative mouse motion is delivered to the window with keyboard focus - if (mouse->relative_mode && SDL_GetKeyboardFocus()) { - SDL_SendMouseMotion(timestamp, mouse->focus, (SDL_MouseID)rawev->sourceid, true, (float)processed_coords[0], (float)processed_coords[1]); - } - - devinfo->prev_coords[0] = coords[0]; - devinfo->prev_coords[1] = coords[1]; - } break; - - case XI_KeyPress: - case XI_KeyRelease: - { - const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data; - SDL_WindowData *windowdata = X11_FindWindow(_this, xev->event); - XEvent xevent; - - if (xev->deviceid != xev->sourceid) { - // Discard events from "Master" devices to avoid duplicates. - break; - } - - if (cookie->evtype == XI_KeyPress) { - xevent.type = KeyPress; - } else { - xevent.type = KeyRelease; - } - xevent.xkey.serial = xev->serial; - xevent.xkey.send_event = xev->send_event; - xevent.xkey.display = xev->display; - xevent.xkey.window = xev->event; - xevent.xkey.root = xev->root; - xevent.xkey.subwindow = xev->child; - xevent.xkey.time = xev->time; - xevent.xkey.x = (int)xev->event_x; - xevent.xkey.y = (int)xev->event_y; - xevent.xkey.x_root = (int)xev->root_x; - xevent.xkey.y_root = (int)xev->root_y; - xevent.xkey.state = xev->mods.effective; - xevent.xkey.keycode = xev->detail; - xevent.xkey.same_screen = 1; - - X11_HandleKeyEvent(_this, windowdata, (SDL_KeyboardID)xev->sourceid, &xevent); - } break; - - case XI_RawButtonPress: - case XI_RawButtonRelease: -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - case XI_RawTouchBegin: - case XI_RawTouchUpdate: - case XI_RawTouchEnd: -#endif - { - videodata->global_mouse_changed = true; - } break; - - case XI_ButtonPress: - case XI_ButtonRelease: - { - const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data; - X11_PenHandle *pen = X11_FindPenByDeviceID(xev->deviceid); - const int button = xev->detail; - const bool down = (cookie->evtype == XI_ButtonPress); - - if (pen) { - // Only report button event; if there was also pen movement / pressure changes, we expect an XI_Motion event first anyway. - SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event); - if (button == 1) { // button 1 is the pen tip - SDL_SendPenTouch(0, pen->pen, window, pen->is_eraser, down); - } else { - SDL_SendPenButton(0, pen->pen, window, button - 1, down); - } - } else { - // Otherwise assume a regular mouse - SDL_WindowData *windowdata = xinput2_get_sdlwindowdata(videodata, xev->event); - - if (xev->deviceid != xev->sourceid) { - // Discard events from "Master" devices to avoid duplicates. - break; - } - - if (down) { - X11_HandleButtonPress(_this, windowdata, (SDL_MouseID)xev->sourceid, button, - (float)xev->event_x, (float)xev->event_y, xev->time); - } else { - X11_HandleButtonRelease(_this, windowdata, (SDL_MouseID)xev->sourceid, button, xev->time); - } - } - } break; - - /* Register to receive XI_Motion (which deactivates MotionNotify), so that we can distinguish - real mouse motions from synthetic ones, for multitouch and pen support. */ - case XI_Motion: - { - const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data; -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - bool pointer_emulated = ((xev->flags & XIPointerEmulated) != 0); -#else - bool pointer_emulated = false; -#endif - - videodata->global_mouse_changed = true; - - X11_PenHandle *pen = X11_FindPenByDeviceID(xev->deviceid); - if (pen) { - if (xev->deviceid != xev->sourceid) { - // Discard events from "Master" devices to avoid duplicates. - break; - } - - SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event); - SDL_SendPenMotion(0, pen->pen, window, (float) xev->event_x, (float) xev->event_y); - - float axes[SDL_PEN_AXIS_COUNT]; - X11_PenAxesFromValuators(pen, xev->valuators.values, xev->valuators.mask, xev->valuators.mask_len, axes); - - for (int i = 0; i < SDL_arraysize(axes); i++) { - if (pen->valuator_for_axis[i] != SDL_X11_PEN_AXIS_VALUATOR_MISSING) { - SDL_SendPenAxis(0, pen->pen, window, (SDL_PenAxis) i, axes[i]); - } - } - } else if (!pointer_emulated && xev->deviceid == videodata->xinput_master_pointer_device) { - // Use the master device for non-relative motion, as the slave devices can seemingly lag behind. - SDL_Mouse *mouse = SDL_GetMouse(); - if (!mouse->relative_mode) { - SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event); - if (window) { - X11_ProcessHitTest(_this, window->internal, (float)xev->event_x, (float)xev->event_y, false); - SDL_SendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, (float)xev->event_x, (float)xev->event_y); - } - } - } - } break; - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - case XI_TouchBegin: - { - const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data; - float x, y; - SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event); - xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y); - SDL_SendTouch(0, xev->sourceid, xev->detail, window, SDL_EVENT_FINGER_DOWN, x, y, 1.0); - } break; - - case XI_TouchEnd: - { - const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data; - float x, y; - SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event); - xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y); - SDL_SendTouch(0, xev->sourceid, xev->detail, window, SDL_EVENT_FINGER_UP, x, y, 1.0); - } break; - - case XI_TouchUpdate: - { - const XIDeviceEvent *xev = (const XIDeviceEvent *)cookie->data; - float x, y; - SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event); - xinput2_normalize_touch_coordinates(window, xev->event_x, xev->event_y, &x, &y); - SDL_SendTouchMotion(0, xev->sourceid, xev->detail, window, x, y, 1.0); - } break; -#endif // SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - } -#endif // SDL_VIDEO_DRIVER_X11_XINPUT2 -} - -void X11_InitXinput2Multitouch(SDL_VideoDevice *_this) -{ -} - -void X11_Xinput2SelectTouch(SDL_VideoDevice *_this, SDL_Window *window) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - SDL_VideoData *data = NULL; - XIEventMask eventmask; - unsigned char mask[4] = { 0, 0, 0, 0 }; - SDL_WindowData *window_data = NULL; - - if (!X11_Xinput2IsMultitouchSupported()) { - return; - } - - data = _this->internal; - window_data = window->internal; - - eventmask.deviceid = XIAllMasterDevices; - eventmask.mask_len = sizeof(mask); - eventmask.mask = mask; - - XISetMask(mask, XI_TouchBegin); - XISetMask(mask, XI_TouchUpdate); - XISetMask(mask, XI_TouchEnd); - XISetMask(mask, XI_Motion); - - X11_XISelectEvents(data->display, window_data->xwindow, &eventmask, 1); -#endif -} - -bool X11_Xinput2IsInitialized(void) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - return xinput2_initialized; -#else - return false; -#endif -} - -bool X11_Xinput2SelectMouseAndKeyboard(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *windowdata = window->internal; - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - const SDL_VideoData *data = _this->internal; - - if (X11_Xinput2IsInitialized()) { - XIEventMask eventmask; - unsigned char mask[4] = { 0, 0, 0, 0 }; - - eventmask.mask_len = sizeof(mask); - eventmask.mask = mask; - eventmask.deviceid = XIAllDevices; - -// This is not enabled by default because these events are only delivered to the window with mouse focus, not keyboard focus -#ifdef USE_XINPUT2_KEYBOARD - XISetMask(mask, XI_KeyPress); - XISetMask(mask, XI_KeyRelease); - windowdata->xinput2_keyboard_enabled = true; -#endif - - XISetMask(mask, XI_ButtonPress); - XISetMask(mask, XI_ButtonRelease); - XISetMask(mask, XI_Motion); - windowdata->xinput2_mouse_enabled = true; - - XISetMask(mask, XI_Enter); - XISetMask(mask, XI_Leave); - - // Hotplugging: - XISetMask(mask, XI_DeviceChanged); - XISetMask(mask, XI_HierarchyChanged); - XISetMask(mask, XI_PropertyEvent); // E.g., when swapping tablet pens - - if (X11_XISelectEvents(data->display, windowdata->xwindow, &eventmask, 1) != Success) { - SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, "Could not enable XInput2 event handling"); - windowdata->xinput2_keyboard_enabled = false; - windowdata->xinput2_mouse_enabled = false; - } - } -#endif - - if (windowdata->xinput2_keyboard_enabled || windowdata->xinput2_mouse_enabled) { - return true; - } - return false; -} - -bool X11_Xinput2IsMultitouchSupported(void) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - return xinput2_initialized && xinput2_multitouch_supported; -#else - return true; -#endif -} - -void X11_Xinput2GrabTouch(SDL_VideoDevice *_this, SDL_Window *window) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - - unsigned char mask[4] = { 0, 0, 0, 0 }; - XIGrabModifiers mods; - XIEventMask eventmask; - - if (!X11_Xinput2IsMultitouchSupported()) { - return; - } - - mods.modifiers = XIAnyModifier; - mods.status = 0; - - eventmask.deviceid = XIAllDevices; - eventmask.mask_len = sizeof(mask); - eventmask.mask = mask; - - XISetMask(eventmask.mask, XI_TouchBegin); - XISetMask(eventmask.mask, XI_TouchUpdate); - XISetMask(eventmask.mask, XI_TouchEnd); - XISetMask(eventmask.mask, XI_Motion); - - X11_XIGrabTouchBegin(display, XIAllDevices, data->xwindow, True, &eventmask, 1, &mods); -#endif -} - -void X11_Xinput2UngrabTouch(SDL_VideoDevice *_this, SDL_Window *window) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - - XIGrabModifiers mods; - - if (!X11_Xinput2IsMultitouchSupported()) { - return; - } - - mods.modifiers = XIAnyModifier; - mods.status = 0; - - X11_XIUngrabTouchBegin(display, XIAllDevices, data->xwindow, 1, &mods); -#endif -} - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - -static void AddDeviceID(Uint32 deviceID, Uint32 **list, int *count) -{ - int new_count = (*count + 1); - Uint32 *new_list = (Uint32 *)SDL_realloc(*list, new_count * sizeof(*new_list)); - if (!new_list) { - // Oh well, we'll drop this one - return; - } - new_list[new_count - 1] = deviceID; - - *count = new_count; - *list = new_list; -} - -static bool HasDeviceID(Uint32 deviceID, const Uint32 *list, int count) -{ - for (int i = 0; i < count; ++i) { - if (deviceID == list[i]) { - return true; - } - } - return false; -} - -static void AddDeviceID64(Uint64 deviceID, Uint64 **list, int *count) -{ - int new_count = (*count + 1); - Uint64 *new_list = (Uint64 *)SDL_realloc(*list, new_count * sizeof(*new_list)); - if (!new_list) { - // Oh well, we'll drop this one - return; - } - new_list[new_count - 1] = deviceID; - - *count = new_count; - *list = new_list; -} - -static bool HasDeviceID64(Uint64 deviceID, const Uint64 *list, int count) -{ - for (int i = 0; i < count; ++i) { - if (deviceID == list[i]) { - return true; - } - } - return false; -} - -#endif // SDL_VIDEO_DRIVER_X11_XINPUT2 - -void X11_Xinput2UpdateDevices(SDL_VideoDevice *_this, bool initial_check) -{ -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 - SDL_VideoData *data = _this->internal; - XIDeviceInfo *info; - int ndevices; - int old_keyboard_count = 0; - SDL_KeyboardID *old_keyboards = NULL; - int new_keyboard_count = 0; - SDL_KeyboardID *new_keyboards = NULL; - int old_mouse_count = 0; - SDL_MouseID *old_mice = NULL; - int new_mouse_count = 0; - SDL_MouseID *new_mice = NULL; - int old_touch_count = 0; - Uint64 *old_touch_devices = NULL; - int new_touch_count = 0; - Uint64 *new_touch_devices = NULL; - bool send_event = !initial_check; - - SDL_assert(X11_Xinput2IsInitialized()); - - info = X11_XIQueryDevice(data->display, XIAllDevices, &ndevices); - - old_keyboards = SDL_GetKeyboards(&old_keyboard_count); - old_mice = SDL_GetMice(&old_mouse_count); - old_touch_devices = SDL_GetTouchDevices(&old_touch_count); - - for (int i = 0; i < ndevices; i++) { - XIDeviceInfo *dev = &info[i]; - - switch (dev->use) { - case XIMasterKeyboard: - case XISlaveKeyboard: - { - SDL_KeyboardID keyboardID = (SDL_KeyboardID)dev->deviceid; - AddDeviceID(keyboardID, &new_keyboards, &new_keyboard_count); - if (!HasDeviceID(keyboardID, old_keyboards, old_keyboard_count)) { - SDL_AddKeyboard(keyboardID, dev->name, send_event); - } - } - break; - case XIMasterPointer: - data->xinput_master_pointer_device = dev->deviceid; - SDL_FALLTHROUGH; - case XISlavePointer: - { - SDL_MouseID mouseID = (SDL_MouseID)dev->deviceid; - AddDeviceID(mouseID, &new_mice, &new_mouse_count); - if (!HasDeviceID(mouseID, old_mice, old_mouse_count)) { - SDL_AddMouse(mouseID, dev->name, send_event); - } - } - break; - default: - break; - } - -#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - for (int j = 0; j < dev->num_classes; j++) { - Uint64 touchID; - SDL_TouchDeviceType touchType; - XIAnyClassInfo *class = dev->classes[j]; - XITouchClassInfo *t = (XITouchClassInfo *)class; - - // Only touch devices - if (class->type != XITouchClass) { - continue; - } - - touchID = (Uint64)t->sourceid; - AddDeviceID64(touchID, &new_touch_devices, &new_touch_count); - if (!HasDeviceID64(touchID, old_touch_devices, old_touch_count)) { - if (t->mode == XIDependentTouch) { - touchType = SDL_TOUCH_DEVICE_INDIRECT_RELATIVE; - } else { // XIDirectTouch - touchType = SDL_TOUCH_DEVICE_DIRECT; - } - SDL_AddTouch(touchID, touchType, dev->name); - } - } -#endif // SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - } - - for (int i = old_keyboard_count; i--;) { - if (!HasDeviceID(old_keyboards[i], new_keyboards, new_keyboard_count)) { - SDL_RemoveKeyboard(old_keyboards[i], send_event); - } - } - - for (int i = old_mouse_count; i--;) { - if (!HasDeviceID(old_mice[i], new_mice, new_mouse_count)) { - SDL_RemoveMouse(old_mice[i], send_event); - } - } - - for (int i = old_touch_count; i--;) { - if (!HasDeviceID64(old_touch_devices[i], new_touch_devices, new_touch_count)) { - SDL_DelTouch(old_touch_devices[i]); - } - } - - SDL_free(old_keyboards); - SDL_free(new_keyboards); - SDL_free(old_mice); - SDL_free(new_mice); - SDL_free(old_touch_devices); - SDL_free(new_touch_devices); - - X11_XIFreeDeviceInfo(info); - -#endif // SDL_VIDEO_DRIVER_X11_XINPUT2 -} - -#endif // SDL_VIDEO_DRIVER_X11 diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.h deleted file mode 100644 index c96c020..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xinput2.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 bool X11_InitXinput2(SDL_VideoDevice *_this); -extern void X11_InitXinput2Multitouch(SDL_VideoDevice *_this); -extern void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie); -extern bool X11_Xinput2IsInitialized(void); -extern bool X11_Xinput2IsMultitouchSupported(void); -extern void X11_Xinput2SelectTouch(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_Xinput2GrabTouch(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_Xinput2UngrabTouch(SDL_VideoDevice *_this, SDL_Window *window); -extern bool X11_Xinput2SelectMouseAndKeyboard(SDL_VideoDevice *_this, SDL_Window *window); -extern void X11_Xinput2UpdateDevices(SDL_VideoDevice *_this, bool initial_check); - -#endif // SDL_x11xinput2_h_ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.c b/contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.c deleted file mode 100644 index 5310d67..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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 defined(SDL_VIDEO_DRIVER_X11) && defined(SDL_VIDEO_DRIVER_X11_XSYNC) - -#include "SDL_x11video.h" -#include "SDL_x11xsync.h" - -static int xsync_initialized = 0; - -static int query_xsync_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_XSyncInitialize(display, &major, &minor); - return (major * 1000) + minor; -} - -static bool xsync_version_atleast(const int version, const int wantmajor, const int wantminor) -{ - return version >= ((wantmajor * 1000) + wantminor); -} - -void X11_InitXsync(SDL_VideoDevice *_this) -{ - SDL_VideoData *data = _this->internal; - - int version = 0; - int event, error; - int sync_opcode; - - if (!SDL_X11_HAVE_XSYNC || - !X11_XQueryExtension(data->display, "SYNC", &sync_opcode, &event, &error)) { - return; - } - - /* We need at least 5.0 for barriers. */ - version = query_xsync_version(data->display, 5, 0); - if (!xsync_version_atleast(version, 3, 0)) { - return; /* X server does not support the version we want at all. */ - } - - xsync_initialized = 1; -} - -int X11_XsyncIsInitialized(void) -{ - return xsync_initialized; -} - -int X11_InitResizeSync(SDL_Window *window) -{ - SDL_assert(window != NULL); - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - Atom counter_prop = data->videodata->atoms._NET_WM_SYNC_REQUEST_COUNTER; - XSyncCounter counter; - CARD32 counter_id; - - if (!X11_XsyncIsInitialized()){ - return SDL_Unsupported(); - } - - counter = X11_XSyncCreateCounter(display, (XSyncValue){0, 0}); - data->resize_counter = counter; - data->resize_id.lo = 0; - data->resize_id.hi = 0; - data->resize_in_progress = false; - - if (counter == None){ - return SDL_Unsupported(); - } - - counter_id = counter; - X11_XChangeProperty(display, data->xwindow, counter_prop, XA_CARDINAL, 32, - PropModeReplace, (unsigned char *)&counter_id, 1); - - return 0; -} - -void X11_TermResizeSync(SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - Atom counter_prop = data->videodata->atoms._NET_WM_SYNC_REQUEST_COUNTER; - XSyncCounter counter = data->resize_counter; - - X11_XDeleteProperty(display, data->xwindow, counter_prop); - if (counter != None) { - X11_XSyncDestroyCounter(display, counter); - } -} - -void X11_HandleSyncRequest(SDL_Window *window, XClientMessageEvent *event) -{ - SDL_WindowData *data = window->internal; - - data->resize_id.lo = event->data.l[2]; - data->resize_id.hi = event->data.l[3]; - data->resize_in_progress = false; -} - -void X11_HandleConfigure(SDL_Window *window, XConfigureEvent *event) -{ - SDL_WindowData *data = window->internal; - - if (data->resize_id.lo || data->resize_id.hi) { - data->resize_in_progress = true; - } -} - -void X11_HandlePresent(SDL_Window *window) -{ - SDL_WindowData *data = window->internal; - Display *display = data->videodata->display; - XSyncCounter counter = data->resize_counter; - - if ((counter == None) || (!data->resize_in_progress)) { - return; - } - - X11_XSyncSetCounter(display, counter, data->resize_id); - - data->resize_id.lo = 0; - data->resize_id.hi = 0; - data->resize_in_progress = false; -} - -#endif /* SDL_VIDEO_DRIVER_X11 && SDL_VIDEO_DRIVER_X11_XSYNC */ diff --git a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.h b/contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.h deleted file mode 100644 index bc747c1..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/SDL_x11xsync.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - 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_x11xsync_h_ -#define SDL_x11xsync_h_ - -#ifdef SDL_VIDEO_DRIVER_X11_XSYNC - -extern void X11_InitXsync(SDL_VideoDevice *_this); -extern int X11_XsyncIsInitialized(void); -int X11_InitResizeSync(SDL_Window *window); -void X11_TermResizeSync(SDL_Window *window); -void X11_HandleSyncRequest(SDL_Window *window, XClientMessageEvent *event); -void X11_HandleConfigure(SDL_Window *window, XConfigureEvent *event); -void X11_HandlePresent(SDL_Window *window); - -#endif /* SDL_VIDEO_DRIVER_X11_XSYNC */ - -#endif /* SDL_x11xsync_h_ */ diff --git a/contrib/SDL-3.2.8/src/video/x11/edid-parse.c b/contrib/SDL-3.2.8/src/video/x11/edid-parse.c deleted file mode 100644 index eca187b..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/edid-parse.c +++ /dev/null @@ -1,753 +0,0 @@ -/* - * 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 */ -#include "SDL_internal.h" - -#include "edid.h" -#include -#include -#include -#include - -#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 (SDL_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 | (Uint32)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 = SDL_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)) { - SDL_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/contrib/SDL-3.2.8/src/video/x11/edid.h b/contrib/SDL-3.2.8/src/video/x11/edid.h deleted file mode 100644 index 4581291..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/edid.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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 */ - -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/contrib/SDL-3.2.8/src/video/x11/xsettings-client.c b/contrib/SDL-3.2.8/src/video/x11/xsettings-client.c deleted file mode 100644 index 8fb1cd3..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/xsettings-client.c +++ /dev/null @@ -1,859 +0,0 @@ -/* - * Copyright © 2001, 2007 Red Hat, Inc. - * Copyright 2024 Igalia S.L. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Red Hat not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Red Hat makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Owen Taylor, Red Hat, Inc. - */ - -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_X11 - -#include "SDL_x11video.h" - -#include -#include -#include -#include - -#include "xsettings-client.h" - -struct _XSettingsClient -{ - Display *display; - int screen; - XSettingsNotifyFunc notify; - XSettingsWatchFunc watch; - void *cb_data; - - XSettingsGrabFunc grab; - XSettingsGrabFunc ungrab; - - Window manager_window; - Atom manager_atom; - Atom selection_atom; - Atom xsettings_atom; - - XSettingsList *settings; -}; - -static void -notify_changes (XSettingsClient *client, - XSettingsList *old_list) -{ - XSettingsList *old_iter = old_list; - XSettingsList *new_iter = client->settings; - - if (!client->notify) - return; - - while (old_iter || new_iter) - { - int cmp; - - if (old_iter && new_iter) - cmp = strcmp (old_iter->setting->name, new_iter->setting->name); - else if (old_iter) - cmp = -1; - else - cmp = 1; - - if (cmp < 0) - { - client->notify (old_iter->setting->name, - XSETTINGS_ACTION_DELETED, - NULL, - client->cb_data); - } - else if (cmp == 0) - { - if (!xsettings_setting_equal (old_iter->setting, - new_iter->setting)) - client->notify (old_iter->setting->name, - XSETTINGS_ACTION_CHANGED, - new_iter->setting, - client->cb_data); - } - else - { - client->notify (new_iter->setting->name, - XSETTINGS_ACTION_NEW, - new_iter->setting, - client->cb_data); - } - - if (old_iter) - old_iter = old_iter->next; - if (new_iter) - new_iter = new_iter->next; - } -} - -static int -ignore_errors (Display *display, XErrorEvent *event) -{ - return True; -} - -static char local_byte_order = '\0'; - -#define BYTES_LEFT(buffer) ((buffer)->data + (buffer)->len - (buffer)->pos) - -static XSettingsResult -fetch_card16 (XSettingsBuffer *buffer, - CARD16 *result) -{ - CARD16 x; - - if (BYTES_LEFT (buffer) < 2) - return XSETTINGS_ACCESS; - - x = *(CARD16 *)buffer->pos; - buffer->pos += 2; - - if (buffer->byte_order == local_byte_order) - *result = x; - else - *result = (x << 8) | (x >> 8); - - return XSETTINGS_SUCCESS; -} - -static XSettingsResult -fetch_ushort (XSettingsBuffer *buffer, - unsigned short *result) -{ - CARD16 x; - XSettingsResult r; - - r = fetch_card16 (buffer, &x); - if (r == XSETTINGS_SUCCESS) - *result = x; - - return r; -} - -static XSettingsResult -fetch_card32 (XSettingsBuffer *buffer, - CARD32 *result) -{ - CARD32 x; - - if (BYTES_LEFT (buffer) < 4) - return XSETTINGS_ACCESS; - - x = *(CARD32 *)buffer->pos; - buffer->pos += 4; - - if (buffer->byte_order == local_byte_order) - *result = x; - else - *result = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24); - - return XSETTINGS_SUCCESS; -} - -static XSettingsResult -fetch_card8 (XSettingsBuffer *buffer, - CARD8 *result) -{ - if (BYTES_LEFT (buffer) < 1) - return XSETTINGS_ACCESS; - - *result = *(CARD8 *)buffer->pos; - buffer->pos += 1; - - return XSETTINGS_SUCCESS; -} - -#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1))) - -static XSettingsList * -parse_settings (unsigned char *data, - size_t len) -{ - XSettingsBuffer buffer; - XSettingsResult result = XSETTINGS_SUCCESS; - XSettingsList *settings = NULL; - CARD32 serial; - CARD32 n_entries; - CARD32 i; - XSettingsSetting *setting = NULL; - char buffer_byte_order = '\0'; - - local_byte_order = xsettings_byte_order (); - - buffer.pos = buffer.data = data; - buffer.len = len; - buffer.byte_order = '\0'; - - result = fetch_card8 (&buffer, (unsigned char *) &buffer_byte_order); - if (buffer_byte_order != MSBFirst && - buffer_byte_order != LSBFirst) - { - fprintf (stderr, "Invalid byte order in XSETTINGS property\n"); - result = XSETTINGS_FAILED; - goto out; - } - - buffer.byte_order = buffer_byte_order; - buffer.pos += 3; - - result = fetch_card32 (&buffer, &serial); - if (result != XSETTINGS_SUCCESS) - goto out; - - result = fetch_card32 (&buffer, &n_entries); - if (result != XSETTINGS_SUCCESS) - goto out; - - for (i = 0; i < n_entries; i++) - { - CARD8 type; - CARD16 name_len; - CARD32 v_int; - size_t pad_len; - - result = fetch_card8 (&buffer, &type); - if (result != XSETTINGS_SUCCESS) - goto out; - - buffer.pos += 1; - - result = fetch_card16 (&buffer, &name_len); - if (result != XSETTINGS_SUCCESS) - goto out; - - pad_len = XSETTINGS_PAD(name_len, 4); - if (BYTES_LEFT (&buffer) < pad_len) - { - result = XSETTINGS_ACCESS; - goto out; - } - - setting = malloc (sizeof *setting); - if (!setting) - { - result = XSETTINGS_NO_MEM; - goto out; - } - setting->type = XSETTINGS_TYPE_INT; /* No allocated memory */ - - setting->name = malloc (name_len + 1); - if (!setting->name) - { - result = XSETTINGS_NO_MEM; - goto out; - } - - memcpy (setting->name, buffer.pos, name_len); - setting->name[name_len] = '\0'; - buffer.pos += pad_len; - - result = fetch_card32 (&buffer, &v_int); - if (result != XSETTINGS_SUCCESS) - goto out; - setting->last_change_serial = v_int; - - switch (type) - { - case XSETTINGS_TYPE_INT: - result = fetch_card32 (&buffer, &v_int); - if (result != XSETTINGS_SUCCESS) - goto out; - - setting->data.v_int = (INT32)v_int; - break; - case XSETTINGS_TYPE_STRING: - result = fetch_card32 (&buffer, &v_int); - if (result != XSETTINGS_SUCCESS) - goto out; - - pad_len = XSETTINGS_PAD (v_int, 4); - if (v_int + 1 == 0 || /* Guard against wrap-around */ - BYTES_LEFT (&buffer) < pad_len) - { - result = XSETTINGS_ACCESS; - goto out; - } - - setting->data.v_string = malloc (v_int + 1); - if (!setting->data.v_string) - { - result = XSETTINGS_NO_MEM; - goto out; - } - - memcpy (setting->data.v_string, buffer.pos, v_int); - setting->data.v_string[v_int] = '\0'; - buffer.pos += pad_len; - - break; - case XSETTINGS_TYPE_COLOR: - result = fetch_ushort (&buffer, &setting->data.v_color.red); - if (result != XSETTINGS_SUCCESS) - goto out; - result = fetch_ushort (&buffer, &setting->data.v_color.green); - if (result != XSETTINGS_SUCCESS) - goto out; - result = fetch_ushort (&buffer, &setting->data.v_color.blue); - if (result != XSETTINGS_SUCCESS) - goto out; - result = fetch_ushort (&buffer, &setting->data.v_color.alpha); - if (result != XSETTINGS_SUCCESS) - goto out; - - break; - default: - /* Quietly ignore unknown types */ - break; - } - - setting->type = type; - - result = xsettings_list_insert (&settings, setting); - if (result != XSETTINGS_SUCCESS) - goto out; - - setting = NULL; - } - - out: - - if (result != XSETTINGS_SUCCESS) - { - switch (result) - { - case XSETTINGS_NO_MEM: - fprintf(stderr, "Out of memory reading XSETTINGS property\n"); - break; - case XSETTINGS_ACCESS: - fprintf(stderr, "Invalid XSETTINGS property (read off end)\n"); - break; - case XSETTINGS_DUPLICATE_ENTRY: - fprintf (stderr, "Duplicate XSETTINGS entry for '%s'\n", setting->name); - SDL_FALLTHROUGH; - case XSETTINGS_FAILED: - SDL_FALLTHROUGH; - case XSETTINGS_SUCCESS: - SDL_FALLTHROUGH; - case XSETTINGS_NO_ENTRY: - break; - } - - if (setting) - xsettings_setting_free (setting); - - xsettings_list_free (settings); - settings = NULL; - - } - - return settings; -} - -static void -read_settings (XSettingsClient *client) -{ - Atom type; - int format; - unsigned long n_items; - unsigned long bytes_after; - unsigned char *data; - int result; - - int (*old_handler) (Display *, XErrorEvent *); - - XSettingsList *old_list = client->settings; - - client->settings = NULL; - - if (client->manager_window) - { - old_handler = X11_XSetErrorHandler (ignore_errors); - result = X11_XGetWindowProperty (client->display, client->manager_window, - client->xsettings_atom, 0, LONG_MAX, - False, client->xsettings_atom, - &type, &format, &n_items, &bytes_after, &data); - X11_XSetErrorHandler (old_handler); - - if (result == Success && type != None) - { - if (type != client->xsettings_atom) - { - fprintf (stderr, "Invalid type for XSETTINGS property"); - } - else if (format != 8) - { - fprintf (stderr, "Invalid format for XSETTINGS property %d", format); - } - else - client->settings = parse_settings (data, n_items); - - X11_XFree (data); - } - } - - notify_changes (client, old_list); - xsettings_list_free (old_list); -} - -static void -add_events (Display *display, - Window window, - long mask) -{ - XWindowAttributes attr; - - X11_XGetWindowAttributes (display, window, &attr); - X11_XSelectInput (display, window, attr.your_event_mask | mask); -} - -static void -check_manager_window (XSettingsClient *client) -{ - if (client->manager_window && client->watch) - client->watch (client->manager_window, False, 0, client->cb_data); - - if (client->grab) - client->grab (client->display); - else - X11_XGrabServer (client->display); - - client->manager_window = X11_XGetSelectionOwner (client->display, - client->selection_atom); - if (client->manager_window) - X11_XSelectInput (client->display, client->manager_window, - PropertyChangeMask | StructureNotifyMask); - - if (client->ungrab) - client->ungrab (client->display); - else - X11_XUngrabServer (client->display); - - X11_XFlush (client->display); - - if (client->manager_window && client->watch) - { - if (!client->watch (client->manager_window, True, - PropertyChangeMask | StructureNotifyMask, - client->cb_data)) - { - /* Inability to watch the window probably means that it was destroyed - * after we ungrabbed - */ - client->manager_window = None; - return; - } - } - - - read_settings (client); -} - -XSettingsClient * -xsettings_client_new (Display *display, - int screen, - XSettingsNotifyFunc notify, - XSettingsWatchFunc watch, - void *cb_data) -{ - return xsettings_client_new_with_grab_funcs (display, screen, notify, watch, cb_data, - NULL, NULL); -} - -XSettingsClient * -xsettings_client_new_with_grab_funcs (Display *display, - int screen, - XSettingsNotifyFunc notify, - XSettingsWatchFunc watch, - void *cb_data, - XSettingsGrabFunc grab, - XSettingsGrabFunc ungrab) -{ - XSettingsClient *client; - char buffer[256]; - char *atom_names[3]; - Atom atoms[3]; - - client = malloc (sizeof *client); - if (!client) - return NULL; - - client->display = display; - client->screen = screen; - client->notify = notify; - client->watch = watch; - client->cb_data = cb_data; - client->grab = grab; - client->ungrab = ungrab; - - client->manager_window = None; - client->settings = NULL; - - sprintf(buffer, "_XSETTINGS_S%d", screen); - atom_names[0] = buffer; - atom_names[1] = "_XSETTINGS_SETTINGS"; - atom_names[2] = "MANAGER"; - -#ifdef HAVE_XINTERNATOMS - XInternAtoms (display, atom_names, 3, False, atoms); -#else - atoms[0] = X11_XInternAtom (display, atom_names[0], False); - atoms[1] = X11_XInternAtom (display, atom_names[1], False); - atoms[2] = X11_XInternAtom (display, atom_names[2], False); -#endif - - client->selection_atom = atoms[0]; - client->xsettings_atom = atoms[1]; - client->manager_atom = atoms[2]; - - /* Select on StructureNotify so we get MANAGER events - */ - add_events (display, RootWindow (display, screen), StructureNotifyMask); - - if (client->watch) - client->watch (RootWindow (display, screen), True, StructureNotifyMask, - client->cb_data); - - check_manager_window (client); - - return client; -} - - -void -xsettings_client_set_grab_func (XSettingsClient *client, - XSettingsGrabFunc grab) -{ - client->grab = grab; -} - -void -xsettings_client_set_ungrab_func (XSettingsClient *client, - XSettingsGrabFunc ungrab) -{ - client->ungrab = ungrab; -} - -void -xsettings_client_destroy (XSettingsClient *client) -{ - if (client->watch) - client->watch (RootWindow (client->display, client->screen), - False, 0, client->cb_data); - if (client->manager_window && client->watch) - client->watch (client->manager_window, False, 0, client->cb_data); - - xsettings_list_free (client->settings); - free (client); -} - -XSettingsResult -xsettings_client_get_setting (XSettingsClient *client, - const char *name, - XSettingsSetting **setting) -{ - XSettingsSetting *search = xsettings_list_lookup (client->settings, name); - if (search) - { - *setting = xsettings_setting_copy (search); - return *setting ? XSETTINGS_SUCCESS : XSETTINGS_NO_MEM; - } - else - return XSETTINGS_NO_ENTRY; -} - -Bool -xsettings_client_process_event (XSettingsClient *client, - const XEvent *xev) -{ - /* The checks here will not unlikely cause us to reread - * the properties from the manager window a number of - * times when the manager changes from A->B. But manager changes - * are going to be pretty rare. - */ - if (xev->xany.window == RootWindow (client->display, client->screen)) - { - if (xev->xany.type == ClientMessage && - xev->xclient.message_type == client->manager_atom && - xev->xclient.data.l[1] == client->selection_atom) - { - check_manager_window (client); - return True; - } - } - else if (xev->xany.window == client->manager_window) - { - if (xev->xany.type == DestroyNotify) - { - check_manager_window (client); - return False; - } - else if (xev->xany.type == PropertyNotify) - { - read_settings (client); - return True; - } - } - - return False; -} - -XSettingsSetting * -xsettings_setting_copy (XSettingsSetting *setting) -{ - XSettingsSetting *result; - size_t str_len; - - result = malloc (sizeof *result); - if (!result) - return NULL; - - str_len = strlen (setting->name); - result->name = malloc (str_len + 1); - if (!result->name) - goto err; - - memcpy (result->name, setting->name, str_len + 1); - - result->type = setting->type; - - switch (setting->type) - { - case XSETTINGS_TYPE_INT: - result->data.v_int = setting->data.v_int; - break; - case XSETTINGS_TYPE_COLOR: - result->data.v_color = setting->data.v_color; - break; - case XSETTINGS_TYPE_STRING: - str_len = strlen (setting->data.v_string); - result->data.v_string = malloc (str_len + 1); - if (!result->data.v_string) - goto err; - - memcpy (result->data.v_string, setting->data.v_string, str_len + 1); - break; - } - - result->last_change_serial = setting->last_change_serial; - - return result; - - err: - if (result->name) - free (result->name); - free (result); - - return NULL; -} - -XSettingsList * -xsettings_list_copy (XSettingsList *list) -{ - XSettingsList *new = NULL; - XSettingsList *old_iter = list; - XSettingsList *new_iter = NULL; - - while (old_iter) - { - XSettingsList *new_node; - - new_node = malloc (sizeof *new_node); - if (!new_node) - goto error; - - new_node->setting = xsettings_setting_copy (old_iter->setting); - if (!new_node->setting) - { - free (new_node); - goto error; - } - - if (new_iter) - new_iter->next = new_node; - else - { - new = new_node; - new->next = NULL; - } - - - new_iter = new_node; - - old_iter = old_iter->next; - } - - return new; - - error: - xsettings_list_free (new); - return NULL; -} - -int -xsettings_setting_equal (XSettingsSetting *setting_a, - XSettingsSetting *setting_b) -{ - if (setting_a->type != setting_b->type) - return 0; - - if (strcmp (setting_a->name, setting_b->name) != 0) - return 0; - - switch (setting_a->type) - { - case XSETTINGS_TYPE_INT: - return setting_a->data.v_int == setting_b->data.v_int; - case XSETTINGS_TYPE_COLOR: - return (setting_a->data.v_color.red == setting_b->data.v_color.red && - setting_a->data.v_color.green == setting_b->data.v_color.green && - setting_a->data.v_color.blue == setting_b->data.v_color.blue && - setting_a->data.v_color.alpha == setting_b->data.v_color.alpha); - case XSETTINGS_TYPE_STRING: - return strcmp (setting_a->data.v_string, setting_b->data.v_string) == 0; - } - - return 0; -} - -void -xsettings_setting_free (XSettingsSetting *setting) -{ - if (setting->type == XSETTINGS_TYPE_STRING) - free (setting->data.v_string); - - if (setting->name) - free (setting->name); - - free (setting); -} - -void -xsettings_list_free (XSettingsList *list) -{ - while (list) - { - XSettingsList *next = list->next; - - xsettings_setting_free (list->setting); - free (list); - - list = next; - } -} - -XSettingsResult -xsettings_list_insert (XSettingsList **list, - XSettingsSetting *setting) -{ - XSettingsList *node; - XSettingsList *iter; - XSettingsList *last = NULL; - - node = malloc (sizeof *node); - if (!node) - return XSETTINGS_NO_MEM; - node->setting = setting; - - iter = *list; - while (iter) - { - int cmp = strcmp (setting->name, iter->setting->name); - - if (cmp < 0) - break; - else if (cmp == 0) - { - free (node); - return XSETTINGS_DUPLICATE_ENTRY; - } - - last = iter; - iter = iter->next; - } - - if (last) - last->next = node; - else - *list = node; - - node->next = iter; - - return XSETTINGS_SUCCESS; -} - -XSettingsResult -xsettings_list_delete (XSettingsList **list, - const char *name) -{ - XSettingsList *iter; - XSettingsList *last = NULL; - - iter = *list; - while (iter) - { - if (strcmp (name, iter->setting->name) == 0) - { - if (last) - last->next = iter->next; - else - *list = iter->next; - - xsettings_setting_free (iter->setting); - free (iter); - - return XSETTINGS_SUCCESS; - } - - last = iter; - iter = iter->next; - } - - return XSETTINGS_FAILED; -} - -XSettingsSetting * -xsettings_list_lookup (XSettingsList *list, - const char *name) -{ - XSettingsList *iter; - - iter = list; - while (iter) - { - if (strcmp (name, iter->setting->name) == 0) - return iter->setting; - - iter = iter->next; - } - - return NULL; -} - -char -xsettings_byte_order (void) -{ - CARD32 myint = 0x01020304; - return (*(char *)&myint == 1) ? MSBFirst : LSBFirst; -} - -#endif /* SDL_VIDEO_DRIVER_X11 */ diff --git a/contrib/SDL-3.2.8/src/video/x11/xsettings-client.h b/contrib/SDL-3.2.8/src/video/x11/xsettings-client.h deleted file mode 100644 index 863c6f9..0000000 --- a/contrib/SDL-3.2.8/src/video/x11/xsettings-client.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright © 2001, 2007 Red Hat, Inc. - * Copyright 2024 Igalia S.L. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Red Hat not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. Red Hat makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL RED HAT - * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Owen Taylor, Red Hat, Inc. - */ -#ifndef XSETTINGS_CLIENT_H -#define XSETTINGS_CLIENT_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -typedef struct _XSettingsBuffer XSettingsBuffer; -typedef struct _XSettingsColor XSettingsColor; -typedef struct _XSettingsList XSettingsList; -typedef struct _XSettingsSetting XSettingsSetting; - -/* Types of settings possible. Enum values correspond to - * protocol values. - */ -typedef enum -{ - XSETTINGS_TYPE_INT = 0, - XSETTINGS_TYPE_STRING = 1, - XSETTINGS_TYPE_COLOR = 2 -} XSettingsType; - -typedef enum -{ - XSETTINGS_SUCCESS, - XSETTINGS_NO_MEM, - XSETTINGS_ACCESS, - XSETTINGS_FAILED, - XSETTINGS_NO_ENTRY, - XSETTINGS_DUPLICATE_ENTRY -} XSettingsResult; - -struct _XSettingsBuffer -{ - char byte_order; - size_t len; - unsigned char *data; - unsigned char *pos; -}; - -struct _XSettingsColor -{ - unsigned short red, green, blue, alpha; -}; - -struct _XSettingsList -{ - XSettingsSetting *setting; - XSettingsList *next; -}; - -struct _XSettingsSetting -{ - char *name; - XSettingsType type; - - union { - int v_int; - char *v_string; - XSettingsColor v_color; - } data; - - unsigned long last_change_serial; -}; - -XSettingsSetting *xsettings_setting_copy (XSettingsSetting *setting); -void xsettings_setting_free (XSettingsSetting *setting); -int xsettings_setting_equal (XSettingsSetting *setting_a, - XSettingsSetting *setting_b); - -void xsettings_list_free (XSettingsList *list); -XSettingsList *xsettings_list_copy (XSettingsList *list); -XSettingsResult xsettings_list_insert (XSettingsList **list, - XSettingsSetting *setting); -XSettingsSetting *xsettings_list_lookup (XSettingsList *list, - const char *name); -XSettingsResult xsettings_list_delete (XSettingsList **list, - const char *name); - -char xsettings_byte_order (void); - -#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1))) - -typedef struct _XSettingsClient XSettingsClient; - -typedef enum -{ - XSETTINGS_ACTION_NEW, - XSETTINGS_ACTION_CHANGED, - XSETTINGS_ACTION_DELETED -} XSettingsAction; - -typedef void (*XSettingsNotifyFunc) (const char *name, - XSettingsAction action, - XSettingsSetting *setting, - void *cb_data); -typedef Bool (*XSettingsWatchFunc) (Window window, - Bool is_start, - long mask, - void *cb_data); -typedef void (*XSettingsGrabFunc) (Display *display); - -XSettingsClient *xsettings_client_new (Display *display, - int screen, - XSettingsNotifyFunc notify, - XSettingsWatchFunc watch, - void *cb_data); -XSettingsClient *xsettings_client_new_with_grab_funcs (Display *display, - int screen, - XSettingsNotifyFunc notify, - XSettingsWatchFunc watch, - void *cb_data, - XSettingsGrabFunc grab, - XSettingsGrabFunc ungrab); -void xsettings_client_set_grab_func (XSettingsClient *client, - XSettingsGrabFunc grab); -void xsettings_client_set_ungrab_func (XSettingsClient *client, - XSettingsGrabFunc ungrab); -void xsettings_client_destroy (XSettingsClient *client); -Bool xsettings_client_process_event (XSettingsClient *client, - const XEvent *xev); -XSettingsResult xsettings_client_get_setting (XSettingsClient *client, - const char *name, - XSettingsSetting **setting); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* XSETTINGS_CLIENT_H */ -- cgit v1.2.3