Wayland: Implement clipboard copy
diff --git a/src/wl_init.c b/src/wl_init.c
index 30d0eca..c6b209b 100644
--- a/src/wl_init.c
+++ b/src/wl_init.c
@@ -1263,6 +1263,8 @@
zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
if (_glfw.wl.wmBase)
xdg_wm_base_destroy(_glfw.wl.wmBase);
+ if (_glfw.wl.dataSource)
+ wl_data_source_destroy(_glfw.wl.dataSource);
if (_glfw.wl.dataDevice)
wl_data_device_destroy(_glfw.wl.dataDevice);
if (_glfw.wl.dataOffer)
@@ -1296,6 +1298,8 @@
if (_glfw.wl.clipboardString)
free(_glfw.wl.clipboardString);
+ if (_glfw.wl.clipboardSendString)
+ free(_glfw.wl.clipboardSendString);
}
const char* _glfwPlatformGetVersionString(void)
diff --git a/src/wl_platform.h b/src/wl_platform.h
index 11c2f91..c17ebe8 100644
--- a/src/wl_platform.h
+++ b/src/wl_platform.h
@@ -236,6 +236,7 @@
struct wl_data_device_manager* dataDeviceManager;
struct wl_data_device* dataDevice;
struct wl_data_offer* dataOffer;
+ struct wl_data_source* dataSource;
struct xdg_wm_base* wmBase;
struct zxdg_decoration_manager_v1* decorationManager;
struct wp_viewporter* viewporter;
@@ -258,6 +259,8 @@
int keyboardLastScancode;
char* clipboardString;
size_t clipboardSize;
+ char* clipboardSendString;
+ size_t clipboardSendSize;
int timerfd;
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
diff --git a/src/wl_window.c b/src/wl_window.c
index 817e2f0..98a6465 100644
--- a/src/wl_window.c
+++ b/src/wl_window.c
@@ -1569,11 +1569,126 @@
}
}
+static void dataSourceHandleTarget(void* data,
+ struct wl_data_source* dataSource,
+ const char* mimeType)
+{
+ if (_glfw.wl.dataSource != dataSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unknown clipboard data source");
+ return;
+ }
+}
+
+static void dataSourceHandleSend(void* data,
+ struct wl_data_source* dataSource,
+ const char* mimeType,
+ int fd)
+{
+ const char* string = _glfw.wl.clipboardSendString;
+ size_t len = _glfw.wl.clipboardSendSize;
+ int ret;
+
+ if (_glfw.wl.dataSource != dataSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unknown clipboard data source");
+ return;
+ }
+
+ if (!string)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Copy requested from an invalid string");
+ return;
+ }
+
+ if (strcmp(mimeType, "text/plain;charset=utf-8") != 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Wrong MIME type asked from clipboard");
+ close(fd);
+ return;
+ }
+
+ while (len > 0)
+ {
+ ret = write(fd, string, len);
+ if (ret == -1 && errno == EINTR)
+ continue;
+ if (ret == -1)
+ {
+ // TODO: also report errno maybe.
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Error while writing the clipboard");
+ close(fd);
+ return;
+ }
+ len -= ret;
+ }
+ close(fd);
+}
+
+static void dataSourceHandleCancelled(void* data,
+ struct wl_data_source* dataSource)
+{
+ wl_data_source_destroy(dataSource);
+
+ if (_glfw.wl.dataSource != dataSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unknown clipboard data source");
+ return;
+ }
+
+ _glfw.wl.dataSource = NULL;
+}
+
+static const struct wl_data_source_listener dataSourceListener = {
+ dataSourceHandleTarget,
+ dataSourceHandleSend,
+ dataSourceHandleCancelled,
+};
+
void _glfwPlatformSetClipboardString(const char* string)
{
- // TODO
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "Wayland: Clipboard setting not implemented yet");
+ if (_glfw.wl.dataSource)
+ {
+ wl_data_source_destroy(_glfw.wl.dataSource);
+ _glfw.wl.dataSource = NULL;
+ }
+
+ if (_glfw.wl.clipboardSendString)
+ {
+ free(_glfw.wl.clipboardSendString);
+ _glfw.wl.clipboardSendString = NULL;
+ }
+
+ _glfw.wl.clipboardSendString = strdup(string);
+ if (!_glfw.wl.clipboardSendString)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Impossible to allocate clipboard string");
+ return;
+ }
+ _glfw.wl.clipboardSendSize = strlen(string);
+ _glfw.wl.dataSource =
+ wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
+ if (!_glfw.wl.dataSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Impossible to create clipboard source");
+ free(_glfw.wl.clipboardSendString);
+ return;
+ }
+ wl_data_source_add_listener(_glfw.wl.dataSource,
+ &dataSourceListener,
+ NULL);
+ wl_data_source_offer(_glfw.wl.dataSource, "text/plain;charset=utf-8");
+ wl_data_device_set_selection(_glfw.wl.dataDevice,
+ _glfw.wl.dataSource,
+ _glfw.wl.serial);
}
static GLFWbool growClipboardString(void)