From 200196dac74647121a04d35a4abe082136ae7b46 Mon Sep 17 00:00:00 2001 From: Ricardo Vieira Date: Tue, 23 Sep 2014 18:24:33 +0100 Subject: [PATCH 1/2] wayland: save serial from all input sources --- src/wl_init.c | 12 ++++++++++-- src/wl_platform.h | 2 +- src/wl_window.c | 9 ++++----- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index 29509ae91..1923e28b6 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -50,7 +50,7 @@ static void pointerHandleEnter(void* data, { _GLFWwindow* window = wl_surface_get_user_data(surface); - _glfw.wl.pointerSerial = serial; + _glfw.wl.serial = serial; _glfw.wl.pointerFocus = window; _glfwPlatformSetCursor(window, window->wl.currentCursor); @@ -67,7 +67,7 @@ static void pointerHandleLeave(void* data, if (!window) return; - _glfw.wl.pointerSerial = serial; + _glfw.wl.serial = serial; _glfw.wl.pointerFocus = NULL; _glfwInputCursorEnter(window, GLFW_FALSE); } @@ -106,6 +106,8 @@ static void pointerHandleButton(void* data, _GLFWwindow* window = _glfw.wl.pointerFocus; int glfwButton; + _glfw.wl.serial = serial; + if (!window) return; @@ -232,6 +234,7 @@ static void keyboardHandleEnter(void* data, { _GLFWwindow* window = wl_surface_get_user_data(surface); + _glfw.wl.serial = serial; _glfw.wl.keyboardFocus = window; _glfwInputWindowFocus(window, GLFW_TRUE); } @@ -246,6 +249,7 @@ static void keyboardHandleLeave(void* data, if (!window) return; + _glfw.wl.serial = serial; _glfw.wl.keyboardFocus = NULL; _glfwInputWindowFocus(window, GLFW_FALSE); } @@ -272,6 +276,8 @@ static void keyboardHandleKey(void* data, const xkb_keysym_t *syms; _GLFWwindow* window = _glfw.wl.keyboardFocus; + _glfw.wl.serial = serial; + if (!window) return; @@ -308,6 +314,8 @@ static void keyboardHandleModifiers(void* data, xkb_mod_mask_t mask; unsigned int modifiers = 0; + _glfw.wl.serial = serial; + if (!_glfw.wl.xkb.keymap) return; diff --git a/src/wl_platform.h b/src/wl_platform.h index 100b12bc0..dcb9ca4df 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -124,7 +124,7 @@ typedef struct _GLFWlibraryWayland struct wl_cursor_theme* cursorTheme; struct wl_surface* cursorSurface; - uint32_t pointerSerial; + uint32_t serial; _GLFWmonitor** monitors; int monitorsCount; diff --git a/src/wl_window.c b/src/wl_window.c index b3b9bea23..cff6b65ee 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -727,7 +727,7 @@ static void lockPointer(_GLFWwindow* window) window->wl.pointerLock.relativePointer = relativePointer; window->wl.pointerLock.lockedPointer = lockedPointer; - wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial, + wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, NULL, 0, 0); } @@ -779,7 +779,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) buffer = wl_cursor_image_get_buffer(image); if (!buffer) return; - wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial, + wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, surface, image->hotspot_x, image->hotspot_y); @@ -790,7 +790,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) } else { - wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial, + wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, surface, cursor->wl.xhot, cursor->wl.yhot); @@ -807,8 +807,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) } else if (window->cursorMode == GLFW_CURSOR_HIDDEN) { - wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial, - NULL, 0, 0); + wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, NULL, 0, 0); } } From 6d38d09e0e96185db5b699c1e0a0ce53fddd7737 Mon Sep 17 00:00:00 2001 From: Ricardo Vieira Date: Fri, 3 Oct 2014 19:29:29 +0100 Subject: [PATCH 2/2] wayland: Implement clipboard support --- src/wl_init.c | 104 +++++++++++++++++++++++++++++++++++++++++++ src/wl_platform.h | 7 +++ src/wl_window.c | 109 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 215 insertions(+), 5 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index 1923e28b6..4d36dbd64 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,76 @@ static inline int min(int n1, int n2) return n1 < n2 ? n1 : n2; } +static void dataOfferOffer(void* data, + struct wl_data_offer* offer, + const char* type) +{ + if (_glfw.wl.dataOffer) + { + wl_data_offer_destroy(_glfw.wl.dataOffer); + _glfw.wl.dataOffer = NULL; + } + if (strcmp(type, _glfw.wl.clipboardMimeType) == 0) + { + _glfw.wl.dataOffer = offer; + } +} + +static const struct wl_data_offer_listener dataOfferListener = { + dataOfferOffer, +}; + +static void dataDeviceHandleDataOffer(void* data, + struct wl_data_device* dataDevice, + struct wl_data_offer* offer) +{ + wl_data_offer_add_listener(offer, &dataOfferListener, NULL); +} + +static void dataDeviceHandleEnter(void* data, + struct wl_data_device* dataDevice, + uint32_t serial, + struct wl_surface *surface, + wl_fixed_t sx, + wl_fixed_t sf, + struct wl_data_offer *offer) +{ + _glfw.wl.serial = serial; +} + +static void dataDeviceHandleLeave(void *data, + struct wl_data_device* dataDevice) +{ +} + +static void dataDeviceHandleMotion(void *data, + struct wl_data_device* dataDevice, + uint32_t time, + wl_fixed_t sx, + wl_fixed_t sf) +{ +} + +static void dataDeviceHandleDrop(void *data, + struct wl_data_device* dataDevice) +{ +} + +static void dataDeviceHandleSelection(void *data, + struct wl_data_device *dataDevice, + struct wl_data_offer *offer) +{ +} + +static const struct wl_data_device_listener dataDeviceListener = { + dataDeviceHandleDataOffer, + dataDeviceHandleEnter, + dataDeviceHandleLeave, + dataDeviceHandleMotion, + dataDeviceHandleDrop, + dataDeviceHandleSelection +}; + static void pointerHandleEnter(void* data, struct wl_pointer* pointer, uint32_t serial, @@ -430,6 +501,14 @@ static void registryHandleGlobal(void* data, &zwp_pointer_constraints_v1_interface, 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, @@ -616,6 +695,17 @@ int _glfwPlatformInit(void) _glfwInitTimerPOSIX(); + if (_glfw.wl.dataDeviceManager && _glfw.wl.seat) + { + _glfw.wl.clipboardMimeType = "text/plain;charset=utf-8"; + _glfw.wl.dataDevice = + wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager, + _glfw.wl.seat); + wl_data_device_add_listener(_glfw.wl.dataDevice, + &dataDeviceListener, + NULL); + } + if (_glfw.wl.pointer && _glfw.wl.shm) { _glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm); @@ -638,6 +728,20 @@ void _glfwPlatformTerminate(void) _glfwTerminateJoysticksLinux(); _glfwTerminateThreadLocalStoragePOSIX(); + if (_glfw.wl.dataOffer) + wl_data_offer_destroy(_glfw.wl.dataOffer); + if (_glfw.wl.clipboardString) + free(_glfw.wl.clipboardString); + if (_glfw.wl.dataSource) + { + free(wl_data_source_get_user_data(_glfw.wl.dataSource)); + wl_data_source_destroy(_glfw.wl.dataSource); + } + 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.cursorTheme) wl_cursor_theme_destroy(_glfw.wl.cursorTheme); if (_glfw.wl.cursorSurface) diff --git a/src/wl_platform.h b/src/wl_platform.h index dcb9ca4df..c297eca34 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -115,6 +115,7 @@ typedef struct _GLFWlibraryWayland struct wl_shell* shell; struct wl_shm* shm; struct wl_seat* seat; + struct wl_data_device_manager* dataDeviceManager; struct wl_pointer* pointer; struct wl_keyboard* keyboard; struct zwp_relative_pointer_manager_v1* relativePointerManager; @@ -122,6 +123,7 @@ typedef struct _GLFWlibraryWayland int wl_compositor_version; + struct wl_data_device* dataDevice; struct wl_cursor_theme* cursorTheme; struct wl_surface* cursorSurface; uint32_t serial; @@ -143,6 +145,11 @@ typedef struct _GLFWlibraryWayland unsigned int modifiers; } xkb; + struct wl_data_offer* dataOffer; + struct wl_data_source* dataSource; + char* clipboardString; + const char* clipboardMimeType; + _GLFWwindow* pointerFocus; _GLFWwindow* keyboardFocus; diff --git a/src/wl_window.c b/src/wl_window.c index cff6b65ee..b4da60211 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -40,6 +40,7 @@ #include #include +#define BUFFER_LEN 500 static void handlePing(void* data, struct wl_shell_surface* shellSurface, @@ -149,6 +150,43 @@ static const struct wl_surface_listener surfaceListener = { handleLeave }; +static void dataSourceTarget(void* data, + struct wl_data_source* source, + const char* mimeType) +{ +} + +static void dataSourceSend(void* data, + struct wl_data_source* source, + const char* mimeType, + int32_t fd) +{ + ssize_t len; + char* string = wl_data_source_get_user_data(source); + + do + { + len = write(fd, string, strlen(string)); + string += len; + } + while(len < strlen(string)); +} + +static void dataSourceCancel(void* data, + struct wl_data_source* source) +{ + if (_glfw.wl.dataSource == source) + _glfw.wl.dataSource = NULL; + free(wl_data_source_get_user_data(source)); + wl_data_source_destroy(source); +} + +static const struct wl_data_source_listener dataSourceListener = { + dataSourceTarget, + dataSourceSend, + dataSourceCancel +}; + static GLFWbool createSurface(_GLFWwindow* window, const _GLFWwndconfig* wndconfig) { @@ -813,15 +851,76 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { - // TODO - fprintf(stderr, "_glfwPlatformSetClipboardString not implemented yet\n"); + if (!_glfw.wl.dataDevice) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Clipboard could not be set."\ + "Data device was not initialized"); + return; + } + if (_glfw.wl.dataSource) + { + free(wl_data_source_get_user_data(_glfw.wl.dataSource)); + wl_data_source_destroy(_glfw.wl.dataSource); + } + _glfw.wl.dataSource = + wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager); + wl_data_source_offer(_glfw.wl.dataSource, + _glfw.wl.clipboardMimeType); + wl_data_source_add_listener(_glfw.wl.dataSource, + &dataSourceListener, + strdup(string)); + wl_data_device_set_selection(_glfw.wl.dataDevice, + _glfw.wl.dataSource, + _glfw.wl.serial); } const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) { - // TODO - fprintf(stderr, "_glfwPlatformGetClipboardString not implemented yet\n"); - return NULL; + int32_t p[2]; + int len, allocatedLen = 0; + char *aux; + + if (!_glfw.wl.dataOffer) + return NULL; + + if (pipe2(p, O_CLOEXEC) == -1) + return NULL; + + wl_data_offer_receive(_glfw.wl.dataOffer, + _glfw.wl.clipboardMimeType, + p[1]); + close(p[1]); + + _glfwPlatformWaitEvents(); + + if (_glfw.wl.clipboardString) + { + free(_glfw.wl.clipboardString); + _glfw.wl.clipboardString = NULL; + } + + do + { + allocatedLen += BUFFER_LEN; + _glfw.wl.clipboardString = + realloc(_glfw.wl.clipboardString, + allocatedLen * sizeof(*_glfw.wl.clipboardString)); + aux = _glfw.wl.clipboardString + (allocatedLen - BUFFER_LEN); + memset(aux, 0, BUFFER_LEN); + len = read(p[0], aux, BUFFER_LEN); + } + while (len == BUFFER_LEN); + + close(p[0]); + + if (len < 0) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Clipboard read error: %d", errno); + return NULL; + } + return _glfw.wl.clipboardString; } char** _glfwPlatformGetRequiredInstanceExtensions(unsigned int* count)