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