glfw/src/x11_clipboard.c

234 lines
7.8 KiB
C
Raw Normal View History

2011-09-21 09:09:47 +00:00
//========================================================================
// GLFW - An OpenGL library
// Platform: X11/GLX
// API version: 3.0
// WWW: http://www.glfw.org/
//------------------------------------------------------------------------
// Copyright (c) 2010 Camilla Berglund <elmindreda@elmindreda.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
// TODO: Incremental support? Overkill perhaps.
2011-09-21 09:09:47 +00:00
#include "internal.h"
#include <stdio.h>
2011-09-21 09:09:47 +00:00
#include <limits.h>
#include <string.h>
#include <stdlib.h>
2011-09-21 09:09:47 +00:00
2012-03-28 13:05:17 +00:00
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
//========================================================================
// X11 selection request event
//========================================================================
2012-03-28 13:05:17 +00:00
Atom _glfwSelectionRequest(XSelectionRequestEvent* request)
{
2012-04-09 13:21:54 +00:00
Atom* formats = _glfwLibrary.X11.selection.formats;
2012-04-09 13:27:32 +00:00
char* target = _glfwLibrary.X11.selection.string;
2012-04-09 13:12:59 +00:00
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,
2012-04-09 13:12:59 +00:00
request->requestor,
request->target,
request->target,
8,
PropModeReplace,
(unsigned char*) target,
8);
}
2012-04-09 13:21:54 +00:00
else if (request->target == formats[_GLFW_CLIPBOARD_FORMAT_COMPOUND] ||
request->target == formats[_GLFW_CLIPBOARD_FORMAT_UTF8])
{
XChangeProperty(_glfwLibrary.X11.display,
2012-04-09 13:12:59 +00:00
request->requestor,
request->target,
request->target,
8,
PropModeReplace,
(unsigned char*) target,
2012-04-09 13:27:32 +00:00
_glfwLibrary.X11.selection.stringLength);
}
else
{
// TODO: Should we set an error? Probably not.
return None;
}
2012-03-28 13:05:17 +00:00
return request->target;
}
2012-03-28 13:05:17 +00:00
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
2011-09-21 09:09:47 +00:00
//========================================================================
// Set the clipboard contents
//========================================================================
void _glfwPlatformSetClipboardString(const char* string)
2011-09-21 09:09:47 +00:00
{
size_t size = strlen(string) + 1;
// Allocate memory to keep track of the clipboard
char* cb = malloc(size);
// Copy the clipboard data
memcpy(cb, string, size);
// Set the string length
_glfwLibrary.X11.selection.stringLength = size;
// Check if existing clipboard memory needs to be freed
if (_glfwLibrary.X11.selection.string)
free(_glfwLibrary.X11.selection.string);
// Now set the clipboard (awaiting the event SelectionRequest)
_glfwLibrary.X11.selection.string = cb;
// Set the selection owner to our active window
XSetSelectionOwner(_glfwLibrary.X11.display, XA_PRIMARY,
2012-03-28 13:05:17 +00:00
_glfwLibrary.activeWindow->X11.handle, CurrentTime);
XSetSelectionOwner(_glfwLibrary.X11.display,
_glfwLibrary.X11.selection.atom,
2012-03-28 13:05:17 +00:00
_glfwLibrary.activeWindow->X11.handle, CurrentTime);
XFlush(_glfwLibrary.X11.display);
2011-09-21 09:09:47 +00:00
}
2012-03-28 13:05:17 +00:00
2011-09-21 09:09:47 +00:00
//========================================================================
// Return the current clipboard contents
//========================================================================
size_t _glfwPlatformGetClipboardString(char* data, size_t size)
2011-09-21 09:09:47 +00:00
{
size_t len, rembytes, dummy;
2012-04-09 13:12:59 +00:00
unsigned char* d;
2012-04-09 13:16:56 +00:00
int i, fmt;
Atom type;
// Get the currently active window
Window window = _glfwLibrary.activeWindow->X11.handle;
2012-04-09 13:21:54 +00:00
for (i = 0; i < _GLFW_CLIPBOARD_FORMAT_COUNT; i++)
{
// Specify the format we would like.
2012-04-09 13:16:56 +00:00
_glfwLibrary.X11.selection.request =
2012-04-09 13:21:54 +00:00
_glfwLibrary.X11.selection.formats[i];
// Convert the selection into a format we would like.
XConvertSelection(_glfwLibrary.X11.display,
_glfwLibrary.X11.selection.atom,
2012-04-09 13:16:56 +00:00
_glfwLibrary.X11.selection.request,
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;
}
// Successful?
if (_glfwLibrary.X11.selection.converted == 1)
_glfwLibrary.X11.selection.converted = 0;
// Unsuccessful conversion, bail with no clipboard data
if (_glfwLibrary.X11.selection.converted)
{
_glfwSetError(GLFW_FORMAT_UNAVAILABLE,
"X11/GLX: Failed to convert selection to string");
return 0;
}
// Reset for the next selection
_glfwLibrary.X11.selection.converted = 0;
// Check the length of data to receive (rembytes)
XGetWindowProperty(_glfwLibrary.X11.display,
window,
2012-04-09 13:16:56 +00:00
_glfwLibrary.X11.selection.request,
0, 0,
0,
AnyPropertyType,
&type,
&fmt,
&len, &rembytes,
&d);
// The number of bytes remaining (which is all of them)
if (rembytes > 0)
{
2012-04-09 13:12:59 +00:00
int result = XGetWindowProperty(_glfwLibrary.X11.display,
window,
2012-04-09 13:16:56 +00:00
_glfwLibrary.X11.selection.request,
2012-04-09 13:12:59 +00:00
0, rembytes,
0,
AnyPropertyType,
&type,
&fmt,
&len, &dummy,
&d);
if (result == Success)
{
2012-04-09 13:12:59 +00:00
size_t s;
if (rembytes < size - 1)
s = rembytes;
else
s = size - 1;
2012-03-28 13:05:17 +00:00
// Copy the data out.
memcpy(data, d, s);
2012-03-28 13:05:17 +00:00
// Null-terminate strings.
((char*) data)[s] = '\0';
2012-03-28 13:05:17 +00:00
// Free the data allocated using X11.
XFree(d);
2012-03-28 13:05:17 +00:00
// Return the actual number of bytes.
return rembytes;
}
else
{
// Free the data allocated using X11.
XFree(d);
return 0;
}
}
2012-03-28 13:05:17 +00:00
return 0;
2011-09-21 09:09:47 +00:00
}