Added support for clipboard manager.

This commit is contained in:
Camilla Berglund 2013-04-29 13:16:56 +02:00
parent 1b34887e10
commit 179194a687
4 changed files with 120 additions and 2 deletions

View File

@ -35,6 +35,21 @@
#include <stdlib.h>
// Returns whether the event is a selection event
//
static Bool isSelectionMessage(Display* display, XEvent* event, XPointer pointer)
{
if (event->type == SelectionRequest ||
event->type == SelectionNotify ||
event->type == SelectionClear)
{
return True;
}
return False;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
@ -86,7 +101,7 @@ Atom _glfwWriteSelection(XSelectionRequestEvent* request)
count = _glfwGetWindowProperty(request->requestor,
request->property,
XA_ATOM,
_glfw.x11.ATOM_PAIR,
(unsigned char**) &targets);
for (i = 0; i < count; i += 2)
@ -117,7 +132,7 @@ Atom _glfwWriteSelection(XSelectionRequestEvent* request)
XChangeProperty(_glfw.x11.display,
request->requestor,
request->property,
request->target,
_glfw.x11.ATOM_PAIR,
32,
PropModeReplace,
(unsigned char*) targets,
@ -128,6 +143,23 @@ Atom _glfwWriteSelection(XSelectionRequestEvent* request)
return request->property;
}
if (request->target == _glfw.x11.SAVE_TARGETS)
{
// Conversion by clients to SAVE_TARGETS should be treated like
// a side-effect target without side effects
XChangeProperty(_glfw.x11.display,
request->requestor,
request->property,
XInternAtom(_glfw.x11.display, "NULL", False),
32,
PropModeReplace,
NULL,
0);
return request->property;
}
for (i = 0; i < formatCount; i++)
{
if (request->target == formats[i])
@ -150,6 +182,79 @@ Atom _glfwWriteSelection(XSelectionRequestEvent* request)
return None;
}
// Save clipboard data to clipboard manager
//
void _glfwPushSelectionToManager(_GLFWwindow* window)
{
XEvent request;
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) !=
window->x11.handle)
{
// This window does not own the clipboard selection
return;
}
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD_MANAGER) ==
None)
{
// There is no running clipboard manager
return;
}
XConvertSelection(_glfw.x11.display,
_glfw.x11.CLIPBOARD_MANAGER,
_glfw.x11.SAVE_TARGETS,
None,
window->x11.handle,
CurrentTime);
for (;;)
{
if (!XCheckIfEvent(_glfw.x11.display, &request, isSelectionMessage, NULL))
continue;
switch (request.type)
{
case SelectionRequest:
{
XEvent response;
memset(&response, 0, sizeof(response));
response.xselection.property = _glfwWriteSelection(&request.xselectionrequest);
response.xselection.type = SelectionNotify;
response.xselection.display = request.xselectionrequest.display;
response.xselection.requestor = request.xselectionrequest.requestor;
response.xselection.selection = request.xselectionrequest.selection;
response.xselection.target = request.xselectionrequest.target;
response.xselection.time = request.xselectionrequest.time;
XSendEvent(_glfw.x11.display,
request.xselectionrequest.requestor,
False, 0, &response);
break;
}
case SelectionClear:
{
free(_glfw.x11.selection.string);
_glfw.x11.selection.string = NULL;
break;
}
case SelectionNotify:
{
if (request.xselection.target == _glfw.x11.SAVE_TARGETS)
return;
break;
}
}
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////

View File

@ -537,6 +537,7 @@ static GLboolean initDisplay(void)
XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
_glfw.x11.COMPOUND_STRING =
XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False);
_glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
// Find or create selection property atom
_glfw.x11.GLFW_SELECTION =
@ -547,6 +548,12 @@ static GLboolean initDisplay(void)
_glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False);
_glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
// Find or create clipboard manager atoms
_glfw.x11.CLIPBOARD_MANAGER =
XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False);
_glfw.x11.SAVE_TARGETS =
XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False);
return GL_TRUE;
}

View File

@ -119,8 +119,11 @@ typedef struct _GLFWlibraryX11
Atom TARGETS;
Atom MULTIPLE;
Atom CLIPBOARD;
Atom CLIPBOARD_MANAGER;
Atom SAVE_TARGETS;
Atom UTF8_STRING;
Atom COMPOUND_STRING;
Atom ATOM_PAIR;
Atom GLFW_SELECTION;
// True if window manager supports EWMH
@ -235,6 +238,7 @@ long _glfwKeySym2Unicode(KeySym keysym);
// Clipboard handling
Atom _glfwWriteSelection(XSelectionRequestEvent* request);
void _glfwPushSelectionToManager(_GLFWwindow* window);
// Window support
_GLFWwindow* _glfwFindWindowByHandle(Window handle);

View File

@ -904,6 +904,8 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
if (window->x11.handle)
{
_glfwPushSelectionToManager(window);
XDeleteContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context);
XUnmapWindow(_glfw.x11.display, window->x11.handle);
XDestroyWindow(_glfw.x11.display, window->x11.handle);