X11 copying code and support PRIMARY & CLIPBOARD clipboards.

This commit is contained in:
Ralph Eastwood
2011-09-22 12:03:45 +01:00
parent 57522db6e2
commit 9f41e5b67a
6 changed files with 179 additions and 40 deletions
+119 -30
View File
@@ -27,6 +27,8 @@
//
//========================================================================
// TODO: Incremental support? Overkill perhaps.
#include "internal.h"
#include <stdio.h>
@@ -45,28 +47,101 @@
static Atom *getInternalFormat(int fmt)
{
// Get the necessary atoms
switch (fmt)
{
case GLFW_CLIPBOARD_FORMAT_STRING:
return _glfwLibrary.X11.selection.stringatoms;
return _glfwLibrary.X11.selection.atoms.string;
default:
return 0;
}
}
//========================================================================
// X11 selection request event
//========================================================================
Atom _glfwSelectionRequest(XSelectionRequestEvent *request)
{
Atom *atoms = _glfwLibrary.X11.selection.atoms.string;
if (request->target == XA_STRING)
{
// TODO: ISO Latin-1 specific characters don't get converted
// (yet). For cleanliness, would we need something like iconv?
XChangeProperty(_glfwLibrary.X11.display,
request->requestor,
request->target,
request->target,
8,
PropModeReplace,
(unsigned char *)_glfwLibrary.X11.selection.clipboard.string,
8);
}
else if (request->target == atoms[_GLFW_STRING_ATOM_COMPOUND] ||
request->target == atoms[_GLFW_STRING_ATOM_UTF8])
{
XChangeProperty(_glfwLibrary.X11.display,
request->requestor,
request->target,
request->target,
8,
PropModeReplace,
(unsigned char *)_glfwLibrary.X11.selection.clipboard.string,
_glfwLibrary.X11.selection.clipboard.stringlen);
}
else
{
// TODO: Should we set an error? Probably not.
return None;
}
return request->target;
}
//========================================================================
// Set the clipboard contents
//========================================================================
void _glfwPlatformSetClipboardData(void *data, size_t size, int format)
{
switch (format)
{
case GLFW_CLIPBOARD_FORMAT_STRING:
{
// Allocate memory to keep track of the clipboard
char *cb = malloc(size+1);
// Copy the clipboard data
memcpy(cb, data, size);
// Set the string length
_glfwLibrary.X11.selection.clipboard.stringlen = size;
// Check if existing clipboard memory needs to be freed
if (_glfwLibrary.X11.selection.clipboard.string)
free(_glfwLibrary.X11.selection.clipboard.string);
// Now set the clipboard (awaiting the event SelectionRequest)
_glfwLibrary.X11.selection.clipboard.string = cb;
break;
}
default:
_glfwSetError(GLFW_CLIPBOARD_FORMAT_UNAVAILABLE,
"X11/GLX: Unavailable clipboard format");
return;
}
// Set the selection owner to our active window
XSetSelectionOwner(_glfwLibrary.X11.display, XA_PRIMARY,
_glfwLibrary.activeWindow->X11.handle, CurrentTime);
XSetSelectionOwner(_glfwLibrary.X11.display,
_glfwLibrary.X11.selection.atoms.clipboard
[_GLFW_CLIPBOARD_ATOM_CLIPBOARD],
_glfwLibrary.activeWindow->X11.handle, CurrentTime);
XFlush(_glfwLibrary.X11.display);
}
//========================================================================
// Return the current clipboard contents
// TODO: Incremental support? Overkill perhaps.
//========================================================================
size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format)
@@ -74,46 +149,60 @@ size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format)
size_t len, rembytes, dummy;
unsigned char *d;
int fmt;
Window window;
Atom *xfmt, type;
Atom type;
// Try different formats that relate to the GLFW format with preference
// for better formats first
for (xfmt = getInternalFormat(format); *xfmt; xfmt++)
// Try different clipboards and formats that relate to the GLFW
// format with preference for more appropriate formats first
Atom *xcbrd = _glfwLibrary.X11.selection.atoms.clipboard;
Atom *xcbrdend = _glfwLibrary.X11.selection.atoms.clipboard +
_GLFW_CLIPBOARD_ATOM_COUNT;
Atom *xfmt = getInternalFormat(format);
Atom *xfmtend = xfmt + _GLFW_STRING_ATOM_COUNT;
// Get the currently active window
Window window = _glfwLibrary.activeWindow->X11.handle;
for (; xcbrd != xcbrdend; xcbrd++)
{
// Specify the format we would like.
_glfwLibrary.X11.selection.request = *xfmt;
// Convert the selection into a format we would like.
window = _glfwLibrary.activeWindow->X11.handle;
XConvertSelection(_glfwLibrary.X11.display, XA_PRIMARY,
*xfmt, None, window,
CurrentTime);
XFlush(_glfwLibrary.X11.display);
// Process pending events until we get a SelectionNotify.
while (!_glfwLibrary.X11.selection.converted)
_glfwPlatformWaitEvents();
// If there is no owner to the selection/wrong request, bail out.
if (_glfwLibrary.X11.selection.converted == 2)
for (; xfmt != xfmtend; xfmt++)
{
_glfwLibrary.X11.selection.converted = 0;
_glfwSetError(GLFW_CLIPBOARD_FORMAT_UNAVAILABLE,
"X11/GLX: Unavailable clipboard format");
return 0;
// Specify the format we would like.
_glfwLibrary.X11.selection.request = *xfmt;
// Convert the selection into a format we would like.
XConvertSelection(_glfwLibrary.X11.display, *xcbrd,
*xfmt, None, window, CurrentTime);
XFlush(_glfwLibrary.X11.display);
// Process pending events until we get a SelectionNotify.
while (!_glfwLibrary.X11.selection.converted)
_glfwPlatformWaitEvents();
// Successful?
if (_glfwLibrary.X11.selection.converted == 1)
break;
}
else // Right format, stop checking
// Successful?
if (_glfwLibrary.X11.selection.converted == 1)
{
_glfwLibrary.X11.selection.converted = 0;
break;
}
}
// Unsuccessful conversion, bail with no clipboard data
if (_glfwLibrary.X11.selection.converted)
{
_glfwSetError(GLFW_CLIPBOARD_FORMAT_UNAVAILABLE,
"X11/GLX: Unavailable clipboard format");
return 0;
}
// Reset for the next selection
_glfwLibrary.X11.selection.converted = 0;
// Check the length of data to receive
// Check the length of data to receive (rembytes)
XGetWindowProperty(_glfwLibrary.X11.display,
window,
*xfmt,