deskflow/src/lib/platform/OSXClipboard.cpp

223 lines
5.8 KiB
C++
Raw Normal View History

2012-06-10 16:50:54 +00:00
/*
* Deskflow -- mouse and keyboard sharing utility
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
2012-06-10 16:50:54 +00:00
*/
#include "platform/OSXClipboard.h"
#include "arch/ArchException.h"
#include "base/Log.h"
#include "platform/OSXClipboardBMPConverter.h"
#include "platform/OSXClipboardHTMLConverter.h"
#include "platform/OSXClipboardTextConverter.h"
#include "platform/OSXClipboardUTF16Converter.h"
#include "platform/OSXClipboardUTF8Converter.h"
2012-06-10 16:50:54 +00:00
//
2014-11-11 13:51:47 +00:00
// OSXClipboard
2012-06-10 16:50:54 +00:00
//
OSXClipboard::OSXClipboard() : m_time(0), m_pboard(nullptr)
{
m_converters.push_back(new OSXClipboardHTMLConverter);
m_converters.push_back(new OSXClipboardBMPConverter);
m_converters.push_back(new OSXClipboardUTF8Converter);
m_converters.push_back(new OSXClipboardUTF16Converter);
m_converters.push_back(new OSXClipboardTextConverter);
OSStatus createErr = PasteboardCreate(kPasteboardClipboard, &m_pboard);
if (createErr != noErr) {
LOG_WARN("failed to create clipboard reference: error %i", createErr);
LOG_ERR("unable to connect to pasteboard, clipboard sharing disabled", createErr);
m_pboard = nullptr;
return;
}
OSStatus syncErr = PasteboardSynchronize(m_pboard);
if (syncErr != noErr) {
LOG_WARN("failed to syncronize clipboard: error %i", syncErr);
}
2012-06-10 16:50:54 +00:00
}
OSXClipboard::~OSXClipboard()
{
clearConverters();
}
2012-06-10 16:50:54 +00:00
bool OSXClipboard::empty()
{
LOG_DEBUG("emptying clipboard");
if (m_pboard == nullptr)
return false;
2012-06-10 16:50:54 +00:00
OSStatus err = PasteboardClear(m_pboard);
if (err != noErr) {
LOG_WARN("failed to clear clipboard: error %i", err);
return false;
}
2012-06-10 16:50:54 +00:00
return true;
2012-06-10 16:50:54 +00:00
}
bool OSXClipboard::synchronize()
{
if (m_pboard == nullptr)
return false;
2012-06-10 16:50:54 +00:00
PasteboardSyncFlags flags = PasteboardSynchronize(m_pboard);
LOG_DEBUG2("flags: %x", flags);
if (flags & kPasteboardModified) {
return true;
}
return false;
}
void OSXClipboard::add(Format format, const std::string &data)
{
if (m_pboard == nullptr)
return;
LOG_DEBUG("add %d bytes to clipboard format: %d", data.size(), format);
if (format == IClipboard::Format::Text) {
LOG_DEBUG("format of data to be added to clipboard was kText");
} else if (format == IClipboard::Format::Bitmap) {
LOG_DEBUG("format of data to be added to clipboard was kBitmap");
} else if (format == IClipboard::Format::HTML) {
LOG_DEBUG("format of data to be added to clipboard was kHTML");
}
for (ConverterList::const_iterator index = m_converters.begin(); index != m_converters.end(); ++index) {
IOSXClipboardConverter *converter = *index;
// skip converters for other formats
if (converter->getFormat() == format) {
std::string osXData = converter->fromIClipboard(data);
CFStringRef flavorType = converter->getOSXFormat();
2025-01-11 00:09:43 +00:00
CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, (uint8_t *)osXData.data(), osXData.size());
PasteboardItemID itemID = 0;
if (dataRef) {
PasteboardPutItemFlavor(m_pboard, itemID, flavorType, dataRef, kPasteboardFlavorNoFlags);
CFRelease(dataRef);
LOG_DEBUG("added %d bytes to clipboard format: %d", data.size(), format);
}
}
}
2012-06-10 16:50:54 +00:00
}
bool OSXClipboard::open(Time time) const
{
if (m_pboard == nullptr)
return false;
2012-06-10 16:50:54 +00:00
LOG_DEBUG("opening clipboard");
m_time = time;
return true;
2012-06-10 16:50:54 +00:00
}
void OSXClipboard::close() const
{
LOG_DEBUG("closing clipboard");
/* not needed */
2012-06-10 16:50:54 +00:00
}
IClipboard::Time OSXClipboard::getTime() const
{
return m_time;
}
2012-06-10 16:50:54 +00:00
bool OSXClipboard::has(Format format) const
{
if (m_pboard == nullptr)
return false;
2012-06-10 16:50:54 +00:00
PasteboardItemID item;
PasteboardGetItemIdentifier(m_pboard, (CFIndex)1, &item);
2012-06-10 16:50:54 +00:00
for (ConverterList::const_iterator index = m_converters.begin(); index != m_converters.end(); ++index) {
IOSXClipboardConverter *converter = *index;
if (converter->getFormat() == format) {
PasteboardFlavorFlags flags;
CFStringRef type = converter->getOSXFormat();
2012-06-10 16:50:54 +00:00
OSStatus res;
2012-06-10 16:50:54 +00:00
if ((res = PasteboardGetItemFlavorFlags(m_pboard, item, type, &flags)) == noErr) {
return true;
}
}
}
2012-06-10 16:50:54 +00:00
return false;
2012-06-10 16:50:54 +00:00
}
std::string OSXClipboard::get(Format format) const
{
CFStringRef type;
PasteboardItemID item;
std::string result;
if (m_pboard == nullptr)
return result;
PasteboardGetItemIdentifier(m_pboard, (CFIndex)1, &item);
// find the converter for the first clipboard format we can handle
IOSXClipboardConverter *converter = nullptr;
for (ConverterList::const_iterator index = m_converters.begin(); index != m_converters.end(); ++index) {
converter = *index;
PasteboardFlavorFlags flags;
type = converter->getOSXFormat();
if (converter->getFormat() == format && PasteboardGetItemFlavorFlags(m_pboard, item, type, &flags) == noErr) {
break;
}
converter = nullptr;
}
// if no converter then we don't recognize any formats
if (converter == nullptr) {
LOG_DEBUG("unable to find converter for data");
return result;
}
// get the clipboard data.
CFDataRef buffer = nullptr;
try {
OSStatus err = PasteboardCopyItemFlavorData(m_pboard, item, type, &buffer);
if (err != noErr) {
throw err;
}
result = std::string((char *)CFDataGetBytePtr(buffer), CFDataGetLength(buffer));
} catch (OSStatus err) {
LOG_DEBUG("exception thrown in OSXClipboard::get MacError (%d)", err);
} catch (...) {
LOG_DEBUG("unknown exception in OSXClipboard::get");
RETHROW_THREADEXCEPTION
}
if (buffer != nullptr)
CFRelease(buffer);
return converter->toIClipboard(result);
2012-06-10 16:50:54 +00:00
}
void OSXClipboard::clearConverters()
{
if (m_pboard == nullptr)
return;
for (ConverterList::iterator index = m_converters.begin(); index != m_converters.end(); ++index) {
delete *index;
}
m_converters.clear();
2012-06-10 16:50:54 +00:00
}