|
@@ -675,6 +675,8 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
|
|
_glfw.x11.COMPOUND_STRING,
|
|
|
XA_STRING };
|
|
|
const int formatCount = sizeof(formats) / sizeof(formats[0]);
|
|
|
+ char *selectionString = request->selection == _glfw.x11.PRIMARY ?
|
|
|
+ _glfw.x11.primarySelectionString : _glfw.x11.clipboardString;
|
|
|
|
|
|
if (request->property == None)
|
|
|
{
|
|
@@ -735,8 +737,8 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
|
|
targets[i],
|
|
|
8,
|
|
|
PropModeReplace,
|
|
|
- (unsigned char*) _glfw.x11.clipboardString,
|
|
|
- strlen(_glfw.x11.clipboardString));
|
|
|
+ (unsigned char *) selectionString,
|
|
|
+ strlen(selectionString));
|
|
|
}
|
|
|
else
|
|
|
targets[i + 1] = None;
|
|
@@ -787,8 +789,8 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
|
|
request->target,
|
|
|
8,
|
|
|
PropModeReplace,
|
|
|
- (unsigned char*) _glfw.x11.clipboardString,
|
|
|
- strlen(_glfw.x11.clipboardString));
|
|
|
+ (unsigned char *) selectionString,
|
|
|
+ strlen(selectionString));
|
|
|
|
|
|
return request->property;
|
|
|
}
|
|
@@ -801,8 +803,17 @@ static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
|
|
|
|
|
|
static void handleSelectionClear(XEvent* event)
|
|
|
{
|
|
|
- free(_glfw.x11.clipboardString);
|
|
|
- _glfw.x11.clipboardString = NULL;
|
|
|
+ const XSelectionClearEvent* request = &event->xselectionclear;
|
|
|
+ if (request->selection == _glfw.x11.PRIMARY)
|
|
|
+ {
|
|
|
+ free(_glfw.x11.primarySelectionString);
|
|
|
+ _glfw.x11.primarySelectionString = NULL;
|
|
|
+ }
|
|
|
+ else if (request->selection == _glfw.x11.CLIPBOARD)
|
|
|
+ {
|
|
|
+ free(_glfw.x11.clipboardString);
|
|
|
+ _glfw.x11.clipboardString = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void handleSelectionRequest(XEvent* event)
|
|
@@ -823,6 +834,76 @@ static void handleSelectionRequest(XEvent* event)
|
|
|
XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply);
|
|
|
}
|
|
|
|
|
|
+static const char *getSelection(Atom selection, char **ptr)
|
|
|
+{
|
|
|
+ size_t i;
|
|
|
+ const Atom formats[] = { _glfw.x11.UTF8_STRING,
|
|
|
+ _glfw.x11.COMPOUND_STRING,
|
|
|
+ XA_STRING };
|
|
|
+ const size_t formatCount = sizeof(formats) / sizeof(formats[0]);
|
|
|
+
|
|
|
+ if (XGetSelectionOwner(_glfw.x11.display, selection) ==
|
|
|
+ _glfw.x11.helperWindowHandle)
|
|
|
+ {
|
|
|
+ // Instead of doing a large number of X round-trips just to put this
|
|
|
+ // string into a window property and then read it back, just return it
|
|
|
+ return *ptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ free(*ptr);
|
|
|
+ *ptr = NULL;
|
|
|
+
|
|
|
+ for (i = 0; i < formatCount; i++)
|
|
|
+ {
|
|
|
+ char* data;
|
|
|
+ XEvent event;
|
|
|
+
|
|
|
+ XConvertSelection(_glfw.x11.display,
|
|
|
+ selection,
|
|
|
+ formats[i],
|
|
|
+ _glfw.x11.GLFW_SELECTION,
|
|
|
+ _glfw.x11.helperWindowHandle,
|
|
|
+ CurrentTime);
|
|
|
+
|
|
|
+ while (!XCheckTypedWindowEvent(_glfw.x11.display,
|
|
|
+ _glfw.x11.helperWindowHandle,
|
|
|
+ SelectionNotify,
|
|
|
+ &event))
|
|
|
+ {
|
|
|
+ waitForEvent(NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (event.xselection.property == None)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (_glfwGetWindowPropertyX11(event.xselection.requestor,
|
|
|
+ event.xselection.property,
|
|
|
+ event.xselection.target,
|
|
|
+ (unsigned char**) &data))
|
|
|
+ {
|
|
|
+ *ptr = strdup(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data)
|
|
|
+ XFree(data);
|
|
|
+
|
|
|
+ XDeleteProperty(_glfw.x11.display,
|
|
|
+ event.xselection.requestor,
|
|
|
+ event.xselection.property);
|
|
|
+
|
|
|
+ if (*ptr)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (*ptr == NULL)
|
|
|
+ {
|
|
|
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
|
|
+ "X11: Failed to convert clipboard to string");
|
|
|
+ }
|
|
|
+
|
|
|
+ return *ptr;
|
|
|
+}
|
|
|
+
|
|
|
// Make the specified window and its video mode active on its monitor
|
|
|
//
|
|
|
static GLFWbool acquireMonitor(_GLFWwindow* window)
|
|
@@ -2572,72 +2653,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
|
|
|
|
|
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
|
|
{
|
|
|
- size_t i;
|
|
|
- const Atom formats[] = { _glfw.x11.UTF8_STRING,
|
|
|
- _glfw.x11.COMPOUND_STRING,
|
|
|
- XA_STRING };
|
|
|
- const size_t formatCount = sizeof(formats) / sizeof(formats[0]);
|
|
|
-
|
|
|
- if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
|
|
|
- _glfw.x11.helperWindowHandle)
|
|
|
- {
|
|
|
- // Instead of doing a large number of X round-trips just to put this
|
|
|
- // string into a window property and then read it back, just return it
|
|
|
- return _glfw.x11.clipboardString;
|
|
|
- }
|
|
|
-
|
|
|
- free(_glfw.x11.clipboardString);
|
|
|
- _glfw.x11.clipboardString = NULL;
|
|
|
-
|
|
|
- for (i = 0; i < formatCount; i++)
|
|
|
- {
|
|
|
- char* data;
|
|
|
- XEvent event;
|
|
|
-
|
|
|
- XConvertSelection(_glfw.x11.display,
|
|
|
- _glfw.x11.CLIPBOARD,
|
|
|
- formats[i],
|
|
|
- _glfw.x11.GLFW_SELECTION,
|
|
|
- _glfw.x11.helperWindowHandle,
|
|
|
- CurrentTime);
|
|
|
-
|
|
|
- while (!XCheckTypedWindowEvent(_glfw.x11.display,
|
|
|
- _glfw.x11.helperWindowHandle,
|
|
|
- SelectionNotify,
|
|
|
- &event))
|
|
|
- {
|
|
|
- waitForEvent(NULL);
|
|
|
- }
|
|
|
-
|
|
|
- if (event.xselection.property == None)
|
|
|
- continue;
|
|
|
-
|
|
|
- if (_glfwGetWindowPropertyX11(event.xselection.requestor,
|
|
|
- event.xselection.property,
|
|
|
- event.xselection.target,
|
|
|
- (unsigned char**) &data))
|
|
|
- {
|
|
|
- _glfw.x11.clipboardString = strdup(data);
|
|
|
- }
|
|
|
-
|
|
|
- if (data)
|
|
|
- XFree(data);
|
|
|
-
|
|
|
- XDeleteProperty(_glfw.x11.display,
|
|
|
- event.xselection.requestor,
|
|
|
- event.xselection.property);
|
|
|
-
|
|
|
- if (_glfw.x11.clipboardString)
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (_glfw.x11.clipboardString == NULL)
|
|
|
- {
|
|
|
- _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
|
|
- "X11: Failed to convert clipboard to string");
|
|
|
- }
|
|
|
-
|
|
|
- return _glfw.x11.clipboardString;
|
|
|
+ return getSelection(_glfw.x11.CLIPBOARD, &_glfw.x11.clipboardString);
|
|
|
}
|
|
|
|
|
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
|
@@ -2807,3 +2823,28 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
|
|
|
return window->x11.handle;
|
|
|
}
|
|
|
|
|
|
+GLFWAPI void glfwSetX11SelectionString(const char* string)
|
|
|
+{
|
|
|
+ _GLFW_REQUIRE_INIT();
|
|
|
+
|
|
|
+ free(_glfw.x11.primarySelectionString);
|
|
|
+ _glfw.x11.primarySelectionString = strdup(string);
|
|
|
+
|
|
|
+ XSetSelectionOwner(_glfw.x11.display,
|
|
|
+ _glfw.x11.PRIMARY,
|
|
|
+ _glfw.x11.helperWindowHandle,
|
|
|
+ CurrentTime);
|
|
|
+
|
|
|
+ if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.PRIMARY) !=
|
|
|
+ _glfw.x11.helperWindowHandle)
|
|
|
+ {
|
|
|
+ _glfwInputError(GLFW_PLATFORM_ERROR,
|
|
|
+ "X11: Failed to become owner of primary selection");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+GLFWAPI const char* glfwGetX11SelectionString(void)
|
|
|
+{
|
|
|
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
|
+ return getSelection(_glfw.x11.PRIMARY, &_glfw.x11.primarySelectionString);
|
|
|
+}
|