Skip to content

Commit 70a58a6

Browse files
[platform][glfw][rgfw] Implementing clipboard image linux (#5603)
* Testing linux implementation * Add implementation for ClipboardImage on Linux * Adding another check to make sure that only X11 include X11 libs * Adding some comments to explain the magic numbers
1 parent 950c064 commit 70a58a6

2 files changed

Lines changed: 99 additions & 0 deletions

File tree

src/platforms/rcore_desktop_glfw.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,11 @@ const char *GetClipboardText(void)
10431043
return glfwGetClipboardString(platform.handle);
10441044
}
10451045

1046+
#if SUPPORT_CLIPBOARD_IMAGE && defined(__linux__) && defined(_GLFW_X11)
1047+
#include <X11/Xlib.h>
1048+
#include <X11/Xatom.h>
1049+
#endif
1050+
10461051
// Get clipboard image
10471052
Image GetClipboardImage(void)
10481053
{
@@ -1059,6 +1064,51 @@ Image GetClipboardImage(void)
10591064

10601065
if (bmpData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data.");
10611066
else image = LoadImageFromMemory(".bmp", (const unsigned char *)bmpData, (int)dataSize);
1067+
1068+
#elif defined(__linux__) && defined(_GLFW_X11)
1069+
1070+
// Implementation based on https://github.com/ColleagueRiley/Clipboard-Copy-Paste/blob/main/x11.c
1071+
Display* dpy = XOpenDisplay(NULL);
1072+
if (!dpy) return image;
1073+
1074+
Window root = DefaultRootWindow(dpy);
1075+
Window win = XCreateSimpleWindow(
1076+
dpy, // The connection to the X Server
1077+
root, // The 'Parent' window (usually the desktop/root)
1078+
0, 0, // X and Y position on the screen
1079+
1, 1, // Width and Height (1x1 pixel)
1080+
0, // Border width
1081+
0, // Border color
1082+
0 // Background color
1083+
);
1084+
1085+
Atom clipboard = XInternAtom(dpy, "CLIPBOARD", False);
1086+
Atom targetType = XInternAtom(dpy, "image/png", False); // Ask for PNG
1087+
Atom property = XInternAtom(dpy, "RAYLIB_CLIPBOARD_MANAGER", False);
1088+
1089+
// Request the data: "Convert whatever is in CLIPBOARD to image/png and put it in RAYLIB_CLIPBOARD_MANAGER"
1090+
XConvertSelection(dpy, clipboard, targetType, property, win, CurrentTime);
1091+
1092+
// Wait for the SelectionNotify event
1093+
XEvent ev;
1094+
XNextEvent(dpy, &ev);
1095+
1096+
Atom actualType;
1097+
int actualFormat;
1098+
unsigned long nitems, bytesAfter;
1099+
unsigned char* data = NULL;
1100+
1101+
// Read the data from our ghost window's property
1102+
XGetWindowProperty(dpy, win, property, 0, ~0L, False, AnyPropertyType,
1103+
&actualType, &actualFormat, &nitems, &bytesAfter, &data);
1104+
1105+
if (data != NULL) {
1106+
image = LoadImageFromMemory(".png", data, (int)nitems);
1107+
XFree(data);
1108+
}
1109+
1110+
XDestroyWindow(dpy, win);
1111+
XCloseDisplay(dpy);
10621112
#else
10631113
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
10641114
#endif // defined(_WIN32)

src/platforms/rcore_desktop_rgfw.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,13 +999,17 @@ const char *GetClipboardText(void)
999999
#define WINBASE_ALREADY_INCLUDED
10001000
#define WINGDI_ALREADY_INCLUDED
10011001
#include "../external/win32_clipboard.h"
1002+
#elif defined(__linux__) && defined(DRGFW_X11)
1003+
#include <X11/Xlib.h>
1004+
#include <X11/Xatom.h>
10021005
#endif
10031006
#endif
10041007

10051008
// Get clipboard image
10061009
Image GetClipboardImage(void)
10071010
{
10081011
Image image = { 0 };
1012+
10091013
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
10101014
#if defined(_WIN32)
10111015

@@ -1018,6 +1022,51 @@ Image GetClipboardImage(void)
10181022

10191023
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data");
10201024
else image = LoadImageFromMemory(".bmp", (const unsigned char *)fileData, dataSize);
1025+
1026+
#elif defined(__linux__) && defined(DRGFW_X11)
1027+
1028+
// Implementation based on https://github.com/ColleagueRiley/Clipboard-Copy-Paste/blob/main/x11.c
1029+
Display* dpy = XOpenDisplay(NULL);
1030+
if (!dpy) return image;
1031+
1032+
Window root = DefaultRootWindow(dpy);
1033+
Window win = XCreateSimpleWindow(
1034+
dpy, // The connection to the X Server
1035+
root, // The 'Parent' window (usually the desktop/root)
1036+
0, 0, // X and Y position on the screen
1037+
1, 1, // Width and Height (1x1 pixel)
1038+
0, // Border width
1039+
0, // Border color
1040+
0 // Background color
1041+
);
1042+
1043+
Atom clipboard = XInternAtom(dpy, "CLIPBOARD", False);
1044+
Atom targetType = XInternAtom(dpy, "image/png", False); // Ask for PNG
1045+
Atom property = XInternAtom(dpy, "RAYLIB_CLIPBOARD_MANAGER", False);
1046+
1047+
// Request the data: "Convert whatever is in CLIPBOARD to image/png and put it in RAYLIB_CLIPBOARD_MANAGER"
1048+
XConvertSelection(dpy, clipboard, targetType, property, win, CurrentTime);
1049+
1050+
// Wait for the SelectionNotify event
1051+
XEvent ev;
1052+
XNextEvent(dpy, &ev);
1053+
1054+
Atom actualType;
1055+
int actualFormat;
1056+
unsigned long nitems, bytesAfter;
1057+
unsigned char* data = NULL;
1058+
1059+
// Read the data from our ghost window's property
1060+
XGetWindowProperty(dpy, win, property, 0, ~0L, False, AnyPropertyType,
1061+
&actualType, &actualFormat, &nitems, &bytesAfter, &data);
1062+
1063+
if (data != NULL) {
1064+
image = LoadImageFromMemory(".png", data, (int)nitems);
1065+
XFree(data);
1066+
}
1067+
1068+
XDestroyWindow(dpy, win);
1069+
XCloseDisplay(dpy);
10211070
#else
10221071
TRACELOG(LOG_WARNING, "Clipboard image: PLATFORM_DESKTOP_RGFW doesn't implement GetClipboardImage() for this OS");
10231072
#endif // defined(_WIN32)

0 commit comments

Comments
 (0)