X11: Make clipboard IPC use helper window

This commit is contained in:
Camilla Berglund 2015-10-24 22:54:30 +02:00 committed by Camilla Berglund
parent 706868dad8
commit ccfd6dde45
3 changed files with 64 additions and 58 deletions

View File

@ -797,6 +797,12 @@ void _glfwPlatformTerminate(void)
if (_glfw.x11.helperWindowHandle) if (_glfw.x11.helperWindowHandle)
{ {
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
_glfw.x11.helperWindowHandle)
{
_glfwPushSelectionToManagerX11();
}
XDestroyWindow(_glfw.x11.display, _glfw.x11.helperWindowHandle); XDestroyWindow(_glfw.x11.display, _glfw.x11.helperWindowHandle);
_glfw.x11.helperWindowHandle = None; _glfw.x11.helperWindowHandle = None;
} }

View File

@ -295,4 +295,6 @@ void _glfwGrabErrorHandlerX11(void);
void _glfwReleaseErrorHandlerX11(void); void _glfwReleaseErrorHandlerX11(void);
void _glfwInputErrorX11(int error, const char* message); void _glfwInputErrorX11(int error, const char* message);
void _glfwPushSelectionToManagerX11(void);
#endif // _glfw3_x11_platform_h_ #endif // _glfw3_x11_platform_h_

View File

@ -815,51 +815,6 @@ static void handleSelectionRequest(XEvent* event)
XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply); XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply);
} }
static void pushSelectionToManager(_GLFWwindow* window)
{
XConvertSelection(_glfw.x11.display,
_glfw.x11.CLIPBOARD_MANAGER,
_glfw.x11.SAVE_TARGETS,
None,
window->x11.handle,
CurrentTime);
for (;;)
{
XEvent event;
while (XCheckIfEvent(_glfw.x11.display, &event, isSelectionEvent, NULL))
{
switch (event.type)
{
case SelectionRequest:
handleSelectionRequest(&event);
break;
case SelectionClear:
handleSelectionClear(&event);
break;
case SelectionNotify:
{
if (event.xselection.target == _glfw.x11.SAVE_TARGETS)
{
// This means one of two things; either the selection was
// not owned, which means there is no clipboard manager, or
// the transfer to the clipboard manager has completed
// In either case, it means we are done here
return;
}
break;
}
}
}
waitForEvent(NULL);
}
}
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static GLFWbool acquireMonitor(_GLFWwindow* window) static GLFWbool acquireMonitor(_GLFWwindow* window)
@ -1533,6 +1488,53 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
return itemCount; return itemCount;
} }
// Push contents of our selection to clipboard manager
//
void _glfwPushSelectionToManagerX11(void)
{
XConvertSelection(_glfw.x11.display,
_glfw.x11.CLIPBOARD_MANAGER,
_glfw.x11.SAVE_TARGETS,
None,
_glfw.x11.helperWindowHandle,
CurrentTime);
for (;;)
{
XEvent event;
while (XCheckIfEvent(_glfw.x11.display, &event, isSelectionEvent, NULL))
{
switch (event.type)
{
case SelectionRequest:
handleSelectionRequest(&event);
break;
case SelectionClear:
handleSelectionClear(&event);
break;
case SelectionNotify:
{
if (event.xselection.target == _glfw.x11.SAVE_TARGETS)
{
// This means one of two things; either the selection was
// not owned, which means there is no clipboard manager, or
// the transfer to the clipboard manager has completed
// In either case, it means we are done here
return;
}
break;
}
}
}
waitForEvent(NULL);
}
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
@ -1619,12 +1621,6 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->x11.handle) if (window->x11.handle)
{ {
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
window->x11.handle)
{
pushSelectionToManager(window);
}
XDeleteContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context); XDeleteContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context);
XUnmapWindow(_glfw.x11.display, window->x11.handle); XUnmapWindow(_glfw.x11.display, window->x11.handle);
XDestroyWindow(_glfw.x11.display, window->x11.handle); XDestroyWindow(_glfw.x11.display, window->x11.handle);
@ -2094,11 +2090,11 @@ void _glfwPlatformPostEmptyEvent(void)
memset(&event, 0, sizeof(event)); memset(&event, 0, sizeof(event));
event.type = ClientMessage; event.type = ClientMessage;
event.xclient.window = _glfw.x11.helper; event.xclient.window = _glfw.x11.helperWindowHandle;
event.xclient.format = 32; // Data is 32-bit longs event.xclient.format = 32; // Data is 32-bit longs
event.xclient.message_type = _glfw.x11.NULL_; event.xclient.message_type = _glfw.x11.NULL_;
XSendEvent(_glfw.x11.display, _glfw.x11.helper, False, 0, &event); XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, False, 0, &event);
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }
@ -2234,10 +2230,11 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
XSetSelectionOwner(_glfw.x11.display, XSetSelectionOwner(_glfw.x11.display,
_glfw.x11.CLIPBOARD, _glfw.x11.CLIPBOARD,
window->x11.handle, CurrentTime); _glfw.x11.helperWindowHandle,
CurrentTime);
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) != if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) !=
window->x11.handle) _glfw.x11.helperWindowHandle)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Failed to become owner of clipboard selection"); "X11: Failed to become owner of clipboard selection");
@ -2252,8 +2249,8 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
XA_STRING }; XA_STRING };
const size_t formatCount = sizeof(formats) / sizeof(formats[0]); const size_t formatCount = sizeof(formats) / sizeof(formats[0]);
if (findWindowByHandle(XGetSelectionOwner(_glfw.x11.display, if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
_glfw.x11.CLIPBOARD))) _glfw.x11.helperWindowHandle)
{ {
// Instead of doing a large number of X round-trips just to put this // 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 // string into a window property and then read it back, just return it
@ -2272,7 +2269,8 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
_glfw.x11.CLIPBOARD, _glfw.x11.CLIPBOARD,
formats[i], formats[i],
_glfw.x11.GLFW_SELECTION, _glfw.x11.GLFW_SELECTION,
window->x11.handle, CurrentTime); _glfw.x11.helperWindowHandle,
CurrentTime);
while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event)) while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event))
waitForEvent(NULL); waitForEvent(NULL);