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( )
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 {
150 CDTransObjFactory objFactory;
151 IDataObjectPtr pIDataObj;
152
153 if ( xTransferable.is( ) )
154 {
155 ClearableMutexGuard aGuard( m_ClipContentMutex );
156
157 m_pCurrentClipContent = new CXNotifyingDataObject(
158 objFactory.createDataObjFromTransferable( m_pWinClipboard->m_SrvMgr , xTransferable ),
159 xTransferable,
160 xClipboardOwner,
161 this );
162
163 aGuard.clear( );
164
165 pIDataObj = IDataObjectPtr( m_pCurrentClipContent );
166 }
167
168 m_MtaOleClipboard.setClipboard(pIDataObj.get());
169 }
170
171 //------------------------------------------------------------------------
172 //
173 //------------------------------------------------------------------------
174
getName()175 OUString SAL_CALL CWinClipbImpl::getName( )
176 {
177 return m_itsName;
178 }
179
180 //------------------------------------------------------------------------
181 //
182 //------------------------------------------------------------------------
183
getRenderingCapabilities()184 sal_Int8 SAL_CALL CWinClipbImpl::getRenderingCapabilities( )
185 {
186 return ( Delayed | Persistant );
187 }
188
189 //------------------------------------------------------------------------
190 //
191 //------------------------------------------------------------------------
192
flushClipboard()193 void SAL_CALL CWinClipbImpl::flushClipboard( )
194 {
195 // sollte eigentlich hier stehen: ClearableMutexGuard aGuard( m_ClipContentMutex );
196 // geht aber nicht, da FlushClipboard zur�ckruft und das DataObject
197 // freigibt und damit w�rde es einen Deadlock in onReleaseDataObject geben
198 // FlushClipboard mu� synchron sein, damit das runterfahren ggf. erst weitergeht,
199 // wenn alle Clipboard-Formate gerendert wurden
200 // die Abfrage ist n�tig, damit nur geflusht wird, wenn wir wirklich Clipboardowner
201 // sind (ich weiss nicht genau was passiert, wenn man flusht und nicht Clipboard
202 // owner ist).
203 // eventuell kann man aber die Abfrage in den Clipboard STA Thread verlagern, indem
204 // man sich dort das DataObject merkt und vor dem flushen OleIsCurrentClipboard ruft
205
206 if ( NULL != m_pCurrentClipContent )
207 m_MtaOleClipboard.flushClipboard( );
208 }
209
210 //------------------------------------------------------------------------
211 //
212 //------------------------------------------------------------------------
213
registerClipboardViewer()214 void SAL_CALL CWinClipbImpl::registerClipboardViewer( )
215 {
216 m_MtaOleClipboard.registerClipViewer( CWinClipbImpl::onClipboardContentChanged );
217 }
218
219 //------------------------------------------------------------------------
220 //
221 //------------------------------------------------------------------------
222
unregisterClipboardViewer()223 void SAL_CALL CWinClipbImpl::unregisterClipboardViewer( )
224 {
225 m_MtaOleClipboard.registerClipViewer( NULL );
226 }
227
228 //------------------------------------------------------------------------
229 //
230 //------------------------------------------------------------------------
231
dispose()232 void SAL_CALL CWinClipbImpl::dispose()
233 {
234 OSL_ENSURE( !m_pCurrentClipContent, "Clipboard was not flushed before shutdown!" );
235 }
236
237 //------------------------------------------------------------------------
238 //
239 //------------------------------------------------------------------------
240
onClipboardContentChanged(void)241 void WINAPI CWinClipbImpl::onClipboardContentChanged( void )
242 {
243 MutexGuard aGuard( s_aMutex );
244
245 // reassocition to instance through static member
246 if ( NULL != s_pCWinClipbImpl )
247 s_pCWinClipbImpl->m_pWinClipboard->notifyAllClipboardListener( );
248 }
249
250 //------------------------------------------------------------------------
251 //
252 //------------------------------------------------------------------------
253
onReleaseDataObject(CXNotifyingDataObject * theCaller)254 void SAL_CALL CWinClipbImpl::onReleaseDataObject( CXNotifyingDataObject* theCaller )
255 {
256 OSL_ASSERT( NULL != theCaller );
257
258 if ( theCaller )
259 theCaller->lostOwnership( );
260
261 // if the current caller is the one we currently
262 // hold, then set it to NULL because an external
263 // source must be the clipboardowner now
264 MutexGuard aGuard( m_ClipContentMutex );
265
266 if ( m_pCurrentClipContent == theCaller )
267 m_pCurrentClipContent = NULL;
268 }
269