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