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 "WinClipboard.hxx"
32 #include <com/sun/star/datatransfer/clipboard/ClipboardEvent.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 #include <com/sun/star/lang/IllegalArgumentException.hpp>
35 #include "WinClipbImpl.hxx"
36 
37 //------------------------------------------------------------------------
38 // namespace directives
39 //------------------------------------------------------------------------
40 
41 using namespace rtl;
42 using namespace osl;
43 using namespace std;
44 using namespace cppu;
45 
46 using namespace com::sun::star::uno;
47 using namespace com::sun::star::datatransfer;
48 using namespace com::sun::star::datatransfer::clipboard;
49 using namespace com::sun::star::lang;
50 
51 //------------------------------------------------------------------------
52 // defines
53 //------------------------------------------------------------------------
54 
55 #define WINCLIPBOARD_IMPL_NAME  "com.sun.star.datatransfer.clipboard.ClipboardW32"
56 
57 //------------------------------------------------------------------------
58 // helper functions
59 //------------------------------------------------------------------------
60 
61 namespace
62 {
63 	Sequence< OUString > SAL_CALL WinClipboard_getSupportedServiceNames()
64 	{
65 		Sequence< OUString > aRet(1);
66 		aRet[0] = OUString::createFromAscii("com.sun.star.datatransfer.clipboard.SystemClipboard");
67 		return aRet;
68 	}
69 }
70 
71 //------------------------------------------------------------------------
72 // ctor
73 //------------------------------------------------------------------------
74 /*XEventListener,*/
75 CWinClipboard::CWinClipboard( const Reference< XMultiServiceFactory >& rServiceManager, const OUString& aClipboardName ) :
76 	WeakComponentImplHelper4< XClipboardEx, XFlushableClipboard, XClipboardNotifier, XServiceInfo >( m_aCbListenerMutex ),
77 	m_SrvMgr( rServiceManager )
78 {
79 	m_pImpl.reset( new CWinClipbImpl( aClipboardName, this ) );
80 }
81 
82 //========================================================================
83 // XClipboard
84 //========================================================================
85 
86 //------------------------------------------------------------------------
87 // getContent
88 // to avoid unecessary traffic we check first if there is a clipboard
89 // content which was set via setContent, in this case we don't need
90 // to query the content from the clipboard, create a new wrapper object
91 // and so on, we simply return the orignial XTransferable instead of our
92 // DOTransferable
93 //------------------------------------------------------------------------
94 
95 Reference< XTransferable > SAL_CALL CWinClipboard::getContents( ) throw( RuntimeException )
96 {
97 	MutexGuard aGuard( m_aMutex );
98 
99 	if ( rBHelper.bDisposed )
100 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
101 								 static_cast< XClipboardEx* >( this ) );
102 
103 	if ( NULL != m_pImpl.get( ) )
104 		return m_pImpl->getContents( );
105 
106 	return Reference< XTransferable >( );
107 }
108 
109 //------------------------------------------------------------------------
110 // setContent
111 //------------------------------------------------------------------------
112 
113 void SAL_CALL CWinClipboard::setContents( const Reference< XTransferable >& xTransferable,
114 										  const Reference< XClipboardOwner >& xClipboardOwner )
115 										  throw( RuntimeException )
116 {
117 	MutexGuard aGuard( m_aMutex );
118 
119 	if ( rBHelper.bDisposed )
120 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
121 								 static_cast< XClipboardEx* >( this ) );
122 
123 	if ( NULL != m_pImpl.get( ) )
124 		m_pImpl->setContents( xTransferable, xClipboardOwner );
125 }
126 
127 //------------------------------------------------------------------------
128 // getName
129 //------------------------------------------------------------------------
130 
131 OUString SAL_CALL CWinClipboard::getName(  ) throw( RuntimeException )
132 {
133 	if ( rBHelper.bDisposed )
134 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
135 								 static_cast< XClipboardEx* >( this ) );
136 
137 	if ( NULL != m_pImpl.get( ) )
138 		return m_pImpl->getName( );
139 
140 	return OUString::createFromAscii( "" );
141 }
142 
143 //========================================================================
144 // XFlushableClipboard
145 //========================================================================
146 
147 void SAL_CALL CWinClipboard::flushClipboard( ) throw( RuntimeException )
148 {
149 	MutexGuard aGuard( m_aMutex );
150 
151 	if ( rBHelper.bDisposed )
152 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
153 								 static_cast< XClipboardEx* >( this ) );
154 
155 	if ( NULL != m_pImpl.get( ) )
156 		m_pImpl->flushClipboard( );
157 }
158 
159 //========================================================================
160 // XClipboardEx
161 //========================================================================
162 
163 sal_Int8 SAL_CALL CWinClipboard::getRenderingCapabilities(  ) throw( RuntimeException )
164 {
165 	if ( rBHelper.bDisposed )
166 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
167 								 static_cast< XClipboardEx* >( this ) );
168 
169 	if ( NULL != m_pImpl.get( ) )
170 		return m_pImpl->getRenderingCapabilities( );
171 
172 	return 0;
173 }
174 
175 //========================================================================
176 // XClipboardNotifier
177 //========================================================================
178 
179 //------------------------------------------------------------------------
180 // getName
181 //------------------------------------------------------------------------
182 
183 void SAL_CALL CWinClipboard::addClipboardListener( const Reference< XClipboardListener >& listener )
184 	throw( RuntimeException )
185 {
186 	if ( rBHelper.bDisposed )
187 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
188 								 static_cast< XClipboardEx* >( this ) );
189 
190 	// check input parameter
191 	if ( !listener.is( ) )
192 		throw IllegalArgumentException( OUString::createFromAscii( "empty reference" ),
193 										static_cast< XClipboardEx* >( this ),
194 										1 );
195 
196 	rBHelper.aLC.addInterface( getCppuType( &listener ), listener );
197 }
198 
199 //------------------------------------------------------------------------
200 // getName
201 //------------------------------------------------------------------------
202 
203 void SAL_CALL CWinClipboard::removeClipboardListener( const Reference< XClipboardListener >& listener )
204 	throw( RuntimeException )
205 {
206 	if ( rBHelper.bDisposed )
207 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
208 								 static_cast< XClipboardEx* >( this ) );
209 
210 	// check input parameter
211 	if ( !listener.is( ) )
212 		throw IllegalArgumentException( OUString::createFromAscii( "empty reference" ),
213 										static_cast< XClipboardEx* >( this ),
214 										1 );
215 
216 	rBHelper.aLC.removeInterface( getCppuType( &listener ), listener );
217 }
218 
219 //------------------------------------------------------------------------
220 // getName
221 //------------------------------------------------------------------------
222 
223 void SAL_CALL CWinClipboard::notifyAllClipboardListener( )
224 {
225 	if ( !rBHelper.bDisposed )
226 	{
227 		ClearableMutexGuard aGuard( rBHelper.rMutex );
228 		if ( !rBHelper.bDisposed )
229 		{
230 			aGuard.clear( );
231 
232 			OInterfaceContainerHelper* pICHelper = rBHelper.aLC.getContainer(
233 				getCppuType( ( Reference< XClipboardListener > * ) 0 ) );
234 
235 			if ( pICHelper )
236 			{
237 			    try
238 			    {
239 				    OInterfaceIteratorHelper iter(*pICHelper);
240 				    Reference<XTransferable> rXTransf(m_pImpl->getContents());
241 				    ClipboardEvent aClipbEvent(static_cast<XClipboard*>(this), rXTransf);
242 
243 				    while(iter.hasMoreElements())
244 				    {
245 					    try
246 					    {
247 						    Reference<XClipboardListener> xCBListener(iter.next(), UNO_QUERY);
248 						    if (xCBListener.is())
249 							    xCBListener->changedContents(aClipbEvent);
250 					    }
251 					    catch(RuntimeException&)
252 					    {
253 						    OSL_ENSURE( false, "RuntimeException caught" );
254 					    }
255 				    }
256 				}
257 			    catch(const ::com::sun::star::lang::DisposedException&)
258 			    {
259 			        OSL_ENSURE(false, "Service Manager disposed");
260 
261 			        // no further clipboard changed notifications
262 			        m_pImpl->unregisterClipboardViewer();
263 			    }
264 
265 			} // end if
266 		} // end if
267 	} // end if
268 }
269 
270 //------------------------------------------------
271 // overwritten base class method which will be
272 // called by the base class dispose method
273 //------------------------------------------------
274 
275 void SAL_CALL CWinClipboard::disposing()
276 {
277 	// do my own stuff
278 	m_pImpl->dispose( );
279 
280 	// force destruction of the impl class
281 	m_pImpl.reset();
282 }
283 
284 // -------------------------------------------------
285 // XServiceInfo
286 // -------------------------------------------------
287 
288 OUString SAL_CALL CWinClipboard::getImplementationName(  )
289 	throw(RuntimeException)
290 {
291 	return OUString::createFromAscii( WINCLIPBOARD_IMPL_NAME );
292 }
293 
294 // -------------------------------------------------
295 //	XServiceInfo
296 // -------------------------------------------------
297 
298 sal_Bool SAL_CALL CWinClipboard::supportsService( const OUString& ServiceName )
299 	throw(RuntimeException)
300 {
301 	Sequence < OUString > SupportedServicesNames = WinClipboard_getSupportedServiceNames();
302 
303 	for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
304 		if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
305 			return sal_True;
306 
307 	return sal_False;
308 }
309 
310 // -------------------------------------------------
311 //	XServiceInfo
312 // -------------------------------------------------
313 
314 Sequence< OUString > SAL_CALL CWinClipboard::getSupportedServiceNames(	 )
315 	throw(RuntimeException)
316 {
317 	return WinClipboard_getSupportedServiceNames();
318 }
319