Wayland backend: Add support for copy to clipboard
This commit is contained in:
parent
b0a39b127d
commit
f3a1ee7b9f
15
glfw/wl_init.c
vendored
15
glfw/wl_init.c
vendored
@ -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
5
glfw/wl_platform.h
vendored
@ -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
88
glfw/wl_window.c
vendored
@ -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, ©_callback_listener, _glfw.wl.dataSourceForClipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetClipboardString(void)
|
const char* _glfwPlatformGetClipboardString(void)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user