1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: aqua_clipboard.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include "aqua_clipboard.hxx"
35 #include "DataFlavorMapping.hxx"
36 #include "OSXTransferable.hxx"
38 #include "vcl/unohelp.hxx"
40 #include "comphelper/makesequence.hxx"
42 #include <boost/assert.hpp>
44 using namespace com::sun::star::datatransfer
;
45 using namespace com::sun::star::datatransfer::clipboard
;
46 using namespace com::sun::star::lang
;
47 using namespace com::sun::star::uno
;
52 using namespace comphelper
;
55 @implementation EventListener
;
57 -(EventListener
*)initWithAquaClipboard
: (AquaClipboard
*) pcb
67 -(void)pasteboard
:(NSPasteboard
*)sender provideDataForType
:(NSString
*)type
70 pAquaClipboard
->provideDataForType(sender
, type
);
73 -(void)applicationDidBecomeActive
:(NSNotification
*)aNotification
76 pAquaClipboard
->applicationDidBecomeActive(aNotification
);
81 pAquaClipboard
= NULL
;
87 OUString
clipboard_getImplementationName()
89 return OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.clipboard.AquaClipboard"));
92 Sequence
<OUString
> clipboard_getSupportedServiceNames()
94 return makeSequence(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.clipboard.SystemClipboard")));
98 AquaClipboard::AquaClipboard(NSPasteboard
* pasteboard
, bool bUseSystemPasteboard
) :
99 WeakComponentImplHelper4
<XClipboardEx
, XClipboardNotifier
, XFlushableClipboard
, XServiceInfo
>(m_aMutex
),
100 mIsSystemPasteboard(bUseSystemPasteboard
)
102 Reference
<XMultiServiceFactory
> mrServiceMgr
= vcl::unohelper::GetMultiServiceFactory();
104 mrXMimeCntFactory
= Reference
<XMimeContentTypeFactory
>(mrServiceMgr
->createInstance(
105 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.datatransfer.MimeContentTypeFactory"))), UNO_QUERY
);
107 if (!mrXMimeCntFactory
.is())
109 throw RuntimeException(OUString(
110 RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create com.sun.star.datatransfer.MimeContentTypeFactory")),
111 static_cast<XClipboardEx
*>(this));
114 mpDataFlavorMapper
= DataFlavorMapperPtr_t(new DataFlavorMapper());
116 if (pasteboard
!= NULL
)
118 mPasteboard
= pasteboard
;
119 mIsSystemPasteboard
= false;
123 mPasteboard
= bUseSystemPasteboard
? [NSPasteboard generalPasteboard
] :
124 [NSPasteboard pasteboardWithName
: NSDragPboard
];
126 if (mPasteboard
== nil
)
128 throw RuntimeException(OUString(
129 RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create Cocoa pasteboard")),
130 static_cast<XClipboardEx
*>(this));
134 [mPasteboard retain
];
136 mEventListener
= [[EventListener alloc
] initWithAquaClipboard
: this];
138 if (mEventListener
== nil
)
140 [mPasteboard release
];
142 throw RuntimeException(
143 OUString(RTL_CONSTASCII_USTRINGPARAM("AquaClipboard: Cannot create pasteboard change listener")),
144 static_cast<XClipboardEx
*>(this));
147 if (mIsSystemPasteboard
)
149 NSNotificationCenter
* notificationCenter
= [NSNotificationCenter defaultCenter
];
151 [notificationCenter addObserver
: mEventListener
152 selector
: @
selector(applicationDidBecomeActive
:)
153 name
: @
"NSApplicationDidBecomeActiveNotification"
154 object
: [NSApplication sharedApplication
]];
157 mPasteboardChangeCount
= [mPasteboard changeCount
];
161 AquaClipboard::~AquaClipboard()
163 if (mIsSystemPasteboard
)
165 [[NSNotificationCenter defaultCenter
] removeObserver
: mEventListener
];
168 [mEventListener disposing
];
169 [mEventListener release
];
170 [mPasteboard release
];
174 Reference
<XTransferable
> SAL_CALL
AquaClipboard::getContents() throw(RuntimeException
)
176 MutexGuard
aGuard(m_aMutex
);
178 // Shortcut: If we are clipboard owner already we don't need
179 // to drag the data through the system clipboard
180 if (mXClipboardContent
.is())
182 return mXClipboardContent
;
185 return Reference
<XTransferable
>(new OSXTransferable(mrXMimeCntFactory
,
191 void SAL_CALL
AquaClipboard::setContents(const Reference
<XTransferable
>& xTransferable
,
192 const Reference
<XClipboardOwner
>& xClipboardOwner
)
193 throw( RuntimeException
)
195 ClearableMutexGuard
aGuard(m_aMutex
);
197 Reference
<XClipboardOwner
> oldOwner(mXClipboardOwner
);
198 mXClipboardOwner
= xClipboardOwner
;
200 Reference
<XTransferable
> oldContent(mXClipboardContent
);
201 mXClipboardContent
= xTransferable
;
203 NSArray
* types
= mXClipboardContent
.is() ?
204 mpDataFlavorMapper
->flavorSequenceToTypesArray(mXClipboardContent
->getTransferDataFlavors()) :
206 mPasteboardChangeCount
= [mPasteboard declareTypes
: types owner
: mEventListener
];
208 // if we are already the owner of the clipboard
209 // then fire lost ownership event
212 fireLostClipboardOwnershipEvent(oldOwner
, oldContent
);
215 fireClipboardChangedEvent();
219 OUString SAL_CALL
AquaClipboard::getName() throw( RuntimeException
)
225 sal_Int8 SAL_CALL
AquaClipboard::getRenderingCapabilities() throw( RuntimeException
)
231 void SAL_CALL
AquaClipboard::addClipboardListener(const Reference
< XClipboardListener
>& listener
)
232 throw( RuntimeException
)
234 MutexGuard
aGuard(m_aMutex
);
237 throw IllegalArgumentException(OUString(RTL_CONSTASCII_USTRINGPARAM("empty reference")),
238 static_cast<XClipboardEx
*>(this), 1);
240 mClipboardListeners
.push_back(listener
);
244 void SAL_CALL
AquaClipboard::removeClipboardListener(const Reference
< XClipboardListener
>& listener
)
245 throw( RuntimeException
)
247 MutexGuard
aGuard(m_aMutex
);
250 throw IllegalArgumentException(OUString(RTL_CONSTASCII_USTRINGPARAM("empty reference")),
251 static_cast<XClipboardEx
*>(this), 1);
253 mClipboardListeners
.remove(listener
);
257 void AquaClipboard::applicationDidBecomeActive(NSNotification
* aNotification
)
259 MutexGuard
aGuard(m_aMutex
);
261 int currentPboardChgCount
= [mPasteboard changeCount
];
263 if (currentPboardChgCount
!= mPasteboardChangeCount
)
265 mPasteboardChangeCount
= currentPboardChgCount
;
267 // Clear clipboard content and owner and send lostOwnership
268 // notification to the old clipboard owner as well as
269 // ClipboardChanged notification to any clipboard listener
270 Reference
<XClipboardOwner
> oldOwner(mXClipboardOwner
);
271 mXClipboardOwner
= Reference
<XClipboardOwner
>();
273 Reference
<XTransferable
> oldContent(mXClipboardContent
);
274 mXClipboardContent
= Reference
<XTransferable
>();
278 fireLostClipboardOwnershipEvent(oldOwner
, oldContent
);
281 fireClipboardChangedEvent();
286 void AquaClipboard::fireClipboardChangedEvent()
288 ClearableMutexGuard
aGuard(m_aMutex
);
290 list
<Reference
< XClipboardListener
> > listeners(mClipboardListeners
);
291 ClipboardEvent aEvent
;
293 if (listeners
.begin() != listeners
.end())
295 aEvent
= ClipboardEvent(static_cast<OWeakObject
*>(this), getContents());
300 while (listeners
.begin() != listeners
.end())
302 if (listeners
.front().is())
304 try { listeners
.front()->changedContents(aEvent
); }
305 catch (RuntimeException
&) { }
307 listeners
.pop_front();
312 void AquaClipboard::fireLostClipboardOwnershipEvent(Reference
<XClipboardOwner
> oldOwner
, Reference
<XTransferable
> oldContent
)
314 BOOST_ASSERT(oldOwner
.is());
316 try { oldOwner
->lostOwnership(static_cast<XClipboardEx
*>(this), oldContent
); }
317 catch(RuntimeException
&) { }
321 void AquaClipboard::provideDataForType(NSPasteboard
* sender
, NSString
* type
)
323 DataProviderPtr_t dp
= mpDataFlavorMapper
->getDataProvider(type
, mXClipboardContent
);
324 NSData
* pBoardData
= NULL
;
326 if (dp
.get() != NULL
)
328 pBoardData
= (NSData
*)dp
->getSystemData();
329 [sender setData
: pBoardData forType
: type
];
334 //------------------------------------------------
335 // XFlushableClipboard
336 //------------------------------------------------
338 void SAL_CALL
AquaClipboard::flushClipboard()
339 throw(RuntimeException
)
341 if (mXClipboardContent
.is())
343 Sequence
<DataFlavor
> flavorList
= mXClipboardContent
->getTransferDataFlavors();
344 sal_uInt32 nFlavors
= flavorList
.getLength();
346 for (sal_uInt32 i
= 0; i
< nFlavors
; i
++)
348 NSString
* sysType
= mpDataFlavorMapper
->openOfficeToSystemFlavor(flavorList
[i
]);
352 provideDataForType(mPasteboard
, sysType
);
359 NSPasteboard
* AquaClipboard::getPasteboard() const
365 //-------------------------------------------------
367 //-------------------------------------------------
369 OUString SAL_CALL
AquaClipboard::getImplementationName() throw( RuntimeException
)
371 return clipboard_getImplementationName();
375 sal_Bool SAL_CALL
AquaClipboard::supportsService( const OUString
& ServiceName
) throw( RuntimeException
)
381 Sequence
< OUString
> SAL_CALL
AquaClipboard::getSupportedServiceNames() throw( RuntimeException
)
383 return clipboard_getSupportedServiceNames();