Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include <cassert>
23 :
24 : #include <boost/logic/tribool.hpp>
25 : #include <config_folders.h>
26 : #include <shutdownicon.hxx>
27 : #include <app.hrc>
28 : #include <sfx2/app.hxx>
29 : #include <osl/mutex.hxx>
30 : #include <svtools/imagemgr.hxx>
31 : #include <svtools/miscopt.hxx>
32 : #include <com/sun/star/task/InteractionHandler.hpp>
33 : #include <com/sun/star/frame/Desktop.hpp>
34 : #include <com/sun/star/frame/XDispatchResultListener.hpp>
35 : #include <com/sun/star/frame/XNotifyingDispatch.hpp>
36 : #include <com/sun/star/frame/XFramesSupplier.hpp>
37 : #include <com/sun/star/frame/XComponentLoader.hpp>
38 : #include <com/sun/star/frame/XFrame.hpp>
39 : #include <com/sun/star/util/URLTransformer.hpp>
40 : #include <com/sun/star/util/XURLTransformer.hpp>
41 : #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
42 : #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
43 : #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
44 : #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
45 : #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
46 : #include <com/sun/star/ui/dialogs/ControlActions.hpp>
47 : #include <com/sun/star/document/MacroExecMode.hpp>
48 : #include <com/sun/star/document/UpdateDocMode.hpp>
49 : #include <sfx2/filedlghelper.hxx>
50 : #include <sfx2/fcontnr.hxx>
51 : #include <comphelper/processfactory.hxx>
52 : #include <cppuhelper/compbase1.hxx>
53 : #include <cppuhelper/supportsservice.hxx>
54 : #include <sfx2/dispatch.hxx>
55 : #include <comphelper/extract.hxx>
56 : #include <tools/urlobj.hxx>
57 : #include <osl/security.hxx>
58 : #include <osl/file.hxx>
59 : #include <rtl/bootstrap.hxx>
60 : #include <rtl/ref.hxx>
61 : #include <rtl/ustrbuf.hxx>
62 : #ifdef UNX // need symlink
63 : #include <unistd.h>
64 : #include <errno.h>
65 : #endif
66 :
67 : #include <sfx2/sfxresid.hxx>
68 :
69 : using namespace ::com::sun::star;
70 : using namespace ::com::sun::star::uno;
71 : using namespace ::com::sun::star::frame;
72 : using namespace ::com::sun::star::container;
73 : using namespace ::com::sun::star::io;
74 : using namespace ::com::sun::star::lang;
75 : using namespace ::com::sun::star::beans;
76 : using namespace ::com::sun::star::util;
77 : using namespace ::com::sun::star::ui::dialogs;
78 : using namespace ::sfx2;
79 :
80 : #ifdef ENABLE_QUICKSTART_APPLET
81 : # if !defined(WIN32) && !defined(MACOSX)
82 0 : extern "C" { static void SAL_CALL thisModule() {} }
83 : # endif
84 : #endif
85 :
86 0 : class SfxNotificationListener_Impl : public cppu::WeakImplHelper1< XDispatchResultListener >
87 : {
88 : public:
89 : virtual void SAL_CALL dispatchFinished( const DispatchResultEvent& aEvent ) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
90 : virtual void SAL_CALL disposing( const EventObject& aEvent ) throw( RuntimeException, std::exception ) SAL_OVERRIDE;
91 : };
92 :
93 0 : void SAL_CALL SfxNotificationListener_Impl::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException, std::exception )
94 : {
95 0 : ShutdownIcon::LeaveModalMode();
96 0 : }
97 :
98 0 : void SAL_CALL SfxNotificationListener_Impl::disposing( const EventObject& ) throw( RuntimeException, std::exception )
99 : {
100 0 : }
101 :
102 0 : OUString SAL_CALL ShutdownIcon::getImplementationName()
103 : throw (css::uno::RuntimeException, std::exception)
104 : {
105 0 : return OUString("com.sun.star.comp.desktop.QuickstartWrapper");
106 : }
107 :
108 0 : sal_Bool SAL_CALL ShutdownIcon::supportsService(OUString const & ServiceName)
109 : throw (css::uno::RuntimeException, std::exception)
110 : {
111 0 : return cppu::supportsService(this, ServiceName);
112 : }
113 :
114 0 : css::uno::Sequence<OUString> SAL_CALL ShutdownIcon::getSupportedServiceNames()
115 : throw (css::uno::RuntimeException, std::exception)
116 : {
117 0 : css::uno::Sequence< OUString > aSeq(1);
118 0 : aSeq[0] = OUString("com.sun.star.office.Quickstart");
119 0 : return aSeq;
120 : }
121 :
122 : bool ShutdownIcon::bModalMode = false;
123 : ShutdownIcon* ShutdownIcon::pShutdownIcon = NULL;
124 :
125 : #if !defined( ENABLE_QUICKSTART_APPLET )
126 : // To remove conditionals
127 : extern "C" {
128 : static void disabled_initSystray() { }
129 : static void disabled_deInitSystray() { }
130 : }
131 : #endif
132 :
133 : namespace {
134 :
135 317 : boost::logic::tribool loaded(boost::logic::indeterminate);
136 : oslGenericFunction pInitSystray(nullptr);
137 : oslGenericFunction pDeInitSystray(nullptr);
138 :
139 0 : bool LoadModule()
140 : {
141 0 : if (boost::logic::indeterminate(loaded))
142 : {
143 : #ifdef ENABLE_QUICKSTART_APPLET
144 : # ifdef WIN32
145 : pInitSystray = win32_init_sys_tray;
146 : pDeInitSystray = win32_shutdown_sys_tray;
147 : loaded = true;
148 : # elif defined MACOSX
149 : pInitSystray = aqua_init_systray;
150 : pDeInitSystray = aqua_shutdown_systray;
151 : loaded = true;
152 : # else // UNX
153 0 : osl::Module plugin;
154 0 : oslGenericFunction pTmpInit = NULL;
155 0 : oslGenericFunction pTmpDeInit = NULL;
156 0 : if ( plugin.loadRelative( &thisModule, "libqstart_gtklo.so" ) )
157 : {
158 0 : pTmpInit = plugin.getFunctionSymbol( "plugin_init_sys_tray" );
159 0 : pTmpDeInit = plugin.getFunctionSymbol( "plugin_shutdown_sys_tray" );
160 : }
161 0 : if ( !pTmpInit || !pTmpDeInit )
162 : {
163 0 : loaded = false;
164 : }
165 : else
166 : {
167 0 : plugin.release();
168 0 : pInitSystray = pTmpInit;
169 0 : pDeInitSystray = pTmpDeInit;
170 0 : loaded = true;
171 0 : }
172 : # endif // UNX
173 : #else
174 : pInitSystray = disabled_initSystray;
175 : pDeInitSystray = disabled_deInitSystray;
176 : loaded = false;
177 : #endif // ENABLE_QUICKSTART_APPLET
178 : }
179 : assert(!boost::logic::indeterminate(loaded));
180 0 : return loaded;
181 : }
182 :
183 : }
184 :
185 0 : void ShutdownIcon::initSystray()
186 : {
187 0 : if (m_bInitialized)
188 0 : return;
189 0 : m_bInitialized = true;
190 :
191 0 : (void) LoadModule();
192 0 : m_bVeto = true;
193 0 : pInitSystray();
194 : }
195 :
196 4 : void ShutdownIcon::deInitSystray()
197 : {
198 4 : if (!m_bInitialized)
199 8 : return;
200 :
201 0 : if (pDeInitSystray)
202 0 : pDeInitSystray();
203 :
204 0 : m_bVeto = false;
205 0 : pInitSystray = 0;
206 0 : pDeInitSystray = 0;
207 :
208 0 : delete m_pFileDlg;
209 0 : m_pFileDlg = NULL;
210 0 : m_bInitialized = false;
211 : }
212 :
213 :
214 2 : ShutdownIcon::ShutdownIcon( const ::com::sun::star::uno::Reference< XComponentContext > & rxContext ) :
215 : ShutdownIconServiceBase( m_aMutex ),
216 : m_bVeto ( false ),
217 : m_bListenForTermination ( false ),
218 : m_bSystemDialogs( false ),
219 : m_pResMgr( NULL ),
220 : m_pFileDlg( NULL ),
221 : m_xContext( rxContext ),
222 2 : m_bInitialized( false )
223 : {
224 2 : m_bSystemDialogs = SvtMiscOptions().UseSystemFileDialog();
225 2 : }
226 :
227 6 : ShutdownIcon::~ShutdownIcon()
228 : {
229 2 : deInitSystray();
230 4 : }
231 :
232 :
233 :
234 0 : void ShutdownIcon::OpenURL( const OUString& aURL, const OUString& rTarget, const Sequence< PropertyValue >& aArgs )
235 : {
236 0 : if ( getInstance() && getInstance()->m_xDesktop.is() )
237 : {
238 0 : ::com::sun::star::uno::Reference < XDispatchProvider > xDispatchProvider( getInstance()->m_xDesktop, UNO_QUERY );
239 0 : if ( xDispatchProvider.is() )
240 : {
241 0 : com::sun::star::util::URL aDispatchURL;
242 0 : aDispatchURL.Complete = aURL;
243 :
244 0 : ::com::sun::star::uno::Reference< util::XURLTransformer > xURLTransformer( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
245 : try
246 : {
247 0 : ::com::sun::star::uno::Reference< com::sun::star::frame::XDispatch > xDispatch;
248 :
249 0 : xURLTransformer->parseStrict( aDispatchURL );
250 0 : xDispatch = xDispatchProvider->queryDispatch( aDispatchURL, rTarget, 0 );
251 0 : if ( xDispatch.is() )
252 0 : xDispatch->dispatch( aDispatchURL, aArgs );
253 : }
254 0 : catch ( com::sun::star::uno::RuntimeException& )
255 : {
256 0 : throw;
257 : }
258 0 : catch ( com::sun::star::uno::Exception& )
259 : {
260 0 : }
261 0 : }
262 : }
263 0 : }
264 :
265 :
266 :
267 0 : void ShutdownIcon::FileOpen()
268 : {
269 0 : if ( getInstance() && getInstance()->m_xDesktop.is() )
270 : {
271 0 : ::SolarMutexGuard aGuard;
272 0 : EnterModalMode();
273 0 : getInstance()->StartFileDialog();
274 : }
275 0 : }
276 :
277 :
278 :
279 0 : void ShutdownIcon::FromTemplate()
280 : {
281 0 : if ( getInstance() && getInstance()->m_xDesktop.is() )
282 : {
283 0 : ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFramesSupplier > xDesktop ( getInstance()->m_xDesktop, UNO_QUERY);
284 0 : ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame > xFrame( xDesktop->getActiveFrame() );
285 0 : if ( !xFrame.is() )
286 0 : xFrame = ::com::sun::star::uno::Reference < ::com::sun::star::frame::XFrame >( xDesktop, UNO_QUERY );
287 :
288 0 : URL aTargetURL;
289 0 : aTargetURL.Complete = "slot:5500";
290 0 : ::com::sun::star::uno::Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
291 0 : xTrans->parseStrict( aTargetURL );
292 :
293 0 : ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatchProvider > xProv( xFrame, UNO_QUERY );
294 0 : ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatch > xDisp;
295 0 : if ( xProv.is() )
296 : {
297 0 : if (aTargetURL.Protocol == "slot:")
298 0 : xDisp = xProv->queryDispatch( aTargetURL, OUString(), 0 );
299 : else
300 0 : xDisp = xProv->queryDispatch( aTargetURL, OUString("_blank"), 0 );
301 : }
302 0 : if ( xDisp.is() )
303 : {
304 0 : Sequence<PropertyValue> aArgs(1);
305 0 : PropertyValue* pArg = aArgs.getArray();
306 0 : pArg[0].Name = "Referer";
307 0 : pArg[0].Value <<= OUString("private:user");
308 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XNotifyingDispatch > xNotifyer( xDisp, UNO_QUERY );
309 0 : if ( xNotifyer.is() )
310 : {
311 0 : EnterModalMode();
312 0 : xNotifyer->dispatchWithNotification( aTargetURL, aArgs, new SfxNotificationListener_Impl() );
313 : }
314 : else
315 0 : xDisp->dispatch( aTargetURL, aArgs );
316 0 : }
317 : }
318 0 : }
319 :
320 :
321 : #include <tools/rcid.h>
322 0 : OUString ShutdownIcon::GetResString( int id )
323 : {
324 0 : ::SolarMutexGuard aGuard;
325 :
326 0 : if( ! m_pResMgr )
327 0 : m_pResMgr = SfxResId::GetResMgr();
328 0 : ResId aResId( id, *m_pResMgr );
329 0 : aResId.SetRT( RSC_STRING );
330 0 : if( !m_pResMgr || !m_pResMgr->IsAvailable( aResId ) )
331 0 : return OUString();
332 :
333 0 : return ResId(id, *m_pResMgr).toString();
334 : }
335 :
336 :
337 :
338 0 : OUString ShutdownIcon::GetUrlDescription( const OUString& aUrl )
339 : {
340 0 : ::SolarMutexGuard aGuard;
341 :
342 0 : return OUString( SvFileInformationManager::GetDescription( INetURLObject( aUrl ) ) );
343 : }
344 :
345 :
346 :
347 0 : void ShutdownIcon::StartFileDialog()
348 : {
349 0 : ::SolarMutexGuard aGuard;
350 :
351 0 : bool bDirty = ( m_bSystemDialogs != static_cast<bool>(SvtMiscOptions().UseSystemFileDialog()) );
352 :
353 0 : if ( m_pFileDlg && bDirty )
354 : {
355 : // Destroy instance as changing the system file dialog setting
356 : // forces us to create a new FileDialogHelper instance!
357 0 : delete m_pFileDlg;
358 0 : m_pFileDlg = NULL;
359 : }
360 :
361 0 : if ( !m_pFileDlg )
362 : m_pFileDlg = new FileDialogHelper(
363 : ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
364 0 : SFXWB_MULTISELECTION, OUString() );
365 0 : m_pFileDlg->StartExecuteModal( STATIC_LINK( this, ShutdownIcon, DialogClosedHdl_Impl ) );
366 0 : }
367 :
368 :
369 :
370 0 : IMPL_STATIC_LINK( ShutdownIcon, DialogClosedHdl_Impl, FileDialogHelper*, EMPTYARG )
371 : {
372 : DBG_ASSERT( pThis->m_pFileDlg, "ShutdownIcon, DialogClosedHdl_Impl(): no file dialog" );
373 :
374 : // use constructor for filling up filters automatically!
375 0 : if ( ERRCODE_NONE == pThis->m_pFileDlg->GetError() )
376 : {
377 0 : ::com::sun::star::uno::Reference< XFilePicker > xPicker = pThis->m_pFileDlg->GetFilePicker();
378 :
379 : try
380 : {
381 :
382 0 : if ( xPicker.is() )
383 : {
384 :
385 0 : ::com::sun::star::uno::Reference < XFilePickerControlAccess > xPickerControls ( xPicker, UNO_QUERY );
386 0 : ::com::sun::star::uno::Reference < XFilterManager > xFilterManager ( xPicker, UNO_QUERY );
387 :
388 0 : Sequence< OUString > sFiles = xPicker->getFiles();
389 0 : int nFiles = sFiles.getLength();
390 :
391 0 : int nArgs=3;
392 0 : Sequence< PropertyValue > aArgs(3);
393 :
394 : ::com::sun::star::uno::Reference < com::sun::star::task::XInteractionHandler2 > xInteraction(
395 0 : task::InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), 0) );
396 :
397 0 : aArgs[0].Name = "InteractionHandler";
398 0 : aArgs[0].Value <<= xInteraction;
399 :
400 0 : sal_Int16 nMacroExecMode = ::com::sun::star::document::MacroExecMode::USE_CONFIG;
401 0 : aArgs[1].Name = "MacroExecutionMode";
402 0 : aArgs[1].Value <<= nMacroExecMode;
403 :
404 0 : sal_Int16 nUpdateDoc = ::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG;
405 0 : aArgs[2].Name = "UpdateDocMode";
406 0 : aArgs[2].Value <<= nUpdateDoc;
407 :
408 : // use the filedlghelper to get the current filter name,
409 : // because it removes the extensions before you get the filter name.
410 0 : OUString aFilterName( pThis->m_pFileDlg->GetCurrentFilter() );
411 :
412 0 : if ( xPickerControls.is() )
413 : {
414 :
415 : // Set readonly flag
416 :
417 0 : bool bReadOnly = false;
418 :
419 :
420 0 : xPickerControls->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 ) >>= bReadOnly;
421 :
422 : // Only set porperty if readonly is set to TRUE
423 :
424 0 : if ( bReadOnly )
425 : {
426 0 : aArgs.realloc( ++nArgs );
427 0 : aArgs[nArgs-1].Name = "ReadOnly";
428 0 : aArgs[nArgs-1].Value <<= bReadOnly;
429 : }
430 :
431 : // Get version string
432 :
433 0 : sal_Int32 iVersion = -1;
434 :
435 0 : xPickerControls->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, ControlActions::GET_SELECTED_ITEM_INDEX ) >>= iVersion;
436 :
437 0 : if ( iVersion >= 0 )
438 : {
439 0 : sal_Int16 uVersion = (sal_Int16)iVersion;
440 :
441 0 : aArgs.realloc( ++nArgs );
442 0 : aArgs[nArgs-1].Name = "Version";
443 0 : aArgs[nArgs-1].Value <<= uVersion;
444 : }
445 :
446 : // Retrieve the current filter
447 :
448 0 : if ( aFilterName.isEmpty() )
449 0 : xPickerControls->getValue( CommonFilePickerElementIds::LISTBOX_FILTER, ControlActions::GET_SELECTED_ITEM ) >>= aFilterName;
450 :
451 : }
452 :
453 :
454 : // Convert UI filter name to internal filter name
455 :
456 0 : if ( !aFilterName.isEmpty() )
457 : {
458 0 : const SfxFilter* pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4UIName( aFilterName, 0, SFX_FILTER_NOTINFILEDLG );
459 :
460 0 : if ( pFilter )
461 : {
462 0 : aFilterName = pFilter->GetFilterName();
463 :
464 0 : if ( !aFilterName.isEmpty() )
465 : {
466 0 : aArgs.realloc( ++nArgs );
467 0 : aArgs[nArgs-1].Name = "FilterName";
468 0 : aArgs[nArgs-1].Value <<= aFilterName;
469 : }
470 : }
471 : }
472 :
473 0 : if ( 1 == nFiles )
474 0 : OpenURL( sFiles[0], OUString( "_default" ), aArgs );
475 : else
476 : {
477 0 : OUString aBaseDirURL = sFiles[0];
478 0 : if ( !aBaseDirURL.isEmpty() && !aBaseDirURL.endsWith("/") )
479 0 : aBaseDirURL += "/";
480 :
481 : int iFiles;
482 0 : for ( iFiles = 1; iFiles < nFiles; iFiles++ )
483 : {
484 0 : OUString aURL = aBaseDirURL;
485 0 : aURL += sFiles[iFiles];
486 0 : OpenURL( aURL, OUString( "_default" ), aArgs );
487 0 : }
488 0 : }
489 : }
490 : }
491 0 : catch ( ... )
492 : {
493 0 : }
494 : }
495 :
496 : #ifdef WNT
497 : // Destroy dialog to prevent problems with custom controls
498 : // This fix is dependent on the dialog settings. Destroying the dialog here will
499 : // crash the non-native dialog implementation! Therefore make this dependent on
500 : // the settings.
501 : if ( SvtMiscOptions().UseSystemFileDialog() )
502 : {
503 : delete pThis->m_pFileDlg;
504 : pThis->m_pFileDlg = NULL;
505 : }
506 : #endif
507 :
508 0 : LeaveModalMode();
509 0 : return 0;
510 : }
511 :
512 :
513 :
514 0 : void ShutdownIcon::addTerminateListener()
515 : {
516 0 : ShutdownIcon* pInst = getInstance();
517 0 : if ( ! pInst)
518 0 : return;
519 :
520 0 : if (pInst->m_bListenForTermination)
521 0 : return;
522 :
523 0 : ::com::sun::star::uno::Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
524 0 : if ( ! xDesktop.is())
525 0 : return;
526 :
527 0 : xDesktop->addTerminateListener( pInst );
528 0 : pInst->m_bListenForTermination = true;
529 : }
530 :
531 :
532 :
533 0 : void ShutdownIcon::terminateDesktop()
534 : {
535 0 : ShutdownIcon* pInst = getInstance();
536 0 : if ( ! pInst)
537 0 : return;
538 :
539 0 : ::com::sun::star::uno::Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
540 0 : if ( ! xDesktop.is())
541 0 : return;
542 :
543 : // always remove ourselves as listener
544 0 : pInst->m_bListenForTermination = true;
545 0 : xDesktop->removeTerminateListener( pInst );
546 :
547 : // terminate desktop only if no tasks exist
548 0 : ::com::sun::star::uno::Reference< XIndexAccess > xTasks ( xDesktop->getFrames(), UNO_QUERY );
549 0 : if( xTasks.is() && xTasks->getCount() < 1 )
550 0 : Application::Quit();
551 :
552 : // remove the instance pointer
553 0 : ShutdownIcon::pShutdownIcon = 0;
554 : }
555 :
556 :
557 :
558 0 : ShutdownIcon* ShutdownIcon::getInstance()
559 : {
560 : OSL_ASSERT( pShutdownIcon );
561 0 : return pShutdownIcon;
562 : }
563 :
564 :
565 :
566 0 : ShutdownIcon* ShutdownIcon::createInstance()
567 : {
568 0 : if (pShutdownIcon)
569 0 : return pShutdownIcon;
570 :
571 0 : ShutdownIcon *pIcon = NULL;
572 : try {
573 0 : pIcon = new ShutdownIcon( comphelper::getProcessComponentContext() );
574 0 : pIcon->init ();
575 0 : pShutdownIcon = pIcon;
576 0 : } catch (...) {
577 0 : delete pIcon;
578 : }
579 :
580 0 : return pShutdownIcon;
581 : }
582 :
583 0 : void ShutdownIcon::init() throw( ::com::sun::star::uno::Exception )
584 : {
585 : // access resource system and sfx only protected by solarmutex
586 0 : ::SolarMutexGuard aSolarGuard;
587 0 : ResMgr *pResMgr = SfxResId::GetResMgr();
588 :
589 0 : ::osl::ResettableMutexGuard aGuard( m_aMutex );
590 0 : m_pResMgr = pResMgr;
591 0 : aGuard.clear();
592 0 : ::com::sun::star::uno::Reference < XDesktop2 > xDesktop = Desktop::create( m_xContext );
593 0 : aGuard.reset();
594 0 : m_xDesktop = xDesktop;
595 0 : }
596 :
597 :
598 :
599 2 : void SAL_CALL ShutdownIcon::disposing()
600 : {
601 2 : m_xContext.clear();
602 2 : m_xDesktop.clear();
603 :
604 2 : deInitSystray();
605 2 : }
606 :
607 :
608 :
609 : // XEventListener
610 0 : void SAL_CALL ShutdownIcon::disposing( const ::com::sun::star::lang::EventObject& )
611 : throw(::com::sun::star::uno::RuntimeException, std::exception)
612 : {
613 0 : }
614 :
615 :
616 :
617 : // XTerminateListener
618 0 : void SAL_CALL ShutdownIcon::queryTermination( const ::com::sun::star::lang::EventObject& )
619 : throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException, std::exception)
620 : {
621 : SAL_INFO("sfx.appl", "ShutdownIcon::queryTermination: veto is " << m_bVeto);
622 0 : ::osl::ClearableMutexGuard aGuard( m_aMutex );
623 :
624 0 : if ( m_bVeto )
625 0 : throw ::com::sun::star::frame::TerminationVetoException();
626 0 : }
627 :
628 :
629 :
630 :
631 0 : void SAL_CALL ShutdownIcon::notifyTermination( const ::com::sun::star::lang::EventObject& )
632 : throw(::com::sun::star::uno::RuntimeException, std::exception)
633 : {
634 0 : }
635 :
636 :
637 :
638 :
639 2 : void SAL_CALL ShutdownIcon::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
640 : throw( ::com::sun::star::uno::Exception, std::exception )
641 : {
642 2 : ::osl::ResettableMutexGuard aGuard( m_aMutex );
643 :
644 : // third argument only sets veto, everything else will be ignored!
645 2 : if (aArguments.getLength() > 2)
646 : {
647 0 : bool bVeto = ::cppu::any2bool(aArguments[2]);
648 0 : m_bVeto = bVeto;
649 0 : return;
650 : }
651 :
652 2 : if ( aArguments.getLength() > 0 )
653 : {
654 0 : if ( !ShutdownIcon::pShutdownIcon )
655 : {
656 : try
657 : {
658 0 : bool bQuickstart = ::cppu::any2bool( aArguments[0] );
659 0 : if( !bQuickstart && !GetAutostart() )
660 0 : return;
661 0 : aGuard.clear();
662 0 : init ();
663 0 : aGuard.reset();
664 0 : if ( !m_xDesktop.is() )
665 0 : return;
666 :
667 : /* Create a sub-classed instance - foo */
668 0 : ShutdownIcon::pShutdownIcon = this;
669 0 : initSystray();
670 : }
671 0 : catch(const ::com::sun::star::lang::IllegalArgumentException&)
672 : {
673 : }
674 : }
675 : }
676 2 : if ( aArguments.getLength() > 1 )
677 : {
678 0 : bool bAutostart = ::cppu::any2bool( aArguments[1] );
679 0 : if (bAutostart && !GetAutostart())
680 0 : SetAutostart( true );
681 0 : if (!bAutostart && GetAutostart())
682 0 : SetAutostart( false );
683 2 : }
684 :
685 : }
686 :
687 :
688 :
689 0 : void ShutdownIcon::EnterModalMode()
690 : {
691 0 : bModalMode = true;
692 0 : }
693 :
694 :
695 :
696 0 : void ShutdownIcon::LeaveModalMode()
697 : {
698 0 : bModalMode = false;
699 0 : }
700 :
701 : #ifdef WNT
702 : // defined in shutdowniconw32.cxx
703 : #elif defined MACOSX
704 : // defined in shutdowniconaqua.cxx
705 : #else
706 0 : bool ShutdownIcon::IsQuickstarterInstalled()
707 : {
708 : #ifndef ENABLE_QUICKSTART_APPLET
709 : return false;
710 : #else // !ENABLE_QUICKSTART_APPLET
711 : #ifdef UNX
712 0 : return LoadModule();
713 : #endif // UNX
714 : #endif // !ENABLE_QUICKSTART_APPLET
715 : }
716 : #endif // !WNT
717 :
718 :
719 :
720 : #if defined (ENABLE_QUICKSTART_APPLET) && defined (UNX)
721 : /**
722 : * Return the XDG autostart directory.
723 : * http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
724 : * Available in Unix and with Quickstart enabled.
725 : * @param bCreate Create the directory if it does not exist yet.
726 : * @return OUString containing the autostart directory path.
727 : */
728 0 : static OUString getAutostartDir( bool bCreate = false )
729 : {
730 0 : OUString aShortcut;
731 : const char *pConfigHome;
732 0 : if( (pConfigHome = getenv("XDG_CONFIG_HOME") ) )
733 0 : aShortcut = OStringToOUString( OString( pConfigHome ),
734 0 : RTL_TEXTENCODING_UTF8 );
735 : else
736 : {
737 0 : OUString aHomeURL;
738 0 : osl::Security().getHomeDir( aHomeURL );
739 0 : ::osl::File::getSystemPathFromFileURL( aHomeURL, aShortcut );
740 0 : aShortcut += "/.config";
741 : }
742 0 : aShortcut += "/autostart";
743 0 : if (bCreate)
744 : {
745 0 : OUString aShortcutUrl;
746 0 : osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
747 0 : osl::Directory::createPath( aShortcutUrl );
748 : }
749 0 : return aShortcut;
750 : }
751 : #endif
752 :
753 0 : OUString ShutdownIcon::getShortcutName()
754 : {
755 : #ifndef ENABLE_QUICKSTART_APPLET
756 : return OUString();
757 : #else
758 :
759 0 : OUString aShortcutName( "StarOffice 6.0" );
760 0 : ResMgr* pMgr = SfxResId::GetResMgr();
761 0 : if( pMgr )
762 : {
763 0 : ::SolarMutexGuard aGuard;
764 0 : aShortcutName = SFX2_RESSTR(STR_QUICKSTART_LNKNAME);
765 : }
766 : #ifdef WNT
767 : aShortcutName += ".lnk";
768 :
769 : OUString aShortcut(GetAutostartFolderNameW32());
770 : aShortcut += "\\";
771 : aShortcut += aShortcutName;
772 : #else // UNX
773 0 : OUString aShortcut = getAutostartDir();
774 0 : aShortcut += "/qstart.desktop";
775 : #endif // UNX
776 0 : return aShortcut;
777 : #endif // ENABLE_QUICKSTART_APPLET
778 : }
779 :
780 0 : bool ShutdownIcon::GetAutostart( )
781 : {
782 : #if defined MACOSX
783 : return true;
784 : #else
785 0 : bool bRet = false;
786 : #ifdef ENABLE_QUICKSTART_APPLET
787 0 : OUString aShortcut( getShortcutName() );
788 0 : OUString aShortcutUrl;
789 0 : osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
790 0 : osl::File f( aShortcutUrl );
791 0 : osl::File::RC error = f.open( osl_File_OpenFlag_Read );
792 0 : if( error == osl::File::E_None )
793 : {
794 0 : f.close();
795 0 : bRet = true;
796 : }
797 : #endif // ENABLE_QUICKSTART_APPLET
798 0 : return bRet;
799 : #endif
800 : }
801 :
802 0 : void ShutdownIcon::SetAutostart( bool bActivate )
803 : {
804 : #ifdef ENABLE_QUICKSTART_APPLET
805 0 : OUString aShortcut( getShortcutName() );
806 :
807 0 : if( bActivate && IsQuickstarterInstalled() )
808 : {
809 : #ifdef WNT
810 : EnableAutostartW32( aShortcut );
811 : #else // UNX
812 0 : getAutostartDir( true );
813 :
814 0 : OUString aPath( "${BRAND_BASE_DIR}/" LIBO_SHARE_FOLDER "/xdg/qstart.desktop" );
815 0 : rtl::Bootstrap::expandMacros( aPath );
816 :
817 0 : OUString aDesktopFile;
818 0 : ::osl::File::getSystemPathFromFileURL( aPath, aDesktopFile );
819 :
820 : OString aDesktopFileUnx = OUStringToOString( aDesktopFile,
821 0 : osl_getThreadTextEncoding() );
822 : OString aShortcutUnx = OUStringToOString( aShortcut,
823 0 : osl_getThreadTextEncoding() );
824 0 : if ((0 != symlink(aDesktopFileUnx.getStr(), aShortcutUnx.getStr())) && (errno == EEXIST))
825 : {
826 0 : unlink(aShortcutUnx.getStr());
827 0 : int ret = symlink(aDesktopFileUnx.getStr(), aShortcutUnx.getStr());
828 : (void)ret; //deliberately ignore return value, it's non-critical if it fails
829 : }
830 :
831 0 : ShutdownIcon *pIcon = ShutdownIcon::createInstance();
832 0 : if( pIcon )
833 0 : pIcon->initSystray();
834 : #endif // UNX
835 : }
836 : else
837 : {
838 0 : OUString aShortcutUrl;
839 0 : ::osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
840 0 : ::osl::File::remove( aShortcutUrl );
841 : #ifdef UNX
842 0 : if (pShutdownIcon)
843 : {
844 0 : ShutdownIcon *pIcon = getInstance();
845 0 : pIcon->deInitSystray();
846 0 : }
847 : #endif
848 0 : }
849 : #else
850 : (void)bActivate; // unused variable
851 : #endif // ENABLE_QUICKSTART_APPLET
852 0 : }
853 :
854 : static const ::sal_Int32 PROPHANDLE_TERMINATEVETOSTATE = 0;
855 :
856 : // XFastPropertySet
857 0 : void SAL_CALL ShutdownIcon::setFastPropertyValue( ::sal_Int32 nHandle,
858 : const ::com::sun::star::uno::Any& aValue )
859 : throw (::com::sun::star::beans::UnknownPropertyException,
860 : ::com::sun::star::beans::PropertyVetoException,
861 : ::com::sun::star::lang::IllegalArgumentException,
862 : ::com::sun::star::lang::WrappedTargetException,
863 : ::com::sun::star::uno::RuntimeException, std::exception)
864 : {
865 0 : switch(nHandle)
866 : {
867 : case PROPHANDLE_TERMINATEVETOSTATE :
868 : {
869 : // use new value in case it's a valid information only
870 0 : bool bState( false );
871 0 : if (! (aValue >>= bState))
872 0 : return;
873 :
874 0 : m_bVeto = bState;
875 0 : if (m_bVeto && ! m_bListenForTermination)
876 0 : addTerminateListener();
877 : }
878 0 : break;
879 :
880 : default :
881 0 : throw ::com::sun::star::beans::UnknownPropertyException();
882 : }
883 : }
884 :
885 : // XFastPropertySet
886 0 : ::com::sun::star::uno::Any SAL_CALL ShutdownIcon::getFastPropertyValue( ::sal_Int32 nHandle )
887 : throw (::com::sun::star::beans::UnknownPropertyException,
888 : ::com::sun::star::lang::WrappedTargetException,
889 : ::com::sun::star::uno::RuntimeException, std::exception)
890 : {
891 0 : ::com::sun::star::uno::Any aValue;
892 0 : switch(nHandle)
893 : {
894 : case PROPHANDLE_TERMINATEVETOSTATE :
895 : {
896 0 : bool bState = (m_bListenForTermination && m_bVeto);
897 0 : aValue <<= bState;
898 : }
899 0 : break;
900 :
901 : default :
902 0 : throw ::com::sun::star::beans::UnknownPropertyException();
903 : }
904 :
905 0 : return aValue;
906 : }
907 :
908 : namespace {
909 :
910 2 : struct Instance {
911 2 : explicit Instance(
912 : css::uno::Reference<css::uno::XComponentContext> const & context):
913 2 : instance(static_cast<cppu::OWeakObject *>(new ShutdownIcon(context)))
914 2 : {}
915 :
916 : rtl::Reference<css::uno::XInterface> instance;
917 : };
918 :
919 : struct Singleton:
920 : public rtl::StaticWithArg<
921 : Instance, css::uno::Reference<css::uno::XComponentContext>, Singleton>
922 : {};
923 :
924 : }
925 :
926 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
927 2 : com_sun_star_comp_desktop_QuickstartWrapper_get_implementation(
928 : css::uno::XComponentContext *context,
929 : css::uno::Sequence<css::uno::Any> const &)
930 : {
931 : return cppu::acquire(static_cast<cppu::OWeakObject *>(
932 2 : Singleton::get(context).instance.get()));
933 951 : }
934 :
935 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|