1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_framework.hxx"
30 
31 //-----------------------------------------------
32 // my own includes
33 
34 #include <algorithm>
35 #include <helper/statusindicatorfactory.hxx>
36 #include <helper/statusindicator.hxx>
37 #include <helper/vclstatusindicator.hxx>
38 #include <threadhelp/writeguard.hxx>
39 #include <threadhelp/readguard.hxx>
40 #include <services.h>
41 #include <properties.h>
42 
43 //-----------------------------------------------
44 // interface includes
45 #include <com/sun/star/awt/Rectangle.hpp>
46 
47 #ifndef _COM_SUN_STAR_AWT_XCONTROLS_HPP_
48 #include <com/sun/star/awt/XControl.hpp>
49 #endif
50 #include <com/sun/star/awt/XLayoutConstrains.hpp>
51 #include <com/sun/star/awt/DeviceInfo.hpp>
52 #include <com/sun/star/awt/PosSize.hpp>
53 #include <com/sun/star/awt/WindowAttribute.hpp>
54 #include <com/sun/star/awt/XTopWindow.hpp>
55 #include <com/sun/star/awt/XWindow2.hpp>
56 #include <com/sun/star/beans/XPropertySet.hpp>
57 #include <com/sun/star/frame/XLayoutManager.hpp>
58 
59 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
60 #include <toolkit/unohlp.hxx>
61 #endif
62 
63 //-----------------------------------------------
64 // includes of other projects
65 #include <comphelper/sequenceashashmap.hxx>
66 #include <comphelper/mediadescriptor.hxx>
67 #include <comphelper/configurationhelper.hxx>
68 #include <vcl/svapp.hxx>
69 #include <vos/mutex.hxx>
70 
71 //-----------------------------------------------
72 // namespace
73 
74 namespace framework{
75 
76 //-----------------------------------------------
77 // definitions
78 
79 sal_Int32 StatusIndicatorFactory::m_nInReschedule = 0;	///	static counter for rescheduling
80 static ::rtl::OUString PROGRESS_RESOURCE = ::rtl::OUString::createFromAscii("private:resource/progressbar/progressbar");
81 
82 //-----------------------------------------------
83 DEFINE_XINTERFACE_5(StatusIndicatorFactory                              ,
84                     OWeakObject                                         ,
85                     DIRECT_INTERFACE(css::lang::XTypeProvider          ),
86                     DIRECT_INTERFACE(css::lang::XServiceInfo           ),
87                     DIRECT_INTERFACE(css::lang::XInitialization        ),
88                     DIRECT_INTERFACE(css::task::XStatusIndicatorFactory),
89                     DIRECT_INTERFACE(css::util::XUpdatable             ))
90 
91 DEFINE_XTYPEPROVIDER_5(StatusIndicatorFactory            ,
92                        css::lang::XTypeProvider          ,
93                        css::lang::XServiceInfo           ,
94                        css::lang::XInitialization        ,
95                        css::task::XStatusIndicatorFactory,
96                        css::util::XUpdatable             )
97 
98 DEFINE_XSERVICEINFO_MULTISERVICE(StatusIndicatorFactory                   ,
99                                  ::cppu::OWeakObject                      ,
100                                  SERVICENAME_STATUSINDICATORFACTORY       ,
101                                  IMPLEMENTATIONNAME_STATUSINDICATORFACTORY)
102 
103 DEFINE_INIT_SERVICE(StatusIndicatorFactory,
104                     {
105                         /*Attention
106                             I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
107                             to create a new instance of this class by our own supported service factory.
108                             see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
109                         */
110                     }
111                    )
112 
113 //-----------------------------------------------
114 StatusIndicatorFactory::StatusIndicatorFactory(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
115     : ThreadHelpBase      (         )
116     , ::cppu::OWeakObject (         )
117     , m_xSMGR             (xSMGR    )
118     , m_pWakeUp           (0        )
119     , m_bAllowReschedule  (sal_False)
120     , m_bAllowParentShow  (sal_False)
121     , m_bDisableReschedule(sal_False)
122 {
123 }
124 
125 //-----------------------------------------------
126 StatusIndicatorFactory::~StatusIndicatorFactory()
127 {
128     impl_stopWakeUpThread();
129 }
130 
131 //-----------------------------------------------
132 void SAL_CALL StatusIndicatorFactory::initialize(const css::uno::Sequence< css::uno::Any >& lArguments)
133     throw(css::uno::Exception       ,
134           css::uno::RuntimeException)
135 {
136     ::comphelper::SequenceAsHashMap lArgs(lArguments);
137 
138     // SAFE -> ----------------------------------
139     WriteGuard aWriteLock(m_aLock);
140 
141     m_xFrame             = lArgs.getUnpackedValueOrDefault(STATUSINDICATORFACTORY_PROPNAME_FRAME            , css::uno::Reference< css::frame::XFrame >());
142     m_xPluggWindow       = lArgs.getUnpackedValueOrDefault(STATUSINDICATORFACTORY_PROPNAME_WINDOW           , css::uno::Reference< css::awt::XWindow >() );
143     m_bAllowParentShow   = lArgs.getUnpackedValueOrDefault(STATUSINDICATORFACTORY_PROPNAME_ALLOWPARENTSHOW  , (sal_Bool)sal_False                        );
144     m_bDisableReschedule = lArgs.getUnpackedValueOrDefault(STATUSINDICATORFACTORY_PROPNAME_DISABLERESCHEDULE, (sal_Bool)sal_False                        );
145 
146     aWriteLock.unlock();
147     // <- SAFE ----------------------------------
148 
149     impl_createProgress();
150 }
151 
152 //-----------------------------------------------
153 css::uno::Reference< css::task::XStatusIndicator > SAL_CALL StatusIndicatorFactory::createStatusIndicator()
154     throw(css::uno::RuntimeException)
155 {
156     StatusIndicator* pIndicator = new StatusIndicator(this);
157     css::uno::Reference< css::task::XStatusIndicator > xIndicator(static_cast< ::cppu::OWeakObject* >(pIndicator), css::uno::UNO_QUERY_THROW);
158 
159 	return xIndicator;
160 }
161 
162 //-----------------------------------------------
163 void SAL_CALL StatusIndicatorFactory::update()
164     throw(css::uno::RuntimeException)
165 {
166     // SAFE -> ----------------------------------
167     WriteGuard aWriteLock(m_aLock);
168     m_bAllowReschedule = sal_True;
169     aWriteLock.unlock();
170     // <- SAFE ----------------------------------
171 }
172 
173 //-----------------------------------------------
174 void StatusIndicatorFactory::start(const css::uno::Reference< css::task::XStatusIndicator >& xChild,
175                                    const ::rtl::OUString&                                    sText ,
176                                          sal_Int32                                           nRange)
177 {
178     // SAFE -> ----------------------------------
179     WriteGuard aWriteLock(m_aLock);
180 
181     // create new info structure for this child or move it to the front of our stack
182     IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild);
183     if (pItem != m_aStack.end())
184         m_aStack.erase(pItem);
185     IndicatorInfo aInfo(xChild, sText, nRange);
186     m_aStack.push_back (aInfo                );
187 
188     m_xActiveChild = xChild;
189     css::uno::Reference< css::task::XStatusIndicator > xProgress = m_xProgress;
190 
191     aWriteLock.unlock();
192     // <- SAFE ----------------------------------
193 
194     implts_makeParentVisibleIfAllowed();
195 
196     if (xProgress.is())
197         xProgress->start(sText, nRange);
198 
199     impl_startWakeUpThread();
200     impl_reschedule(sal_True);
201 }
202 
203 //-----------------------------------------------
204 void StatusIndicatorFactory::reset(const css::uno::Reference< css::task::XStatusIndicator >& xChild)
205 {
206     // SAFE -> ----------------------------------
207     ReadGuard aReadLock(m_aLock);
208 
209     // reset the internal info structure related to this child
210     IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild);
211     if (pItem != m_aStack.end())
212     {
213         pItem->m_nValue = 0;
214         pItem->m_sText  = ::rtl::OUString();
215     }
216 
217     css::uno::Reference< css::task::XStatusIndicator > xActive   = m_xActiveChild;
218     css::uno::Reference< css::task::XStatusIndicator > xProgress = m_xProgress;
219 
220     aReadLock.unlock();
221     // <- SAFE ----------------------------------
222 
223     // not the top most child => dont change UI
224     // But dont forget Reschedule!
225     if (
226         (xChild == xActive) &&
227         (xProgress.is()   )
228        )
229         xProgress->reset();
230 
231     impl_reschedule(sal_True);
232 }
233 
234 //-----------------------------------------------
235 void StatusIndicatorFactory::end(const css::uno::Reference< css::task::XStatusIndicator >& xChild)
236 {
237     // SAFE -> ----------------------------------
238     WriteGuard aWriteLock(m_aLock);
239 
240     // remove this child from our stack
241     IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild);
242     if (pItem != m_aStack.end())
243         m_aStack.erase(pItem);
244 
245     // activate next child ... or finish the progress if there is no further one.
246     m_xActiveChild.clear();
247     ::rtl::OUString                  sText;
248     sal_Int32                        nValue = 0;
249     IndicatorStack::reverse_iterator pNext  = m_aStack.rbegin();
250     if (pNext != m_aStack.rend())
251     {
252         m_xActiveChild = pNext->m_xIndicator;
253         sText          = pNext->m_sText;
254         nValue         = pNext->m_nValue;
255     }
256 
257     css::uno::Reference< css::task::XStatusIndicator > xActive   = m_xActiveChild;
258     css::uno::Reference< css::task::XStatusIndicator > xProgress = m_xProgress;
259 
260     aWriteLock.unlock();
261     // <- SAFE ----------------------------------
262 
263     if (xActive.is())
264     {
265         // There is at least one further child indicator.
266         // Actualize our progress, so it shows these values from now.
267         if (xProgress.is())
268         {
269             xProgress->setText (sText );
270             xProgress->setValue(nValue);
271         }
272     }
273     else
274     {
275         // Our stack is empty. No further child exists.
276         // Se we must "end" our progress realy
277         if (xProgress.is())
278             xProgress->end();
279         // Now hide the progress bar again.
280         impl_hideProgress();
281 
282         impl_stopWakeUpThread();
283     }
284 
285     impl_reschedule(sal_True);
286 }
287 
288 //-----------------------------------------------
289 void StatusIndicatorFactory::setText(const css::uno::Reference< css::task::XStatusIndicator >& xChild,
290                                      const ::rtl::OUString&                                    sText )
291 {
292     // SAFE -> ----------------------------------
293     WriteGuard aWriteLock(m_aLock);
294 
295     IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild);
296     if (pItem != m_aStack.end())
297         pItem->m_sText = sText;
298 
299     css::uno::Reference< css::task::XStatusIndicator > xActive   = m_xActiveChild;
300     css::uno::Reference< css::task::XStatusIndicator > xProgress = m_xProgress;
301 
302     aWriteLock.unlock();
303     // SAFE -> ----------------------------------
304 
305     // paint only the top most indicator
306     // but dont forget to Reschedule!
307     if (
308         (xChild == xActive) &&
309         (xProgress.is()   )
310        )
311     {
312         xProgress->setText(sText);
313     }
314 
315     impl_reschedule(sal_True);
316 }
317 
318 //-----------------------------------------------
319 void StatusIndicatorFactory::setValue( const css::uno::Reference< css::task::XStatusIndicator >& xChild ,
320                                              sal_Int32                                           nValue )
321 {
322     // SAFE -> ----------------------------------
323     WriteGuard aWriteLock(m_aLock);
324 
325     sal_Int32 nOldValue = 0;
326     IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild);
327     if (pItem != m_aStack.end())
328     {
329         nOldValue       = pItem->m_nValue;
330         pItem->m_nValue = nValue;
331     }
332 
333     css::uno::Reference< css::task::XStatusIndicator > xActive    = m_xActiveChild;
334     css::uno::Reference< css::task::XStatusIndicator > xProgress  = m_xProgress;
335 
336     aWriteLock.unlock();
337     // SAFE -> ----------------------------------
338 
339     if (
340         (xChild    == xActive) &&
341         (nOldValue != nValue ) &&
342         (xProgress.is()      )
343        )
344     {
345         xProgress->setValue(nValue);
346     }
347 
348     impl_reschedule(sal_False);
349 }
350 
351 //-----------------------------------------------
352 void StatusIndicatorFactory::implts_makeParentVisibleIfAllowed()
353 {
354     // SAFE -> ----------------------------------
355     ReadGuard aReadLock(m_aLock);
356 
357     if (!m_bAllowParentShow)
358         return;
359 
360     css::uno::Reference< css::frame::XFrame > xFrame      (m_xFrame.get()      , css::uno::UNO_QUERY);
361     css::uno::Reference< css::awt::XWindow >  xPluggWindow(m_xPluggWindow.get(), css::uno::UNO_QUERY);
362     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR( m_xSMGR.get(), css::uno::UNO_QUERY);
363 
364     aReadLock.unlock();
365     // <- SAFE ----------------------------------
366 
367     css::uno::Reference< css::awt::XWindow > xParentWindow;
368     if (xFrame.is())
369         xParentWindow = xFrame->getContainerWindow();
370     else
371         xParentWindow = xPluggWindow;
372 
373     // dont disturb user in case he put the loading document into the background!
374     // Supress any setVisible() or toFront() call in case the initial show was
375     // already made.
376     css::uno::Reference< css::awt::XWindow2 > xVisibleCheck(xParentWindow, css::uno::UNO_QUERY);
377     sal_Bool bIsVisible = sal_False;
378     if (xVisibleCheck.is())
379         bIsVisible = xVisibleCheck->isVisible();
380 
381     if (bIsVisible)
382     {
383         impl_showProgress();
384         return;
385     }
386 
387     // Check if the layout manager has been set to invisible state. It this case we are also
388     // not allowed to set the frame visible!
389     css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY);
390     if (xPropSet.is())
391     {
392         css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
393         xPropSet->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER) >>= xLayoutManager;
394         if (xLayoutManager.is())
395         {
396             if ( !xLayoutManager->isVisible() )
397                 return;
398         }
399     }
400 
401     // Ok the window should be made visible ... becuase it isnt currently visible.
402     // BUT ..!
403     // We need a Hack for our applications: They get her progress from the frame directly
404     // on saving documents. Because there is no progress set on the MediaDescriptor.
405     // But that's wrong. In case the document was opened hidden, they shouldnt use any progress .-(
406     // They only possible workaround: dont show the parent window here, if the document was opened hidden.
407     sal_Bool bHiddenDoc = sal_False;
408     if (xFrame.is())
409     {
410         css::uno::Reference< css::frame::XController > xController;
411         css::uno::Reference< css::frame::XModel >      xModel     ;
412         xController = xFrame->getController();
413         if (xController.is())
414             xModel = xController->getModel();
415         if (xModel.is())
416         {
417             ::comphelper::MediaDescriptor lDocArgs(xModel->getArgs());
418             bHiddenDoc = lDocArgs.getUnpackedValueOrDefault(
419                 ::comphelper::MediaDescriptor::PROP_HIDDEN(),
420                 (sal_Bool)sal_False);
421         }
422     }
423 
424     if (bHiddenDoc)
425         return;
426 
427     // OK: The document was not opened in hidden mode ...
428     // and the window isnt already visible.
429     // Show it and bring it to front.
430     // But before we have to be sure, that our internal used helper progress
431     // is visible too.
432     impl_showProgress();
433 
434     ::vos::OClearableGuard aSolarGuard(Application::GetSolarMutex());
435     Window* pWindow = VCLUnoHelper::GetWindow(xParentWindow);
436     if ( pWindow )
437     {
438         bool bForceFrontAndFocus(false);
439         ::comphelper::ConfigurationHelper::readDirectKey(
440             xSMGR,
441             ::rtl::OUString::createFromAscii("org.openoffice.Office.Common/View"),
442             ::rtl::OUString::createFromAscii("NewDocumentHandling"),
443             ::rtl::OUString::createFromAscii("ForceFocusAndToFront"),
444             ::comphelper::ConfigurationHelper::E_READONLY) >>= bForceFrontAndFocus;
445 
446         pWindow->Show(sal_True, bForceFrontAndFocus ? SHOW_FOREGROUNDTASK : 0 );
447     }
448 
449     /*
450     #i75167# dont disturb window manager handling .-)
451     css::uno::Reference< css::awt::XTopWindow > xParentWindowTop(xParentWindow, css::uno::UNO_QUERY);
452     if (xParentWindowTop.is())
453         xParentWindowTop->toFront();
454     */
455 }
456 
457 //-----------------------------------------------
458 void StatusIndicatorFactory::impl_createProgress()
459 {
460     // SAFE -> ----------------------------------
461     ReadGuard aReadLock(m_aLock);
462 
463     css::uno::Reference< css::frame::XFrame >              xFrame (m_xFrame.get()      , css::uno::UNO_QUERY);
464     css::uno::Reference< css::awt::XWindow >               xWindow(m_xPluggWindow.get(), css::uno::UNO_QUERY);
465     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR  = m_xSMGR;
466 
467     aReadLock.lock();
468     // <- SAFE ----------------------------------
469 
470     css::uno::Reference< css::task::XStatusIndicator > xProgress;
471 
472     if (xWindow.is())
473     {
474         // use vcl based progress implementation in plugged mode
475         VCLStatusIndicator* pVCLProgress = new VCLStatusIndicator(xSMGR, xWindow);
476         xProgress = css::uno::Reference< css::task::XStatusIndicator >(static_cast< css::task::XStatusIndicator* >(pVCLProgress), css::uno::UNO_QUERY);
477     }
478     else
479     if (xFrame.is())
480     {
481         // use frame layouted progress implementation
482         css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY);
483         if (xPropSet.is())
484         {
485             css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
486             xPropSet->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER) >>= xLayoutManager;
487             if (xLayoutManager.is())
488             {
489                 xLayoutManager->lock();
490                 xLayoutManager->createElement( PROGRESS_RESOURCE );
491                 xLayoutManager->hideElement( PROGRESS_RESOURCE );
492 
493                 css::uno::Reference< css::ui::XUIElement > xProgressBar = xLayoutManager->getElement(PROGRESS_RESOURCE);
494                 if (xProgressBar.is())
495                     xProgress = css::uno::Reference< css::task::XStatusIndicator >(xProgressBar->getRealInterface(), css::uno::UNO_QUERY);
496                 xLayoutManager->unlock();
497             }
498         }
499     }
500 
501     // SAFE -> ----------------------------------
502     WriteGuard aWriteLock(m_aLock);
503     m_xProgress = xProgress;
504     aWriteLock.lock();
505     // <- SAFE ----------------------------------
506 }
507 
508 //-----------------------------------------------
509 void StatusIndicatorFactory::impl_showProgress()
510 {
511     // SAFE -> ----------------------------------
512     ReadGuard aReadLock(m_aLock);
513 
514     css::uno::Reference< css::frame::XFrame >              xFrame (m_xFrame.get()      , css::uno::UNO_QUERY);
515     css::uno::Reference< css::awt::XWindow >               xWindow(m_xPluggWindow.get(), css::uno::UNO_QUERY);
516     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR  = m_xSMGR;
517 
518     aReadLock.lock();
519     // <- SAFE ----------------------------------
520 
521     css::uno::Reference< css::task::XStatusIndicator > xProgress;
522 
523     if (xFrame.is())
524     {
525         // use frame layouted progress implementation
526         css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY);
527         if (xPropSet.is())
528         {
529             css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
530             xPropSet->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER) >>= xLayoutManager;
531             if (xLayoutManager.is())
532             {
533                 // Be sure that we have always a progress. It can be that our frame
534                 // was recycled and therefore the progress was destroyed!
535                 // CreateElement does nothing if there is already a valid progress.
536                 xLayoutManager->createElement( PROGRESS_RESOURCE );
537                 xLayoutManager->showElement( PROGRESS_RESOURCE );
538 
539                 css::uno::Reference< css::ui::XUIElement > xProgressBar = xLayoutManager->getElement(PROGRESS_RESOURCE);
540                 if (xProgressBar.is())
541                     xProgress = css::uno::Reference< css::task::XStatusIndicator >(xProgressBar->getRealInterface(), css::uno::UNO_QUERY);
542             }
543         }
544 
545         // SAFE -> ----------------------------------
546         WriteGuard aWriteLock(m_aLock);
547         m_xProgress = xProgress;
548         aWriteLock.lock();
549         // <- SAFE ----------------------------------
550     }
551 }
552 
553 //-----------------------------------------------
554 void StatusIndicatorFactory::impl_hideProgress()
555 {
556     // SAFE -> ----------------------------------
557     ReadGuard aReadLock(m_aLock);
558 
559     css::uno::Reference< css::frame::XFrame >              xFrame (m_xFrame.get()      , css::uno::UNO_QUERY);
560     css::uno::Reference< css::awt::XWindow >               xWindow(m_xPluggWindow.get(), css::uno::UNO_QUERY);
561     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR  = m_xSMGR;
562 
563     aReadLock.lock();
564     // <- SAFE ----------------------------------
565 
566     if (xFrame.is())
567     {
568         // use frame layouted progress implementation
569         css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY);
570         if (xPropSet.is())
571         {
572             css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
573             xPropSet->getPropertyValue(FRAME_PROPNAME_LAYOUTMANAGER) >>= xLayoutManager;
574             if (xLayoutManager.is())
575                 xLayoutManager->hideElement( PROGRESS_RESOURCE );
576         }
577     }
578 }
579 
580 //-----------------------------------------------
581 void StatusIndicatorFactory::impl_reschedule(sal_Bool bForce)
582 {
583     // SAFE ->
584     ReadGuard aReadLock(m_aLock);
585     if (m_bDisableReschedule)
586         return;
587     aReadLock.unlock();
588     // <- SAFE
589 
590     sal_Bool bReschedule = bForce;
591     if (!bReschedule)
592     {
593         // SAFE ->
594         WriteGuard aWriteLock(m_aLock);
595         bReschedule        = m_bAllowReschedule;
596         m_bAllowReschedule = sal_False;
597         aWriteLock.unlock();
598         // <- SAFE
599     }
600 
601     if (!bReschedule)
602         return;
603 
604     // SAFE ->
605     WriteGuard aGlobalLock(LockHelper::getGlobalLock());
606 
607 	if (m_nInReschedule == 0)
608 	{
609 		++m_nInReschedule;
610         aGlobalLock.unlock();
611         // <- SAFE
612 
613         Application::Reschedule(true);
614 
615         // SAFE ->
616         aGlobalLock.lock();
617 		--m_nInReschedule;
618 	}
619 }
620 
621 //-----------------------------------------------
622 void StatusIndicatorFactory::impl_startWakeUpThread()
623 {
624     // SAFE ->
625     WriteGuard aWriteLock(m_aLock);
626 
627     if (m_bDisableReschedule)
628         return;
629 
630     if (!m_pWakeUp)
631     {
632         m_pWakeUp = new WakeUpThread(this);
633         m_pWakeUp->create();
634     }
635     aWriteLock.unlock();
636     // <- SAFE
637 }
638 
639 //-----------------------------------------------
640 void StatusIndicatorFactory::impl_stopWakeUpThread()
641 {
642     // SAFE ->
643     WriteGuard aWriteLock(m_aLock);
644     if (m_pWakeUp)
645     {
646         // Thread kill itself after terminate()!
647         m_pWakeUp->terminate();
648         m_pWakeUp = 0;
649     }
650     aWriteLock.unlock();
651     // <- SAFE
652 }
653 
654 } // namespace framework
655