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_vcl.hxx"
30 
31 #include <X11/Xatom.h>
32 #include <X11_clipboard.hxx>
33 #include <X11_transferable.hxx>
34 #include <com/sun/star/lang/DisposedException.hpp>
35 #include <com/sun/star/datatransfer/clipboard/RenderingCapabilities.hpp>
36 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
37 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
38 #include <com/sun/star/registry/XRegistryKey.hpp>
39 #include <uno/dispatcher.h> // declaration of generic uno interface
40 #include <uno/mapping.hxx> // mapping stuff
41 #include <cppuhelper/factory.hxx>
42 #include <rtl/tencinfo.h>
43 
44 #if OSL_DEBUG_LEVEL > 1
45 #include <stdio.h>
46 #endif
47 
48 using namespace com::sun::star::datatransfer;
49 using namespace com::sun::star::datatransfer::clipboard;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::awt;
53 using namespace cppu;
54 using namespace osl;
55 using namespace rtl;
56 using namespace x11;
57 
58 X11Clipboard::X11Clipboard( SelectionManager& rManager, Atom aSelection ) :
59         ::cppu::WeakComponentImplHelper4<
60     ::com::sun::star::datatransfer::clipboard::XClipboardEx,
61     ::com::sun::star::datatransfer::clipboard::XClipboardNotifier,
62     ::com::sun::star::lang::XServiceInfo,
63     ::com::sun::star::lang::XInitialization
64     >( rManager.getMutex() ),
65 
66 		m_rSelectionManager( rManager ),
67 		m_xSelectionManager( & rManager ),
68 		m_aSelection( aSelection )
69 {
70 #if OSL_DEBUG_LEVEL > 1
71 	fprintf( stderr, "creating instance of X11Clipboard (this=%p)\n", this );
72 #endif
73 
74 	if( m_aSelection != None )
75     {
76 		m_rSelectionManager.registerHandler( m_aSelection, *this );
77     }
78 	else
79 	{
80 		m_rSelectionManager.registerHandler( XA_PRIMARY, *this );
81 		m_rSelectionManager.registerHandler( m_rSelectionManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ), *this );
82 	}
83 }
84 
85 // ------------------------------------------------------------------------
86 
87 X11Clipboard::~X11Clipboard()
88 {
89 	MutexGuard aGuard( *Mutex::getGlobalMutex() );
90 
91 #if OSL_DEBUG_LEVEL > 1
92 	fprintf( stderr, "shutting down instance of X11Clipboard (this=%p, Selecttion=\"%s\")\n", this, OUStringToOString( m_rSelectionManager.getString( m_aSelection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
93 #endif
94 	if( m_aSelection != None )
95 		m_rSelectionManager.deregisterHandler( m_aSelection );
96 	else
97 	{
98 		m_rSelectionManager.deregisterHandler( XA_PRIMARY );
99 		m_rSelectionManager.deregisterHandler( m_rSelectionManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ) );
100 	}
101 }
102 
103 
104 // ------------------------------------------------------------------------
105 
106 void X11Clipboard::fireChangedContentsEvent()
107 {
108     ClearableMutexGuard aGuard( m_rSelectionManager.getMutex() );
109 #if OSL_DEBUG_LEVEL > 1
110     fprintf( stderr, "X11Clipboard::fireChangedContentsEvent for %s (%d listeners)\n",
111              OUStringToOString( m_rSelectionManager.getString( m_aSelection ), RTL_TEXTENCODING_ISO_8859_1 ).getStr(), m_aListeners.size() );
112 #endif
113     ::std::list< Reference< XClipboardListener > > listeners( m_aListeners );
114     aGuard.clear();
115 
116     ClipboardEvent aEvent( static_cast<OWeakObject*>(this), m_aContents);
117     while( listeners.begin() != listeners.end() )
118     {
119         if( listeners.front().is() )
120             listeners.front()->changedContents(aEvent);
121         listeners.pop_front();
122     }
123 }
124 
125 // ------------------------------------------------------------------------
126 
127 void X11Clipboard::clearContents()
128 {
129 	ClearableMutexGuard aGuard(m_rSelectionManager.getMutex());
130     // protect against deletion during outside call
131     Reference< XClipboard > xThis( static_cast<XClipboard*>(this));
132     // copy member references on stack so they can be called
133     // without having the mutex
134     Reference< XClipboardOwner > xOwner( m_aOwner );
135     Reference< XTransferable > xTrans( m_aContents );
136 	// clear members
137     m_aOwner.clear();
138     m_aContents.clear();
139 
140     // release the mutex
141     aGuard.clear();
142 
143     // inform previous owner of lost ownership
144 	if ( xOwner.is() )
145 		xOwner->lostOwnership(xThis, m_aContents);
146 }
147 
148 // ------------------------------------------------------------------------
149 
150 Reference< XTransferable > SAL_CALL X11Clipboard::getContents()
151 	throw(RuntimeException)
152 {
153 	MutexGuard aGuard(m_rSelectionManager.getMutex());
154 
155 	if( ! m_aContents.is() )
156 		m_aContents = new X11Transferable( SelectionManager::get(), static_cast< OWeakObject* >(this), m_aSelection );
157 	return m_aContents;
158 }
159 
160 // ------------------------------------------------------------------------
161 
162 void SAL_CALL X11Clipboard::setContents(
163 	const Reference< XTransferable >& xTrans,
164 	const Reference< XClipboardOwner >& xClipboardOwner )
165 	throw(RuntimeException)
166 {
167 	// remember old values for callbacks before setting the new ones.
168 	ClearableMutexGuard aGuard(m_rSelectionManager.getMutex());
169 
170 	Reference< XClipboardOwner > oldOwner( m_aOwner );
171 	m_aOwner = xClipboardOwner;
172 
173 	Reference< XTransferable > oldContents( m_aContents );
174 	m_aContents = xTrans;
175 
176 	aGuard.clear();
177 
178 	// for now request ownership for both selections
179 	if( m_aSelection != None )
180 		m_rSelectionManager.requestOwnership( m_aSelection );
181 	else
182 	{
183 		m_rSelectionManager.requestOwnership( XA_PRIMARY );
184 		m_rSelectionManager.requestOwnership( m_rSelectionManager.getAtom( OUString::createFromAscii( "CLIPBOARD" ) ) );
185 	}
186 
187 	// notify old owner on loss of ownership
188 	if( oldOwner.is() )
189 		oldOwner->lostOwnership(static_cast < XClipboard * > (this), oldContents);
190 
191 	// notify all listeners on content changes
192 	fireChangedContentsEvent();
193 }
194 
195 // ------------------------------------------------------------------------
196 
197 OUString SAL_CALL X11Clipboard::getName()
198 	throw(RuntimeException)
199 {
200 	return m_rSelectionManager.getString( m_aSelection );
201 }
202 
203 // ------------------------------------------------------------------------
204 
205 sal_Int8 SAL_CALL X11Clipboard::getRenderingCapabilities()
206 	throw(RuntimeException)
207 {
208 	return RenderingCapabilities::Delayed;
209 }
210 
211 
212 // ------------------------------------------------------------------------
213 void SAL_CALL X11Clipboard::addClipboardListener( const Reference< XClipboardListener >& listener )
214 	throw(RuntimeException)
215 {
216     MutexGuard aGuard( m_rSelectionManager.getMutex() );
217     m_aListeners.push_back( listener );
218 }
219 
220 // ------------------------------------------------------------------------
221 
222 void SAL_CALL X11Clipboard::removeClipboardListener( const Reference< XClipboardListener >& listener )
223 	throw(RuntimeException)
224 {
225     MutexGuard aGuard( m_rSelectionManager.getMutex() );
226     m_aListeners.remove( listener );
227 }
228 
229 
230 // ------------------------------------------------------------------------
231 
232 Reference< XTransferable > X11Clipboard::getTransferable()
233 {
234 	return getContents();
235 }
236 
237 // ------------------------------------------------------------------------
238 
239 void X11Clipboard::clearTransferable()
240 {
241 	clearContents();
242 }
243 
244 // ------------------------------------------------------------------------
245 
246 void X11Clipboard::fireContentsChanged()
247 {
248     fireChangedContentsEvent();
249 }
250 
251 // ------------------------------------------------------------------------
252 
253 Reference< XInterface > X11Clipboard::getReference() throw()
254 {
255     return Reference< XInterface >( static_cast< OWeakObject* >(this) );
256 }
257 
258 // ------------------------------------------------------------------------
259 
260 OUString SAL_CALL X11Clipboard::getImplementationName(  )
261 	throw(RuntimeException)
262 {
263 	return OUString::createFromAscii(X11_CLIPBOARD_IMPLEMENTATION_NAME);
264 }
265 
266 // ------------------------------------------------------------------------
267 
268 sal_Bool SAL_CALL X11Clipboard::supportsService( const OUString& ServiceName )
269 	throw(RuntimeException)
270 {
271 	Sequence < OUString > SupportedServicesNames = X11Clipboard_getSupportedServiceNames();
272 
273 	for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
274 		if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
275 			return sal_True;
276 
277 	return sal_False;
278 }
279 
280 // ------------------------------------------------------------------------
281 
282 void SAL_CALL X11Clipboard::initialize( const Sequence< Any >& ) throw( ::com::sun::star::uno::Exception )
283 {
284 }
285 
286 // ------------------------------------------------------------------------
287 
288 Sequence< OUString > SAL_CALL X11Clipboard::getSupportedServiceNames(	 )
289 	throw(RuntimeException)
290 {
291 	return X11Clipboard_getSupportedServiceNames();
292 }
293 
294