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