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