diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index e84bdbba..5ad6f289 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -455,10 +455,16 @@ 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_CLIPBOARD_CANNOT_OWN 0x00070011 /* Gamma ramps */ #define GLFW_GAMMA_RAMP_SIZE 256 +/* Clipboard formats */ +#define GLFW_CLIPBOARD_FORMAT_NONE 0 +#define GLFW_CLIPBOARD_FORMAT_STRING 1 + /************************************************************************* * Typedefs *************************************************************************/ @@ -566,6 +572,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 b5569c40..f308c299 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,24 +15,25 @@ include_directories(${GLFW_SOURCE_DIR}/src ${GLFW_BINARY_DIR}/src ${GLFW_INCLUDE_DIR}) -set(common_SOURCES error.c fullscreen.c gamma.c init.c input.c +set(common_SOURCES clipboard.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_fullscreen.m cocoa_gamma.c - cocoa_init.m cocoa_input.m cocoa_joystick.m - cocoa_opengl.m cocoa_time.c cocoa_window.m) + set(libglfw_SOURCES ${common_SOURCES} cocoa_clipboard.m cocoa_fullscreen.m + cocoa_gamma.c cocoa_init.m cocoa_input.m + cocoa_joystick.m cocoa_opengl.m cocoa_time.c + 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_fullscreen.c win32_gamma.c - win32_init.c win32_input.c win32_joystick.c + set(libglfw_SOURCES ${common_SOURCES} win32_clipboard.c win32_fullscreen.c + win32_gamma.c win32_init.c win32_input.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_fullscreen.c x11_gamma.c - x11_init.c x11_input.c x11_joystick.c + set(libglfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_fullscreen.c + x11_gamma.c x11_init.c x11_input.c x11_joystick.c x11_keysym2unicode.c x11_opengl.c x11_time.c x11_window.c) else() diff --git a/src/clipboard.c b/src/clipboard.c new file mode 100644 index 00000000..b055c168 --- /dev/null +++ b/src/clipboard.c @@ -0,0 +1,78 @@ +//======================================================================== +// 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; + } + + if (format == GLFW_CLIPBOARD_FORMAT_NONE) + 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; + } + + if (format == GLFW_CLIPBOARD_FORMAT_NONE) + return 0; + + if (!data || !size) + 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 1f13ac02..83ab78ba 100644 --- a/src/internal.h +++ b/src/internal.h @@ -285,6 +285,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/libglfw.pc.cmake b/src/libglfw.pc.cmake index 47cfb4f5..1a712d9d 100644 --- a/src/libglfw.pc.cmake +++ b/src/libglfw.pc.cmake @@ -8,5 +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} 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..1be0ac23 --- /dev/null +++ b/src/x11_clipboard.c @@ -0,0 +1,248 @@ +//======================================================================== +// 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. +// +//======================================================================== + +// TODO: Incremental support? Overkill perhaps. + +#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.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 +//======================================================================== + +size_t _glfwPlatformGetClipboardData(void *data, size_t size, int format) +{ + size_t len, rembytes, dummy; + unsigned char *d; + int fmt; + Atom type; + + // 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++) + { + // 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; + } + + // 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 (rembytes) + 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 4d3c0f74..0c529553 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -447,6 +447,21 @@ 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.atoms.string[_GLFW_STRING_ATOM_UTF8] = + XInternAtom(_glfwLibrary.X11.display, "UTF8_STRING", False); + _glfwLibrary.X11.selection.atoms.string[_GLFW_STRING_ATOM_COMPOUND] = + XInternAtom(_glfwLibrary.X11.display, "COMPOUND_STRING", False); + _glfwLibrary.X11.selection.atoms.string[_GLFW_STRING_ATOM_STRING] = XA_STRING; + return GL_TRUE; } @@ -610,6 +625,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 3b824d64..c6be6db3 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -85,6 +85,17 @@ #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 +#define _GLFW_STRING_ATOM_STRING 2 +#define _GLFW_STRING_ATOM_COUNT 3 //======================================================================== // GLFW platform specific types @@ -223,6 +234,20 @@ typedef struct _GLFWlibraryX11 uint64_t base; } timer; + // 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; + int converted; + } selection; + #if defined(_GLFW_DLOPEN_LIBGL) void* libGL; // dlopen handle for libGL.so #endif @@ -262,5 +287,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 37915f6a..db630b10 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 @@ -1359,6 +1359,41 @@ 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; + } + + 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); + 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; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d7ac0954..fe1df13b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,6 +5,8 @@ set(SHARED_DEPS libglfwShared ${GLFW_LIBRARIES} ${OPENGL_glu_LIBRARY}) include_directories(${GLFW_SOURCE_DIR}/include ${GLFW_SOURCE_DIR}/support ${OPENGL_INCLUDE_DIR}) +add_executable(clipboard clipboard.c) +target_link_libraries(clipboard ${STATIC_DEPS}) add_executable(defaults defaults.c) target_link_libraries(defaults ${STATIC_DEPS}) 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); +} +