Wayland backend: Add support for copy to clipboard

This commit is contained in:
Kovid Goyal 2018-09-04 22:22:43 +05:30
parent b0a39b127d
commit f3a1ee7b9f
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 106 additions and 4 deletions

15
glfw/wl_init.c vendored
View File

@ -593,6 +593,14 @@ static void registryHandleGlobal(void* data,
&zwp_idle_inhibit_manager_v1_interface, &zwp_idle_inhibit_manager_v1_interface,
1); 1);
} }
else if (strcmp(interface, "wl_data_device_manager") == 0)
{
_glfw.wl.dataDeviceManager =
wl_registry_bind(registry, name,
&wl_data_device_manager_interface,
1);
}
} }
static void registryHandleGlobalRemove(void *data, static void registryHandleGlobalRemove(void *data,
@ -761,6 +769,12 @@ void _glfwPlatformTerminate(void)
zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints); zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
if (_glfw.wl.idleInhibitManager) if (_glfw.wl.idleInhibitManager)
zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager); zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
if (_glfw.wl.dataSourceForClipboard)
wl_data_source_destroy(_glfw.wl.dataSourceForClipboard);
if (_glfw.wl.dataDevice)
wl_data_device_destroy(_glfw.wl.dataDevice);
if (_glfw.wl.dataDeviceManager)
wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
if (_glfw.wl.registry) if (_glfw.wl.registry)
wl_registry_destroy(_glfw.wl.registry); wl_registry_destroy(_glfw.wl.registry);
if (_glfw.wl.display) if (_glfw.wl.display)
@ -769,6 +783,7 @@ void _glfwPlatformTerminate(void)
wl_display_disconnect(_glfw.wl.display); wl_display_disconnect(_glfw.wl.display);
} }
closeFds(_glfw.wl.eventLoopData.wakeupFds, sizeof(_glfw.wl.eventLoopData.wakeupFds)/sizeof(_glfw.wl.eventLoopData.wakeupFds[0])); closeFds(_glfw.wl.eventLoopData.wakeupFds, sizeof(_glfw.wl.eventLoopData.wakeupFds)/sizeof(_glfw.wl.eventLoopData.wakeupFds[0]));
free(_glfw.wl.clipboardString); _glfw.wl.clipboardString = NULL;
} }
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)

5
glfw/wl_platform.h vendored
View File

@ -193,6 +193,9 @@ typedef struct _GLFWlibraryWayland
struct zwp_relative_pointer_manager_v1* relativePointerManager; struct zwp_relative_pointer_manager_v1* relativePointerManager;
struct zwp_pointer_constraints_v1* pointerConstraints; struct zwp_pointer_constraints_v1* pointerConstraints;
struct zwp_idle_inhibit_manager_v1* idleInhibitManager; struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
struct wl_data_device_manager* dataDeviceManager;
struct wl_data_device* dataDevice;
struct wl_data_source* dataSourceForClipboard;
int compositorVersion; int compositorVersion;
int seatVersion; int seatVersion;
@ -232,7 +235,7 @@ typedef struct _GLFWlibraryWayland
} egl; } egl;
EventLoopData eventLoopData; EventLoopData eventLoopData;
char *clipboardString;
} _GLFWlibraryWayland; } _GLFWlibraryWayland;
// Wayland-specific per-monitor data // Wayland-specific per-monitor data

88
glfw/wl_window.c vendored
View File

@ -1435,11 +1435,95 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
} }
} }
static void _glfwSendClipboardText(void *data, struct wl_data_source *data_source, const char *mime_type, int fd)
{
if (_glfw.wl.clipboardString) {
size_t len = strlen(_glfw.wl.clipboardString), pos = 0;
double start = glfwGetTime();
while (pos < len && glfwGetTime() - start < 2.0) {
ssize_t ret = write(fd, _glfw.wl.clipboardString + pos, len - pos);
if (ret < 0) {
if (errno == EAGAIN || errno == EINTR) continue;
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Could not copy writing to destination fd failed with error: %s", strerror(errno));
break;
}
if (ret > 0) {
start = glfwGetTime();
pos += ret;
}
}
}
close(fd);
}
static void _glfwDataSourceTargetHandler(void *data, struct wl_data_source *data_source, const char *mime_type) {}
static void _glfwDataSourceCanceledHandler(void *data, struct wl_data_source *data_source) {}
const struct wl_data_source_listener data_source_listener = {
.send = _glfwSendClipboardText,
.target = _glfwDataSourceTargetHandler,
.cancelled = _glfwDataSourceCanceledHandler
};
static void
copy_callback_done(void *data, struct wl_callback *callback, uint32_t serial) {
if (!_glfw.wl.dataDevice) return;
if (data == (void*)_glfw.wl.dataSourceForClipboard) {
wl_data_device_set_selection(_glfw.wl.dataDevice, data, serial);
}
}
const struct wl_callback_listener copy_callback_listener = {
.done = copy_callback_done
};
void _glfwPlatformSetClipboardString(const char* string) void _glfwPlatformSetClipboardString(const char* string)
{ {
// TODO if (!_glfw.wl.dataDeviceManager)
{
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Clipboard setting not implemented yet"); "Wayland: Cannot copy to clipboard data device manager is not ready");
return;
}
if (!_glfw.wl.dataDevice)
{
if (!_glfw.wl.seat)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Cannot copy to clipboard seat is not ready");
return;
}
_glfw.wl.dataDevice = wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager, _glfw.wl.seat);
if (!_glfw.wl.dataDevice)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Clipboard copy not enabled, failed to create data device");
return;
}
}
free(_glfw.wl.clipboardString);
_glfw.wl.clipboardString = _glfw_strdup(string);
if (_glfw.wl.dataSourceForClipboard)
wl_data_source_destroy(_glfw.wl.dataSourceForClipboard);
_glfw.wl.dataSourceForClipboard = wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
if (!_glfw.wl.dataSourceForClipboard)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Cannot copy failed to create data source");
return;
}
wl_data_source_add_listener(_glfw.wl.dataSourceForClipboard, &data_source_listener, NULL);
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "text/plain");
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "text/plain;charset=utf-8");
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "TEXT");
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "STRING");
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "UTF8_STRING");
struct wl_callback *callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(callback, &copy_callback_listener, _glfw.wl.dataSourceForClipboard);
} }
const char* _glfwPlatformGetClipboardString(void) const char* _glfwPlatformGetClipboardString(void)