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 ) throw( RuntimeException );
101 virtual void SAL_CALL disposing( const EventObject& aEvent ) throw( RuntimeException );
102 };
103
dispatchFinished(const DispatchResultEvent &)104 void SAL_CALL SfxNotificationListener_Impl::dispatchFinished( const DispatchResultEvent& ) throw( RuntimeException )
105 {
106 ShutdownIcon::LeaveModalMode();
107 }
108
disposing(const EventObject &)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" {
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 porperty 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() throw( ::com::sun::star::uno::Exception )
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 throw(::com::sun::star::uno::RuntimeException)
676 {
677 }
678
679 // ---------------------------------------------------------------------------
680
681 // XTerminateListener
queryTermination(const::com::sun::star::lang::EventObject &)682 void SAL_CALL ShutdownIcon::queryTermination( const ::com::sun::star::lang::EventObject& )
683 throw(::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException)
684 {
685 ::osl::ClearableMutexGuard aGuard( m_aMutex );
686
687 if ( m_bVeto )
688 throw ::com::sun::star::frame::TerminationVetoException();
689 }
690
691
692 // ---------------------------------------------------------------------------
693
notifyTermination(const::com::sun::star::lang::EventObject &)694 void SAL_CALL ShutdownIcon::notifyTermination( const ::com::sun::star::lang::EventObject& )
695 throw(::com::sun::star::uno::RuntimeException)
696 {
697 }
698
699
700 // ---------------------------------------------------------------------------
701
initialize(const::com::sun::star::uno::Sequence<::com::sun::star::uno::Any> & aArguments)702 void SAL_CALL ShutdownIcon::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any>& aArguments )
703 throw( ::com::sun::star::uno::Exception )
704 {
705 ::osl::ResettableMutexGuard aGuard( m_aMutex );
706
707 // third argument only sets veto, everything else will be ignored!
708 if (aArguments.getLength() > 2)
709 {
710 sal_Bool bVeto = sal_True;
711 bVeto = ::cppu::any2bool(aArguments[2]);
712 m_bVeto = bVeto;
713 return;
714 }
715
716 if ( aArguments.getLength() > 0 )
717 {
718 if ( !ShutdownIcon::pShutdownIcon )
719 {
720 try
721 {
722 sal_Bool bQuickstart = sal_False;
723 bQuickstart = ::cppu::any2bool( aArguments[0] );
724 if( !bQuickstart && !GetAutostart() )
725 return;
726 aGuard.clear();
727 init ();
728 aGuard.reset();
729 if ( !m_xDesktop.is() )
730 return;
731
732 /* Create a sub-classed instance - foo */
733 ShutdownIcon::pShutdownIcon = this;
734 initSystray();
735 #ifdef OS2
736 // above win32 starts the quickstart thread, but we have
737 // quickstart running only when -quickstart is specified
738 // on command line (next boot).
739 // so if -quickstart was not specified, we cannot issue
740 // quickstart veto on shutdown.
741 if (bQuickstart)
742 {
743 // disable shutdown
744 ShutdownIcon::getInstance()->SetVeto( true );
745 ShutdownIcon::getInstance()->addTerminateListener();
746 }
747 #endif
748 }
749 catch(const ::com::sun::star::lang::IllegalArgumentException&)
750 {
751 }
752 }
753 }
754 if ( aArguments.getLength() > 1 )
755 {
756 sal_Bool bAutostart = sal_False;
757 bAutostart = ::cppu::any2bool( aArguments[1] );
758 if (bAutostart && !GetAutostart())
759 SetAutostart( sal_True );
760 if (!bAutostart && GetAutostart())
761 SetAutostart( sal_False );
762 }
763
764 }
765
766 // -------------------------------
767
EnterModalMode()768 void ShutdownIcon::EnterModalMode()
769 {
770 bModalMode = sal_True;
771 }
772
773 // -------------------------------
774
LeaveModalMode()775 void ShutdownIcon::LeaveModalMode()
776 {
777 bModalMode = sal_False;
778 }
779
780 #ifdef WNT
781 // defined in shutdowniconw32.cxx
782 #elif defined(OS2)
783 // defined in shutdowniconOs2.cxx
784 #elif defined QUARTZ
785 // defined in shutdowniconaqua.cxx
786 #else
IsQuickstarterInstalled()787 bool ShutdownIcon::IsQuickstarterInstalled()
788 {
789 #ifndef ENABLE_QUICKSTART_APPLET
790 return false;
791 #else // !ENABLE_QUICKSTART_APPLET
792 #ifdef UNX
793 return LoadModule( NULL, NULL, NULL);
794 #endif // UNX
795 #endif // !ENABLE_QUICKSTART_APPLET
796 }
797 #endif // !WNT
798
799 // ---------------------------------------------------------------------------
800
801 #if defined (ENABLE_QUICKSTART_APPLET) && defined (UNX)
getDotAutostart(bool bCreate=false)802 static OUString getDotAutostart( bool bCreate = false )
803 {
804 OUString aShortcut;
805 const char *pConfigHome;
806 if( (pConfigHome = getenv("XDG_CONFIG_HOME") ) )
807 aShortcut = OStringToOUString( OString( pConfigHome ), RTL_TEXTENCODING_UTF8 );
808 else
809 {
810 OUString aHomeURL;
811 osl::Security().getHomeDir( aHomeURL );
812 ::osl::File::getSystemPathFromFileURL( aHomeURL, aShortcut );
813 aShortcut += OUString( RTL_CONSTASCII_USTRINGPARAM( "/.config" ) );
814 }
815 aShortcut += OUString( RTL_CONSTASCII_USTRINGPARAM( "/autostart" ) );
816 if (bCreate)
817 {
818 OUString aShortcutUrl;
819 osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
820 osl::Directory::createPath( aShortcutUrl );
821 }
822 return aShortcut;
823 }
824 #endif
825
getShortcutName()826 rtl::OUString ShutdownIcon::getShortcutName()
827 {
828 #ifndef ENABLE_QUICKSTART_APPLET
829 return OUString();
830 #else
831
832 OUString aShortcutName( RTL_CONSTASCII_USTRINGPARAM( "StarOffice 6.0" ) );
833 ResMgr* pMgr = SfxResId::GetResMgr();
834 if( pMgr )
835 {
836 ::vos::OGuard aGuard( Application::GetSolarMutex() );
837 UniString aRes( SfxResId( STR_QUICKSTART_LNKNAME ) );
838 aShortcutName = OUString( aRes );
839 }
840 #ifdef WNT
841 aShortcutName += OUString( RTL_CONSTASCII_USTRINGPARAM( ".lnk" ) );
842
843 OUString aShortcut(GetAutostartFolderNameW32());
844 aShortcut += OUString( RTL_CONSTASCII_USTRINGPARAM( "\\" ) );
845 aShortcut += aShortcutName;
846 #else // UNX
847 OUStringBuffer aStrBuff( getDotAutostart() );
848 aStrBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( "/" ) );
849 if ( sal_Int32 len = aShortcutName.getLength() )
850 aStrBuff.append( aShortcutName.getStr(), len );
851 else
852 aStrBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( "qstart" ) );
853 aStrBuff.appendAscii( RTL_CONSTASCII_STRINGPARAM( ".desktop" ) );
854
855 OUString aShortcut( aStrBuff.makeStringAndClear() );
856 #endif // UNX
857 return aShortcut;
858 #endif // ENABLE_QUICKSTART_APPLET
859 }
860
GetAutostart()861 bool ShutdownIcon::GetAutostart( )
862 {
863 #if defined(OS2)
864 return GetAutostartOs2( );
865 #elif defined QUARTZ
866 return true;
867 #else
868 bool bRet = false;
869 #ifdef ENABLE_QUICKSTART_APPLET
870 OUString aShortcut( getShortcutName() );
871 OUString aShortcutUrl;
872 osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
873 osl::File f( aShortcutUrl );
874 osl::File::RC error = f.open( OpenFlag_Read );
875 if( error == osl::File::E_None )
876 {
877 f.close();
878 bRet = true;
879 }
880 #endif // ENABLE_QUICKSTART_APPLET
881 return bRet;
882 #endif
883 }
884
SetAutostart(bool bActivate)885 void ShutdownIcon::SetAutostart( bool bActivate )
886 {
887 #ifdef ENABLE_QUICKSTART_APPLET
888 OUString aShortcut( getShortcutName() );
889
890 if( bActivate && IsQuickstarterInstalled() )
891 {
892 #ifdef WNT
893 EnableAutostartW32( aShortcut );
894 #else // UNX
895 getDotAutostart( true );
896
897 OUString aPath( RTL_CONSTASCII_USTRINGPARAM("${OOO_BASE_DIR}/share/xdg/qstart.desktop" ) );
898 Bootstrap::expandMacros( aPath );
899
900 OUString aDesktopFile;
901 ::osl::File::getSystemPathFromFileURL( aPath, aDesktopFile );
902
903 OString aDesktopFileUnx = OUStringToOString( aDesktopFile,
904 osl_getThreadTextEncoding() );
905 OString aShortcutUnx = OUStringToOString( aShortcut,
906 osl_getThreadTextEncoding() );
907 if ((0 != symlink( aDesktopFileUnx.getStr(), aShortcutUnx.getStr())) && (errno == EEXIST))
908 {
909 unlink( aShortcutUnx.getStr());
910 symlink( aDesktopFileUnx.getStr(), aShortcutUnx.getStr());
911 }
912
913 ShutdownIcon *pIcon = ShutdownIcon::createInstance();
914 if( pIcon )
915 pIcon->initSystray();
916 #endif // UNX
917 }
918 else
919 {
920 OUString aShortcutUrl;
921 ::osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
922 ::osl::File::remove( aShortcutUrl );
923 #ifdef UNX
924 if (pShutdownIcon)
925 {
926 ShutdownIcon *pIcon = getInstance();
927 pIcon->deInitSystray();
928 }
929 #endif
930 }
931 #elif defined OS2
932 SetAutostartOs2( bActivate );
933 #else
934 (void)bActivate; // unused variable
935 #endif // ENABLE_QUICKSTART_APPLET
936 }
937
938 static const ::sal_Int32 PROPHANDLE_TERMINATEVETOSTATE = 0;
939
940 // XFastPropertySet
setFastPropertyValue(::sal_Int32 nHandle,const::com::sun::star::uno::Any & aValue)941 void SAL_CALL ShutdownIcon::setFastPropertyValue( ::sal_Int32 nHandle,
942 const ::com::sun::star::uno::Any& aValue )
943 throw (::com::sun::star::beans::UnknownPropertyException,
944 ::com::sun::star::beans::PropertyVetoException,
945 ::com::sun::star::lang::IllegalArgumentException,
946 ::com::sun::star::lang::WrappedTargetException,
947 ::com::sun::star::uno::RuntimeException)
948 {
949 switch(nHandle)
950 {
951 case PROPHANDLE_TERMINATEVETOSTATE :
952 {
953 // use new value in case it's a valid information only
954 ::sal_Bool bState( sal_False );
955 if (! (aValue >>= bState))
956 return;
957
958 m_bVeto = bState;
959 if (m_bVeto && ! m_bListenForTermination)
960 addTerminateListener();
961 }
962 break;
963
964 default :
965 throw ::com::sun::star::beans::UnknownPropertyException();
966 }
967 }
968
969 // XFastPropertySet
getFastPropertyValue(::sal_Int32 nHandle)970 ::com::sun::star::uno::Any SAL_CALL ShutdownIcon::getFastPropertyValue( ::sal_Int32 nHandle )
971 throw (::com::sun::star::beans::UnknownPropertyException,
972 ::com::sun::star::lang::WrappedTargetException,
973 ::com::sun::star::uno::RuntimeException)
974 {
975 ::com::sun::star::uno::Any aValue;
976 switch(nHandle)
977 {
978 case PROPHANDLE_TERMINATEVETOSTATE :
979 {
980 bool bState = (m_bListenForTermination && m_bVeto);
981 aValue <<= bState;
982 }
983 break;
984
985 default :
986 throw ::com::sun::star::beans::UnknownPropertyException();
987 }
988
989 return aValue;
990 }
991