mirror of
https://github.com/deskflow/deskflow.git
synced 2026-06-19 21:12:01 +08:00
* Use Deskflow Name * Remove business-oriented options from issue templates * Remove business-oriented workflow * Bump version to 3.0.0 (to avoid confusion with previously used version numbers 1.x & 2.x) * Update readme to reflect new project name and goals * Found some more "synergy" to rename * Rename `synlib` to `app` * Rename `syntool` to `deskflow-legacy` * Rename `synwinhk` to `dfwhook` * Rename dirs from synergy to deskflow * Rename more "Synergy" files * Rename app bundle ID * Fixed copyright typo * Rename only title in serial key dialog (to be moved downstream later) * Preserve original serial key window for moving downstream * Restore dialogs ready for moving downstream * Rename `QDeskflowApplication` to `DeskflowApplication` (the Q is confusing) * Restore Volker's original project name * Fixed mimetype * Fixed weird grammar * Fixed (more) weird grammar * Broken link, restoring (but we should move all links out of source) * Broken link, restoring (but we should move all links out of source) * Add write permission to valgrind-analysis.yml * Restore AUR conflicts * Apply Clang format * Update ChangeLog * Back out version change --------- Co-authored-by: Nick Bolton <nick@symless.com>
235 lines
6.4 KiB
C++
235 lines
6.4 KiB
C++
/*
|
|
* Deskflow -- mouse and keyboard sharing utility
|
|
* Copyright (C) 2012-2016 Symless Ltd.
|
|
* Copyright (C) 2004 Chris Schoeneman
|
|
*
|
|
* This package is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* found in the file LICENSE that should have accompanied this file.
|
|
*
|
|
* This package is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "platform/OSXClipboard.h"
|
|
|
|
#include "arch/XArch.h"
|
|
#include "base/Log.h"
|
|
#include "deskflow/Clipboard.h"
|
|
#include "platform/OSXClipboardBMPConverter.h"
|
|
#include "platform/OSXClipboardHTMLConverter.h"
|
|
#include "platform/OSXClipboardTextConverter.h"
|
|
#include "platform/OSXClipboardUTF16Converter.h"
|
|
#include "platform/OSXClipboardUTF8Converter.h"
|
|
|
|
//
|
|
// OSXClipboard
|
|
//
|
|
|
|
OSXClipboard::OSXClipboard() : m_time(0), m_pboard(NULL) {
|
|
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(
|
|
(CLOG_DEBUG "failed to create clipboard reference: error %i",
|
|
createErr));
|
|
LOG(
|
|
(CLOG_ERR "unable to connect to pasteboard, clipboard sharing disabled",
|
|
createErr));
|
|
m_pboard = NULL;
|
|
return;
|
|
}
|
|
|
|
OSStatus syncErr = PasteboardSynchronize(m_pboard);
|
|
if (syncErr != noErr) {
|
|
LOG((CLOG_DEBUG "failed to syncronize clipboard: error %i", syncErr));
|
|
}
|
|
}
|
|
|
|
OSXClipboard::~OSXClipboard() { clearConverters(); }
|
|
|
|
bool OSXClipboard::empty() {
|
|
LOG((CLOG_DEBUG "emptying clipboard"));
|
|
if (m_pboard == NULL)
|
|
return false;
|
|
|
|
OSStatus err = PasteboardClear(m_pboard);
|
|
if (err != noErr) {
|
|
LOG((CLOG_DEBUG "failed to clear clipboard: error %i", err));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OSXClipboard::synchronize() {
|
|
if (m_pboard == NULL)
|
|
return false;
|
|
|
|
PasteboardSyncFlags flags = PasteboardSynchronize(m_pboard);
|
|
LOG((CLOG_DEBUG2 "flags: %x", flags));
|
|
|
|
if (flags & kPasteboardModified) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void OSXClipboard::add(EFormat format, const String &data) {
|
|
if (m_pboard == NULL)
|
|
return;
|
|
|
|
LOG((CLOG_DEBUG "add %d bytes to clipboard format: %d", data.size(), format));
|
|
if (format == IClipboard::kText) {
|
|
LOG((CLOG_DEBUG "format of data to be added to clipboard was kText"));
|
|
} else if (format == IClipboard::kBitmap) {
|
|
LOG((CLOG_DEBUG "format of data to be added to clipboard was kBitmap"));
|
|
} else if (format == IClipboard::kHTML) {
|
|
LOG((CLOG_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) {
|
|
String osXData = converter->fromIClipboard(data);
|
|
CFStringRef flavorType = converter->getOSXFormat();
|
|
CFDataRef dataRef = CFDataCreate(
|
|
kCFAllocatorDefault, (UInt8 *)osXData.data(), osXData.size());
|
|
PasteboardItemID itemID = 0;
|
|
|
|
if (dataRef) {
|
|
PasteboardPutItemFlavor(
|
|
m_pboard, itemID, flavorType, dataRef, kPasteboardFlavorNoFlags);
|
|
|
|
CFRelease(dataRef);
|
|
LOG(
|
|
(CLOG_DEBUG "added %d bytes to clipboard format: %d", data.size(),
|
|
format));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool OSXClipboard::open(Time time) const {
|
|
if (m_pboard == NULL)
|
|
return false;
|
|
|
|
LOG((CLOG_DEBUG "opening clipboard"));
|
|
m_time = time;
|
|
return true;
|
|
}
|
|
|
|
void OSXClipboard::close() const {
|
|
LOG((CLOG_DEBUG "closing clipboard"));
|
|
/* not needed */
|
|
}
|
|
|
|
IClipboard::Time OSXClipboard::getTime() const { return m_time; }
|
|
|
|
bool OSXClipboard::has(EFormat format) const {
|
|
if (m_pboard == NULL)
|
|
return false;
|
|
|
|
PasteboardItemID item;
|
|
PasteboardGetItemIdentifier(m_pboard, (CFIndex)1, &item);
|
|
|
|
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();
|
|
|
|
OSStatus res;
|
|
|
|
if ((res = PasteboardGetItemFlavorFlags(m_pboard, item, type, &flags)) ==
|
|
noErr) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
String OSXClipboard::get(EFormat format) const {
|
|
CFStringRef type;
|
|
PasteboardItemID item;
|
|
String result;
|
|
|
|
if (m_pboard == NULL)
|
|
return result;
|
|
|
|
PasteboardGetItemIdentifier(m_pboard, (CFIndex)1, &item);
|
|
|
|
// find the converter for the first clipboard format we can handle
|
|
IOSXClipboardConverter *converter = NULL;
|
|
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 = NULL;
|
|
}
|
|
|
|
// if no converter then we don't recognize any formats
|
|
if (converter == NULL) {
|
|
LOG((CLOG_DEBUG "unable to find converter for data"));
|
|
return result;
|
|
}
|
|
|
|
// get the clipboard data.
|
|
CFDataRef buffer = NULL;
|
|
try {
|
|
OSStatus err = PasteboardCopyItemFlavorData(m_pboard, item, type, &buffer);
|
|
|
|
if (err != noErr) {
|
|
throw err;
|
|
}
|
|
|
|
result = String((char *)CFDataGetBytePtr(buffer), CFDataGetLength(buffer));
|
|
} catch (OSStatus err) {
|
|
LOG((
|
|
CLOG_DEBUG "exception thrown in OSXClipboard::get MacError (%d)", err));
|
|
} catch (...) {
|
|
LOG((CLOG_DEBUG "unknown exception in OSXClipboard::get"));
|
|
RETHROW_XTHREAD
|
|
}
|
|
|
|
if (buffer != NULL)
|
|
CFRelease(buffer);
|
|
|
|
return converter->toIClipboard(result);
|
|
}
|
|
|
|
void OSXClipboard::clearConverters() {
|
|
if (m_pboard == NULL)
|
|
return;
|
|
|
|
for (ConverterList::iterator index = m_converters.begin();
|
|
index != m_converters.end(); ++index) {
|
|
delete *index;
|
|
}
|
|
m_converters.clear();
|
|
}
|