소스 검색

Wayland: Make data offer reading a generic utility

This will be needed for drag and drop reception as well.
Camilla Löwy 3 년 전
부모
커밋
f010335b8c
2개의 변경된 파일73개의 추가작업 그리고 75개의 파일을 삭제
  1. 0 1
      src/wl_platform.h
  2. 73 74
      src/wl_window.c

+ 0 - 1
src/wl_platform.h

@@ -316,7 +316,6 @@ typedef struct _GLFWlibraryWayland
     int                         keyboardLastKey;
     int                         keyboardLastKey;
     int                         keyboardLastScancode;
     int                         keyboardLastScancode;
     char*                       clipboardString;
     char*                       clipboardString;
-    size_t                      clipboardSize;
     int                         timerfd;
     int                         timerfd;
     short int                   keycodes[256];
     short int                   keycodes[256];
     short int                   scancodes[GLFW_KEY_LAST + 1];
     short int                   scancodes[GLFW_KEY_LAST + 1];

+ 73 - 74
src/wl_window.c

@@ -812,6 +812,70 @@ static void handleEvents(double* timeout)
     }
     }
 }
 }
 
 
+// Reads the specified data offer as the specified MIME type
+//
+static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mimeType)
+{
+    int fds[2];
+
+    if (pipe2(fds, O_CLOEXEC) == -1)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to create pipe for data offer: %s",
+                        strerror(errno));
+        return NULL;
+    }
+
+    wl_data_offer_receive(offer, mimeType, fds[1]);
+    flushDisplay();
+    close(fds[1]);
+
+    char* string = NULL;
+    size_t size = 0;
+    size_t length = 0;
+
+    for (;;)
+    {
+        const size_t readSize = 4096;
+        const size_t requiredSize = length + readSize + 1;
+        if (requiredSize > size)
+        {
+            char* longer = _glfw_realloc(string, requiredSize);
+            if (!longer)
+            {
+                _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
+                close(fds[0]);
+                return NULL;
+            }
+
+            string = longer;
+            size = requiredSize;
+        }
+
+        const ssize_t result = read(fds[0], string + length, readSize);
+        if (result == 0)
+            break;
+        else if (result == -1)
+        {
+            if (errno == EINTR)
+                continue;
+
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Wayland: Failed to read from data offer pipe: %s",
+                            strerror(errno));
+            close(fds[0]);
+            return NULL;
+        }
+
+        length += result;
+    }
+
+    close(fds[0]);
+
+    string[length] = '\0';
+    return string;
+}
+
 static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
 static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
                                                     int* which)
                                                     int* which)
 {
 {
@@ -2418,23 +2482,15 @@ void _glfwSetClipboardStringWayland(const char* string)
         _glfw.wl.selectionSource = NULL;
         _glfw.wl.selectionSource = NULL;
     }
     }
 
 
-    const size_t requiredSize = strlen(string) + 1;
-    if (requiredSize > _glfw.wl.clipboardSize)
+    char* copy = _glfw_strdup(string);
+    if (!copy)
     {
     {
-        _glfw_free(_glfw.wl.clipboardString);
-        _glfw.wl.clipboardString = _glfw_calloc(requiredSize, 1);
-        if (!_glfw.wl.clipboardString)
-        {
-            _glfwInputError(GLFW_OUT_OF_MEMORY,
-                            "Wayland: Failed to allocate clipboard string");
-            return;
-        }
-
-        _glfw.wl.clipboardSize = requiredSize;
+        _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
+        return;
     }
     }
 
 
-    // The argument may be a substring of the clipboard string
-    memmove(_glfw.wl.clipboardString, string, requiredSize);
+    _glfw_free(_glfw.wl.clipboardString);
+    _glfw.wl.clipboardString = copy;
 
 
     _glfw.wl.selectionSource =
     _glfw.wl.selectionSource =
         wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
         wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
@@ -2465,66 +2521,9 @@ const char* _glfwGetClipboardStringWayland(void)
     if (_glfw.wl.selectionSource)
     if (_glfw.wl.selectionSource)
         return _glfw.wl.clipboardString;
         return _glfw.wl.clipboardString;
 
 
-    int fds[2];
-
-    if (pipe2(fds, O_CLOEXEC) == -1)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to create clipboard pipe: %s",
-                        strerror(errno));
-        return NULL;
-    }
-
-    wl_data_offer_receive(_glfw.wl.selectionOffer, "text/plain;charset=utf-8", fds[1]);
-
-    flushDisplay();
-    close(fds[1]);
-
-    size_t length = 0;
-
-    for (;;)
-    {
-        // Grow the clipboard if we need to paste something bigger, there is no
-        // shrink operation yet.
-        const size_t readSize = 4096;
-        const size_t requiredSize = length + readSize + 1;
-        if (requiredSize > _glfw.wl.clipboardSize)
-        {
-            char* string = _glfw_realloc(_glfw.wl.clipboardString, requiredSize);
-            if (!string)
-            {
-                _glfwInputError(GLFW_OUT_OF_MEMORY,
-                                "Wayland: Failed to grow clipboard string");
-                close(fds[0]);
-                return NULL;
-            }
-
-            _glfw.wl.clipboardString = string;
-            _glfw.wl.clipboardSize = requiredSize;
-        }
-
-        // Then read from the fd to the clipboard, handling all known errors.
-        const ssize_t result = read(fds[0], _glfw.wl.clipboardString + length, readSize);
-        if (result == 0)
-            break;
-        else if (result == -1)
-        {
-            if (errno == EINTR)
-                continue;
-
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Failed to read from clipboard pipe: %s",
-                            strerror(errno));
-            close(fds[0]);
-            return NULL;
-        }
-
-        length += result;
-    }
-
-    close(fds[0]);
-
-    _glfw.wl.clipboardString[length] = '\0';
+    _glfw_free(_glfw.wl.clipboardString);
+    _glfw.wl.clipboardString =
+        readDataOfferAsString(_glfw.wl.selectionOffer, "text/plain;charset=utf-8");
     return _glfw.wl.clipboardString;
     return _glfw.wl.clipboardString;
 }
 }