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