xref: /aoo42x/main/sfx2/source/appl/shutdownicon.cxx (revision d119d52d)
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