SDL: x11: store all atoms in a specific struct

From 818d7d892a6405aef1a74b74293a4a7938b255f6 Mon Sep 17 00:00:00 2001
From: David Fort <[EMAIL REDACTED]>
Date: Mon, 30 Sep 2024 19:43:49 +0200
Subject: [PATCH] x11: store all atoms in a specific struct

---
 src/video/x11/SDL_x11clipboard.c |  8 +--
 src/video/x11/SDL_x11events.c    | 50 ++++++++--------
 src/video/x11/SDL_x11pen.c       | 26 ++++-----
 src/video/x11/SDL_x11video.c     |  2 +-
 src/video/x11/SDL_x11video.h     | 98 ++++++++++++++++----------------
 src/video/x11/SDL_x11window.c    | 74 ++++++++++++------------
 6 files changed, 130 insertions(+), 128 deletions(-)

diff --git a/src/video/x11/SDL_x11clipboard.c b/src/video/x11/SDL_x11clipboard.c
index 3b7332b53094b..913be162bcc49 100644
--- a/src/video/x11/SDL_x11clipboard.c
+++ b/src/video/x11/SDL_x11clipboard.c
@@ -198,7 +198,7 @@ static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type,
     } else {
         // Request that the selection owner copy the data to our window
         owner = window;
-        selection = videodata->SDL_SELECTION;
+        selection = videodata->atoms.SDL_SELECTION;
         X11_XConvertSelection(display, selection_type, XA_MIME, selection, owner,
                               CurrentTime);
 
@@ -212,7 +212,7 @@ static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type,
             if (seln_type == XA_MIME) {
                 *length = (size_t)count;
                 data = CloneDataBuffer(src, count);
-            } else if (seln_type == videodata->INCR) {
+            } 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);
@@ -267,13 +267,13 @@ const char **X11_GetTextMimeTypes(SDL_VideoDevice *_this, size_t *num_mime_types
 bool X11_SetClipboardData(SDL_VideoDevice *_this)
 {
     SDL_VideoData *videodata = _this->internal;
-    return SetSelectionData(_this, videodata->CLIPBOARD, _this->clipboard_callback, _this->clipboard_userdata, (const char **)_this->clipboard_mime_types, _this->num_clipboard_mime_types, _this->clipboard_sequence);
+    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->CLIPBOARD, mime_type, length);
+    return GetSelectionData(_this, videodata->atoms.CLIPBOARD, mime_type, length);
 }
 
 bool X11_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type)
diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 73454e681998f..1b883b8673cb1 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -525,7 +525,7 @@ static void X11_UpdateUserTime(SDL_WindowData *data, const unsigned long latest)
     if (latest && (latest != data->user_time)) {
         SDL_VideoData *videodata = data->videodata;
         Display *display = videodata->display;
-        X11_XChangeProperty(display, data->xwindow, videodata->_NET_WM_USER_TIME,
+        X11_XChangeProperty(display, data->xwindow, videodata->atoms._NET_WM_USER_TIME,
                             XA_CARDINAL, 32, PropModeReplace,
                             (const unsigned char *)&latest, 1);
 #ifdef DEBUG_XEVENTS
@@ -918,7 +918,7 @@ void X11_GetBorderValues(SDL_WindowData *data)
 
     // 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->_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &property) == Success) {
+        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];
@@ -995,7 +995,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
 #endif
 
         if (ev->selection == XA_PRIMARY ||
-            (videodata->CLIPBOARD != None && ev->selection == videodata->CLIPBOARD)) {
+            (videodata->atoms.CLIPBOARD != None && ev->selection == videodata->atoms.CLIPBOARD)) {
             SDL_SendClipboardUpdate();
             return;
         }
@@ -1331,7 +1331,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
 
         static int xdnd_version = 0;
 
-        if (xevent->xclient.message_type == videodata->XdndEnter) {
+        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];
@@ -1345,7 +1345,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
             if (use_list) {
                 // fetch conversion targets
                 SDL_x11Prop p;
-                X11_ReadProperty(&p, display, data->xdnd_source, videodata->XdndTypeList);
+                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);
@@ -1353,10 +1353,10 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
                 // pick from list of three
                 data->xdnd_req = X11_PickTargetFromAtoms(display, xevent->xclient.data.l[2], xevent->xclient.data.l[3], xevent->xclient.data.l[4]);
             }
-        } else if (xevent->xclient.message_type == videodata->XdndPosition) {
+        } else if (xevent->xclient.message_type == videodata->atoms.XdndPosition) {
 
 #ifdef DEBUG_XEVENTS
-            Atom act = videodata->XdndActionCopy;
+            Atom act = videodata->atoms.XdndActionCopy;
             if (xdnd_version >= 2) {
                 act = xevent->xclient.data.l[4];
             }
@@ -1380,24 +1380,24 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
             m.type = ClientMessage;
             m.display = xevent->xclient.display;
             m.window = xevent->xclient.data.l[0];
-            m.message_type = videodata->XdndStatus;
+            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->XdndActionCopy; // we only accept copying anyway
+            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->XdndDrop) {
+        } 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->XdndFinished;
+                m.message_type = videodata->atoms.XdndFinished;
                 m.format = 32;
                 m.data.l[0] = data->xwindow;
                 m.data.l[1] = 0;
@@ -1406,14 +1406,14 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
             } else {
                 // convert
                 if (xdnd_version >= 1) {
-                    X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent->xclient.data.l[2]);
+                    X11_XConvertSelection(display, videodata->atoms.XdndSelection, data->xdnd_req, videodata->atoms.PRIMARY, data->xwindow, xevent->xclient.data.l[2]);
                 } else {
-                    X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, CurrentTime);
+                    X11_XConvertSelection(display, videodata->atoms.XdndSelection, data->xdnd_req, videodata->atoms.PRIMARY, data->xwindow, CurrentTime);
                 }
             }
-        } else if ((xevent->xclient.message_type == videodata->WM_PROTOCOLS) &&
+        } else if ((xevent->xclient.message_type == videodata->atoms.WM_PROTOCOLS) &&
                    (xevent->xclient.format == 32) &&
-                   (xevent->xclient.data.l[0] == videodata->_NET_WM_PING)) {
+                   (xevent->xclient.data.l[0] == videodata->atoms._NET_WM_PING)) {
             Window root = DefaultRootWindow(display);
 
 #ifdef DEBUG_XEVENTS
@@ -1424,9 +1424,9 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
             break;
         }
 
-        else if ((xevent->xclient.message_type == videodata->WM_PROTOCOLS) &&
+        else if ((xevent->xclient.message_type == videodata->atoms.WM_PROTOCOLS) &&
                  (xevent->xclient.format == 32) &&
-                 (xevent->xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) {
+                 (xevent->xclient.data.l[0] == videodata->atoms.WM_DELETE_WINDOW)) {
 
 #ifdef DEBUG_XEVENTS
             SDL_Log("window 0x%lx: WM_DELETE_WINDOW\n", xevent->xany.window);
@@ -1553,7 +1553,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
                     SDL_Log(" }\n");
                 }
             } else if (real_type == XA_STRING ||
-                       real_type == videodata->UTF8_STRING) {
+                       real_type == videodata->atoms.UTF8_STRING) {
                 SDL_Log("{ \"%s\" }\n", propdata);
             } else if (real_type == XA_ATOM) {
                 Atom *atoms = (Atom *)propdata;
@@ -1591,7 +1591,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
             data->user_time = xevent->xproperty.time;
         }
 
-        if (xevent->xproperty.atom == data->videodata->_NET_WM_STATE) {
+        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,
@@ -1710,7 +1710,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
             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->XKLAVIER_STATE) {
+        } 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
@@ -1718,7 +1718,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
                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->_NET_FRAME_EXTENTS) {
+        } else if (xevent->xproperty.atom == videodata->atoms._NET_FRAME_EXTENTS) {
             if (data->disable_size_position_events) {
                 /* Re-enable size events if they were turned off waiting for the borders to come back
                  * when leaving fullscreen.
@@ -1758,7 +1758,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
         if (target == data->xdnd_req) {
             // read data
             SDL_x11Prop p;
-            X11_ReadProperty(&p, display, data->xwindow, videodata->PRIMARY);
+            X11_ReadProperty(&p, display, data->xwindow, videodata->atoms.PRIMARY);
 
             if (p.format == 8) {
                 char *saveptr = NULL;
@@ -1789,11 +1789,11 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
             m.type = ClientMessage;
             m.display = display;
             m.window = data->xdnd_source;
-            m.message_type = videodata->XdndFinished;
+            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->XdndActionCopy;
+            m.data.l[2] = videodata->atoms.XdndActionCopy;
             X11_XSendEvent(display, data->xdnd_source, False, NoEventMask, (XEvent *)&m);
 
             X11_XSync(display, False);
@@ -1857,7 +1857,7 @@ void X11_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window)
     event.type = ClientMessage;
     event.display = req_display;
     event.send_event = True;
-    event.message_type = data->_SDL_WAKEUP;
+    event.message_type = data->atoms._SDL_WAKEUP;
     event.format = 8;
 
     X11_XSendEvent(req_display, xwindow, False, NoEventMask, (XEvent *)&event);
diff --git a/src/video/x11/SDL_x11pen.c b/src/video/x11/SDL_x11pen.c
index d08d0f2bba74a..a6fb1562c81e8 100644
--- a/src/video/x11/SDL_x11pen.c
+++ b/src/video/x11/SDL_x11pen.c
@@ -36,7 +36,7 @@ static bool X11_XInput2DeviceIsPen(SDL_VideoDevice *_this, const XIDeviceInfo *d
         const XIAnyClassInfo *classinfo = dev->classes[i];
         if (classinfo->type == XIValuatorClass) {
             const XIValuatorClassInfo *val_classinfo = (const XIValuatorClassInfo *)classinfo;
-            if (val_classinfo->label == data->pen_atom_abs_pressure) {
+            if (val_classinfo->label == data->atoms.pen_atom_abs_pressure) {
                 return true;
             }
         }
@@ -51,7 +51,7 @@ static bool X11_XInput2PenIsEraser(SDL_VideoDevice *_this, int deviceid, char *d
     #define PEN_ERASER_NAME_TAG  "eraser" // String constant to identify erasers
     SDL_VideoData *data = (SDL_VideoData *)_this->internal;
 
-    if (data->pen_atom_wacom_tool_type != None) {
+    if (data->atoms.pen_atom_wacom_tool_type != None) {
         Atom type_return;
         int format_return;
         unsigned long num_items_return;
@@ -60,7 +60,7 @@ static bool X11_XInput2PenIsEraser(SDL_VideoDevice *_this, int deviceid, char *d
 
         // Try Wacom-specific method
         if (Success == X11_XIGetProperty(data->display, deviceid,
-                                         data->pen_atom_wacom_tool_type,
+                                         data->atoms.pen_atom_wacom_tool_type,
                                          0, 32, False,
                                          AnyPropertyType, &type_return, &format_return,
                                          &num_items_return, &bytes_after_return,
@@ -154,7 +154,7 @@ static bool X11_XInput2PenWacomDeviceID(SDL_VideoDevice *_this, int deviceid, Ui
     Sint32 serial_id_buf[3];
     int result;
 
-    if ((result = X11_XInput2PenGetIntProperty(_this, deviceid, data->pen_atom_wacom_serial_ids, serial_id_buf, 3)) == 3) {
+    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;
@@ -225,11 +225,11 @@ static X11_PenHandle *X11_MaybeAddPen(SDL_VideoDevice *_this, const XIDeviceInfo
             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->pen_atom_abs_pressure) {
+            if (vname == data->atoms.pen_atom_abs_pressure) {
                 axis = SDL_PEN_AXIS_PRESSURE;
-            } else if (vname == data->pen_atom_abs_tilt_x) {
+            } else if (vname == data->atoms.pen_atom_abs_tilt_x) {
                 axis = SDL_PEN_AXIS_XTILT;
-            } else if (vname == data->pen_atom_abs_tilt_y) {
+            } else if (vname == data->atoms.pen_atom_abs_tilt_y) {
                 axis = SDL_PEN_AXIS_YTILT;
             } else {
                 use_this_axis = false;
@@ -304,12 +304,12 @@ void X11_InitPen(SDL_VideoDevice *_this)
     SDL_VideoData *data = (SDL_VideoData *)_this->internal;
 
     #define LOOKUP_PEN_ATOM(X) X11_XInternAtom(data->display, X, False)
-    data->pen_atom_device_product_id = LOOKUP_PEN_ATOM("Device Product ID");
-    data->pen_atom_wacom_serial_ids = LOOKUP_PEN_ATOM("Wacom Serial IDs");
-    data->pen_atom_wacom_tool_type = LOOKUP_PEN_ATOM("Wacom Tool Type");
-    data->pen_atom_abs_pressure = LOOKUP_PEN_ATOM("Abs Pressure");
-    data->pen_atom_abs_tilt_x = LOOKUP_PEN_ATOM("Abs Tilt X");
-    data->pen_atom_abs_tilt_y = LOOKUP_PEN_ATOM("Abs Tilt Y");
+    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.
diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c
index ffe94f2c799e0..a8d6ec86bb73f 100644
--- a/src/video/x11/SDL_x11video.c
+++ b/src/video/x11/SDL_x11video.c
@@ -388,7 +388,7 @@ static bool X11_VideoInit(SDL_VideoDevice *_this)
     data->window_group = (XID)(((size_t)data->pid) ^ ((size_t)_this));
 
     // Look up some useful Atoms
-#define GET_ATOM(X) data->X = X11_XInternAtom(data->display, #X, False)
+#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);
diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h
index 0bce790c36dac..ce92e480c777a 100644
--- a/src/video/x11/SDL_x11video.h
+++ b/src/video/x11/SDL_x11video.h
@@ -66,54 +66,56 @@ struct SDL_VideoData
     bool net_wm;
 
     // Useful atoms
-    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_ALLOWED_ACTIONS;
-    Atom _NET_WM_ACTION_FULLSCREEN;
-    Atom _NET_WM_NAME;
-    Atom _NET_WM_ICON_NAME;
-    Atom _NET_WM_ICON;
-    Atom _NET_WM_PING;
-    Atom _NET_WM_WINDOW_OPACITY;
-    Atom _NET_WM_USER_TIME;
-    Atom _NET_ACTIVE_WINDOW;
-    Atom _NET_FRAME_EXTENTS;
-    Atom _SDL_WAKEUP;
-    Atom UTF8_STRING;
-    Atom PRIMARY;
-    Atom CLIPBOARD;
-    Atom INCR;
-    Atom SDL_SELECTION;
-    Atom XdndEnter;
-    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;
+    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_ALLOWED_ACTIONS;
+        Atom _NET_WM_ACTION_FULLSCREEN;
+        Atom _NET_WM_NAME;
+        Atom _NET_WM_ICON_NAME;
+        Atom _NET_WM_ICON;
+        Atom _NET_WM_PING;
+        Atom _NET_WM_WINDOW_OPACITY;
+        Atom _NET_WM_USER_TIME;
+        Atom _NET_ACTIVE_WINDOW;
+        Atom _NET_FRAME_EXTENTS;
+        Atom _SDL_WAKEUP;
+        Atom UTF8_STRING;
+        Atom PRIMARY;
+        Atom CLIPBOARD;
+        Atom INCR;
+        Atom SDL_SELECTION;
+        Atom XdndEnter;
+        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;
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index 509fa08c04404..7de9024414757 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -129,16 +129,16 @@ void X11_SetNetWMState(SDL_VideoDevice *_this, Window xwindow, SDL_WindowFlags f
     SDL_VideoData *videodata = _this->internal;
     Display *display = videodata->display;
     // !!! FIXME: just dereference videodata below instead of copying to locals.
-    Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
-    // Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;
-    Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
-    Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
-    Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
-    Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
-    Atom _NET_WM_STATE_ABOVE = videodata->_NET_WM_STATE_ABOVE;
-    Atom _NET_WM_STATE_SKIP_TASKBAR = videodata->_NET_WM_STATE_SKIP_TASKBAR;
-    Atom _NET_WM_STATE_SKIP_PAGER = videodata->_NET_WM_STATE_SKIP_PAGER;
-    Atom _NET_WM_STATE_MODAL = videodata->_NET_WM_STATE_MODAL;
+    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;
 
@@ -238,12 +238,12 @@ Uint32 X11_GetNetWMState(SDL_VideoDevice *_this, SDL_Window *window, Window xwin
 {
     SDL_VideoData *videodata = _this->internal;
     Display *display = videodata->display;
-    Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
-    Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN;
-    Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
-    Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
-    Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
-    Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
+    Atom _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;
@@ -773,12 +773,12 @@ bool X11_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
         Atom protocols[3];
         int proto_count = 0;
 
-        protocols[proto_count++] = data->WM_DELETE_WINDOW; // Allow window to be deleted by the WM
-        protocols[proto_count++] = data->WM_TAKE_FOCUS;    // Since we will want to set input focus explicitly
+        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->_NET_WM_PING; // Respond so WM knows we're alive
+            protocols[proto_count++] = data->atoms._NET_WM_PING; // Respond so WM knows we're alive
         }
 
         SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0]));
@@ -855,8 +855,8 @@ char *X11_GetWindowTitle(SDL_VideoDevice *_this, Window xwindow)
     unsigned char *propdata;
     char *title = NULL;
 
-    status = X11_XGetWindowProperty(display, xwindow, data->_NET_WM_NAME,
-                                    0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
+    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));
@@ -971,7 +971,7 @@ bool X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Surface *
 {
     SDL_WindowData *data = window->internal;
     Display *display = data->videodata->display;
-    Atom _NET_WM_ICON = data->videodata->_NET_WM_ICON;
+    Atom _NET_WM_ICON = data->videodata->atoms._NET_WM_ICON;
     int (*prevHandler)(Display *, XErrorEvent *) = NULL;
     bool result = true;
 
@@ -1226,7 +1226,7 @@ bool X11_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opac
 {
     SDL_WindowData *data = window->internal;
     Display *display = data->videodata->display;
-    Atom _NET_WM_WINDOW_OPACITY = data->videodata->_NET_WM_WINDOW_OPACITY;
+    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);
@@ -1250,7 +1250,7 @@ bool X11_SetWindowParent(SDL_VideoDevice *_this, SDL_Window *window, SDL_Window
     if (parent_data) {
         X11_XSetTransientForHint(display, data->xwindow, parent_data->xwindow);
     } else {
-        X11_XDeleteProperty(display, data->xwindow, video_data->WM_TRANSIENT_FOR);
+        X11_XDeleteProperty(display, data->xwindow, video_data->atoms.WM_TRANSIENT_FOR);
     }
 
     return true;
@@ -1263,14 +1263,14 @@ bool X11_SetWindowModal(SDL_VideoDevice *_this, SDL_Window *window, bool modal)
     SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window);
     Display *display = video_data->display;
     Uint32 flags = window->flags;
-    Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
-    Atom _NET_WM_STATE_MODAL = data->videodata->_NET_WM_STATE_MODAL;
+    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->WM_TRANSIENT_FOR);
+        X11_XDeleteProperty(display, data->xwindow, video_data->atoms.WM_TRANSIENT_FOR);
     }
 
     if (X11_IsWindowMapped(_this, window)) {
@@ -1363,8 +1363,8 @@ void X11_SetWindowAlwaysOnTop(SDL_VideoDevice *_this, SDL_Window *window, bool o
     SDL_WindowData *data = window->internal;
     SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window);
     Display *display = data->videodata->display;
-    Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
-    Atom _NET_WM_STATE_ABOVE = data->videodata->_NET_WM_STATE_ABOVE;
+    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;
@@ -1504,7 +1504,7 @@ static bool X11_SetWindowActive(SDL_VideoDevice *_this, SDL_Window *window)
     SDL_WindowData *data = window->internal;
     SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window);
     Display *display = data->videodata->display;
-    Atom _NET_ACTIVE_WINDOW = data->videodata->_NET_ACTIVE_WINDOW;
+    Atom _NET_ACTIVE_WINDOW = data->videodata->atoms._NET_ACTIVE_WINDOW;
 
     if (X11_IsWindowMapped(_this, window)) {
         XEvent e;
@@ -1548,9 +1548,9 @@ static bool X11_SetWindowMaximized(SDL_VideoDevice *_this, SDL_Window *window, b
     SDL_WindowData *data = window->internal;
     SDL_DisplayData *displaydata = SDL_GetDisplayDriverDataForWindow(window);
     Display *display = data->videodata->display;
-    Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
-    Atom _NET_WM_STATE_MAXIMIZED_VERT = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
-    Atom _NET_WM_STATE_MAXIMIZED_HORZ = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
+    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 (!maximized && window->flags & SDL_WINDOW_FULLSCREEN) {
         /* Fullscreen windows are maximized on some window managers,
@@ -1654,8 +1654,8 @@ static SDL_FullscreenResult X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this,
     SDL_WindowData *data = window->internal;
     SDL_DisplayData *displaydata = _display->internal;
     Display *display = data->videodata->display;
-    Atom _NET_WM_STATE = data->videodata->_NET_WM_STATE;
-    Atom _NET_WM_STATE_FULLSCREEN = data->videodata->_NET_WM_STATE_FULLSCREEN;
+    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;
@@ -1737,8 +1737,8 @@ static SDL_FullscreenResult X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this,
             } else {
                 e.xclient.data.l[0] = _

(Patch may be truncated, please check the link at the top of this post.)