diff --git a/lib/platform/COSXClipboard.cpp b/lib/platform/COSXClipboard.cpp index 3fdfb479..bdf941b0 100644 --- a/lib/platform/COSXClipboard.cpp +++ b/lib/platform/COSXClipboard.cpp @@ -12,6 +12,7 @@ * GNU General Public License for more details. */ +#include "CClipboard.h" #include "COSXClipboard.h" #include "COSXClipboardUTF16Converter.h" #include "COSXClipboardTextConverter.h" @@ -28,6 +29,20 @@ COSXClipboard::COSXClipboard() : { m_converters.push_back(new COSXClipboardUTF16Converter); m_converters.push_back(new COSXClipboardTextConverter); + + 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)); + } } COSXClipboard::~COSXClipboard() @@ -35,44 +50,47 @@ COSXClipboard::~COSXClipboard() clearConverters(); } -bool + bool COSXClipboard::empty() { - LOG((CLOG_DEBUG "empty clipboard")); - assert(m_pboard != NULL); + LOG((CLOG_DEBUG "emptying clipboard")); + if (m_pboard == NULL) + return false; OSStatus err = PasteboardClear(m_pboard); if (err != noErr) { - LOG((CLOG_DEBUG "failed to grab clipboard")); - return false; - } - - - // we own the clipboard - UInt8 claimString[] = {'s', 'y', 'n', 'e'}; - CFDataRef claimData = CFDataCreate(kCFAllocatorDefault, claimString, 4); - - err = PasteboardPutItemFlavor( - m_pboard, - 0, - getOwnershipFlavor(), - claimData, - kPasteboardFlavorNoFlags); - if (err != noErr) { - LOG((CLOG_DEBUG "failed to grab clipboard (%d)", err)); + LOG((CLOG_DEBUG "failed to clear clipboard: error %i", err)); return false; } return true; } -void + bool +COSXClipboard::synchronize() +{ + if (m_pboard == NULL) + return false; + + PasteboardSyncFlags flags = PasteboardSynchronize(m_pboard); + LOG((CLOG_DEBUG1 "flags: %x", flags)); + + if (flags & kPasteboardModified) { + return true; + } + return false; +} + + void COSXClipboard::add(EFormat format, const CString & data) { + if (m_pboard == NULL) + return; + LOG((CLOG_DEBUG "add %d bytes to clipboard format: %d", data.size(), format)); for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { + index != m_converters.end(); ++index) { IOSXClipboardConverter* converter = *index; @@ -80,15 +98,15 @@ COSXClipboard::add(EFormat format, const CString & data) if (converter->getFormat() == format) { CString osXData = converter->fromIClipboard(data); CFStringRef flavorType = converter->getOSXFormat(); - CFDataRef data_ref = CFDataCreate(kCFAllocatorDefault, (UInt8 *)osXData.data(), osXData.size()); + CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, (UInt8 *)osXData.data(), osXData.size()); PasteboardPutItemFlavor( - m_pboard, - (PasteboardItemID) 1, - flavorType, - data_ref, - kPasteboardFlavorNoFlags); - LOG((CLOG_DEBUG "added %d bytes to clipboard format: %d", data.size(), format)); + m_pboard, + (PasteboardItemID) 0, + flavorType, + dataRef, + kPasteboardFlavorNoFlags); + LOG((CLOG_DEBUG "added %d bytes to clipboard format: %d", data.size(), format)); } } } @@ -96,17 +114,19 @@ COSXClipboard::add(EFormat format, const CString & data) bool COSXClipboard::open(Time time) const { - LOG((CLOG_DEBUG "open clipboard")); + if (m_pboard == NULL) + return false; + + LOG((CLOG_DEBUG "opening clipboard")); m_time = time; - OSStatus err = PasteboardCreate(kPasteboardClipboard, &m_pboard); - return (err == noErr); + return true; } void COSXClipboard::close() const { - LOG((CLOG_DEBUG "close clipboard")); - m_pboard = NULL; + LOG((CLOG_DEBUG "closing clipboard")); + /* not needed */ } IClipboard::Time @@ -118,16 +138,22 @@ COSXClipboard::getTime() const bool COSXClipboard::has(EFormat format) const { - assert(m_pboard != NULL); + 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) { + index != m_converters.end(); ++index) { IOSXClipboardConverter* converter = *index; if (converter->getFormat() == format) { - PasteboardFlavorFlags* flags = NULL; + PasteboardFlavorFlags flags; CFStringRef type = converter->getOSXFormat(); - if (PasteboardGetItemFlavorFlags(m_pboard, (void *)1, type, flags) == noErr) { + OSStatus res; + + if ((res = PasteboardGetItemFlavorFlags(m_pboard, item, type, &flags)) == noErr) { return true; } } @@ -139,20 +165,27 @@ COSXClipboard::has(EFormat format) const CString COSXClipboard::get(EFormat format) const { + CFStringRef type; + PasteboardItemID item; CString result; - CFStringRef type; + + 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) { + index != m_converters.end(); ++index) { converter = *index; - PasteboardFlavorFlags* flags = NULL; + PasteboardFlavorFlags flags; type = converter->getOSXFormat(); if (converter->getFormat() == format && - PasteboardGetItemFlavorFlags(m_pboard, (void *)1, type, flags) == noErr) { + PasteboardGetItemFlavorFlags(m_pboard, item, type, &flags) == noErr) { break; } converter = NULL; @@ -160,15 +193,15 @@ COSXClipboard::get(EFormat format) const // 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; + CFDataRef buffer = NULL; try { - OSStatus err = PasteboardCopyItemFlavorData(m_pboard, (void *)1, - type, &buffer); - + OSStatus err = PasteboardCopyItemFlavorData(m_pboard, item, type, &buffer); + if (err != noErr) { throw err; } @@ -183,37 +216,21 @@ COSXClipboard::get(EFormat format) const RETHROW_XTHREAD } - if (buffer != NULL) - CFRelease(buffer); + if (buffer != NULL) + CFRelease(buffer); return converter->toIClipboard(result); } -void + void COSXClipboard::clearConverters() { + if (m_pboard == NULL) + return; + for (ConverterList::iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { + index != m_converters.end(); ++index) { delete *index; } m_converters.clear(); } - -bool -COSXClipboard::isOwnedBySynergy() -{ - PasteboardFlavorFlags flags; - PasteboardRef pboard; - OSStatus err = PasteboardCreate(kPasteboardClipboard, &pboard); - if (err == noErr) { - err = PasteboardGetItemFlavorFlags(pboard, 0, getOwnershipFlavor() , &flags); - } - return (err == noErr); -} - -CFStringRef -COSXClipboard::getOwnershipFlavor() -{ - return CFSTR("Syne"); -} - diff --git a/lib/platform/COSXClipboard.h b/lib/platform/COSXClipboard.h index 48edf854..76902b3c 100644 --- a/lib/platform/COSXClipboard.h +++ b/lib/platform/COSXClipboard.h @@ -39,17 +39,16 @@ public: virtual bool has(EFormat) const; virtual CString get(EFormat) const; + bool synchronize(); private: void clearConverters(); - static CFStringRef - getOwnershipFlavor(); private: typedef std::vector ConverterList; mutable Time m_time; ConverterList m_converters; - mutable PasteboardRef m_pboard; + PasteboardRef m_pboard; }; //! Clipboard format converter interface diff --git a/lib/platform/COSXScreen.cpp b/lib/platform/COSXScreen.cpp index a8e53cf6..b33c8c81 100644 --- a/lib/platform/COSXScreen.cpp +++ b/lib/platform/COSXScreen.cpp @@ -185,8 +185,7 @@ COSXScreen::getEventTarget() const bool COSXScreen::getClipboard(ClipboardID, IClipboard* dst) const { - COSXClipboard src; - CClipboard::copy(dst, &src); + CClipboard::copy(dst, &m_pasteboard); return true; } @@ -643,41 +642,22 @@ COSXScreen::leave() bool COSXScreen::setClipboard(ClipboardID, const IClipboard* src) { - COSXClipboard dst; - if (src != NULL) { - // save clipboard data - if (!CClipboard::copy(&dst, src)) { - return false; - } - } - else { - // assert clipboard ownership - if (!dst.open(0)) { - return false; - } - dst.empty(); - dst.close(); - } - checkClipboards(); - return true; + if(src != NULL) { + LOG((CLOG_DEBUG "setting clipboard")); + CClipboard::copy(&m_pasteboard, src); + } + return true; } void COSXScreen::checkClipboards() { - // check if clipboard ownership changed - if (!COSXClipboard::isOwnedBySynergy()) { - if (m_ownClipboard) { - LOG((CLOG_DEBUG "clipboard changed: lost ownership")); - m_ownClipboard = false; - sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard); - sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection); - } - } - else if (!m_ownClipboard) { - LOG((CLOG_DEBUG "clipboard changed: synergy owned")); - m_ownClipboard = true; - } + LOG((CLOG_DEBUG1 "checking clipboard")); + if (m_pasteboard.synchronize()) { + LOG((CLOG_DEBUG "clipboard changed")); + sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard); + sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection); + } } void @@ -1629,4 +1609,4 @@ COSXScreen::handleCGInputEvent(CGEventTapProxy proxy, } else { return NULL; } -} \ No newline at end of file +} diff --git a/lib/platform/COSXScreen.h b/lib/platform/COSXScreen.h index d2bc3685..00a04472 100644 --- a/lib/platform/COSXScreen.h +++ b/lib/platform/COSXScreen.h @@ -16,6 +16,7 @@ #define COSXSCREEN_H #include +#include "COSXClipboard.h" #include "CPlatformScreen.h" #include "stdmap.h" #include "stdvector.h" @@ -205,6 +206,7 @@ private: COSXKeyState* m_keyState; // clipboards + COSXClipboard m_pasteboard; UInt32 m_sequenceNumber; // screen saver stuff