Implements copy/paste for OS X using NSPasteboard including pre-10.6 API support. Fixes #1326

This was SVN commit r12464.
This commit is contained in:
historic_bruno 2012-08-18 19:47:55 +00:00
parent 9519635869
commit e485fb9e2c
3 changed files with 151 additions and 15 deletions

View File

@ -23,10 +23,11 @@
#include "precompiled.h"
#include "lib/lib.h"
#include "lib/sysdep/sysdep.h"
#include "lib/sysdep/gfx.h"
#include "lib/utf8.h"
#include "osx_bundle.h"
#include "osx_pasteboard.h"
#include <ApplicationServices/ApplicationServices.h>
#include <AvailabilityMacros.h> // MAC_OS_X_VERSION_MIN_REQUIRED
@ -34,29 +35,38 @@
#include <mach-o/dyld.h> // _NSGetExecutablePath
// "copy" text into the clipboard. replaces previous contents.
Status sys_clipboard_set(const wchar_t* text)
{
return INFO::OK;
Status ret = INFO::OK;
std::string str = utf8_from_wstring(text);
bool ok = osx_SendStringToPasteboard(str);
if (!ok)
ret = ERR::FAIL;
return ret;
}
// allow "pasting" from clipboard. returns the current contents if they
// can be represented as text, otherwise 0.
// when it is no longer needed, the returned pointer must be freed via
// sys_clipboard_free. (NB: not necessary if zero, but doesn't hurt)
wchar_t* sys_clipboard_get(void)
wchar_t* sys_clipboard_get()
{
// Remember to implement sys_clipboard_free when implementing this method!
return NULL;
wchar_t* ret = NULL;
std::string str;
bool ok = osx_GetStringFromPasteboard(str);
if (ok)
{
// TODO: this is yucky, why are we passing around wchar_t*?
std::wstring wstr = wstring_from_utf8(str);
size_t len = wcslen(wstr.c_str());
ret = (wchar_t*)malloc((len+1)*sizeof(wchar_t));
std::copy(wstr.c_str(), wstr.c_str()+len, ret);
ret[len] = 0;
}
return ret;
}
// frees memory used by <copy>, which must have been returned by
// sys_clipboard_get. see note above.
Status sys_clipboard_free(wchar_t* copy)
{
// Since clipboard_get never returns allocated memory (unimplemented), we
// should only ever get called with a NULL pointer.
ENSURE(!copy);
free(copy);
return INFO::OK;
}

View File

@ -0,0 +1,47 @@
/* Copyright (c) 2012 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef OSX_PASTEBOARD_H
#define OSX_PASTEBOARD_H
/**
* @file
* C++ interface to Cocoa implementation for pasteboards
*/
/**
* Get a string from the pasteboard
*
* @param[out] out pasteboard string in UTF-8 encoding, if found
* @return true if string was found on pasteboard and successfully retrieved, false otherwise
*/
bool osx_GetStringFromPasteboard(std::string& out);
/**
* Store a string on the pasteboard
*
* @param[in] string string to store in UTF-8 encoding
* @return true if string was successfully sent to pasteboard, false on error
*/
bool osx_SendStringToPasteboard(const std::string& string);
#endif // OSX_PASTEBOARD_H

View File

@ -0,0 +1,79 @@
/* Copyright (c) 2012 Wildfire Games
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#import <AppKit/AppKit.h>
#import <AvailabilityMacros.h> // MAC_OS_X_VERSION_MIN_REQUIRED
#import <Foundation/Foundation.h>
#import <string>
#import "osx_pasteboard.h"
bool osx_GetStringFromPasteboard(std::string& out)
{
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
NSString* string = nil;
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
// As of 10.6, pasteboards can hold multiple items
NSArray* classes = [NSArray arrayWithObjects:[NSString class], nil];
NSDictionary* options = [NSDictionary dictionary];
NSArray* copiedItems = [pasteboard readObjectsForClasses:classes options:options];
if (copiedItems != nil && [copiedItems count] > 0)
// We only need to support a single item, so grab the first string
string = [copiedItems objectAtIndex:0];
else
return false; // No strings found on pasteboard
#else // 10.5
// Verify that there is a string available for us
NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil];
if ([pasteboard availableTypeFromArray:types] != nil)
string = [pasteboard stringForType:NSStringPboardType];
else
return false; // No strings found on pasteboard
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
if (string != nil)
out = std::string([string UTF8String]);
else
return false; // fail
return true; // success
}
bool osx_SendStringToPasteboard(const std::string& string)
{
// We're only working with strings, so we don't need to lazily write
// anything (otherwise we'd need to set up an owner and data provider)
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
NSString* type = NSPasteboardTypeString;
[pasteboard clearContents];
#else // 10.5
NSString* type = NSStringPboardType;
NSArray* types = [NSArray arrayWithObjects: type, nil];
// Roughly equivalent to clearContents followed by addTypes:owner
[pasteboard declareTypes:types owner:nil];
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
// May raise a NSPasteboardCommunicationException
BOOL ok = [pasteboard setString:[NSString stringWithUTF8String:string.c_str()] forType:type];
return ok == YES;
}