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 
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 
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 
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 		// remeber 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 
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 
176 OUString SAL_CALL CWinClipbImpl::getName(  ) throw( RuntimeException )
177 {
178 	return m_itsName;
179 }
180 
181 //------------------------------------------------------------------------
182 //
183 //------------------------------------------------------------------------
184 
185 sal_Int8 SAL_CALL CWinClipbImpl::getRenderingCapabilities(  ) throw( RuntimeException )
186 {
187 	return ( Delayed | Persistant );
188 }
189 
190 //------------------------------------------------------------------------
191 //
192 //------------------------------------------------------------------------
193 
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 
215 void SAL_CALL CWinClipbImpl::registerClipboardViewer( )
216 {
217 	m_MtaOleClipboard.registerClipViewer( CWinClipbImpl::onClipboardContentChanged );
218 }
219 
220 //------------------------------------------------------------------------
221 //
222 //------------------------------------------------------------------------
223 
224 void SAL_CALL CWinClipbImpl::unregisterClipboardViewer( )
225 {
226 	m_MtaOleClipboard.registerClipViewer( NULL );
227 }
228 
229 //------------------------------------------------------------------------
230 //
231 //------------------------------------------------------------------------
232 
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 
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 
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