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.
|
|
|
|
//
|
|
|
|
//========================================================================
|
|
|
|
|
2011-09-22 11:03:45 +00:00
|
|
|
// TODO: Incremental support? Overkill perhaps.
|
|
|
|
|
2011-09-21 09:09:47 +00:00
|
|
|
#include "internal.h"
|
|
|
|
|
2011-09-21 14:43:28 +00:00
|
|
|
#include <stdio.h>
|
2011-09-21 09:09:47 +00:00
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
2011-09-21 14:43:28 +00:00
|
|
|
#include <stdlib.h>
|
2011-09-21 09:09:47 +00:00
|
|
|
|
|
|
|
|
2012-03-28 13:05:17 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
////// GLFW internal API //////
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2011-09-22 11:03:45 +00:00
|
|
|
//========================================================================
|
|
|
|
// X11 selection request event
|
|
|
|
//========================================================================
|
|
|
|
|
2012-03-28 13:05:17 +00:00
|
|
|
Atom _glfwSelectionRequest(XSelectionRequestEvent* request)
|
2011-09-22 11:03:45 +00:00
|
|
|
{
|
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
|
|
|
|
2011-09-22 11:03:45 +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);
|
2011-09-22 11:03:45 +00:00
|
|
|
}
|
2012-04-09 13:21:54 +00:00
|
|
|
else if (request->target == formats[_GLFW_CLIPBOARD_FORMAT_COMPOUND] ||
|
|
|
|
request->target == formats[_GLFW_CLIPBOARD_FORMAT_UTF8])
|
2011-09-22 11:03:45 +00:00
|
|
|
{
|
|
|
|
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);
|
2011-09-22 11:03:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// TODO: Should we set an error? Probably not.
|
|
|
|
return None;
|
|
|
|
}
|
2012-03-28 13:05:17 +00:00
|
|
|
|
2011-09-22 11:03:45 +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
|
|
|
|
//========================================================================
|
|
|
|
|
2012-04-09 14:00:54 +00:00
|
|
|
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
2011-09-21 09:09:47 +00:00
|
|
|
{
|
2012-04-09 13:54:36 +00:00
|
|
|
size_t size = strlen(string) + 1;
|
2011-09-22 11:03:45 +00:00
|
|
|
|
2012-04-09 13:54:36 +00:00
|
|
|
// Allocate memory to keep track of the clipboard
|
|
|
|
char* cb = malloc(size);
|
2011-09-22 11:03:45 +00:00
|
|
|
|
2012-04-09 13:54:36 +00:00
|
|
|
// Copy the clipboard data
|
|
|
|
memcpy(cb, string, size);
|
2011-09-22 11:03:45 +00:00
|
|
|
|
2012-04-09 13:54:36 +00:00
|
|
|
// Set the string length
|
|
|
|
_glfwLibrary.X11.selection.stringLength = size;
|
2011-09-22 11:03:45 +00:00
|
|
|
|
2012-04-09 13:54:36 +00:00
|
|
|
// Check if existing clipboard memory needs to be freed
|
|
|
|
if (_glfwLibrary.X11.selection.string)
|
|
|
|
free(_glfwLibrary.X11.selection.string);
|
2011-09-21 14:43:28 +00:00
|
|
|
|
2012-04-09 13:54:36 +00:00
|
|
|
// Now set the clipboard (awaiting the event SelectionRequest)
|
|
|
|
_glfwLibrary.X11.selection.string = cb;
|
2011-09-22 11:03:45 +00:00
|
|
|
|
|
|
|
// Set the selection owner to our active window
|
|
|
|
XSetSelectionOwner(_glfwLibrary.X11.display, XA_PRIMARY,
|
2012-04-09 14:00:54 +00:00
|
|
|
window->X11.handle, CurrentTime);
|
2011-09-22 11:03:45 +00:00
|
|
|
XSetSelectionOwner(_glfwLibrary.X11.display,
|
2012-04-09 13:00:52 +00:00
|
|
|
_glfwLibrary.X11.selection.atom,
|
2012-04-09 14:00:54 +00:00
|
|
|
window->X11.handle, CurrentTime);
|
2011-09-22 11:03:45 +00:00
|
|
|
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
|
|
|
|
//========================================================================
|
|
|
|
|
2012-04-09 14:00:54 +00:00
|
|
|
size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* data, size_t size)
|
2011-09-21 09:09:47 +00:00
|
|
|
{
|
2011-09-21 14:43:28 +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;
|
2011-09-22 11:03:45 +00:00
|
|
|
Atom type;
|
|
|
|
|
2012-04-09 13:21:54 +00:00
|
|
|
for (i = 0; i < _GLFW_CLIPBOARD_FORMAT_COUNT; i++)
|
2011-09-21 14:43:28 +00:00
|
|
|
{
|
2012-04-09 13:00:52 +00:00
|
|
|
// 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];
|
2011-09-22 11:03:45 +00:00
|
|
|
|
2012-04-09 13:00:52 +00:00
|
|
|
// 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,
|
2012-04-09 14:00:54 +00:00
|
|
|
None, window->X11.handle, CurrentTime);
|
2012-04-09 13:00:52 +00:00
|
|
|
XFlush(_glfwLibrary.X11.display);
|
2011-09-22 11:03:45 +00:00
|
|
|
|
2012-04-09 13:00:52 +00:00
|
|
|
// Process pending events until we get a SelectionNotify.
|
|
|
|
while (!_glfwLibrary.X11.selection.converted)
|
|
|
|
_glfwPlatformWaitEvents();
|
2011-09-22 11:03:45 +00:00
|
|
|
|
|
|
|
// Successful?
|
|
|
|
if (_glfwLibrary.X11.selection.converted == 1)
|
2011-09-21 14:43:28 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-04-09 13:00:52 +00:00
|
|
|
// Successful?
|
|
|
|
if (_glfwLibrary.X11.selection.converted == 1)
|
|
|
|
_glfwLibrary.X11.selection.converted = 0;
|
|
|
|
|
2011-09-22 11:03:45 +00:00
|
|
|
// Unsuccessful conversion, bail with no clipboard data
|
|
|
|
if (_glfwLibrary.X11.selection.converted)
|
|
|
|
{
|
2012-04-09 13:54:36 +00:00
|
|
|
_glfwSetError(GLFW_FORMAT_UNAVAILABLE,
|
|
|
|
"X11/GLX: Failed to convert selection to string");
|
2011-09-22 11:03:45 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-09-21 14:43:28 +00:00
|
|
|
// Reset for the next selection
|
|
|
|
_glfwLibrary.X11.selection.converted = 0;
|
|
|
|
|
2011-09-22 11:03:45 +00:00
|
|
|
// Check the length of data to receive (rembytes)
|
2011-09-21 14:43:28 +00:00
|
|
|
XGetWindowProperty(_glfwLibrary.X11.display,
|
2012-04-09 14:00:54 +00:00
|
|
|
window->X11.handle,
|
2012-04-09 13:16:56 +00:00
|
|
|
_glfwLibrary.X11.selection.request,
|
2011-09-21 14:43:28 +00:00
|
|
|
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,
|
2012-04-09 14:00:54 +00:00
|
|
|
window->X11.handle,
|
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);
|
2011-09-21 14:43:28 +00:00
|
|
|
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
|
|
|
|
2011-09-21 14:43:28 +00:00
|
|
|
// Copy the data out.
|
|
|
|
memcpy(data, d, s);
|
2012-03-28 13:05:17 +00:00
|
|
|
|
2011-09-21 14:43:28 +00:00
|
|
|
// Null-terminate strings.
|
2012-04-09 13:54:36 +00:00
|
|
|
((char*) data)[s] = '\0';
|
2012-03-28 13:05:17 +00:00
|
|
|
|
2011-09-21 14:43:28 +00:00
|
|
|
// Free the data allocated using X11.
|
|
|
|
XFree(d);
|
2012-03-28 13:05:17 +00:00
|
|
|
|
2011-09-21 14:43:28 +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
|
|
|
|
2011-09-21 14:43:28 +00:00
|
|
|
return 0;
|
2011-09-21 09:09:47 +00:00
|
|
|
}
|
|
|
|
|