Improve GetClipboardImage implementation under X11

This commit is contained in:
steampuker 2026-05-16 01:51:46 +05:00
parent c04e57399a
commit 50bee82421

View File

@ -112,6 +112,13 @@
typedef struct { typedef struct {
GLFWwindow *handle; // GLFW window handle (graphic device) GLFWwindow *handle; // GLFW window handle (graphic device)
#if defined(__linux__) && defined(_GLFW_X11) #if defined(__linux__) && defined(_GLFW_X11)
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
// Clipboard specific
Display *cbDisplay;
XID cbWindow;
Atom cbAtom, cbTargetAtom, cbPropertyAtom;
#endif
// Local storage for the window handle returned by glfwGetX11Window // Local storage for the window handle returned by glfwGetX11Window
// This is needed as X11 handles are integers and may not fit inside a pointer depending on platform // This is needed as X11 handles are integers and may not fit inside a pointer depending on platform
// Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width // Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width
@ -1042,11 +1049,6 @@ const char *GetClipboardText(void)
return glfwGetClipboardString(platform.handle); return glfwGetClipboardString(platform.handle);
} }
#if SUPPORT_CLIPBOARD_IMAGE && defined(__linux__) && defined(_GLFW_X11)
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#endif
// Get clipboard image // Get clipboard image
Image GetClipboardImage(void) Image GetClipboardImage(void)
{ {
@ -1068,30 +1070,32 @@ Image GetClipboardImage(void)
#elif defined(__linux__) && defined(_GLFW_X11) #elif defined(__linux__) && defined(_GLFW_X11)
// REF: https://github.com/ColleagueRiley/Clipboard-Copy-Paste/blob/main/x11.c // REF: https://github.com/ColleagueRiley/Clipboard-Copy-Paste/blob/main/x11.c
Display *dpy = XOpenDisplay(NULL); if(!platform.cbDisplay)
if (!dpy) return image; {
platform.cbDisplay = XOpenDisplay(NULL);
if (!platform.cbDisplay) return image;
Window root = DefaultRootWindow(dpy); platform.cbWindow = XCreateSimpleWindow(
Window win = XCreateSimpleWindow( platform.cbDisplay, // The connection to the X Server
dpy, // The connection to the X Server DefaultRootWindow(platform.cbDisplay), // The 'Parent' window (usually the desktop/root)
root, // The 'Parent' window (usually the desktop/root) 0, 0, // X and Y position on the screen
0, 0, // X and Y position on the screen 1, 1, // Width and Height (1x1 pixel)
1, 1, // Width and Height (1x1 pixel) 0, // Border width
0, // Border width 0, // Border color
0, // Border color 0 // Background color
0 // Background color );
);
Atom clipboard = XInternAtom(dpy, "CLIPBOARD", False); platform.cbAtom = XInternAtom(platform.cbDisplay, "CLIPBOARD", False);
Atom targetType = XInternAtom(dpy, "image/png", False); // Ask for PNG platform.cbTargetAtom = XInternAtom(platform.cbDisplay, "image/png", False); // Ask for PNG
Atom property = XInternAtom(dpy, "RAYLIB_CLIPBOARD_MANAGER", False); platform.cbPropertyAtom = XInternAtom(platform.cbDisplay, "RAYLIB_CLIPBOARD_MANAGER", False);
}
// Request the data: "Convert whatever is in CLIPBOARD to image/png and put it in RAYLIB_CLIPBOARD_MANAGER" // Request the data: "Convert whatever is in CLIPBOARD to image/png and put it in RAYLIB_CLIPBOARD_MANAGER"
XConvertSelection(dpy, clipboard, targetType, property, win, CurrentTime); XConvertSelection(platform.cbDisplay, platform.cbAtom, platform.cbTargetAtom, platform.cbPropertyAtom, platform.cbWindow, CurrentTime);
// Wait for the SelectionNotify event // Wait for the SelectionNotify event
XEvent ev = { 0 }; XEvent ev = { 0 };
XNextEvent(dpy, &ev); XNextEvent(platform.cbDisplay, &ev);
Atom actualType = { 0 }; Atom actualType = { 0 };
int actualFormat = 0; int actualFormat = 0;
@ -1100,7 +1104,7 @@ Image GetClipboardImage(void)
unsigned char *data = NULL; unsigned char *data = NULL;
// Read the data from our ghost window's property // Read the data from our ghost window's property
XGetWindowProperty(dpy, win, property, 0, ~0L, False, AnyPropertyType, XGetWindowProperty(platform.cbDisplay, platform.cbWindow, platform.cbPropertyAtom, 0, ~0L, False, AnyPropertyType,
&actualType, &actualFormat, &nitems, &bytesAfter, &data); &actualType, &actualFormat, &nitems, &bytesAfter, &data);
if (data != NULL) if (data != NULL)
@ -1108,9 +1112,6 @@ Image GetClipboardImage(void)
image = LoadImageFromMemory(".png", data, (int)nitems); image = LoadImageFromMemory(".png", data, (int)nitems);
XFree(data); XFree(data);
} }
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
#else #else
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform"); TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
#endif // _WIN32 #endif // _WIN32
@ -1876,6 +1877,13 @@ void ClosePlatform(void)
#if defined(_WIN32) && SUPPORT_WINMM_HIGHRES_TIMER && !SUPPORT_BUSY_WAIT_LOOP #if defined(_WIN32) && SUPPORT_WINMM_HIGHRES_TIMER && !SUPPORT_BUSY_WAIT_LOOP
timeEndPeriod(1); // Restore time period timeEndPeriod(1); // Restore time period
#elif defined(__linux__) && defined(_GLFW_X11) && SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
if(platform.cbDisplay) // Unload clipboard connection
{
XDestroyWindow(platform.cbDisplay, platform.cbWindow);
XCloseDisplay(platform.cbDisplay);
platform.cbDisplay = NULL;
}
#endif #endif
} }