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