1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dtrans.hxx"
26
27 //------------------------------------------------------------------------
28 // includes
29 //------------------------------------------------------------------------
30 #include <osl/diagnose.h>
31 #include "WinClipbImpl.hxx"
32
33 #include <systools/win32/comtools.hxx>
34 #include "..\..\inc\DtObjFactory.hxx"
35 #include "..\dtobj\APNDataObject.hxx"
36 #include "WinClipboard.hxx"
37 #include <com/sun/star/datatransfer/clipboard/RenderingCapabilities.hpp>
38 #include "..\dtobj\XNotifyingDataObject.hxx"
39
40 #if defined _MSC_VER
41 #pragma warning(push,1)
42 #endif
43 #include <windows.h>
44 #include <ole2.h>
45 #include <objidl.h>
46 #if defined _MSC_VER
47 #pragma warning(pop)
48 #endif
49
50 //------------------------------------------------------------------------
51 // namespace directives
52 //------------------------------------------------------------------------
53
54 using namespace rtl;
55 using namespace osl;
56 using namespace std;
57 using namespace cppu;
58
59 using namespace com::sun::star::uno;
60 using namespace com::sun::star::datatransfer;
61 using namespace com::sun::star::datatransfer::clipboard;
62 using namespace com::sun::star::datatransfer::clipboard::RenderingCapabilities;
63
64 //------------------------------------------------------------------------
65 // deklarations
66 //------------------------------------------------------------------------
67
68 // definition of static members
69 CWinClipbImpl* CWinClipbImpl::s_pCWinClipbImpl = NULL;
70 osl::Mutex CWinClipbImpl::s_aMutex;
71
72 //------------------------------------------------------------------------
73 //
74 //------------------------------------------------------------------------
75
CWinClipbImpl(const OUString & aClipboardName,CWinClipboard * theWinClipboard)76 CWinClipbImpl::CWinClipbImpl( const OUString& aClipboardName, CWinClipboard* theWinClipboard ) :
77 m_itsName( aClipboardName ),
78 m_pWinClipboard( theWinClipboard ),
79 m_pCurrentClipContent( NULL )
80 {
81 OSL_ASSERT( NULL != m_pWinClipboard );
82
83 // necessary to reassociate from
84 // the static callback function
85 s_pCWinClipbImpl = this;
86 registerClipboardViewer( );
87 }
88
89 //------------------------------------------------------------------------
90 //
91 //------------------------------------------------------------------------
92
~CWinClipbImpl()93 CWinClipbImpl::~CWinClipbImpl( )
94 {
95 ClearableMutexGuard aGuard( s_aMutex );
96 s_pCWinClipbImpl = NULL;
97 aGuard.clear( );
98
99 unregisterClipboardViewer( );
100 }
101
102 //------------------------------------------------------------------------
103 // getContent
104 //------------------------------------------------------------------------
105
getContents()106 Reference< XTransferable > SAL_CALL CWinClipbImpl::getContents( ) throw( RuntimeException )
107 {
108 // use the shotcut or create a transferable from
109 // system clipboard
110 ClearableMutexGuard aGuard( m_ClipContentMutex );
111
112 if ( NULL != m_pCurrentClipContent )
113 {
114 return m_pCurrentClipContent->m_XTransferable;
115 }
116
117 // release the mutex, so that the variable may be
118 // changed by other threads
119 aGuard.clear( );
120
121 Reference< XTransferable > rClipContent;
122
123 // get the current dataobject from clipboard
124 IDataObjectPtr pIDataObject;
125 HRESULT hr = m_MtaOleClipboard.getClipboard( &pIDataObject );
126
127 if ( SUCCEEDED( hr ) )
128 {
129 // create an apartment neutral dataobject and initialize it with a
130 // com smart pointer to the IDataObject from clipboard
131 IDataObjectPtr pIDo( new CAPNDataObject( pIDataObject ) );
132
133 CDTransObjFactory objFactory;
134
135 // remember pIDo destroys itself due to the smart pointer
136 rClipContent = objFactory.createTransferableFromDataObj( m_pWinClipboard->m_SrvMgr, pIDo );
137 }
138
139 return rClipContent;
140 }
141
142 //------------------------------------------------------------------------
143 // setContent
144 //------------------------------------------------------------------------
145
setContents(const Reference<XTransferable> & xTransferable,const Reference<XClipboardOwner> & xClipboardOwner)146 void SAL_CALL CWinClipbImpl::setContents(
147 const Reference< XTransferable >& xTransferable,
148 const Reference< XClipboardOwner >& xClipboardOwner )
149 throw( RuntimeException )
150 {
151 CDTransObjFactory objFactory;
152 IDataObjectPtr pIDataObj;
153
154 if ( xTransferable.is( ) )
155 {
156 ClearableMutexGuard aGuard( m_ClipContentMutex );
157
158 m_pCurrentClipContent = new CXNotifyingDataObject(
159 objFactory.createDataObjFromTransferable( m_pWinClipboard->m_SrvMgr , xTransferable ),
160 xTransferable,
161 xClipboardOwner,
162 this );
163
164 aGuard.clear( );
165
166 pIDataObj = IDataObjectPtr( m_pCurrentClipContent );
167 }
168
169 m_MtaOleClipboard.setClipboard(pIDataObj.get());
170 }
171
172 //------------------------------------------------------------------------
173 //
174 //------------------------------------------------------------------------
175
getName()176 OUString SAL_CALL CWinClipbImpl::getName( ) throw( RuntimeException )
177 {
178 return m_itsName;
179 }
180
181 //------------------------------------------------------------------------
182 //
183 //------------------------------------------------------------------------
184
getRenderingCapabilities()185 sal_Int8 SAL_CALL CWinClipbImpl::getRenderingCapabilities( ) throw( RuntimeException )
186 {
187 return ( Delayed | Persistant );
188 }
189
190 //------------------------------------------------------------------------
191 //
192 //------------------------------------------------------------------------
193
flushClipboard()194 void SAL_CALL CWinClipbImpl::flushClipboard( ) throw( RuntimeException )
195 {
196 // sollte eigentlich hier stehen: ClearableMutexGuard aGuard( m_ClipContentMutex );
197 // geht aber nicht, da FlushClipboard zur�ckruft und das DataObject
198 // freigibt und damit w�rde es einen Deadlock in onReleaseDataObject geben
199 // FlushClipboard mu� synchron sein, damit das runterfahren ggf. erst weitergeht,
200 // wenn alle Clipboard-Formate gerendert wurden
201 // die Abfrage ist n�tig, damit nur geflusht wird, wenn wir wirklich Clipboardowner
202 // sind (ich weiss nicht genau was passiert, wenn man flusht und nicht Clipboard
203 // owner ist).
204 // eventuell kann man aber die Abfrage in den Clipboard STA Thread verlagern, indem
205 // man sich dort das DataObject merkt und vor dem flushen OleIsCurrentClipboard ruft
206
207 if ( NULL != m_pCurrentClipContent )
208 m_MtaOleClipboard.flushClipboard( );
209 }
210
211 //------------------------------------------------------------------------
212 //
213 //------------------------------------------------------------------------
214
registerClipboardViewer()215 void SAL_CALL CWinClipbImpl::registerClipboardViewer( )
216 {
217 m_MtaOleClipboard.registerClipViewer( CWinClipbImpl::onClipboardContentChanged );
218 }
219
220 //------------------------------------------------------------------------
221 //
222 //------------------------------------------------------------------------
223
unregisterClipboardViewer()224 void SAL_CALL CWinClipbImpl::unregisterClipboardViewer( )
225 {
226 m_MtaOleClipboard.registerClipViewer( NULL );
227 }
228
229 //------------------------------------------------------------------------
230 //
231 //------------------------------------------------------------------------
232
dispose()233 void SAL_CALL CWinClipbImpl::dispose() throw( RuntimeException )
234 {
235 OSL_ENSURE( !m_pCurrentClipContent, "Clipboard was not flushed before shutdown!" );
236 }
237
238 //------------------------------------------------------------------------
239 //
240 //------------------------------------------------------------------------
241
onClipboardContentChanged(void)242 void WINAPI CWinClipbImpl::onClipboardContentChanged( void )
243 {
244 MutexGuard aGuard( s_aMutex );
245
246 // reassocition to instance through static member
247 if ( NULL != s_pCWinClipbImpl )
248 s_pCWinClipbImpl->m_pWinClipboard->notifyAllClipboardListener( );
249 }
250
251 //------------------------------------------------------------------------
252 //
253 //------------------------------------------------------------------------
254
onReleaseDataObject(CXNotifyingDataObject * theCaller)255 void SAL_CALL CWinClipbImpl::onReleaseDataObject( CXNotifyingDataObject* theCaller )
256 {
257 OSL_ASSERT( NULL != theCaller );
258
259 if ( theCaller )
260 theCaller->lostOwnership( );
261
262 // if the current caller is the one we currently
263 // hold, then set it to NULL because an external
264 // source must be the clipboardowner now
265 MutexGuard aGuard( m_ClipContentMutex );
266
267 if ( m_pCurrentClipContent == theCaller )
268 m_pCurrentClipContent = NULL;
269 }
270