X11 implementation of clipboard pasting.

This commit is contained in:
Ralph Eastwood 2011-09-21 15:43:28 +01:00
parent 31c91545be
commit 57522db6e2
7 changed files with 147 additions and 5 deletions

View File

@ -465,6 +465,7 @@ extern "C" {
#define GLFW_VERSION_UNAVAILABLE 0x00070007 #define GLFW_VERSION_UNAVAILABLE 0x00070007
#define GLFW_PLATFORM_ERROR 0x00070008 #define GLFW_PLATFORM_ERROR 0x00070008
#define GLFW_WINDOW_NOT_ACTIVE 0x00070009 #define GLFW_WINDOW_NOT_ACTIVE 0x00070009
#define GLFW_CLIPBOARD_FORMAT_UNAVAILABLE 0x00070010
/* Gamma ramps */ /* Gamma ramps */
#define GLFW_GAMMA_RAMP_SIZE 256 #define GLFW_GAMMA_RAMP_SIZE 256

View File

@ -48,6 +48,10 @@ GLFWAPI void glfwSetClipboardData(void *data, size_t size, int format)
_glfwSetError(GLFW_NOT_INITIALIZED, NULL); _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
return; return;
} }
if (format == GLFW_CLIPBOARD_FORMAT_NONE)
return;
_glfwPlatformSetClipboardData(data, size, format); _glfwPlatformSetClipboardData(data, size, format);
} }
@ -61,8 +65,11 @@ GLFWAPI size_t glfwGetClipboardData(void *data, size_t size, int format)
if (!_glfwInitialized) if (!_glfwInitialized)
{ {
_glfwSetError(GLFW_NOT_INITIALIZED, NULL); _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
return 0; return 0;
} }
if (format == GLFW_CLIPBOARD_FORMAT_NONE)
return 0;
return _glfwPlatformGetClipboardData(data, size, format); return _glfwPlatformGetClipboardData(data, size, format);
} }

View File

@ -29,28 +29,131 @@
#include "internal.h" #include "internal.h"
#include <stdio.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
//========================================================================
// Get the corresponding X11 format for a given GLFW format.
//========================================================================
static Atom *getInternalFormat(int fmt)
{
// Get the necessary atoms
switch (fmt)
{
case GLFW_CLIPBOARD_FORMAT_STRING:
return _glfwLibrary.X11.selection.stringatoms;
default:
return 0;
}
}
//======================================================================== //========================================================================
// Set the clipboard contents // Set the clipboard contents
//======================================================================== //========================================================================
void _glfwPlatformSetClipboardData(void *data, size_t size, int format) void _glfwPlatformSetClipboardData(void *data, size_t size, int format)
{ {
} }
//======================================================================== //========================================================================
// Return the current clipboard contents // Return the current clipboard contents
// TODO: Incremental support? Overkill perhaps.
//======================================================================== //========================================================================
size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format)
{ {
return 0; size_t len, rembytes, dummy;
unsigned char *d;
int fmt;
Window window;
Atom *xfmt, type;
// Try different formats that relate to the GLFW format with preference
// for better formats first
for (xfmt = getInternalFormat(format); *xfmt; xfmt++)
{
// 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)
{
_glfwLibrary.X11.selection.converted = 0;
_glfwSetError(GLFW_CLIPBOARD_FORMAT_UNAVAILABLE,
"X11/GLX: Unavailable clipboard format");
return 0;
}
else // Right format, stop checking
{
_glfwLibrary.X11.selection.converted = 0;
break;
}
}
// Reset for the next selection
_glfwLibrary.X11.selection.converted = 0;
// Check the length of data to receive
XGetWindowProperty(_glfwLibrary.X11.display,
window,
*xfmt,
0, 0,
0,
AnyPropertyType,
&type,
&fmt,
&len, &rembytes,
&d);
// The number of bytes remaining (which is all of them)
if (rembytes > 0)
{
int result = XGetWindowProperty(_glfwLibrary.X11.display, window,
*xfmt, 0, rembytes, 0,
AnyPropertyType, &type, &fmt,
&len, &dummy, &d);
if (result == Success)
{
size_t s = size - 1 > rembytes ? rembytes : size - 1;
// Copy the data out.
memcpy(data, d, s);
// Null-terminate strings.
if (format == GLFW_CLIPBOARD_FORMAT_STRING)
{
((char *)data)[s] = '\0';
}
// Free the data allocated using X11.
XFree(d);
// Return the actual number of bytes.
return rembytes;
}
else
{
// Free the data allocated using X11.
XFree(d);
return 0;
}
}
return 0;
} }

View File

@ -446,6 +446,14 @@ static GLboolean initDisplay(void)
// the keyboard mapping. // the keyboard mapping.
updateKeyCodeLUT(); updateKeyCodeLUT();
// Find or create selection atoms
_glfwLibrary.X11.selection.stringatoms[0] =
XInternAtom(_glfwLibrary.X11.display, "UTF8_STRING", False);
_glfwLibrary.X11.selection.stringatoms[1] =
XInternAtom(_glfwLibrary.X11.display, "COMPOUND_STRING", False);
_glfwLibrary.X11.selection.stringatoms[2] = XA_STRING;
_glfwLibrary.X11.selection.stringatoms[3] = 0;
return GL_TRUE; return GL_TRUE;
} }

View File

@ -89,6 +89,8 @@
#define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryX11 X11 #define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryX11 X11
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX GLX #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX GLX
// Number of string atoms that will be checked
#define _GLFW_STRING_ATOMS_COUNT 4
//======================================================================== //========================================================================
// GLFW platform specific types // GLFW platform specific types
@ -225,6 +227,13 @@ typedef struct _GLFWlibraryX11
uint64_t t0; uint64_t t0;
} timer; } timer;
// Selection data
struct {
Atom stringatoms[_GLFW_STRING_ATOMS_COUNT];
Atom request;
int converted;
} selection;
#if defined(_GLFW_DLOPEN_LIBGL) #if defined(_GLFW_DLOPEN_LIBGL)
void* libGL; // dlopen handle for libGL.so void* libGL; // dlopen handle for libGL.so
#endif #endif

View File

@ -1381,6 +1381,19 @@ static void processSingleEvent(void)
break; break;
} }
case SelectionNotify:
{
// Selection notification triggered by the XConvertSelection
// Check if the notification property matches the request
if (event.xselection.property != _glfwLibrary.X11.selection.request)
_glfwLibrary.X11.selection.converted = 2;
else // It was successful
_glfwLibrary.X11.selection.converted = 1;
break;
}
// Was the window destroyed? // Was the window destroyed?
case DestroyNotify: case DestroyNotify:
return; return;

View File

@ -5,6 +5,7 @@ include_directories(${GLFW_SOURCE_DIR}/include
${GLFW_SOURCE_DIR}/support ${GLFW_SOURCE_DIR}/support
${OPENGL_INCLUDE_DIR}) ${OPENGL_INCLUDE_DIR})
add_executable(clipboard clipboard.c)
add_executable(defaults defaults.c) add_executable(defaults defaults.c)
add_executable(events events.c) add_executable(events events.c)
add_executable(fsaa fsaa.c getopt.c) add_executable(fsaa fsaa.c getopt.c)
@ -32,8 +33,8 @@ else()
endif(APPLE) endif(APPLE)
set(WINDOWS_BINARIES accuracy sharing tearing windows) set(WINDOWS_BINARIES accuracy sharing tearing windows)
set(CONSOLE_BINARIES defaults events fsaa fsfocus gamma iconify joysticks set(CONSOLE_BINARIES clipboard defaults events fsaa fsfocus gamma iconify
listmodes peter reopen version) joysticks listmodes peter reopen version)
if(MSVC) if(MSVC)
# Tell MSVC to use main instead of WinMain for Windows subsystem executables # Tell MSVC to use main instead of WinMain for Windows subsystem executables