parent
66c3af7628
commit
8d170c7f47
13 changed files with 478 additions and 675 deletions
@ -1,50 +0,0 @@ |
||||
//========================================================================
|
||||
// GLFW 3.1 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h" |
||||
|
||||
#include <math.h> |
||||
#include <string.h> |
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW public API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string) |
||||
{ |
||||
_GLFWwindow* window = (_GLFWwindow*) handle; |
||||
_GLFW_REQUIRE_INIT(); |
||||
_glfwPlatformSetClipboardString(window, string); |
||||
} |
||||
|
||||
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle) |
||||
{ |
||||
_GLFWwindow* window = (_GLFWwindow*) handle; |
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); |
||||
return _glfwPlatformGetClipboardString(window); |
||||
} |
||||
|
@ -1,70 +0,0 @@ |
||||
//======================================================================== |
||||
// GLFW 3.1 OS X - www.glfw.org |
||||
//------------------------------------------------------------------------ |
||||
// Copyright (c) 2010 Camilla Berglund <elmindreda@elmindreda.org> |
||||
// |
||||
// This software is provided 'as-is', without any express or implied |
||||
// warranty. In no event will the authors be held liable for any damages |
||||
// arising from the use of this software. |
||||
// |
||||
// Permission is granted to anyone to use this software for any purpose, |
||||
// including commercial applications, and to alter it and redistribute it |
||||
// freely, subject to the following restrictions: |
||||
// |
||||
// 1. The origin of this software must not be misrepresented; you must not |
||||
// claim that you wrote the original software. If you use this software |
||||
// in a product, an acknowledgment in the product documentation would |
||||
// be appreciated but is not required. |
||||
// |
||||
// 2. Altered source versions must be plainly marked as such, and must not |
||||
// be misrepresented as being the original software. |
||||
// |
||||
// 3. This notice may not be removed or altered from any source |
||||
// distribution. |
||||
// |
||||
//======================================================================== |
||||
|
||||
#include "internal.h" |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////// |
||||
////// GLFW platform API ////// |
||||
////////////////////////////////////////////////////////////////////////// |
||||
|
||||
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]; |
||||
} |
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) |
||||
{ |
||||
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; |
||||
|
||||
if (![[pasteboard types] containsObject:NSStringPboardType]) |
||||
{ |
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE, NULL); |
||||
return NULL; |
||||
} |
||||
|
||||
NSString* object = [pasteboard stringForType:NSStringPboardType]; |
||||
if (!object) |
||||
{ |
||||
_glfwInputError(GLFW_PLATFORM_ERROR, |
||||
"Cocoa: Failed to retrieve object from pasteboard"); |
||||
return NULL; |
||||
} |
||||
|
||||
free(_glfw.ns.clipboardString); |
||||
_glfw.ns.clipboardString = strdup([object UTF8String]); |
||||
|
||||
return _glfw.ns.clipboardString; |
||||
} |
||||
|
@ -1,127 +0,0 @@ |
||||
//========================================================================
|
||||
// GLFW 3.1 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h" |
||||
|
||||
#include <limits.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include <malloc.h> |
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) |
||||
{ |
||||
WCHAR* wideString; |
||||
HANDLE stringHandle; |
||||
size_t wideSize; |
||||
|
||||
wideString = _glfwCreateWideStringFromUTF8(string); |
||||
if (!wideString) |
||||
{ |
||||
_glfwInputError(GLFW_PLATFORM_ERROR, |
||||
"Win32: Failed to convert clipboard string to " |
||||
"wide string"); |
||||
return; |
||||
} |
||||
|
||||
wideSize = (wcslen(wideString) + 1) * sizeof(WCHAR); |
||||
|
||||
stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideSize); |
||||
if (!stringHandle) |
||||
{ |
||||
free(wideString); |
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, |
||||
"Win32: Failed to allocate global handle for clipboard"); |
||||
return; |
||||
} |
||||
|
||||
memcpy(GlobalLock(stringHandle), wideString, wideSize); |
||||
GlobalUnlock(stringHandle); |
||||
|
||||
if (!OpenClipboard(window->win32.handle)) |
||||
{ |
||||
GlobalFree(stringHandle); |
||||
free(wideString); |
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard"); |
||||
return; |
||||
} |
||||
|
||||
EmptyClipboard(); |
||||
SetClipboardData(CF_UNICODETEXT, stringHandle); |
||||
CloseClipboard(); |
||||
|
||||
free(wideString); |
||||
} |
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) |
||||
{ |
||||
HANDLE stringHandle; |
||||
|
||||
if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) |
||||
{ |
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE, NULL); |
||||
return NULL; |
||||
} |
||||
|
||||
if (!OpenClipboard(window->win32.handle)) |
||||
{ |
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard"); |
||||
return NULL; |
||||
} |
||||
|
||||
stringHandle = GetClipboardData(CF_UNICODETEXT); |
||||
if (!stringHandle) |
||||
{ |
||||
CloseClipboard(); |
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, |
||||
"Win32: Failed to retrieve clipboard data"); |
||||
return NULL; |
||||
} |
||||
|
||||
free(_glfw.win32.clipboardString); |
||||
_glfw.win32.clipboardString = |
||||
_glfwCreateUTF8FromWideString(GlobalLock(stringHandle)); |
||||
|
||||
GlobalUnlock(stringHandle); |
||||
CloseClipboard(); |
||||
|
||||
if (!_glfw.win32.clipboardString) |
||||
{ |
||||
_glfwInputError(GLFW_PLATFORM_ERROR, |
||||
"Win32: Failed to convert wide string to UTF-8"); |
||||
return NULL; |
||||
} |
||||
|
||||
return _glfw.win32.clipboardString; |
||||
} |
||||
|
@ -1,48 +0,0 @@ |
||||
//========================================================================
|
||||
// GLFW 3.1 Wayland - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||
//
|
||||
// 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 <stdio.h> |
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) |
||||
{ |
||||
// TODO
|
||||
fprintf(stderr, "_glfwPlatformSetClipboardString not implemented yet\n"); |
||||
} |
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) |
||||
{ |
||||
// TODO
|
||||
fprintf(stderr, "_glfwPlatformGetClipboardString not implemented yet\n"); |
||||
return NULL; |
||||
} |
||||
|
@ -1,335 +0,0 @@ |
||||
//========================================================================
|
||||
// GLFW 3.1 X11 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h" |
||||
|
||||
#include <stdio.h> |
||||
#include <limits.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
|
||||
|
||||
// Returns whether the event is a selection event
|
||||
//
|
||||
static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer) |
||||
{ |
||||
return event->type == SelectionRequest || |
||||
event->type == SelectionNotify || |
||||
event->type == SelectionClear; |
||||
} |
||||
|
||||
// Set the specified property to the selection converted to the requested target
|
||||
//
|
||||
static Atom writeTargetToProperty(const XSelectionRequestEvent* request) |
||||
{ |
||||
int i; |
||||
const Atom formats[] = { _glfw.x11.UTF8_STRING, |
||||
_glfw.x11.COMPOUND_STRING, |
||||
XA_STRING }; |
||||
const int formatCount = sizeof(formats) / sizeof(formats[0]); |
||||
|
||||
if (request->property == None) |
||||
{ |
||||
// The requestor is a legacy client (ICCCM section 2.2)
|
||||
// We don't support legacy clients, so fail here
|
||||
return None; |
||||
} |
||||
|
||||
if (request->target == _glfw.x11.TARGETS) |
||||
{ |
||||
// The list of supported targets was requested
|
||||
|
||||
const Atom targets[] = { _glfw.x11.TARGETS, |
||||
_glfw.x11.MULTIPLE, |
||||
_glfw.x11.UTF8_STRING, |
||||
_glfw.x11.COMPOUND_STRING, |
||||
XA_STRING }; |
||||
|
||||
XChangeProperty(_glfw.x11.display, |
||||
request->requestor, |
||||
request->property, |
||||
XA_ATOM, |
||||
32, |
||||
PropModeReplace, |
||||
(unsigned char*) targets, |
||||
sizeof(targets) / sizeof(targets[0])); |
||||
|
||||
return request->property; |
||||
} |
||||
|
||||
if (request->target == _glfw.x11.MULTIPLE) |
||||
{ |
||||
// Multiple conversions were requested
|
||||
|
||||
Atom* targets; |
||||
unsigned long i, count; |
||||
|
||||
count = _glfwGetWindowProperty(request->requestor, |
||||
request->property, |
||||
_glfw.x11.ATOM_PAIR, |
||||
(unsigned char**) &targets); |
||||
|
||||
for (i = 0; i < count; i += 2) |
||||
{ |
||||
int j; |
||||
|
||||
for (j = 0; j < formatCount; j++) |
||||
{ |
||||
if (targets[i] == formats[j]) |
||||
break; |
||||
} |
||||
|
||||
if (j < formatCount) |
||||
{ |
||||
XChangeProperty(_glfw.x11.display, |
||||
request->requestor, |
||||
targets[i + 1], |
||||
targets[i], |
||||
8, |
||||
PropModeReplace, |
||||
(unsigned char*) _glfw.x11.clipboardString, |
||||
strlen(_glfw.x11.clipboardString)); |
||||
} |
||||
else |
||||
targets[i + 1] = None; |
||||
} |
||||
|
||||
XChangeProperty(_glfw.x11.display, |
||||
request->requestor, |
||||
request->property, |
||||
_glfw.x11.ATOM_PAIR, |
||||
32, |
||||
PropModeReplace, |
||||
(unsigned char*) targets, |
||||
count); |
||||
|
||||
XFree(targets); |
||||
|
||||
return request->property; |
||||
} |
||||
|
||||
if (request->target == _glfw.x11.SAVE_TARGETS) |
||||
{ |
||||
// The request is a check whether we support SAVE_TARGETS
|
||||
// It should be handled as a no-op side effect target
|
||||
|
||||
XChangeProperty(_glfw.x11.display, |
||||
request->requestor, |
||||
request->property, |
||||
_glfw.x11._NULL, |
||||
32, |
||||
PropModeReplace, |
||||
NULL, |
||||
0); |
||||
|
||||
return request->property; |
||||
} |
||||
|
||||
// Conversion to a data target was requested
|
||||
|
||||
for (i = 0; i < formatCount; i++) |
||||
{ |
||||
if (request->target == formats[i]) |
||||
{ |
||||
// The requested target is one we support
|
||||
|
||||
XChangeProperty(_glfw.x11.display, |
||||
request->requestor, |
||||
request->property, |
||||
request->target, |
||||
8, |
||||
PropModeReplace, |
||||
(unsigned char*) _glfw.x11.clipboardString, |
||||
strlen(_glfw.x11.clipboardString)); |
||||
|
||||
return request->property; |
||||
} |
||||
} |
||||
|
||||
// The requested target is not supported
|
||||
|
||||
return None; |
||||
} |
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwHandleSelectionClear(XEvent* event) |
||||
{ |
||||
free(_glfw.x11.clipboardString); |
||||
_glfw.x11.clipboardString = NULL; |
||||
} |
||||
|
||||
void _glfwHandleSelectionRequest(XEvent* event) |
||||
{ |
||||
const XSelectionRequestEvent* request = &event->xselectionrequest; |
||||
|
||||
XEvent response; |
||||
memset(&response, 0, sizeof(response)); |
||||
|
||||
response.xselection.property = writeTargetToProperty(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; |
||||
|
||||
XSendEvent(_glfw.x11.display, request->requestor, False, 0, &response); |
||||
} |
||||
|
||||
void _glfwPushSelectionToManager(_GLFWwindow* window) |
||||
{ |
||||
XConvertSelection(_glfw.x11.display, |
||||
_glfw.x11.CLIPBOARD_MANAGER, |
||||
_glfw.x11.SAVE_TARGETS, |
||||
None, |
||||
window->x11.handle, |
||||
CurrentTime); |
||||
|
||||
for (;;) |
||||
{ |
||||
XEvent event; |
||||
|
||||
if (!XCheckIfEvent(_glfw.x11.display, &event, isSelectionEvent, NULL)) |
||||
continue; |
||||
|
||||
switch (event.type) |
||||
{ |
||||
case SelectionRequest: |
||||
_glfwHandleSelectionRequest(&event); |
||||
break; |
||||
|
||||
case SelectionClear: |
||||
_glfwHandleSelectionClear(&event); |
||||
break; |
||||
|
||||
case SelectionNotify: |
||||
{ |
||||
if (event.xselection.target == _glfw.x11.SAVE_TARGETS) |
||||
{ |
||||
// This means one of two things; either the selection was
|
||||
// not owned, which means there is no clipboard manager, or
|
||||
// the transfer to the clipboard manager has completed
|
||||
// In either case, it means we are done here
|
||||
return; |
||||
} |
||||
|
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) |
||||
{ |
||||
free(_glfw.x11.clipboardString); |
||||
_glfw.x11.clipboardString = strdup(string); |
||||
|
||||
XSetSelectionOwner(_glfw.x11.display, |
||||
_glfw.x11.CLIPBOARD, |
||||
window->x11.handle, CurrentTime); |
||||
|
||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) != |
||||
window->x11.handle) |
||||
{ |
||||
_glfwInputError(GLFW_PLATFORM_ERROR, |
||||
"X11: Failed to become owner of the clipboard selection"); |
||||
} |
||||
} |
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) |
||||
{ |
||||
size_t i; |
||||
const Atom formats[] = { _glfw.x11.UTF8_STRING, |
||||
_glfw.x11.COMPOUND_STRING, |
||||
XA_STRING }; |
||||
const size_t formatCount = sizeof(formats) / sizeof(formats[0]); |
||||
|
||||
if (_glfwFindWindowByHandle(XGetSelectionOwner(_glfw.x11.display, |
||||
_glfw.x11.CLIPBOARD))) |
||||
{ |
||||
// Instead of doing a large number of X round-trips just to put this
|
||||
// string into a window property and then read it back, just return it
|
||||
return _glfw.x11.clipboardString; |
||||
} |
||||
|
||||
free(_glfw.x11.clipboardString); |
||||
_glfw.x11.clipboardString = NULL; |
||||
|
||||
for (i = 0; i < formatCount; i++) |
||||
{ |
||||
char* data; |
||||
XEvent event; |
||||
|
||||
XConvertSelection(_glfw.x11.display, |
||||
_glfw.x11.CLIPBOARD, |
||||
formats[i], |
||||
_glfw.x11.GLFW_SELECTION, |
||||
window->x11.handle, CurrentTime); |
||||
|
||||
// XCheckTypedEvent is used instead of XIfEvent in order not to lock
|
||||
// other threads out from the display during the entire wait period
|
||||
while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event)) |
||||
; |
||||
|
||||
if (event.xselection.property == None) |
||||
continue; |
||||
|
||||
if (_glfwGetWindowProperty(event.xselection.requestor, |
||||
event.xselection.property, |
||||
event.xselection.target, |
||||
(unsigned char**) &data)) |
||||
{ |
||||
_glfw.x11.clipboardString = strdup(data); |
||||
} |
||||
|
||||
XFree(data); |
||||
|
||||
XDeleteProperty(_glfw.x11.display, |
||||
event.xselection.requestor, |
||||
event.xselection.property); |
||||
|
||||
if (_glfw.x11.clipboardString) |
||||
break; |
||||
} |
||||
|
||||
if (_glfw.x11.clipboardString == NULL) |
||||
{ |
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE, |
||||
"X11: Failed to convert selection to string"); |
||||
} |
||||
|
||||
return _glfw.x11.clipboardString; |
||||
} |
||||
|
Loading…
Reference in New Issue