From a6900443d536332c0b696b547da12d73b1f13073 Mon Sep 17 00:00:00 2001 From: Tarmack Date: Tue, 13 Nov 2018 20:58:02 +0100 Subject: [PATCH] Wayland primary selection migrated to unstable protocol This change is actually backwards compatible with the GTK implementation before. --- glfw/glfw.py | 9 +- glfw/source-info.json | 2 +- glfw/wl_init.c | 9 +- glfw/wl_platform.h | 10 +- glfw/wl_protocols/gtk-primary-selection.xml | 225 -------------------- glfw/wl_window.c | 54 ++--- 6 files changed, 41 insertions(+), 268 deletions(-) delete mode 100644 glfw/wl_protocols/gtk-primary-selection.xml diff --git a/glfw/glfw.py b/glfw/glfw.py index cb2392d09..c0a798dee 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -90,12 +90,9 @@ def init_env(env, pkg_config, at_least_version, test_compile, module='x11'): def build_wayland_protocols(env, run_tool, emphasis, newer, dest_dir): for protocol in env.wayland_protocols: - if os.path.dirname(protocol) == 'wl_protocols': - src = os.path.join(dest_dir, protocol) - else: - src = os.path.join(env.wayland_packagedir, protocol) - if not os.path.exists(src): - raise SystemExit('The wayland-protocols package on your system is missing the {} protocol definition file'.format(protocol)) + src = os.path.join(env.wayland_packagedir, protocol) + if not os.path.exists(src): + raise SystemExit('The wayland-protocols package on your system is missing the {} protocol definition file'.format(protocol)) for ext in 'hc': dest = wayland_protocol_file_name(src, ext) dest = os.path.join(dest_dir, dest) diff --git a/glfw/source-info.json b/glfw/source-info.json index fe8955696..b621d781d 100644 --- a/glfw/source-info.json +++ b/glfw/source-info.json @@ -73,7 +73,7 @@ "unstable/pointer-constraints/pointer-constraints-unstable-v1.xml", "unstable/idle-inhibit/idle-inhibit-unstable-v1.xml", "unstable/xdg-decoration/xdg-decoration-unstable-v1.xml", - "wl_protocols/gtk-primary-selection.xml" + "unstable/primary-selection/primary-selection-unstable-v1.xml" ], "sources": [ "wl_init.c", diff --git a/glfw/wl_init.c b/glfw/wl_init.c index 9bb7040c3..5a3571d2d 100644 --- a/glfw/wl_init.c +++ b/glfw/wl_init.c @@ -618,11 +618,12 @@ static void registryHandleGlobal(void* data, _glfwSetupWaylandDataDevice(); } } - else if (strcmp(interface, "gtk_primary_selection_device_manager") == 0) + else if (strcmp(interface, "zwp_primary_selection_device_manager_v1") == 0 || + strcmp(interface, "gtk_primary_selection_device_manager") == 0) { _glfw.wl.primarySelectionDeviceManager = wl_registry_bind(registry, name, - >k_primary_selection_device_manager_interface, + &zwp_primary_selection_device_manager_v1_interface, 1); if (_glfw.wl.seat && _glfw.wl.primarySelectionDeviceManager && !_glfw.wl.primarySelectionDevice) { _glfwSetupWaylandPrimarySelectionDevice(); @@ -822,9 +823,9 @@ void _glfwPlatformTerminate(void) if (_glfw.wl.dataDeviceManager) wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager); if (_glfw.wl.primarySelectionDevice) - gtk_primary_selection_device_destroy(_glfw.wl.primarySelectionDevice); + zwp_primary_selection_device_v1_destroy(_glfw.wl.primarySelectionDevice); if (_glfw.wl.primarySelectionDeviceManager) - gtk_primary_selection_device_manager_destroy(_glfw.wl.primarySelectionDeviceManager); + zwp_primary_selection_device_manager_v1_destroy(_glfw.wl.primarySelectionDeviceManager); if (_glfw.wl.registry) wl_registry_destroy(_glfw.wl.registry); if (_glfw.wl.display) diff --git a/glfw/wl_platform.h b/glfw/wl_platform.h index 9f69dab69..d2a42ee50 100644 --- a/glfw/wl_platform.h +++ b/glfw/wl_platform.h @@ -60,7 +60,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR #include "wayland-relative-pointer-unstable-v1-client-protocol.h" #include "wayland-pointer-constraints-unstable-v1-client-protocol.h" #include "wayland-idle-inhibit-unstable-v1-client-protocol.h" -#include "wayland-gtk-primary-selection-client-protocol.h" +#include "wayland-primary-selection-unstable-v1-client-protocol.h" #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlclose(handle) dlclose(handle) @@ -210,7 +210,7 @@ typedef struct _GLFWWaylandDataOffer typedef struct _GLFWWaylandPrimaryOffer { - struct gtk_primary_selection_offer *id; + struct zwp_primary_selection_offer_v1 *id; const char *mime; _GLFWWaylandOfferType offer_type; size_t idx; @@ -241,9 +241,9 @@ typedef struct _GLFWlibraryWayland struct wl_data_device_manager* dataDeviceManager; struct wl_data_device* dataDevice; struct wl_data_source* dataSourceForClipboard; - struct gtk_primary_selection_device_manager* primarySelectionDeviceManager; - struct gtk_primary_selection_device* primarySelectionDevice; - struct gtk_primary_selection_source* dataSourceForPrimarySelection; + struct zwp_primary_selection_device_manager_v1* primarySelectionDeviceManager; + struct zwp_primary_selection_device_v1* primarySelectionDevice; + struct zwp_primary_selection_source_v1* dataSourceForPrimarySelection; int compositorVersion; int seatVersion; diff --git a/glfw/wl_protocols/gtk-primary-selection.xml b/glfw/wl_protocols/gtk-primary-selection.xml deleted file mode 100644 index 02cab94fc..000000000 --- a/glfw/wl_protocols/gtk-primary-selection.xml +++ /dev/null @@ -1,225 +0,0 @@ - - - - Copyright © 2015, 2016 Red Hat - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - - - This protocol provides the ability to have a primary selection device to - match that of the X server. This primary selection is a shortcut to the - common clipboard selection, where text just needs to be selected in order - to allow copying it elsewhere. The de facto way to perform this action - is the middle mouse button, although it is not limited to this one. - - Clients wishing to honor primary selection should create a primary - selection source and set it as the selection through - wp_primary_selection_device.set_selection whenever the text selection - changes. In order to minimize calls in pointer-driven text selection, - it should happen only once after the operation finished. Similarly, - a NULL source should be set when text is unselected. - - wp_primary_selection_offer objects are first announced through the - wp_primary_selection_device.data_offer event. Immediately after this event, - the primary data offer will emit wp_primary_selection_offer.offer events - to let know of the mime types being offered. - - When the primary selection changes, the client with the keyboard focus - will receive wp_primary_selection_device.selection events. Only the client - with the keyboard focus will receive such events with a non-NULL - wp_primary_selection_offer. Across keyboard focus changes, previously - focused clients will receive wp_primary_selection_device.events with a - NULL wp_primary_selection_offer. - - In order to request the primary selection data, the client must pass - a recent serial pertaining to the press event that is triggering the - operation, if the compositor deems the serial valid and recent, the - wp_primary_selection_source.send event will happen in the other end - to let the transfer begin. The client owning the primary selection - should write the requested data, and close the file descriptor - immediately. - - If the primary selection owner client disappeared during the transfer, - the client reading the data will receive a - wp_primary_selection_device.selection event with a NULL - wp_primary_selection_offer, the client should take this as a hint - to finish the reads related to the no longer existing offer. - - The primary selection owner should be checking for errors during - writes, merely cancelling the ongoing transfer if any happened. - - - - - The primary selection device manager is a singleton global object that - provides access to the primary selection. It allows to create - wp_primary_selection_source objects, as well as retrieving the per-seat - wp_primary_selection_device objects. - - - - - Create a new primary selection source. - - - - - - - Create a new data device for a given seat. - - - - - - - - Destroy the primary selection device manager. - - - - - - - - Replaces the current selection. The previous owner of the primary selection - will receive a wp_primary_selection_source.cancelled event. - - To unset the selection, set the source to NULL. - - - - - - - - Introduces a new wp_primary_selection_offer object that may be used - to receive the current primary selection. Immediately following this - event, the new wp_primary_selection_offer object will send - wp_primary_selection_offer.offer events to describe the offered mime - types. - - - - - - - The wp_primary_selection_device.selection event is sent to notify the - client of a new primary selection. This event is sent after the - wp_primary_selection.data_offer event introducing this object, and after - the offer has announced its mimetypes through - wp_primary_selection_offer.offer. - - The data_offer is valid until a new offer or NULL is received - or until the client loses keyboard focus. The client must destroy the - previous selection data_offer, if any, upon receiving this event. - - - - - - - Destroy the primary selection device. - - - - - - - A wp_primary_selection_offer represents an offer to transfer the contents - of the primary selection clipboard to the client. Similar to - wl_data_offer, the offer also describes the mime types that the source - will transferthat the - data can be converted to and provides the mechanisms for transferring the - data directly to the client. - - - - - To transfer the contents of the primary selection clipboard, the client - issues this request and indicates the mime type that it wants to - receive. The transfer happens through the passed file descriptor - (typically created with the pipe system call). The source client writes - the data in the mime type representation requested and then closes the - file descriptor. - - The receiving client reads from the read end of the pipe until EOF and - closes its end, at which point the transfer is complete. - - - - - - - - Destroy the primary selection offer. - - - - - - Sent immediately after creating announcing the wp_primary_selection_offer - through wp_primary_selection_device.data_offer. One event is sent per - offered mime type. - - - - - - - - The source side of a wp_primary_selection_offer, it provides a way to - describe the offered data and respond to requests to transfer the - requested contents of the primary selection clipboard. - - - - - This request adds a mime type to the set of mime types advertised to - targets. Can be called several times to offer multiple types. - - - - - - - Destroy the primary selection source. - - - - - - Request for the current primary selection contents from the client. - Send the specified mime type over the passed file descriptor, then - close it. - - - - - - - - This primary selection source is no longer valid. The client should - clean up and destroy this primary selection source. - - - - diff --git a/glfw/wl_window.c b/glfw/wl_window.c index d0698968a..e4990577e 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -1568,7 +1568,7 @@ static void _glfwSendClipboardText(void *data, struct wl_data_source *data_sourc send_text(_glfw.wl.clipboardString, fd); } -static void _glfwSendPrimarySelectionText(void *data, struct gtk_primary_selection_source *primary_selection_source, +static void _glfwSendPrimarySelectionText(void *data, struct zwp_primary_selection_source_v1 *primary_selection_source, const char *mime_type, int fd) { send_text(_glfw.wl.primarySelectionString, fd); } @@ -1618,10 +1618,10 @@ static char* read_offer_string(int data_pipe) { } -static char* read_primary_selection_offer(struct gtk_primary_selection_offer *primary_selection_offer, const char *mime) { +static char* read_primary_selection_offer(struct zwp_primary_selection_offer_v1 *primary_selection_offer, const char *mime) { int pipefd[2]; if (pipe2(pipefd, O_CLOEXEC) != 0) return NULL; - gtk_primary_selection_offer_receive(primary_selection_offer, mime, pipefd[1]); + zwp_primary_selection_offer_v1_receive(primary_selection_offer, mime, pipefd[1]); close(pipefd[1]); return read_offer_string(pipefd[0]); } @@ -1640,10 +1640,10 @@ static void data_source_canceled(void *data, struct wl_data_source *wl_data_sour wl_data_source_destroy(wl_data_source); } -static void primary_selection_source_canceled(void *data, struct gtk_primary_selection_source *primary_selection_source) { +static void primary_selection_source_canceled(void *data, struct zwp_primary_selection_source_v1 *primary_selection_source) { if (_glfw.wl.dataSourceForPrimarySelection == primary_selection_source) _glfw.wl.dataSourceForPrimarySelection = NULL; - gtk_primary_selection_source_destroy(primary_selection_source); + zwp_primary_selection_source_v1_destroy(primary_selection_source); } static void data_source_target(void *data, struct wl_data_source *wl_data_source, const char* mime) { @@ -1655,7 +1655,7 @@ const static struct wl_data_source_listener data_source_listener = { .target = data_source_target, }; -const static struct gtk_primary_selection_source_listener primary_selection_source_listener = { +const static struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = { .send = _glfwSendPrimarySelectionText, .cancelled = primary_selection_source_canceled, }; @@ -1672,7 +1672,7 @@ static void prune_unclaimed_data_offers() { static void prune_unclaimed_primary_selection_offers() { for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) { if (_glfw.wl.primarySelectionOffers[i].id && !_glfw.wl.dataOffers[i].offer_type) { - gtk_primary_selection_offer_destroy(_glfw.wl.primarySelectionOffers[i].id); + zwp_primary_selection_offer_v1_destroy(_glfw.wl.primarySelectionOffers[i].id); memset(_glfw.wl.primarySelectionOffers + i, 0, sizeof(_glfw.wl.primarySelectionOffers[0])); } } @@ -1690,8 +1690,8 @@ static void mark_selection_offer(void *data, struct wl_data_device *data_device, prune_unclaimed_data_offers(); } -static void mark_primary_selection_offer(void *data, struct gtk_primary_selection_device* primary_selection_device, - struct gtk_primary_selection_offer *primary_selection_offer) { +static void mark_primary_selection_offer(void *data, struct zwp_primary_selection_device_v1* primary_selection_device, + struct zwp_primary_selection_offer_v1 *primary_selection_offer) { for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) { if (_glfw.wl.primarySelectionOffers[i].id == primary_selection_offer) { _glfw.wl.primarySelectionOffers[i].offer_type = PRIMARY_SELECTION; @@ -1722,7 +1722,7 @@ static void handle_offer_mimetype(void *data, struct wl_data_offer* id, const ch } } -static void handle_primary_selection_offer_mimetype(void *data, struct gtk_primary_selection_offer* id, const char *mime) { +static void handle_primary_selection_offer_mimetype(void *data, struct zwp_primary_selection_offer_v1* id, const char *mime) { for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) { if (_glfw.wl.primarySelectionOffers[i].id == id) { set_offer_mimetype((struct _GLFWWaylandDataOffer*)&_glfw.wl.primarySelectionOffers[i], mime); @@ -1756,7 +1756,7 @@ static const struct wl_data_offer_listener data_offer_listener = { .action = data_offer_action, }; -static const struct gtk_primary_selection_offer_listener primary_selection_offer_listener = { +static const struct zwp_primary_selection_offer_v1_listener primary_selection_offer_listener = { .offer = handle_primary_selection_offer_mimetype, }; @@ -1781,7 +1781,7 @@ end: wl_data_offer_add_listener(id, &data_offer_listener, NULL); } -static void handle_primary_selection_offer(void *data, struct gtk_primary_selection_device *gtk_primary_selection_device, struct gtk_primary_selection_offer *id) { +static void handle_primary_selection_offer(void *data, struct zwp_primary_selection_device_v1 *zwp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *id) { size_t smallest_idx = SIZE_MAX, pos = 0; for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) { if (_glfw.wl.primarySelectionOffers[i].idx && _glfw.wl.primarySelectionOffers[i].idx < smallest_idx) { @@ -1794,12 +1794,12 @@ static void handle_primary_selection_offer(void *data, struct gtk_primary_select goto end; } } - if (_glfw.wl.primarySelectionOffers[pos].id) gtk_primary_selection_offer_destroy(_glfw.wl.primarySelectionOffers[pos].id); + if (_glfw.wl.primarySelectionOffers[pos].id) zwp_primary_selection_offer_v1_destroy(_glfw.wl.primarySelectionOffers[pos].id); memset(_glfw.wl.primarySelectionOffers + pos, 0, sizeof(_glfw.wl.primarySelectionOffers[0])); _glfw.wl.primarySelectionOffers[pos].id = id; _glfw.wl.primarySelectionOffers[pos].idx = ++_glfw.wl.primarySelectionOffersCounter; end: - gtk_primary_selection_offer_add_listener(id, &primary_selection_offer_listener, NULL); + zwp_primary_selection_offer_v1_add_listener(id, &primary_selection_offer_listener, NULL); } static void drag_enter(void *data, struct wl_data_device *wl_data_device, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id) { @@ -1869,7 +1869,7 @@ const static struct wl_data_device_listener data_device_listener = { .leave = drag_leave, }; -const static struct gtk_primary_selection_device_listener primary_selection_device_listener = { +const static struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = { .data_offer = handle_primary_selection_offer, .selection = mark_primary_selection_offer, }; @@ -1886,7 +1886,7 @@ clipboard_copy_callback_done(void *data, struct wl_callback *callback, uint32_t static void primary_selection_copy_callback_done(void *data, struct wl_callback *callback, uint32_t serial) { if (_glfw.wl.primarySelectionDevice && data == (void*)_glfw.wl.dataSourceForPrimarySelection) { - gtk_primary_selection_device_set_selection(_glfw.wl.primarySelectionDevice, data, serial); + zwp_primary_selection_device_v1_set_selection(_glfw.wl.primarySelectionDevice, data, serial); } wl_callback_destroy(callback); } @@ -1897,8 +1897,8 @@ void _glfwSetupWaylandDataDevice() { } void _glfwSetupWaylandPrimarySelectionDevice() { - _glfw.wl.primarySelectionDevice = gtk_primary_selection_device_manager_get_device(_glfw.wl.primarySelectionDeviceManager, _glfw.wl.seat); - if (_glfw.wl.primarySelectionDevice) gtk_primary_selection_device_add_listener(_glfw.wl.primarySelectionDevice, &primary_selection_device_listener, NULL); + _glfw.wl.primarySelectionDevice = zwp_primary_selection_device_manager_v1_get_device(_glfw.wl.primarySelectionDeviceManager, _glfw.wl.seat); + if (_glfw.wl.primarySelectionDevice) zwp_primary_selection_device_v1_add_listener(_glfw.wl.primarySelectionDevice, &primary_selection_device_listener, NULL); } static inline GLFWbool _glfwEnsureDataDevice() { @@ -1982,21 +1982,21 @@ void _glfwPlatformSetPrimarySelectionString(const char* string) _glfw.wl.primarySelectionString = _glfw_strdup(string); if (_glfw.wl.dataSourceForPrimarySelection) - gtk_primary_selection_source_destroy(_glfw.wl.dataSourceForPrimarySelection); - _glfw.wl.dataSourceForPrimarySelection = gtk_primary_selection_device_manager_create_source(_glfw.wl.primarySelectionDeviceManager); + zwp_primary_selection_source_v1_destroy(_glfw.wl.dataSourceForPrimarySelection); + _glfw.wl.dataSourceForPrimarySelection = zwp_primary_selection_device_manager_v1_create_source(_glfw.wl.primarySelectionDeviceManager); if (!_glfw.wl.dataSourceForPrimarySelection) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Cannot copy failed to create primary selection source"); return; } - gtk_primary_selection_source_add_listener(_glfw.wl.dataSourceForPrimarySelection, &primary_selection_source_listener, NULL); - gtk_primary_selection_source_offer(_glfw.wl.dataSourceForPrimarySelection, clipboard_mime()); - gtk_primary_selection_source_offer(_glfw.wl.dataSourceForPrimarySelection, "text/plain"); - gtk_primary_selection_source_offer(_glfw.wl.dataSourceForPrimarySelection, "text/plain;charset=utf-8"); - gtk_primary_selection_source_offer(_glfw.wl.dataSourceForPrimarySelection, "TEXT"); - gtk_primary_selection_source_offer(_glfw.wl.dataSourceForPrimarySelection, "STRING"); - gtk_primary_selection_source_offer(_glfw.wl.dataSourceForPrimarySelection, "UTF8_STRING"); + zwp_primary_selection_source_v1_add_listener(_glfw.wl.dataSourceForPrimarySelection, &primary_selection_source_listener, NULL); + zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, clipboard_mime()); + zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "text/plain"); + zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "text/plain;charset=utf-8"); + zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "TEXT"); + zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "STRING"); + zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "UTF8_STRING"); struct wl_callback *callback = wl_display_sync(_glfw.wl.display); const static struct wl_callback_listener primary_selection_copy_callback_listener = {.done = primary_selection_copy_callback_done}; wl_callback_add_listener(callback, &primary_selection_copy_callback_listener, _glfw.wl.dataSourceForPrimarySelection);