From 31c91545be9c65c7ad3701c71286102e07186bb8 Mon Sep 17 00:00:00 2001 From: Ralph Eastwood Date: Wed, 21 Sep 2011 10:09:47 +0100 Subject: [PATCH 01/37] Added clipboard stubs. --- include/GL/glfw3.h | 8 +++++ src/CMakeLists.txt | 11 ++++--- src/clipboard.c | 68 +++++++++++++++++++++++++++++++++++++++++++ src/cocoa_clipboard.m | 56 +++++++++++++++++++++++++++++++++++ src/internal.h | 4 +++ src/win32_clipboard.c | 56 +++++++++++++++++++++++++++++++++++ src/x11_clipboard.c | 56 +++++++++++++++++++++++++++++++++++ 7 files changed, 255 insertions(+), 4 deletions(-) create mode 100644 src/clipboard.c create mode 100644 src/cocoa_clipboard.m create mode 100644 src/win32_clipboard.c create mode 100644 src/x11_clipboard.c diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 1f52e742..e3687b5c 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -469,6 +469,10 @@ extern "C" { /* Gamma ramps */ #define GLFW_GAMMA_RAMP_SIZE 256 +/* Clipboard formats */ +#define GLFW_CLIPBOARD_FORMAT_NONE 0 +#define GLFW_CLIPBOARD_FORMAT_STRING 1 + /************************************************************************* * Typedefs *************************************************************************/ @@ -591,6 +595,10 @@ GLFWAPI int glfwGetJoystickParam(int joy, int param); GLFWAPI int glfwGetJoystickPos(int joy, float* pos, int numaxes); GLFWAPI int glfwGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons); +/* Clipboard */ +GLFWAPI void glfwSetClipboardData(void *data, size_t size, int format); +GLFWAPI size_t glfwGetClipboardData(void *data, size_t size, int format); + /* Time */ GLFWAPI double glfwGetTime(void); GLFWAPI void glfwSetTime(double time); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd50b41d..08ce8365 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,23 +27,26 @@ include_directories(${GLFW_SOURCE_DIR}/src ${GLFW_BINARY_DIR}/src ${GLFW_INCLUDE_DIR}) -set(common_SOURCES enable.c error.c fullscreen.c gamma.c init.c input.c +set(common_SOURCES clipboard.c enable.c error.c fullscreen.c gamma.c init.c input.c joystick.c opengl.c time.c window.c) if(_GLFW_COCOA_NSGL) - set(libglfw_SOURCES ${common_SOURCES} cocoa_enable.m cocoa_fullscreen.m + set(libglfw_SOURCES ${common_SOURCES} cocoa_clipboard.c + cocoa_enable.m cocoa_fullscreen.m cocoa_gamma.m cocoa_init.m cocoa_joystick.m cocoa_opengl.m cocoa_time.m cocoa_window.m) # For some reason, CMake doesn't know about .m set_source_files_properties(${libglfw_SOURCES} PROPERTIES LANGUAGE C) elseif(_GLFW_WIN32_WGL) - set(libglfw_SOURCES ${common_SOURCES} win32_enable.c win32_fullscreen.c + set(libglfw_SOURCES ${common_SOURCES} win32_clipboard.c + win32_enable.c win32_fullscreen.c win32_gamma.c win32_init.c win32_joystick.c win32_opengl.c win32_time.c win32_window.c win32_dllmain.c) elseif(_GLFW_X11_GLX) - set(libglfw_SOURCES ${common_SOURCES} x11_enable.c x11_fullscreen.c + set(libglfw_SOURCES ${common_SOURCES} x11_clipboard.c + x11_enable.c x11_fullscreen.c x11_gamma.c x11_init.c x11_joystick.c x11_keysym2unicode.c x11_opengl.c x11_time.c x11_window.c) diff --git a/src/clipboard.c b/src/clipboard.c new file mode 100644 index 00000000..5e38904f --- /dev/null +++ b/src/clipboard.c @@ -0,0 +1,68 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: Any +// API version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2010 Camilla Berglund +// +// 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. +// +//======================================================================== + +#include "internal.h" + +#include +#include + + +////////////////////////////////////////////////////////////////////////// +////// GLFW public API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Set the clipboard contents +//======================================================================== + +GLFWAPI void glfwSetClipboardData(void *data, size_t size, int format) +{ + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return; + } + _glfwPlatformSetClipboardData(data, size, format); +} + + +//======================================================================== +// Return the current clipboard contents +//======================================================================== + +GLFWAPI size_t glfwGetClipboardData(void *data, size_t size, int format) +{ + if (!_glfwInitialized) + { + _glfwSetError(GLFW_NOT_INITIALIZED, NULL); + return 0; + } + + return _glfwPlatformGetClipboardData(data, size, format); +} diff --git a/src/cocoa_clipboard.m b/src/cocoa_clipboard.m new file mode 100644 index 00000000..0f78cf21 --- /dev/null +++ b/src/cocoa_clipboard.m @@ -0,0 +1,56 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: Cocoa/NSOpenGL +// API version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2010 Camilla Berglund +// +// 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. +// +//======================================================================== + +#include "internal.h" + +#include +#include + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Set the clipboard contents +//======================================================================== + +void _glfwPlatformSetClipboardData(void *data, size_t size, int format) +{ +} + +//======================================================================== +// Return the current clipboard contents +//======================================================================== + +size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) +{ + return 0; +} + diff --git a/src/internal.h b/src/internal.h index 83559ecc..3b82d47e 100644 --- a/src/internal.h +++ b/src/internal.h @@ -284,6 +284,10 @@ void _glfwPlatformGetDesktopMode(GLFWvidmode* mode); void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp); void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp); +// Clipboard +void _glfwPlatformSetClipboardData(void *data, size_t size, int format); +size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format); + // Joystick int _glfwPlatformGetJoystickParam(int joy, int param); int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes); diff --git a/src/win32_clipboard.c b/src/win32_clipboard.c new file mode 100644 index 00000000..b16c51c4 --- /dev/null +++ b/src/win32_clipboard.c @@ -0,0 +1,56 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: Win32/WGL +// API version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2010 Camilla Berglund +// +// 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. +// +//======================================================================== + +#include "internal.h" + +#include +#include + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Set the clipboard contents +//======================================================================== + +void _glfwPlatformSetClipboardData(void *data, size_t size, int format) +{ +} + +//======================================================================== +// Return the current clipboard contents +//======================================================================== + +size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) +{ + return 0; +} + diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c new file mode 100644 index 00000000..164bad49 --- /dev/null +++ b/src/x11_clipboard.c @@ -0,0 +1,56 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: X11/GLX +// API version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2010 Camilla Berglund +// +// 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. +// +//======================================================================== + +#include "internal.h" + +#include +#include + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Set the clipboard contents +//======================================================================== + +void _glfwPlatformSetClipboardData(void *data, size_t size, int format) +{ +} + +//======================================================================== +// Return the current clipboard contents +//======================================================================== + +size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) +{ + return 0; +} + From 57522db6e2919406efd0d44a170962ed8f480f2f Mon Sep 17 00:00:00 2001 From: Ralph Eastwood Date: Wed, 21 Sep 2011 15:43:28 +0100 Subject: [PATCH 02/37] X11 implementation of clipboard pasting. --- include/GL/glfw3.h | 1 + src/clipboard.c | 9 +++- src/x11_clipboard.c | 107 ++++++++++++++++++++++++++++++++++++++++++- src/x11_init.c | 8 ++++ src/x11_platform.h | 9 ++++ src/x11_window.c | 13 ++++++ tests/CMakeLists.txt | 5 +- 7 files changed, 147 insertions(+), 5 deletions(-) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index e3687b5c..21ed049a 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -465,6 +465,7 @@ extern "C" { #define GLFW_VERSION_UNAVAILABLE 0x00070007 #define GLFW_PLATFORM_ERROR 0x00070008 #define GLFW_WINDOW_NOT_ACTIVE 0x00070009 +#define GLFW_CLIPBOARD_FORMAT_UNAVAILABLE 0x00070010 /* Gamma ramps */ #define GLFW_GAMMA_RAMP_SIZE 256 diff --git a/src/clipboard.c b/src/clipboard.c index 5e38904f..79cf680c 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -48,6 +48,10 @@ GLFWAPI void glfwSetClipboardData(void *data, size_t size, int format) _glfwSetError(GLFW_NOT_INITIALIZED, NULL); return; } + + if (format == GLFW_CLIPBOARD_FORMAT_NONE) + return; + _glfwPlatformSetClipboardData(data, size, format); } @@ -61,8 +65,11 @@ GLFWAPI size_t glfwGetClipboardData(void *data, size_t size, int format) if (!_glfwInitialized) { _glfwSetError(GLFW_NOT_INITIALIZED, NULL); - return 0; + return 0; } + if (format == GLFW_CLIPBOARD_FORMAT_NONE) + return 0; + return _glfwPlatformGetClipboardData(data, size, format); } diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index 164bad49..467a0d52 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -29,28 +29,131 @@ #include "internal.h" +#include #include #include - +#include ////////////////////////////////////////////////////////////////////////// ////// 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 //======================================================================== void _glfwPlatformSetClipboardData(void *data, size_t size, int format) { + } //======================================================================== // Return the current clipboard contents +// TODO: Incremental support? Overkill perhaps. //======================================================================== 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; } diff --git a/src/x11_init.c b/src/x11_init.c index 9af7783e..a824528b 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -446,6 +446,14 @@ static GLboolean initDisplay(void) // the keyboard mapping. 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; } diff --git a/src/x11_platform.h b/src/x11_platform.h index b3cf642e..90b6e75c 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -89,6 +89,8 @@ #define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryX11 X11 #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 @@ -225,6 +227,13 @@ typedef struct _GLFWlibraryX11 uint64_t t0; } timer; + // Selection data + struct { + Atom stringatoms[_GLFW_STRING_ATOMS_COUNT]; + Atom request; + int converted; + } selection; + #if defined(_GLFW_DLOPEN_LIBGL) void* libGL; // dlopen handle for libGL.so #endif diff --git a/src/x11_window.c b/src/x11_window.c index a05b121c..ff54a11b 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1381,6 +1381,19 @@ static void processSingleEvent(void) 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? case DestroyNotify: return; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9ef07acc..23a1ebd0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories(${GLFW_SOURCE_DIR}/include ${GLFW_SOURCE_DIR}/support ${OPENGL_INCLUDE_DIR}) +add_executable(clipboard clipboard.c) add_executable(defaults defaults.c) add_executable(events events.c) add_executable(fsaa fsaa.c getopt.c) @@ -32,8 +33,8 @@ else() endif(APPLE) set(WINDOWS_BINARIES accuracy sharing tearing windows) -set(CONSOLE_BINARIES defaults events fsaa fsfocus gamma iconify joysticks - listmodes peter reopen version) +set(CONSOLE_BINARIES clipboard defaults events fsaa fsfocus gamma iconify + joysticks listmodes peter reopen version) if(MSVC) # Tell MSVC to use main instead of WinMain for Windows subsystem executables From 9f41e5b67a89dbd93f96e39d2d1d7d6c79a872c2 Mon Sep 17 00:00:00 2001 From: Ralph Eastwood Date: Thu, 22 Sep 2011 12:03:45 +0100 Subject: [PATCH 03/37] X11 copying code and support PRIMARY & CLIPBOARD clipboards. --- include/GL/glfw3.h | 1 + src/clipboard.c | 3 + src/x11_clipboard.c | 149 +++++++++++++++++++++++++++++++++++--------- src/x11_init.c | 19 ++++-- src/x11_platform.h | 26 ++++++-- src/x11_window.c | 21 ++++++- 6 files changed, 179 insertions(+), 40 deletions(-) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 21ed049a..7f054e5f 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -466,6 +466,7 @@ extern "C" { #define GLFW_PLATFORM_ERROR 0x00070008 #define GLFW_WINDOW_NOT_ACTIVE 0x00070009 #define GLFW_CLIPBOARD_FORMAT_UNAVAILABLE 0x00070010 +#define GLFW_CLIPBOARD_CANNOT_OWN 0x00070011 /* Gamma ramps */ #define GLFW_GAMMA_RAMP_SIZE 256 diff --git a/src/clipboard.c b/src/clipboard.c index 79cf680c..b055c168 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -71,5 +71,8 @@ GLFWAPI size_t glfwGetClipboardData(void *data, size_t size, int format) if (format == GLFW_CLIPBOARD_FORMAT_NONE) return 0; + if (!data || !size) + return 0; + return _glfwPlatformGetClipboardData(data, size, format); } diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index 467a0d52..1be0ac23 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -27,6 +27,8 @@ // //======================================================================== +// TODO: Incremental support? Overkill perhaps. + #include "internal.h" #include @@ -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, diff --git a/src/x11_init.c b/src/x11_init.c index a824528b..1fa549bd 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -446,13 +446,20 @@ static GLboolean initDisplay(void) // the keyboard mapping. updateKeyCodeLUT(); + // Find or create clipboard atoms + _glfwLibrary.X11.selection.atoms.clipboard[_GLFW_CLIPBOARD_ATOM_PRIMARY] = + XA_PRIMARY; + _glfwLibrary.X11.selection.atoms.clipboard[_GLFW_CLIPBOARD_ATOM_CLIPBOARD] = + XInternAtom(_glfwLibrary.X11.display, "CLIPBOARD", False); + _glfwLibrary.X11.selection.atoms.clipboard[_GLFW_CLIPBOARD_ATOM_SECONDARY] = + XA_SECONDARY; + // Find or create selection atoms - _glfwLibrary.X11.selection.stringatoms[0] = + _glfwLibrary.X11.selection.atoms.string[_GLFW_STRING_ATOM_UTF8] = XInternAtom(_glfwLibrary.X11.display, "UTF8_STRING", False); - _glfwLibrary.X11.selection.stringatoms[1] = + _glfwLibrary.X11.selection.atoms.string[_GLFW_STRING_ATOM_COMPOUND] = XInternAtom(_glfwLibrary.X11.display, "COMPOUND_STRING", False); - _glfwLibrary.X11.selection.stringatoms[2] = XA_STRING; - _glfwLibrary.X11.selection.stringatoms[3] = 0; + _glfwLibrary.X11.selection.atoms.string[_GLFW_STRING_ATOM_STRING] = XA_STRING; return GL_TRUE; } @@ -616,6 +623,10 @@ int _glfwPlatformTerminate(void) } #endif + // Free clipboard memory + if (_glfwLibrary.X11.selection.clipboard.string) + free(_glfwLibrary.X11.selection.clipboard.string); + return GL_TRUE; } diff --git a/src/x11_platform.h b/src/x11_platform.h index 90b6e75c..6f1bf6a5 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -89,8 +89,17 @@ #define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryX11 X11 #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX GLX -// Number of string atoms that will be checked -#define _GLFW_STRING_ATOMS_COUNT 4 +// Clipboard atoms +#define _GLFW_CLIPBOARD_ATOM_PRIMARY 0 +#define _GLFW_CLIPBOARD_ATOM_CLIPBOARD 1 +#define _GLFW_CLIPBOARD_ATOM_SECONDARY 2 +#define _GLFW_CLIPBOARD_ATOM_COUNT 3 + +// String atoms +#define _GLFW_STRING_ATOM_UTF8 0 +#define _GLFW_STRING_ATOM_COMPOUND 1 +#define _GLFW_STRING_ATOM_STRING 2 +#define _GLFW_STRING_ATOM_COUNT 3 //======================================================================== // GLFW platform specific types @@ -229,8 +238,15 @@ typedef struct _GLFWlibraryX11 // Selection data struct { - Atom stringatoms[_GLFW_STRING_ATOMS_COUNT]; - Atom request; + struct { + Atom clipboard[_GLFW_CLIPBOARD_ATOM_COUNT]; + Atom string[_GLFW_STRING_ATOM_COUNT]; + } atoms; + struct { + size_t stringlen; + char *string; + } clipboard; + Atom request; int converted; } selection; @@ -273,5 +289,7 @@ void _glfwTerminateJoysticks(void); // Unicode support long _glfwKeySym2Unicode(KeySym keysym); +// Clipboard handling +Atom _glfwSelectionRequest(XSelectionRequestEvent *request); #endif // _platform_h_ diff --git a/src/x11_window.c b/src/x11_window.c index ff54a11b..cfb19980 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -41,8 +41,8 @@ #define _NET_WM_STATE_TOGGLE 2 // Additional mouse button names for XButtonEvent -#define Button6 6 -#define Button7 7 +#define Button6 6 +#define Button7 7 //======================================================================== // Error handler for BadMatch errors when requesting context with @@ -1394,6 +1394,23 @@ static void processSingleEvent(void) break; } + case SelectionRequest: + { + XSelectionRequestEvent *request = &event.xselectionrequest; + // Construct the response + XEvent response; + response.xselection.property = _glfwSelectionRequest(request); + response.xselection.type = SelectionNotify; + response.xselection.display = request->display; + response.xselection.requestor = request->requestor; + response.xselection.selection = request->selection; + response.xselection.target = request->target; + response.xselection.time = request->time; + // Send off the event + XSendEvent(_glfwLibrary.X11.display, request->requestor, 0, 0, &response); + break; + } + // Was the window destroyed? case DestroyNotify: return; From a2ffa80e82729afcca0b0929a03b21661c2d00d7 Mon Sep 17 00:00:00 2001 From: Ralph Eastwood Date: Thu, 22 Sep 2011 12:09:01 +0100 Subject: [PATCH 04/37] Some reformatting with new X11 SelectionRequest event. --- src/x11_window.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/x11_window.c b/src/x11_window.c index cfb19980..0fe4db83 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1396,7 +1396,10 @@ static void processSingleEvent(void) case SelectionRequest: { + // Selection request triggered by someone wanting data from the + // X11 clipboard XSelectionRequestEvent *request = &event.xselectionrequest; + // Construct the response XEvent response; response.xselection.property = _glfwSelectionRequest(request); @@ -1406,8 +1409,10 @@ static void processSingleEvent(void) response.xselection.selection = request->selection; response.xselection.target = request->target; response.xselection.time = request->time; + // Send off the event XSendEvent(_glfwLibrary.X11.display, request->requestor, 0, 0, &response); + break; } From f332e0009d46f71ee23e91eafc50821dcc2a0acd Mon Sep 17 00:00:00 2001 From: Tai Chi Minh Ralph Eastwood Date: Sun, 19 Feb 2012 05:39:21 +0000 Subject: [PATCH 05/37] Add mising clipboard test program. --- tests/clipboard.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 tests/clipboard.c diff --git a/tests/clipboard.c b/tests/clipboard.c new file mode 100644 index 00000000..cdbba6d2 --- /dev/null +++ b/tests/clipboard.c @@ -0,0 +1,147 @@ +//======================================================================== +// Gamma correction test program +// Copyright (c) Camilla Berglund +// +// 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. +// +//======================================================================== +// +// This program is used to test the clipboard functionality. +// +//======================================================================== + +#include + +#include +#include + +#include "getopt.h" + +static void usage(void) +{ + printf("Usage: clipboard [-h]\n"); +} + +static void key_callback(GLFWwindow window, int key, int action) +{ + static int control = GL_FALSE; + if (key == GLFW_KEY_LEFT_CONTROL) + { + control = (action == GLFW_PRESS); + return; + } + + if (action != GLFW_PRESS) + return; + + switch (key) + { + case GLFW_KEY_ESCAPE: + glfwCloseWindow(window); + break; + case GLFW_KEY_V: + if (control) + { + char buffer[4096]; + size_t size; + printf("Paste test.\n"); + size = glfwGetClipboardData(buffer, sizeof(buffer), GLFW_CLIPBOARD_FORMAT_STRING); + if (size >= sizeof(buffer)) + { + printf("Buffer wasn't big enough to hold clipboard data.\n"); + } + printf("[%ld]: %s\n", size, buffer); + } + break; + case GLFW_KEY_C: + if (control) + { + glfwSetClipboardData("Hello GLFW World!", sizeof("Hello GLFW World!"), + GLFW_CLIPBOARD_FORMAT_STRING); + printf("Setting clipboard to: %s\n", "Hello GLFW World!"); + } + break; + } +} + +static void size_callback(GLFWwindow window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +int main(int argc, char** argv) +{ + int ch; + GLFWwindow window; + + while ((ch = getopt(argc, argv, "h")) != -1) + { + switch (ch) + { + case 'h': + usage(); + exit(EXIT_SUCCESS); + + default: + usage(); + exit(EXIT_FAILURE); + } + } + + if (!glfwInit()) + { + fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); + exit(EXIT_FAILURE); + } + + window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Clipboard Test", NULL); + if (!window) + { + glfwTerminate(); + + fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); + exit(EXIT_FAILURE); + } + + glfwSwapInterval(1); + glfwSetKeyCallback(key_callback); + glfwSetWindowSizeCallback(size_callback); + + glMatrixMode(GL_PROJECTION); + glOrtho(-1.f, 1.f, -1.f, 1.f, -1.f, 1.f); + glMatrixMode(GL_MODELVIEW); + + glClearColor(0.5f, 0.5f, 0.5f, 0); + + while (glfwIsWindow(window)) + { + glClear(GL_COLOR_BUFFER_BIT); + + glColor3f(0.8f, 0.2f, 0.4f); + glRectf(-0.5f, -0.5f, 0.5f, 0.5f); + + glfwSwapBuffers(); + glfwPollEvents(); + } + + glfwTerminate(); + exit(EXIT_SUCCESS); +} + From a3430c2dec9991cc9ed2aef2019dd7ce95f4591e Mon Sep 17 00:00:00 2001 From: Tai Chi Minh Ralph Eastwood Date: Sun, 19 Feb 2012 05:40:11 +0000 Subject: [PATCH 06/37] No idea why this file changed... or should it be changed at all. --- src/libglfw.pc.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libglfw.pc.cmake b/src/libglfw.pc.cmake index 47cfb4f5..7538b885 100644 --- a/src/libglfw.pc.cmake +++ b/src/libglfw.pc.cmake @@ -9,4 +9,5 @@ Version: 3.0.0 URL: http://www.glfw.org/ Requires.private: gl x11 @GLFW_PKGLIBS@ Libs: -L${libdir} -lglfw +Libs.private: @GLFW_LIBRARIES@ Cflags: -I${includedir} From 8b7fc5d6013bf99af5c538dd73d24a38d835cd32 Mon Sep 17 00:00:00 2001 From: Tai Chi Minh Ralph Eastwood Date: Sun, 19 Feb 2012 06:30:45 +0000 Subject: [PATCH 07/37] Trailing whitespace. --- src/libglfw.pc.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libglfw.pc.cmake b/src/libglfw.pc.cmake index 7538b885..1a712d9d 100644 --- a/src/libglfw.pc.cmake +++ b/src/libglfw.pc.cmake @@ -8,6 +8,6 @@ Description: A portable library for OpenGL, window and input Version: 3.0.0 URL: http://www.glfw.org/ Requires.private: gl x11 @GLFW_PKGLIBS@ -Libs: -L${libdir} -lglfw +Libs: -L${libdir} -lglfw Libs.private: @GLFW_LIBRARIES@ Cflags: -I${includedir} From 7f470065fc3b0a2c8c9fe72a146d7346d965ef98 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Wed, 28 Mar 2012 15:05:17 +0200 Subject: [PATCH 08/37] Applied coding conventions. --- src/clipboard.c | 1 + src/x11_clipboard.c | 54 +++++++++++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/clipboard.c b/src/clipboard.c index b055c168..480bad8e 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -76,3 +76,4 @@ GLFWAPI size_t glfwGetClipboardData(void *data, size_t size, int format) return _glfwPlatformGetClipboardData(data, size, format); } + diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index 1be0ac23..71f2f7c9 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -36,18 +36,15 @@ #include #include -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// //======================================================================== // Get the corresponding X11 format for a given GLFW format. //======================================================================== -static Atom *getInternalFormat(int fmt) +static Atom* getInternalFormat(int format) { // Get the necessary atoms - switch (fmt) + switch (format) { case GLFW_CLIPBOARD_FORMAT_STRING: return _glfwLibrary.X11.selection.atoms.string; @@ -56,13 +53,18 @@ static Atom *getInternalFormat(int fmt) } } + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + //======================================================================== // X11 selection request event //======================================================================== -Atom _glfwSelectionRequest(XSelectionRequestEvent *request) +Atom _glfwSelectionRequest(XSelectionRequestEvent* request) { - Atom *atoms = _glfwLibrary.X11.selection.atoms.string; + Atom* atoms = _glfwLibrary.X11.selection.atoms.string; if (request->target == XA_STRING) { // TODO: ISO Latin-1 specific characters don't get converted @@ -73,7 +75,7 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent *request) request->target, 8, PropModeReplace, - (unsigned char *)_glfwLibrary.X11.selection.clipboard.string, + (unsigned char*) _glfwLibrary.X11.selection.clipboard.string, 8); } else if (request->target == atoms[_GLFW_STRING_ATOM_COMPOUND] || @@ -85,7 +87,7 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent *request) request->target, 8, PropModeReplace, - (unsigned char *)_glfwLibrary.X11.selection.clipboard.string, + (unsigned char*) _glfwLibrary.X11.selection.clipboard.string, _glfwLibrary.X11.selection.clipboard.stringlen); } else @@ -93,9 +95,15 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent *request) // TODO: Should we set an error? Probably not. return None; } + return request->target; } + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + //======================================================================== // Set the clipboard contents //======================================================================== @@ -132,14 +140,15 @@ void _glfwPlatformSetClipboardData(void *data, size_t size, int format) // Set the selection owner to our active window XSetSelectionOwner(_glfwLibrary.X11.display, XA_PRIMARY, - _glfwLibrary.activeWindow->X11.handle, CurrentTime); + _glfwLibrary.activeWindow->X11.handle, CurrentTime); XSetSelectionOwner(_glfwLibrary.X11.display, - _glfwLibrary.X11.selection.atoms.clipboard - [_GLFW_CLIPBOARD_ATOM_CLIPBOARD], - _glfwLibrary.activeWindow->X11.handle, CurrentTime); + _glfwLibrary.X11.selection.atoms.clipboard + [_GLFW_CLIPBOARD_ATOM_CLIPBOARD], + _glfwLibrary.activeWindow->X11.handle, CurrentTime); XFlush(_glfwLibrary.X11.display); } + //======================================================================== // Return the current clipboard contents //======================================================================== @@ -155,16 +164,16 @@ size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) // 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; + _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++) + for ( ; xcbrd != xcbrdend; xcbrd++) { - for (; xfmt != xfmtend; xfmt++) + for ( ; xfmt != xfmtend; xfmt++) { // Specify the format we would like. _glfwLibrary.X11.selection.request = *xfmt; @@ -218,21 +227,23 @@ size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) if (rembytes > 0) { int result = XGetWindowProperty(_glfwLibrary.X11.display, window, - *xfmt, 0, rembytes, 0, - AnyPropertyType, &type, &fmt, - &len, &dummy, &d); + *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; } @@ -243,6 +254,7 @@ size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) return 0; } } + return 0; } From a1d5fc039d39ee1a925874ce3abbed0a821133f1 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Wed, 28 Mar 2012 15:07:47 +0200 Subject: [PATCH 09/37] Added support for right control key. --- tests/clipboard.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tests/clipboard.c b/tests/clipboard.c index cdbba6d2..16249f8a 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -39,15 +39,14 @@ static void usage(void) printf("Usage: clipboard [-h]\n"); } +static GLboolean control_is_down(void) +{ + return glfwGetKey(GLFW_KEY_LEFT_CONTROL) || + glfwGetKey(GLFW_KEY_RIGHT_CONTROL); +} + static void key_callback(GLFWwindow window, int key, int action) { - static int control = GL_FALSE; - if (key == GLFW_KEY_LEFT_CONTROL) - { - control = (action == GLFW_PRESS); - return; - } - if (action != GLFW_PRESS) return; @@ -57,7 +56,7 @@ static void key_callback(GLFWwindow window, int key, int action) glfwCloseWindow(window); break; case GLFW_KEY_V: - if (control) + if (control_is_down()) { char buffer[4096]; size_t size; @@ -71,7 +70,7 @@ static void key_callback(GLFWwindow window, int key, int action) } break; case GLFW_KEY_C: - if (control) + if (control_is_down()) { glfwSetClipboardData("Hello GLFW World!", sizeof("Hello GLFW World!"), GLFW_CLIPBOARD_FORMAT_STRING); From e4328af790de86d14811a10a1f266c30f08f9a33 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Wed, 28 Mar 2012 16:08:55 +0200 Subject: [PATCH 10/37] Formatting. --- src/x11_platform.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/x11_platform.h b/src/x11_platform.h index c6be6db3..2e6bbc21 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -236,15 +236,15 @@ typedef struct _GLFWlibraryX11 // Selection data struct { - struct { - Atom clipboard[_GLFW_CLIPBOARD_ATOM_COUNT]; - Atom string[_GLFW_STRING_ATOM_COUNT]; - } atoms; - struct { - size_t stringlen; - char *string; - } clipboard; - Atom request; + struct { + Atom clipboard[_GLFW_CLIPBOARD_ATOM_COUNT]; + Atom string[_GLFW_STRING_ATOM_COUNT]; + } atoms; + struct { + size_t stringlen; + char *string; + } clipboard; + Atom request; int converted; } selection; From e49f1b88011838fafe705a8fd00d54f280f27f4a Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Thu, 29 Mar 2012 13:30:40 +0200 Subject: [PATCH 11/37] Fixed broken example. --- tests/clipboard.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/clipboard.c b/tests/clipboard.c index 16249f8a..5388ba4d 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -39,10 +39,10 @@ static void usage(void) printf("Usage: clipboard [-h]\n"); } -static GLboolean control_is_down(void) +static GLboolean control_is_down(GLFWwindow window) { - return glfwGetKey(GLFW_KEY_LEFT_CONTROL) || - glfwGetKey(GLFW_KEY_RIGHT_CONTROL); + return glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) || + glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL); } static void key_callback(GLFWwindow window, int key, int action) @@ -56,7 +56,7 @@ static void key_callback(GLFWwindow window, int key, int action) glfwCloseWindow(window); break; case GLFW_KEY_V: - if (control_is_down()) + if (control_is_down(window)) { char buffer[4096]; size_t size; @@ -66,11 +66,11 @@ static void key_callback(GLFWwindow window, int key, int action) { printf("Buffer wasn't big enough to hold clipboard data.\n"); } - printf("[%ld]: %s\n", size, buffer); + printf("[%lu]: %s\n", (unsigned long) size, buffer); } break; case GLFW_KEY_C: - if (control_is_down()) + if (control_is_down(window)) { glfwSetClipboardData("Hello GLFW World!", sizeof("Hello GLFW World!"), GLFW_CLIPBOARD_FORMAT_STRING); From cca6b521208bcdc693dffc28922713064d647d6b Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Thu, 29 Mar 2012 13:31:19 +0200 Subject: [PATCH 12/37] Formatting. --- tests/clipboard.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/clipboard.c b/tests/clipboard.c index 5388ba4d..0065e0a6 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -60,12 +60,13 @@ static void key_callback(GLFWwindow window, int key, int action) { char buffer[4096]; size_t size; + printf("Paste test.\n"); + size = glfwGetClipboardData(buffer, sizeof(buffer), GLFW_CLIPBOARD_FORMAT_STRING); if (size >= sizeof(buffer)) - { printf("Buffer wasn't big enough to hold clipboard data.\n"); - } + printf("[%lu]: %s\n", (unsigned long) size, buffer); } break; From 2ad5764f0627b6a949ac7e69f21f177a5d58db0b Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Thu, 29 Mar 2012 13:44:55 +0200 Subject: [PATCH 13/37] Formatting. --- tests/clipboard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/clipboard.c b/tests/clipboard.c index 0065e0a6..1960d6ec 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -55,6 +55,7 @@ static void key_callback(GLFWwindow window, int key, int action) case GLFW_KEY_ESCAPE: glfwCloseWindow(window); break; + case GLFW_KEY_V: if (control_is_down(window)) { @@ -70,6 +71,7 @@ static void key_callback(GLFWwindow window, int key, int action) printf("[%lu]: %s\n", (unsigned long) size, buffer); } break; + case GLFW_KEY_C: if (control_is_down(window)) { From d55616661d7a2b27807fe94c37dfcb546fa42f0d Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 15:00:52 +0200 Subject: [PATCH 14/37] Removed support for primary and secondary selections. --- src/x11_clipboard.c | 41 ++++++++++++++++------------------------- src/x11_init.c | 8 ++------ src/x11_platform.h | 8 +------- 3 files changed, 19 insertions(+), 38 deletions(-) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index 71f2f7c9..a0640873 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -142,8 +142,7 @@ void _glfwPlatformSetClipboardData(void *data, size_t size, int format) 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.X11.selection.atom, _glfwLibrary.activeWindow->X11.handle, CurrentTime); XFlush(_glfwLibrary.X11.display); } @@ -162,44 +161,36 @@ size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) // 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++) + for ( ; xfmt != xfmtend; xfmt++) { - for ( ; xfmt != xfmtend; xfmt++) - { - // Specify the format we would like. - _glfwLibrary.X11.selection.request = *xfmt; + // 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); + // Convert the selection into a format we would like. + XConvertSelection(_glfwLibrary.X11.display, + _glfwLibrary.X11.selection.atom, + *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; - } + // Process pending events until we get a SelectionNotify. + while (!_glfwLibrary.X11.selection.converted) + _glfwPlatformWaitEvents(); // Successful? if (_glfwLibrary.X11.selection.converted == 1) - { - _glfwLibrary.X11.selection.converted = 0; 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) { diff --git a/src/x11_init.c b/src/x11_init.c index 8b832d52..f9adc7f5 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -456,13 +456,9 @@ static GLboolean initDisplay(void) // the keyboard mapping. updateKeyCodeLUT(); - // Find or create clipboard atoms - _glfwLibrary.X11.selection.atoms.clipboard[_GLFW_CLIPBOARD_ATOM_PRIMARY] = - XA_PRIMARY; - _glfwLibrary.X11.selection.atoms.clipboard[_GLFW_CLIPBOARD_ATOM_CLIPBOARD] = + // Find or create clipboard atom + _glfwLibrary.X11.selection.atom = XInternAtom(_glfwLibrary.X11.display, "CLIPBOARD", False); - _glfwLibrary.X11.selection.atoms.clipboard[_GLFW_CLIPBOARD_ATOM_SECONDARY] = - XA_SECONDARY; // Find or create selection atoms _glfwLibrary.X11.selection.atoms.string[_GLFW_STRING_ATOM_UTF8] = diff --git a/src/x11_platform.h b/src/x11_platform.h index 2e6bbc21..163fcd19 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -85,12 +85,6 @@ #define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryX11 X11 #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX GLX -// Clipboard atoms -#define _GLFW_CLIPBOARD_ATOM_PRIMARY 0 -#define _GLFW_CLIPBOARD_ATOM_CLIPBOARD 1 -#define _GLFW_CLIPBOARD_ATOM_SECONDARY 2 -#define _GLFW_CLIPBOARD_ATOM_COUNT 3 - // String atoms #define _GLFW_STRING_ATOM_UTF8 0 #define _GLFW_STRING_ATOM_COMPOUND 1 @@ -236,8 +230,8 @@ typedef struct _GLFWlibraryX11 // Selection data struct { + Atom atom; struct { - Atom clipboard[_GLFW_CLIPBOARD_ATOM_COUNT]; Atom string[_GLFW_STRING_ATOM_COUNT]; } atoms; struct { From 508207ae04b06bee853adfba89033e8e95349662 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 15:04:14 +0200 Subject: [PATCH 15/37] Removed superfluous function. --- src/x11_clipboard.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index a0640873..ab2a5c1d 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -37,23 +37,6 @@ #include -//======================================================================== -// Get the corresponding X11 format for a given GLFW format. -//======================================================================== - -static Atom* getInternalFormat(int format) -{ - // Get the necessary atoms - switch (format) - { - case GLFW_CLIPBOARD_FORMAT_STRING: - return _glfwLibrary.X11.selection.atoms.string; - default: - return 0; - } -} - - ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// @@ -161,7 +144,7 @@ size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) // Try different clipboards and formats that relate to the GLFW // format with preference for more appropriate formats first - Atom *xfmt = getInternalFormat(format); + Atom *xfmt = _glfwLibrary.X11.selection.atoms.string; Atom *xfmtend = xfmt + _GLFW_STRING_ATOM_COUNT; // Get the currently active window From 168aba78d4f8f6cd7058627c9095b33ef056c393 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 15:12:59 +0200 Subject: [PATCH 16/37] Formatting. --- src/x11_clipboard.c | 69 +++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index ab2a5c1d..c46b0dd1 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -47,31 +47,33 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent* request) { - Atom* atoms = _glfwLibrary.X11.selection.atoms.string; + Atom* formats = _glfwLibrary.X11.selection.atoms.string; + char* target = _glfwLibrary.X11.selection.clipboard.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); + request->requestor, + request->target, + request->target, + 8, + PropModeReplace, + (unsigned char*) target, + 8); } - else if (request->target == atoms[_GLFW_STRING_ATOM_COMPOUND] || - request->target == atoms[_GLFW_STRING_ATOM_UTF8]) + else if (request->target == formats[_GLFW_STRING_ATOM_COMPOUND] || + request->target == formats[_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); + request->requestor, + request->target, + request->target, + 8, + PropModeReplace, + (unsigned char*) target, + _glfwLibrary.X11.selection.clipboard.stringlen); } else { @@ -91,14 +93,14 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent* request) // Set the clipboard contents //======================================================================== -void _glfwPlatformSetClipboardData(void *data, size_t size, int format) +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); + char* cb = malloc(size + 1); // Copy the clipboard data memcpy(cb, data, size); @@ -135,10 +137,10 @@ void _glfwPlatformSetClipboardData(void *data, size_t size, int format) // Return the current clipboard contents //======================================================================== -size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) +size_t _glfwPlatformGetClipboardData(void* data, size_t size, int format) { size_t len, rembytes, dummy; - unsigned char *d; + unsigned char* d; int fmt; Atom type; @@ -158,7 +160,7 @@ size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) // Convert the selection into a format we would like. XConvertSelection(_glfwLibrary.X11.display, _glfwLibrary.X11.selection.atom, - *xfmt, None, window, CurrentTime); + *xfmt, None, window, CurrentTime); XFlush(_glfwLibrary.X11.display); // Process pending events until we get a SelectionNotify. @@ -200,20 +202,31 @@ size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) // 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); + 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; + size_t s; + + if (rembytes < size - 1) + s = rembytes; + else + s = size - 1; // Copy the data out. memcpy(data, d, s); // Null-terminate strings. if (format == GLFW_CLIPBOARD_FORMAT_STRING) - ((char *)data)[s] = '\0'; + ((char*) data)[s] = '\0'; // Free the data allocated using X11. XFree(d); From 3252829fe007ac27aab89d6a3aad571a9f1af079 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 15:16:56 +0200 Subject: [PATCH 17/37] Replaced iterators with index. --- src/x11_clipboard.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index c46b0dd1..c5d00deb 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -141,26 +141,23 @@ size_t _glfwPlatformGetClipboardData(void* data, size_t size, int format) { size_t len, rembytes, dummy; unsigned char* d; - int fmt; + int i, fmt; Atom type; - // Try different clipboards and formats that relate to the GLFW - // format with preference for more appropriate formats first - Atom *xfmt = _glfwLibrary.X11.selection.atoms.string; - Atom *xfmtend = xfmt + _GLFW_STRING_ATOM_COUNT; - // Get the currently active window Window window = _glfwLibrary.activeWindow->X11.handle; - for ( ; xfmt != xfmtend; xfmt++) + for (i = 0; i < _GLFW_STRING_ATOM_COUNT; i++) { // Specify the format we would like. - _glfwLibrary.X11.selection.request = *xfmt; + _glfwLibrary.X11.selection.request = + _glfwLibrary.X11.selection.atoms.strings[i]; // Convert the selection into a format we would like. XConvertSelection(_glfwLibrary.X11.display, _glfwLibrary.X11.selection.atom, - *xfmt, None, window, CurrentTime); + _glfwLibrary.X11.selection.request, + None, window, CurrentTime); XFlush(_glfwLibrary.X11.display); // Process pending events until we get a SelectionNotify. @@ -190,7 +187,7 @@ size_t _glfwPlatformGetClipboardData(void* data, size_t size, int format) // Check the length of data to receive (rembytes) XGetWindowProperty(_glfwLibrary.X11.display, window, - *xfmt, + _glfwLibrary.X11.selection.request, 0, 0, 0, AnyPropertyType, @@ -204,7 +201,7 @@ size_t _glfwPlatformGetClipboardData(void* data, size_t size, int format) { int result = XGetWindowProperty(_glfwLibrary.X11.display, window, - *xfmt, + _glfwLibrary.X11.selection.request, 0, rembytes, 0, AnyPropertyType, From b8676f01db7fd42b3127b21593bec6c7198fe378 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 15:21:54 +0200 Subject: [PATCH 18/37] Clarified clipboard format atom use. --- src/x11_clipboard.c | 10 +++++----- src/x11_init.c | 7 ++++--- src/x11_platform.h | 14 ++++++-------- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index c5d00deb..56d71904 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -47,7 +47,7 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent* request) { - Atom* formats = _glfwLibrary.X11.selection.atoms.string; + Atom* formats = _glfwLibrary.X11.selection.formats; char* target = _glfwLibrary.X11.selection.clipboard.string; if (request->target == XA_STRING) @@ -63,8 +63,8 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent* request) (unsigned char*) target, 8); } - else if (request->target == formats[_GLFW_STRING_ATOM_COMPOUND] || - request->target == formats[_GLFW_STRING_ATOM_UTF8]) + else if (request->target == formats[_GLFW_CLIPBOARD_FORMAT_COMPOUND] || + request->target == formats[_GLFW_CLIPBOARD_FORMAT_UTF8]) { XChangeProperty(_glfwLibrary.X11.display, request->requestor, @@ -147,11 +147,11 @@ size_t _glfwPlatformGetClipboardData(void* data, size_t size, int format) // Get the currently active window Window window = _glfwLibrary.activeWindow->X11.handle; - for (i = 0; i < _GLFW_STRING_ATOM_COUNT; i++) + for (i = 0; i < _GLFW_CLIPBOARD_FORMAT_COUNT; i++) { // Specify the format we would like. _glfwLibrary.X11.selection.request = - _glfwLibrary.X11.selection.atoms.strings[i]; + _glfwLibrary.X11.selection.formats[i]; // Convert the selection into a format we would like. XConvertSelection(_glfwLibrary.X11.display, diff --git a/src/x11_init.c b/src/x11_init.c index f9adc7f5..dbadc916 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -461,11 +461,12 @@ static GLboolean initDisplay(void) XInternAtom(_glfwLibrary.X11.display, "CLIPBOARD", False); // Find or create selection atoms - _glfwLibrary.X11.selection.atoms.string[_GLFW_STRING_ATOM_UTF8] = + _glfwLibrary.X11.selection.formats[_GLFW_CLIPBOARD_FORMAT_UTF8] = XInternAtom(_glfwLibrary.X11.display, "UTF8_STRING", False); - _glfwLibrary.X11.selection.atoms.string[_GLFW_STRING_ATOM_COMPOUND] = + _glfwLibrary.X11.selection.formats[_GLFW_CLIPBOARD_FORMAT_COMPOUND] = XInternAtom(_glfwLibrary.X11.display, "COMPOUND_STRING", False); - _glfwLibrary.X11.selection.atoms.string[_GLFW_STRING_ATOM_STRING] = XA_STRING; + _glfwLibrary.X11.selection.formats[_GLFW_CLIPBOARD_FORMAT_STRING] = + XA_STRING; return GL_TRUE; } diff --git a/src/x11_platform.h b/src/x11_platform.h index 163fcd19..0bb4c6c4 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -85,11 +85,11 @@ #define _GLFW_PLATFORM_LIBRARY_STATE _GLFWlibraryX11 X11 #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX GLX -// String atoms -#define _GLFW_STRING_ATOM_UTF8 0 -#define _GLFW_STRING_ATOM_COMPOUND 1 -#define _GLFW_STRING_ATOM_STRING 2 -#define _GLFW_STRING_ATOM_COUNT 3 +// Clipboard format atom indices +#define _GLFW_CLIPBOARD_FORMAT_UTF8 0 +#define _GLFW_CLIPBOARD_FORMAT_COMPOUND 1 +#define _GLFW_CLIPBOARD_FORMAT_STRING 2 +#define _GLFW_CLIPBOARD_FORMAT_COUNT 3 //======================================================================== // GLFW platform specific types @@ -231,9 +231,7 @@ typedef struct _GLFWlibraryX11 // Selection data struct { Atom atom; - struct { - Atom string[_GLFW_STRING_ATOM_COUNT]; - } atoms; + Atom formats[_GLFW_CLIPBOARD_FORMAT_COUNT]; struct { size_t stringlen; char *string; From fcd67c69ec956987e6f8e6f88368872a3e037fcc Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 15:27:32 +0200 Subject: [PATCH 19/37] Simplified clipboard cache layout. --- src/x11_clipboard.c | 12 ++++++------ src/x11_init.c | 4 ++-- src/x11_platform.h | 6 ++---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index 56d71904..e260e7cb 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -48,7 +48,7 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent* request) { Atom* formats = _glfwLibrary.X11.selection.formats; - char* target = _glfwLibrary.X11.selection.clipboard.string; + char* target = _glfwLibrary.X11.selection.string; if (request->target == XA_STRING) { @@ -73,7 +73,7 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent* request) 8, PropModeReplace, (unsigned char*) target, - _glfwLibrary.X11.selection.clipboard.stringlen); + _glfwLibrary.X11.selection.stringLength); } else { @@ -106,14 +106,14 @@ void _glfwPlatformSetClipboardData(void* data, size_t size, int format) memcpy(cb, data, size); // Set the string length - _glfwLibrary.X11.selection.clipboard.stringlen = size; + _glfwLibrary.X11.selection.stringLength = size; // Check if existing clipboard memory needs to be freed - if (_glfwLibrary.X11.selection.clipboard.string) - free(_glfwLibrary.X11.selection.clipboard.string); + if (_glfwLibrary.X11.selection.string) + free(_glfwLibrary.X11.selection.string); // Now set the clipboard (awaiting the event SelectionRequest) - _glfwLibrary.X11.selection.clipboard.string = cb; + _glfwLibrary.X11.selection.string = cb; break; } diff --git a/src/x11_init.c b/src/x11_init.c index dbadc916..a702ad19 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -632,8 +632,8 @@ int _glfwPlatformTerminate(void) #endif // Free clipboard memory - if (_glfwLibrary.X11.selection.clipboard.string) - free(_glfwLibrary.X11.selection.clipboard.string); + if (_glfwLibrary.X11.selection.string) + free(_glfwLibrary.X11.selection.string); return GL_TRUE; } diff --git a/src/x11_platform.h b/src/x11_platform.h index 0bb4c6c4..19447d47 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -232,10 +232,8 @@ typedef struct _GLFWlibraryX11 struct { Atom atom; Atom formats[_GLFW_CLIPBOARD_FORMAT_COUNT]; - struct { - size_t stringlen; - char *string; - } clipboard; + size_t stringLength; + char* string; Atom request; int converted; } selection; From 2bc8d442f4807bd985b7d6038487a8991b350391 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 15:36:39 +0200 Subject: [PATCH 20/37] Formatting. --- include/GL/glfw3.h | 4 ++-- src/clipboard.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index f87be382..a7449099 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -581,8 +581,8 @@ GLFWAPI int glfwGetJoystickPos(int joy, float* pos, int numaxes); GLFWAPI int glfwGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons); /* Clipboard */ -GLFWAPI void glfwSetClipboardData(void *data, size_t size, int format); -GLFWAPI size_t glfwGetClipboardData(void *data, size_t size, int format); +GLFWAPI void glfwSetClipboardData(void* data, size_t size, int format); +GLFWAPI size_t glfwGetClipboardData(void* data, size_t size, int format); /* Time */ GLFWAPI double glfwGetTime(void); diff --git a/src/clipboard.c b/src/clipboard.c index 480bad8e..0f1889c3 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -41,7 +41,7 @@ // Set the clipboard contents //======================================================================== -GLFWAPI void glfwSetClipboardData(void *data, size_t size, int format) +GLFWAPI void glfwSetClipboardData(void* data, size_t size, int format) { if (!_glfwInitialized) { @@ -60,7 +60,7 @@ GLFWAPI void glfwSetClipboardData(void *data, size_t size, int format) // Return the current clipboard contents //======================================================================== -GLFWAPI size_t glfwGetClipboardData(void *data, size_t size, int format) +GLFWAPI size_t glfwGetClipboardData(void* data, size_t size, int format) { if (!_glfwInitialized) { From 490c472328ad625e3476f3bb127defdf8cadeb7d Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 15:38:26 +0200 Subject: [PATCH 21/37] Removed unused error. --- include/GL/glfw3.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index a7449099..e2f25901 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -462,7 +462,6 @@ extern "C" { #define GLFW_PLATFORM_ERROR 0x00070008 #define GLFW_WINDOW_NOT_ACTIVE 0x00070009 #define GLFW_CLIPBOARD_FORMAT_UNAVAILABLE 0x00070010 -#define GLFW_CLIPBOARD_CANNOT_OWN 0x00070011 /* Gamma ramps */ #define GLFW_GAMMA_RAMP_SIZE 256 From 7044ed6f06a042eba8e694ba9f14812a35040fce Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 15:54:36 +0200 Subject: [PATCH 22/37] Simplified and made clipboard API more type safe. --- include/GL/glfw3.h | 10 +++------- src/clipboard.c | 16 +++++----------- src/internal.h | 4 ++-- src/x11_clipboard.c | 45 +++++++++++++++++---------------------------- tests/clipboard.c | 8 ++++---- 5 files changed, 31 insertions(+), 52 deletions(-) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index e2f25901..d7be4fd2 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -461,15 +461,11 @@ extern "C" { #define GLFW_VERSION_UNAVAILABLE 0x00070007 #define GLFW_PLATFORM_ERROR 0x00070008 #define GLFW_WINDOW_NOT_ACTIVE 0x00070009 -#define GLFW_CLIPBOARD_FORMAT_UNAVAILABLE 0x00070010 +#define GLFW_FORMAT_UNAVAILABLE 0x0007000A /* Gamma ramps */ #define GLFW_GAMMA_RAMP_SIZE 256 -/* Clipboard formats */ -#define GLFW_CLIPBOARD_FORMAT_NONE 0 -#define GLFW_CLIPBOARD_FORMAT_STRING 1 - /************************************************************************* * Typedefs *************************************************************************/ @@ -580,8 +576,8 @@ GLFWAPI int glfwGetJoystickPos(int joy, float* pos, int numaxes); GLFWAPI int glfwGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons); /* Clipboard */ -GLFWAPI void glfwSetClipboardData(void* data, size_t size, int format); -GLFWAPI size_t glfwGetClipboardData(void* data, size_t size, int format); +GLFWAPI void glfwSetClipboardString(const char* data); +GLFWAPI size_t glfwGetClipboardString(char* data, size_t size); /* Time */ GLFWAPI double glfwGetTime(void); diff --git a/src/clipboard.c b/src/clipboard.c index 0f1889c3..a816ebb0 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -41,7 +41,7 @@ // Set the clipboard contents //======================================================================== -GLFWAPI void glfwSetClipboardData(void* data, size_t size, int format) +GLFWAPI void glfwSetClipboardString(const char* string) { if (!_glfwInitialized) { @@ -49,10 +49,7 @@ GLFWAPI void glfwSetClipboardData(void* data, size_t size, int format) return; } - if (format == GLFW_CLIPBOARD_FORMAT_NONE) - return; - - _glfwPlatformSetClipboardData(data, size, format); + _glfwPlatformSetClipboardString(string); } @@ -60,7 +57,7 @@ GLFWAPI void glfwSetClipboardData(void* data, size_t size, int format) // Return the current clipboard contents //======================================================================== -GLFWAPI size_t glfwGetClipboardData(void* data, size_t size, int format) +GLFWAPI size_t glfwGetClipboardString(char* string, size_t size) { if (!_glfwInitialized) { @@ -68,12 +65,9 @@ GLFWAPI size_t glfwGetClipboardData(void* data, size_t size, int format) return 0; } - if (format == GLFW_CLIPBOARD_FORMAT_NONE) + if (!string || !size) return 0; - if (!data || !size) - return 0; - - return _glfwPlatformGetClipboardData(data, size, format); + return _glfwPlatformGetClipboardString(string, size); } diff --git a/src/internal.h b/src/internal.h index c16fc03f..2e0b9c38 100644 --- a/src/internal.h +++ b/src/internal.h @@ -289,8 +289,8 @@ void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp); void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp); // Clipboard -void _glfwPlatformSetClipboardData(void *data, size_t size, int format); -size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format); +void _glfwPlatformSetClipboardString(const char* string); +size_t _glfwPlatformGetClipboardString(char *data, size_t size); // Joystick int _glfwPlatformGetJoystickParam(int joy, int param); diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index e260e7cb..b733b486 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -93,35 +93,25 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent* request) // Set the clipboard contents //======================================================================== -void _glfwPlatformSetClipboardData(void* data, size_t size, int format) +void _glfwPlatformSetClipboardString(const char* string) { - switch (format) - { - case GLFW_CLIPBOARD_FORMAT_STRING: - { - // Allocate memory to keep track of the clipboard - char* cb = malloc(size + 1); + size_t size = strlen(string) + 1; - // Copy the clipboard data - memcpy(cb, data, size); + // Allocate memory to keep track of the clipboard + char* cb = malloc(size); - // Set the string length - _glfwLibrary.X11.selection.stringLength = size; + // Copy the clipboard data + memcpy(cb, string, size); - // Check if existing clipboard memory needs to be freed - if (_glfwLibrary.X11.selection.string) - free(_glfwLibrary.X11.selection.string); + // Set the string length + _glfwLibrary.X11.selection.stringLength = size; - // Now set the clipboard (awaiting the event SelectionRequest) - _glfwLibrary.X11.selection.string = cb; - break; - } + // Check if existing clipboard memory needs to be freed + if (_glfwLibrary.X11.selection.string) + free(_glfwLibrary.X11.selection.string); - default: - _glfwSetError(GLFW_CLIPBOARD_FORMAT_UNAVAILABLE, - "X11/GLX: Unavailable clipboard format"); - return; - } + // 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, @@ -137,7 +127,7 @@ void _glfwPlatformSetClipboardData(void* data, size_t size, int format) // Return the current clipboard contents //======================================================================== -size_t _glfwPlatformGetClipboardData(void* data, size_t size, int format) +size_t _glfwPlatformGetClipboardString(char* data, size_t size) { size_t len, rembytes, dummy; unsigned char* d; @@ -176,8 +166,8 @@ size_t _glfwPlatformGetClipboardData(void* data, size_t size, int format) // Unsuccessful conversion, bail with no clipboard data if (_glfwLibrary.X11.selection.converted) { - _glfwSetError(GLFW_CLIPBOARD_FORMAT_UNAVAILABLE, - "X11/GLX: Unavailable clipboard format"); + _glfwSetError(GLFW_FORMAT_UNAVAILABLE, + "X11/GLX: Failed to convert selection to string"); return 0; } @@ -222,8 +212,7 @@ size_t _glfwPlatformGetClipboardData(void* data, size_t size, int format) memcpy(data, d, s); // Null-terminate strings. - if (format == GLFW_CLIPBOARD_FORMAT_STRING) - ((char*) data)[s] = '\0'; + ((char*) data)[s] = '\0'; // Free the data allocated using X11. XFree(d); diff --git a/tests/clipboard.c b/tests/clipboard.c index 1960d6ec..ac83448b 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -64,7 +64,7 @@ static void key_callback(GLFWwindow window, int key, int action) printf("Paste test.\n"); - size = glfwGetClipboardData(buffer, sizeof(buffer), GLFW_CLIPBOARD_FORMAT_STRING); + size = glfwGetClipboardString(buffer, sizeof(buffer)); if (size >= sizeof(buffer)) printf("Buffer wasn't big enough to hold clipboard data.\n"); @@ -75,9 +75,9 @@ static void key_callback(GLFWwindow window, int key, int action) case GLFW_KEY_C: if (control_is_down(window)) { - glfwSetClipboardData("Hello GLFW World!", sizeof("Hello GLFW World!"), - GLFW_CLIPBOARD_FORMAT_STRING); - printf("Setting clipboard to: %s\n", "Hello GLFW World!"); + const char* string = "Hello GLFW World!"; + glfwSetClipboardString(string); + printf("Setting clipboard to: %s\n", string); } break; } From bf1ada029b9032249dcc4d5af605fbefbfeb68d3 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 16:00:54 +0200 Subject: [PATCH 23/37] Added window parameter to clipboard API. --- include/GL/glfw3.h | 4 ++-- src/clipboard.c | 12 ++++++++---- src/internal.h | 4 ++-- src/x11_clipboard.c | 17 +++++++---------- tests/clipboard.c | 4 ++-- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index d7be4fd2..6b1cc470 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -576,8 +576,8 @@ GLFWAPI int glfwGetJoystickPos(int joy, float* pos, int numaxes); GLFWAPI int glfwGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons); /* Clipboard */ -GLFWAPI void glfwSetClipboardString(const char* data); -GLFWAPI size_t glfwGetClipboardString(char* data, size_t size); +GLFWAPI void glfwSetClipboardString(GLFWwindow window, const char* data); +GLFWAPI size_t glfwGetClipboardString(GLFWwindow window, char* data, size_t size); /* Time */ GLFWAPI double glfwGetTime(void); diff --git a/src/clipboard.c b/src/clipboard.c index a816ebb0..b66d5656 100644 --- a/src/clipboard.c +++ b/src/clipboard.c @@ -41,15 +41,17 @@ // Set the clipboard contents //======================================================================== -GLFWAPI void glfwSetClipboardString(const char* string) +GLFWAPI void glfwSetClipboardString(GLFWwindow handle, const char* string) { + _GLFWwindow* window = (_GLFWwindow*) handle; + if (!_glfwInitialized) { _glfwSetError(GLFW_NOT_INITIALIZED, NULL); return; } - _glfwPlatformSetClipboardString(string); + _glfwPlatformSetClipboardString(window, string); } @@ -57,8 +59,10 @@ GLFWAPI void glfwSetClipboardString(const char* string) // Return the current clipboard contents //======================================================================== -GLFWAPI size_t glfwGetClipboardString(char* string, size_t size) +GLFWAPI size_t glfwGetClipboardString(GLFWwindow handle, char* string, size_t size) { + _GLFWwindow* window = (_GLFWwindow*) handle; + if (!_glfwInitialized) { _glfwSetError(GLFW_NOT_INITIALIZED, NULL); @@ -68,6 +72,6 @@ GLFWAPI size_t glfwGetClipboardString(char* string, size_t size) if (!string || !size) return 0; - return _glfwPlatformGetClipboardString(string, size); + return _glfwPlatformGetClipboardString(window, string, size); } diff --git a/src/internal.h b/src/internal.h index 2e0b9c38..407270ea 100644 --- a/src/internal.h +++ b/src/internal.h @@ -289,8 +289,8 @@ void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp); void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp); // Clipboard -void _glfwPlatformSetClipboardString(const char* string); -size_t _glfwPlatformGetClipboardString(char *data, size_t size); +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string); +size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char *data, size_t size); // Joystick int _glfwPlatformGetJoystickParam(int joy, int param); diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index b733b486..4bbfb83c 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -93,7 +93,7 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent* request) // Set the clipboard contents //======================================================================== -void _glfwPlatformSetClipboardString(const char* string) +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { size_t size = strlen(string) + 1; @@ -115,10 +115,10 @@ void _glfwPlatformSetClipboardString(const char* string) // Set the selection owner to our active window XSetSelectionOwner(_glfwLibrary.X11.display, XA_PRIMARY, - _glfwLibrary.activeWindow->X11.handle, CurrentTime); + window->X11.handle, CurrentTime); XSetSelectionOwner(_glfwLibrary.X11.display, _glfwLibrary.X11.selection.atom, - _glfwLibrary.activeWindow->X11.handle, CurrentTime); + window->X11.handle, CurrentTime); XFlush(_glfwLibrary.X11.display); } @@ -127,16 +127,13 @@ void _glfwPlatformSetClipboardString(const char* string) // Return the current clipboard contents //======================================================================== -size_t _glfwPlatformGetClipboardString(char* data, size_t size) +size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* data, size_t size) { size_t len, rembytes, dummy; unsigned char* d; int i, fmt; Atom type; - // Get the currently active window - Window window = _glfwLibrary.activeWindow->X11.handle; - for (i = 0; i < _GLFW_CLIPBOARD_FORMAT_COUNT; i++) { // Specify the format we would like. @@ -147,7 +144,7 @@ size_t _glfwPlatformGetClipboardString(char* data, size_t size) XConvertSelection(_glfwLibrary.X11.display, _glfwLibrary.X11.selection.atom, _glfwLibrary.X11.selection.request, - None, window, CurrentTime); + None, window->X11.handle, CurrentTime); XFlush(_glfwLibrary.X11.display); // Process pending events until we get a SelectionNotify. @@ -176,7 +173,7 @@ size_t _glfwPlatformGetClipboardString(char* data, size_t size) // Check the length of data to receive (rembytes) XGetWindowProperty(_glfwLibrary.X11.display, - window, + window->X11.handle, _glfwLibrary.X11.selection.request, 0, 0, 0, @@ -190,7 +187,7 @@ size_t _glfwPlatformGetClipboardString(char* data, size_t size) if (rembytes > 0) { int result = XGetWindowProperty(_glfwLibrary.X11.display, - window, + window->X11.handle, _glfwLibrary.X11.selection.request, 0, rembytes, 0, diff --git a/tests/clipboard.c b/tests/clipboard.c index ac83448b..376ebbcd 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -64,7 +64,7 @@ static void key_callback(GLFWwindow window, int key, int action) printf("Paste test.\n"); - size = glfwGetClipboardString(buffer, sizeof(buffer)); + size = glfwGetClipboardString(window, buffer, sizeof(buffer)); if (size >= sizeof(buffer)) printf("Buffer wasn't big enough to hold clipboard data.\n"); @@ -76,7 +76,7 @@ static void key_callback(GLFWwindow window, int key, int action) if (control_is_down(window)) { const char* string = "Hello GLFW World!"; - glfwSetClipboardString(string); + glfwSetClipboardString(window, string); printf("Setting clipboard to: %s\n", string); } break; From 1214fa1157e59b870d9f03845624f489dc00139d Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 16:03:14 +0200 Subject: [PATCH 24/37] Formatting. --- include/GL/glfw3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 6b1cc470..955086af 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -576,8 +576,8 @@ GLFWAPI int glfwGetJoystickPos(int joy, float* pos, int numaxes); GLFWAPI int glfwGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons); /* Clipboard */ -GLFWAPI void glfwSetClipboardString(GLFWwindow window, const char* data); -GLFWAPI size_t glfwGetClipboardString(GLFWwindow window, char* data, size_t size); +GLFWAPI void glfwSetClipboardString(GLFWwindow window, const char* string); +GLFWAPI size_t glfwGetClipboardString(GLFWwindow window, char* string, size_t size); /* Time */ GLFWAPI double glfwGetTime(void); From 877c6337c3d2034b510ccbd7de64368976d99bff Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 16:10:14 +0200 Subject: [PATCH 25/37] Updated remaining ports. --- src/cocoa_clipboard.m | 4 ++-- src/win32_clipboard.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cocoa_clipboard.m b/src/cocoa_clipboard.m index 0f78cf21..4ed01758 100644 --- a/src/cocoa_clipboard.m +++ b/src/cocoa_clipboard.m @@ -41,7 +41,7 @@ // Set the clipboard contents //======================================================================== -void _glfwPlatformSetClipboardData(void *data, size_t size, int format) +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { } @@ -49,7 +49,7 @@ void _glfwPlatformSetClipboardData(void *data, size_t size, int format) // Return the current clipboard contents //======================================================================== -size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) +size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* string, size_t size) { return 0; } diff --git a/src/win32_clipboard.c b/src/win32_clipboard.c index b16c51c4..9a05b08e 100644 --- a/src/win32_clipboard.c +++ b/src/win32_clipboard.c @@ -41,7 +41,7 @@ // Set the clipboard contents //======================================================================== -void _glfwPlatformSetClipboardData(void *data, size_t size, int format) +void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { } @@ -49,7 +49,7 @@ void _glfwPlatformSetClipboardData(void *data, size_t size, int format) // Return the current clipboard contents //======================================================================== -size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) +size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* string, size_t size) { return 0; } From 67a3f5dc8f62b65648aa4dab16baab548727daa5 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 17:41:17 +0200 Subject: [PATCH 26/37] Added error callback. --- tests/clipboard.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/clipboard.c b/tests/clipboard.c index 376ebbcd..da776e61 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -88,6 +88,11 @@ static void size_callback(GLFWwindow window, int width, int height) glViewport(0, 0, width, height); } +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s in %s\n", glfwErrorString(error), description); +} + int main(int argc, char** argv) { int ch; @@ -107,6 +112,8 @@ int main(int argc, char** argv) } } + glfwSetErrorCallback(error_callback); + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); From ad18589c6c6ffe1898c6aab5471906912c067909 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 17:45:26 +0200 Subject: [PATCH 27/37] Added initial implementation for Win32. --- src/win32_clipboard.c | 94 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/src/win32_clipboard.c b/src/win32_clipboard.c index 9a05b08e..c2888236 100644 --- a/src/win32_clipboard.c +++ b/src/win32_clipboard.c @@ -31,6 +31,7 @@ #include #include +#include ////////////////////////////////////////////////////////////////////////// @@ -43,6 +44,49 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { + WCHAR* wideString; + HANDLE stringHandle; + size_t wideSize; + + wideString = _glfwCreateWideStringFromUTF8(string); + if (!wideString) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to convert clipboard string to " + "wide string"); + return; + } + + wideSize = (wcslen(wideString) + 1) * sizeof(WCHAR); + + stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideSize); + if (!stringHandle) + { + free(wideString); + + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to allocate global handle for clipboard"); + return; + } + + memcpy(GlobalLock(stringHandle), wideString, wideSize); + GlobalUnlock(stringHandle); + + if (!OpenClipboard(window->Win32.handle)) + { + GlobalFree(stringHandle); + free(wideString); + + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to open clipboard"); + return; + } + + EmptyClipboard(); + SetClipboardData(CF_UNICODETEXT, stringHandle); + CloseClipboard(); + + free(wideString); } //======================================================================== @@ -51,6 +95,54 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* string, size_t size) { - return 0; + HANDLE stringHandle; + char* utf8String; + size_t utf8Size; + + if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) + { + _glfwSetError(GLFW_FORMAT_UNAVAILABLE, NULL); + return 0; + } + + if (!OpenClipboard(window->Win32.handle)) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to open clipboard"); + return 0; + } + + stringHandle = GetClipboardData(CF_UNICODETEXT); + if (!stringHandle) + { + CloseClipboard(); + + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to retrieve clipboard data"); + return 0; + } + + utf8String = _glfwCreateUTF8FromWideString(GlobalLock(stringHandle)); + GlobalUnlock(stringHandle); + CloseClipboard(); + + if (!utf8String) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: Failed to convert wide string to UTF-8"); + return 0; + } + + utf8Size = strlen(utf8String) + 1; + if (utf8Size > size) + { + memcpy(string, utf8String, size); + string[size - 1] = '\0'; + } + else + memcpy(string, utf8String, utf8Size); + + free(utf8String); + return utf8Size; } From ab40dab23590093f7be8a24966e9580d988f203c Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 18:00:07 +0200 Subject: [PATCH 28/37] Formatting. --- src/cocoa_clipboard.m | 1 + src/win32_clipboard.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/cocoa_clipboard.m b/src/cocoa_clipboard.m index 4ed01758..8ac64bcc 100644 --- a/src/cocoa_clipboard.m +++ b/src/cocoa_clipboard.m @@ -45,6 +45,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { } + //======================================================================== // Return the current clipboard contents //======================================================================== diff --git a/src/win32_clipboard.c b/src/win32_clipboard.c index c2888236..9b14f158 100644 --- a/src/win32_clipboard.c +++ b/src/win32_clipboard.c @@ -89,6 +89,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) free(wideString); } + //======================================================================== // Return the current clipboard contents //======================================================================== From 8fe46ac1fecaddc1554a33e3d1bff95aa23b2ef3 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 23:27:06 +0200 Subject: [PATCH 29/37] Formatting. --- src/cocoa_clipboard.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cocoa_clipboard.m b/src/cocoa_clipboard.m index 8ac64bcc..e43e9906 100644 --- a/src/cocoa_clipboard.m +++ b/src/cocoa_clipboard.m @@ -52,6 +52,6 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* string, size_t size) { - return 0; + return 0; } From 3bd54e0b60dcfeb10826f155d0cea1b19912d14c Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 23:55:44 +0200 Subject: [PATCH 30/37] Added inclusion of declaration of size_t. --- include/GL/glfw3.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 955086af..32c3899a 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -173,6 +173,10 @@ extern "C" { #endif #endif +/* This is needed for the declaration of size_t. + */ +#include + /************************************************************************* * GLFW version From 83901218698a708ef6284d967a757bf9c5f6c068 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 9 Apr 2012 23:56:14 +0200 Subject: [PATCH 31/37] Fixed legacy C warnings. --- src/cocoa_joystick.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m index b3bd6e41..97510fdf 100644 --- a/src/cocoa_joystick.m +++ b/src/cocoa_joystick.m @@ -572,7 +572,7 @@ int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes) int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons) { - int button; + int i, j, button; if (joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_LAST) return 0; @@ -599,13 +599,13 @@ int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; // Bit fields of button presses for each direction, including nil - for (int i = 0; i < joystick.numHats; i++) + for (i = 0; i < joystick.numHats; i++) { _glfwJoystickElement* hat = (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick.hats, i); int value = hat->value; if (value < 0 || value > 8) value = 8; - for (int j = 0; j < 4 && button < numbuttons; j++) + for (j = 0; j < 4 && button < numbuttons; j++) { buttons[button++] = directions[value] & (1 << j) ? GLFW_PRESS : GLFW_RELEASE; } From 15e8af1f79337ed3802aefd72ef57f8b0e92244e Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Tue, 10 Apr 2012 00:34:08 +0200 Subject: [PATCH 32/37] Added initial implementation for Cocoa. --- src/cocoa_clipboard.m | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/cocoa_clipboard.m b/src/cocoa_clipboard.m index e43e9906..e52b839e 100644 --- a/src/cocoa_clipboard.m +++ b/src/cocoa_clipboard.m @@ -43,6 +43,12 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { + NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil]; + + NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + [pasteboard declareTypes:types owner:nil]; + [pasteboard setString:[NSString stringWithUTF8String:string] + forType:NSStringPboardType]; } @@ -52,6 +58,30 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* string, size_t size) { + const char* source; + size_t targetSize; + NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + + if (![[pasteboard types] containsObject:NSStringPboardType]) + { + _glfwSetError(GLFW_FORMAT_UNAVAILABLE, NULL); + return 0; + } + + NSString* object = [pasteboard stringForType:NSStringPboardType]; + if (!object) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "Cocoa/NSGL: Failed to retrieve object from pasteboard"); + return 0; + } + + source = [object UTF8String]; + targetSize = strlen(source) + 1; + if (targetSize > size) + targetSize = size; + + strlcpy(string, source, targetSize); return 0; } From 0ee55ab8e5c947f92284ed26e012baa0b33cf583 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Tue, 10 Apr 2012 00:37:53 +0200 Subject: [PATCH 33/37] Updated change log, added credit. --- readme.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readme.html b/readme.html index 3e0966c0..e890f955 100644 --- a/readme.html +++ b/readme.html @@ -271,6 +271,7 @@ version of GLFW.

  • Added glfwGetWindowPos function for querying the position of the specified window
  • Added glfwSetWindowFocusCallback function and GLFWwindowfocusfun type for receiving window focus events
  • Added glfwSetWindowIconifyCallback function and GLFWwindowiconifyfun type for receiving window iconification events
  • +
  • Added glfwGetClipboardString and glfwSetClipboardString functions for interacting with the system clipboard
  • Added glfwGetCurrentContext function for retrieving the window whose OpenGL context is current
  • Added glfwCopyContext function for copying OpenGL state categories between contexts
  • Added GLFW_OPENGL_ES2_PROFILE profile for creating OpenGL ES 2.0 contexts using the GLX_EXT_create_context_es2_profile and WGL_EXT_create_context_es2_profile extensions
  • @@ -844,7 +845,7 @@ their skills. Special thanks go out to:

    adding logic for the GLFW_ICON resource
  • Ralph Eastwood, for the initial design and implementation of the gamma - correction API
  • + correction and clipboard APIs
  • GeO4d, for the implementation of cursor enter/leave notifications on Win32.
  • From 0e9e37bfc451e35ba39b6de231aed84a44dd6823 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Tue, 10 Apr 2012 00:52:21 +0200 Subject: [PATCH 34/37] Simplified string storage. --- src/x11_clipboard.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index 4bbfb83c..37d002b5 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -97,21 +97,11 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { 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 + // Store the new string in preparation for a request event + free(_glfwLibrary.X11.selection.string); + _glfwLibrary.X11.selection.string = malloc(size); _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; + memcpy(_glfwLibrary.X11.selection.string, string, size); // Set the selection owner to our active window XSetSelectionOwner(_glfwLibrary.X11.display, XA_PRIMARY, From e0c4d81e46e9a604b7d3064dd8c7dfb2c1c34ddd Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Tue, 10 Apr 2012 01:15:50 +0200 Subject: [PATCH 35/37] Added function for processing only pending events. --- src/x11_clipboard.c | 7 +++---- src/x11_platform.h | 3 +++ src/x11_window.c | 19 ++++++++++++++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index 37d002b5..cd0b5976 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -135,11 +135,10 @@ size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* data, size_t s _glfwLibrary.X11.selection.atom, _glfwLibrary.X11.selection.request, None, window->X11.handle, CurrentTime); - XFlush(_glfwLibrary.X11.display); - // Process pending events until we get a SelectionNotify. - while (!_glfwLibrary.X11.selection.converted) - _glfwPlatformWaitEvents(); + // Process the resulting SelectionNotify event + XSync(_glfwLibrary.X11.display, False); + _glfwProcessPendingEvents(); // Successful? if (_glfwLibrary.X11.selection.converted == 1) diff --git a/src/x11_platform.h b/src/x11_platform.h index f3c4dd35..8de54ead 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -283,4 +283,7 @@ long _glfwKeySym2Unicode(KeySym keysym); // Clipboard handling Atom _glfwSelectionRequest(XSelectionRequestEvent *request); +// Event processing +void _glfwProcessPendingEvents(void); + #endif // _platform_h_ diff --git a/src/x11_window.c b/src/x11_window.c index 57871d65..854480c5 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1299,6 +1299,23 @@ static void processSingleEvent(void) } +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Processes all pending events +//======================================================================== + +void _glfwProcessPendingEvents(void) +{ + int i, count = XPending(_glfwLibrary.X11.display); + + for (i = 0; i < count; i++) + processSingleEvent(); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -1369,7 +1386,7 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, } // Process the window map event and any other that may have arrived - _glfwPlatformPollEvents(); + _glfwProcessPendingEvents(); // Retrieve and set initial cursor position { From ad48c0e5ef7d61fc76754d62bad32d3ba0970368 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Tue, 10 Apr 2012 18:22:15 +0200 Subject: [PATCH 36/37] Added string for new error. --- src/error.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/error.c b/src/error.c index 2b46a72c..062fb76a 100644 --- a/src/error.c +++ b/src/error.c @@ -109,6 +109,8 @@ GLFWAPI const char* glfwErrorString(int error) return "A platform-specific error occurred"; case GLFW_WINDOW_NOT_ACTIVE: return "The specified window is not active"; + case GLFW_FORMAT_UNAVAILABLE: + return "The requested format is unavailable"; } return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString"; From f231ed37f007e482e8f5f5d77e1ff161fe338ad6 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Wed, 11 Apr 2012 23:32:50 +0200 Subject: [PATCH 37/37] Re-worked and fixed X11 clipboard support. --- src/x11_clipboard.c | 214 ++++++++++++++++++++------------------------ src/x11_init.c | 10 ++- src/x11_platform.h | 16 +++- src/x11_window.c | 39 +++++--- 4 files changed, 144 insertions(+), 135 deletions(-) diff --git a/src/x11_clipboard.c b/src/x11_clipboard.c index cd0b5976..1b9e1fa3 100644 --- a/src/x11_clipboard.c +++ b/src/x11_clipboard.c @@ -27,8 +27,6 @@ // //======================================================================== -// TODO: Incremental support? Overkill perhaps. - #include "internal.h" #include @@ -42,46 +40,90 @@ ////////////////////////////////////////////////////////////////////////// //======================================================================== -// X11 selection request event +// Save the contents of the specified property //======================================================================== -Atom _glfwSelectionRequest(XSelectionRequestEvent* request) +GLboolean _glfwReadSelection(XSelectionEvent* request) { - Atom* formats = _glfwLibrary.X11.selection.formats; - char* target = _glfwLibrary.X11.selection.string; + Atom actualType; + int actualFormat; + unsigned long itemCount, bytesAfter; + char* data; - if (request->target == XA_STRING) + if (request->property == None) + return GL_FALSE; + + XGetWindowProperty(_glfwLibrary.X11.display, + request->requestor, + request->property, + 0, LONG_MAX, + False, + request->target, + &actualType, + &actualFormat, + &itemCount, + &bytesAfter, + (unsigned char**) &data); + + if (actualType == None) + return GL_FALSE; + + free(_glfwLibrary.X11.selection.string); + _glfwLibrary.X11.selection.string = strdup(data); + + XFree(data); + return GL_TRUE; +} + + +//======================================================================== +// Set the specified property to the contents of the requested selection +//======================================================================== + +Atom _glfwWriteSelection(XSelectionRequestEvent* request) +{ + int i; + Atom property = request->property; + + if (property == None) + property = _glfwLibrary.X11.selection.property; + + if (request->target == _glfwLibrary.X11.selection.targets) { - // TODO: ISO Latin-1 specific characters don't get converted - // (yet). For cleanliness, would we need something like iconv? + // The list of supported targets was requested + XChangeProperty(_glfwLibrary.X11.display, request->requestor, - request->target, - request->target, - 8, + property, + XA_ATOM, + 32, PropModeReplace, - (unsigned char*) target, - 8); - } - else if (request->target == formats[_GLFW_CLIPBOARD_FORMAT_COMPOUND] || - request->target == formats[_GLFW_CLIPBOARD_FORMAT_UTF8]) - { - XChangeProperty(_glfwLibrary.X11.display, - request->requestor, - request->target, - request->target, - 8, - PropModeReplace, - (unsigned char*) target, - _glfwLibrary.X11.selection.stringLength); - } - else - { - // TODO: Should we set an error? Probably not. - return None; + (unsigned char*) _glfwLibrary.X11.selection.formats, + _GLFW_CLIPBOARD_FORMAT_COUNT); + + return property; } - return request->target; + for (i = 0; i < _GLFW_CLIPBOARD_FORMAT_COUNT; i++) + { + if (request->target == _glfwLibrary.X11.selection.formats[i]) + { + // The requested format is one we support + + XChangeProperty(_glfwLibrary.X11.display, + request->requestor, + property, + request->target, + 8, + PropModeReplace, + (unsigned char*) _glfwLibrary.X11.selection.string, + strlen(_glfwLibrary.X11.selection.string)); + + return property; + } + } + + return None; } @@ -95,21 +137,14 @@ Atom _glfwSelectionRequest(XSelectionRequestEvent* request) void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { - size_t size = strlen(string) + 1; - - // Store the new string in preparation for a request event + // Store the new string in preparation for a selection request event free(_glfwLibrary.X11.selection.string); - _glfwLibrary.X11.selection.string = malloc(size); - _glfwLibrary.X11.selection.stringLength = size; - memcpy(_glfwLibrary.X11.selection.string, string, size); + _glfwLibrary.X11.selection.string = strdup(string); - // Set the selection owner to our active window - XSetSelectionOwner(_glfwLibrary.X11.display, XA_PRIMARY, - window->X11.handle, CurrentTime); + // Set the specified window as owner of the selection XSetSelectionOwner(_glfwLibrary.X11.display, _glfwLibrary.X11.selection.atom, window->X11.handle, CurrentTime); - XFlush(_glfwLibrary.X11.display); } @@ -117,103 +152,50 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) // Return the current clipboard contents //======================================================================== -size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* data, size_t size) +size_t _glfwPlatformGetClipboardString(_GLFWwindow* window, char* string, size_t size) { - size_t len, rembytes, dummy; - unsigned char* d; - int i, fmt; - Atom type; + int i; + size_t sourceSize, targetSize; + + _glfwLibrary.X11.selection.status = _GLFW_CONVERSION_INACTIVE; for (i = 0; i < _GLFW_CLIPBOARD_FORMAT_COUNT; i++) { - // Specify the format we would like. - _glfwLibrary.X11.selection.request = + // Request conversion to the selected format + _glfwLibrary.X11.selection.target = _glfwLibrary.X11.selection.formats[i]; - // Convert the selection into a format we would like. XConvertSelection(_glfwLibrary.X11.display, _glfwLibrary.X11.selection.atom, - _glfwLibrary.X11.selection.request, - None, window->X11.handle, CurrentTime); + _glfwLibrary.X11.selection.target, + _glfwLibrary.X11.selection.property, + window->X11.handle, CurrentTime); // Process the resulting SelectionNotify event XSync(_glfwLibrary.X11.display, False); - _glfwProcessPendingEvents(); + while (_glfwLibrary.X11.selection.status == _GLFW_CONVERSION_INACTIVE) + _glfwPlatformWaitEvents(); - // Successful? - if (_glfwLibrary.X11.selection.converted == 1) + if (_glfwLibrary.X11.selection.status == _GLFW_CONVERSION_SUCCEEDED) 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) + if (_glfwLibrary.X11.selection.status == _GLFW_CONVERSION_FAILED) { _glfwSetError(GLFW_FORMAT_UNAVAILABLE, "X11/GLX: Failed to convert selection to string"); return 0; } - // Reset for the next selection - _glfwLibrary.X11.selection.converted = 0; + sourceSize = strlen(_glfwLibrary.X11.selection.string) + 1; - // Check the length of data to receive (rembytes) - XGetWindowProperty(_glfwLibrary.X11.display, - window->X11.handle, - _glfwLibrary.X11.selection.request, - 0, 0, - 0, - AnyPropertyType, - &type, - &fmt, - &len, &rembytes, - &d); + targetSize = sourceSize; + if (targetSize > size) + targetSize = size; - // The number of bytes remaining (which is all of them) - if (rembytes > 0) - { - int result = XGetWindowProperty(_glfwLibrary.X11.display, - window->X11.handle, - _glfwLibrary.X11.selection.request, - 0, rembytes, - 0, - AnyPropertyType, - &type, - &fmt, - &len, &dummy, - &d); - if (result == Success) - { - size_t s; + memcpy(string, _glfwLibrary.X11.selection.string, targetSize); + string[targetSize - 1] = '\0'; - if (rembytes < size - 1) - s = rembytes; - else - s = size - 1; - - // Copy the data out. - memcpy(data, d, s); - - // Null-terminate strings. - ((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; + return sourceSize; } diff --git a/src/x11_init.c b/src/x11_init.c index 535ede30..3af08cf4 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -597,11 +597,15 @@ static GLboolean initDisplay(void) // the keyboard mapping. updateKeyCodeLUT(); + // Find or create selection property atom + _glfwLibrary.X11.selection.property = + XInternAtom(_glfwLibrary.X11.display, "GLFW_SELECTION", False); + // Find or create clipboard atom _glfwLibrary.X11.selection.atom = XInternAtom(_glfwLibrary.X11.display, "CLIPBOARD", False); - // Find or create selection atoms + // Find or create selection target atoms _glfwLibrary.X11.selection.formats[_GLFW_CLIPBOARD_FORMAT_UTF8] = XInternAtom(_glfwLibrary.X11.display, "UTF8_STRING", False); _glfwLibrary.X11.selection.formats[_GLFW_CLIPBOARD_FORMAT_COMPOUND] = @@ -609,6 +613,10 @@ static GLboolean initDisplay(void) _glfwLibrary.X11.selection.formats[_GLFW_CLIPBOARD_FORMAT_STRING] = XA_STRING; + _glfwLibrary.X11.selection.targets = XInternAtom(_glfwLibrary.X11.display, + "TARGETS", + False); + return GL_TRUE; } diff --git a/src/x11_platform.h b/src/x11_platform.h index 8de54ead..2de3367e 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -91,6 +91,12 @@ #define _GLFW_CLIPBOARD_FORMAT_STRING 2 #define _GLFW_CLIPBOARD_FORMAT_COUNT 3 +// Clipboard conversion status tokens +#define _GLFW_CONVERSION_INACTIVE 0 +#define _GLFW_CONVERSION_SUCCEEDED 1 +#define _GLFW_CONVERSION_FAILED 2 + + //======================================================================== // GLFW platform specific types //======================================================================== @@ -235,10 +241,11 @@ typedef struct _GLFWlibraryX11 struct { Atom atom; Atom formats[_GLFW_CLIPBOARD_FORMAT_COUNT]; - size_t stringLength; char* string; - Atom request; - int converted; + Atom target; + Atom targets; + Atom property; + int status; } selection; #if defined(_GLFW_DLOPEN_LIBGL) @@ -281,7 +288,8 @@ void _glfwTerminateJoysticks(void); long _glfwKeySym2Unicode(KeySym keysym); // Clipboard handling -Atom _glfwSelectionRequest(XSelectionRequestEvent *request); +GLboolean _glfwReadSelection(XSelectionEvent* request); +Atom _glfwWriteSelection(XSelectionRequestEvent* request); // Event processing void _glfwProcessPendingEvents(void); diff --git a/src/x11_window.c b/src/x11_window.c index 854480c5..a84e209a 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1241,28 +1241,39 @@ static void processSingleEvent(void) break; } + case SelectionClear: + { + // The ownership of the selection was lost + + free(_glfwLibrary.X11.selection.string); + _glfwLibrary.X11.selection.string = NULL; + break; + } + case SelectionNotify: { - // Selection notification triggered by the XConvertSelection + // The selection conversion status is available - // 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; + XSelectionEvent* request = &event.xselection; + + if (_glfwReadSelection(request)) + _glfwLibrary.X11.selection.status = _GLFW_CONVERSION_SUCCEEDED; + else + _glfwLibrary.X11.selection.status = _GLFW_CONVERSION_FAILED; break; } case SelectionRequest: { - // Selection request triggered by someone wanting data from the - // X11 clipboard - XSelectionRequestEvent *request = &event.xselectionrequest; + // The contents of the selection was requested + + XSelectionRequestEvent* request = &event.xselectionrequest; - // Construct the response XEvent response; - response.xselection.property = _glfwSelectionRequest(request); + memset(&response, 0, sizeof(response)); + + response.xselection.property = _glfwWriteSelection(request); response.xselection.type = SelectionNotify; response.xselection.display = request->display; response.xselection.requestor = request->requestor; @@ -1270,9 +1281,9 @@ static void processSingleEvent(void) response.xselection.target = request->target; response.xselection.time = request->time; - // Send off the event - XSendEvent(_glfwLibrary.X11.display, request->requestor, 0, 0, &response); - + XSendEvent(_glfwLibrary.X11.display, + request->requestor, + False, 0, &response); break; }