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