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_svtools.hxx"
26 
27 #include <svtools/contextmenuhelper.hxx>
28 #include <svtools/menuoptions.hxx>
29 #include <svtools/miscopt.hxx>
30 
31 #include <com/sun/star/frame/XDispatch.hpp>
32 #include <com/sun/star/frame/XDispatchProvider.hpp>
33 #include <com/sun/star/frame/XModuleManager.hpp>
34 #include <com/sun/star/frame/XStatusListener.hpp>
35 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
36 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
37 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
38 #include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
39 #include <com/sun/star/ui/ImageType.hpp>
40 #include <com/sun/star/beans/PropertyValue.hpp>
41 
42 #include <osl/conditn.hxx>
43 #include <cppuhelper/weak.hxx>
44 #include <comphelper/processfactory.hxx>
45 #include <vos/mutex.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/image.hxx>
48 #include <toolkit/helper/vclunohelper.hxx>
49 #include <toolkit/awt/vclxwindow.hxx>
50 #include <toolkit/awt/vclxmenu.hxx>
51 
52 using namespace ::com::sun::star;
53 
54 namespace svt
55 {
56 
57 // internal helper class to retrieve status updates
58 class StateEventHelper : public ::com::sun::star::frame::XStatusListener,
59                          public ::cppu::OWeakObject
60 {
61     public:
62         StateEventHelper( const uno::Reference< frame::XDispatchProvider >& xDispatchProvider,
63                           const uno::Reference< util::XURLTransformer >& xURLTransformer,
64                           const rtl::OUString& aCommandURL );
65         virtual ~StateEventHelper();
66 
67         bool isCommandEnabled();
68 
69 		// XInterface
70 		virtual uno::Any SAL_CALL queryInterface( const uno::Type& aType ) throw ( uno::RuntimeException);
71 		virtual void SAL_CALL acquire() throw ();
72 		virtual void SAL_CALL release() throw ();
73 
74         // XEventListener
75 	    virtual void SAL_CALL disposing(const lang::EventObject& Source) throw( uno::RuntimeException );
76 
77         // XStatusListener
78 	    virtual void SAL_CALL statusChanged(const frame::FeatureStateEvent& Event) throw( uno::RuntimeException );
79 
80     private:
81         StateEventHelper();
82         StateEventHelper( const StateEventHelper& );
83         StateEventHelper& operator=( const StateEventHelper& );
84 
85         bool                                       m_bCurrentCommandEnabled;
86         ::rtl::OUString                            m_aCommandURL;
87         uno::Reference< frame::XDispatchProvider > m_xDispatchProvider;
88         uno::Reference< util::XURLTransformer >    m_xURLTransformer;
89         osl::Condition                             m_aCondition;
90 };
91 
StateEventHelper(const uno::Reference<frame::XDispatchProvider> & xDispatchProvider,const uno::Reference<util::XURLTransformer> & xURLTransformer,const rtl::OUString & rCommandURL)92 StateEventHelper::StateEventHelper(
93     const uno::Reference< frame::XDispatchProvider >& xDispatchProvider,
94     const uno::Reference< util::XURLTransformer >& xURLTransformer,
95     const rtl::OUString& rCommandURL ) :
96     m_bCurrentCommandEnabled( true ),
97     m_aCommandURL( rCommandURL ),
98     m_xDispatchProvider( xDispatchProvider ),
99     m_xURLTransformer( xURLTransformer )
100 {
101     m_aCondition.reset();
102 }
103 
~StateEventHelper()104 StateEventHelper::~StateEventHelper()
105 {}
106 
queryInterface(const uno::Type & aType)107 uno::Any SAL_CALL StateEventHelper::queryInterface(
108     const uno::Type& aType )
109 throw ( uno::RuntimeException )
110 {
111     uno::Any a = ::cppu::queryInterface(
112 				aType,
113 				SAL_STATIC_CAST( XStatusListener*, this ));
114 
115 	if( a.hasValue() )
116 		return a;
117 
118     return ::cppu::OWeakObject::queryInterface( aType );
119 }
120 
acquire()121 void SAL_CALL StateEventHelper::acquire()
122 throw ()
123 {
124     ::cppu::OWeakObject::acquire();
125 }
126 
release()127 void SAL_CALL StateEventHelper::release()
128 throw ()
129 {
130     ::cppu::OWeakObject::release();
131 }
132 
disposing(const lang::EventObject &)133 void SAL_CALL StateEventHelper::disposing(
134     const lang::EventObject& )
135 throw ( uno::RuntimeException )
136 {
137     vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
138     m_xDispatchProvider.clear();
139     m_xURLTransformer.clear();
140     m_aCondition.set();
141 }
142 
statusChanged(const frame::FeatureStateEvent & Event)143 void SAL_CALL StateEventHelper::statusChanged(
144     const frame::FeatureStateEvent& Event )
145 throw ( uno::RuntimeException )
146 {
147     vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
148     m_bCurrentCommandEnabled = Event.IsEnabled;
149     m_aCondition.set();
150 }
151 
isCommandEnabled()152 bool StateEventHelper::isCommandEnabled()
153 {
154     // Be sure that we cannot die during condition wait
155     uno::Reference< frame::XStatusListener > xSelf(
156         SAL_STATIC_CAST( frame::XStatusListener*, this ));
157 
158     uno::Reference< frame::XDispatch > xDispatch;
159     util::URL                          aTargetURL;
160     {
161         vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
162         if ( m_xDispatchProvider.is() && m_xURLTransformer.is() )
163         {
164             ::rtl::OUString aSelf( RTL_CONSTASCII_USTRINGPARAM( "_self" ));
165 
166             aTargetURL.Complete = m_aCommandURL;
167             m_xURLTransformer->parseStrict( aTargetURL );
168 
169             try
170             {
171                 xDispatch = m_xDispatchProvider->queryDispatch( aTargetURL, aSelf, 0 );
172             }
173             catch ( uno::RuntimeException& )
174             {
175                 throw;
176             }
177             catch ( uno::Exception& )
178             {
179             }
180         }
181     }
182 
183     bool bResult( false );
184     if ( xDispatch.is() )
185     {
186         try
187         {
188             // add/remove ourself to retrieve status by callback
189             xDispatch->addStatusListener( xSelf, aTargetURL );
190             xDispatch->removeStatusListener( xSelf, aTargetURL );
191 
192             // wait for anwser
193             m_aCondition.wait();
194         }
195         catch ( uno::RuntimeException& )
196         {
197             throw;
198         }
199         catch ( uno::Exception& )
200         {
201         }
202 
203         vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
204         bResult = m_bCurrentCommandEnabled;
205     }
206 
207     return bResult;
208 }
209 
210 /*************************************************************************/
211 
212 struct ExecuteInfo
213 {
214     uno::Reference< frame::XDispatch >    xDispatch;
215     util::URL                             aTargetURL;
216     uno::Sequence< beans::PropertyValue > aArgs;
217 };
218 
lcl_FindPopupFromItemId(const PopupMenu * pPopupMenu,sal_uInt16 nItemId)219 static const PopupMenu* lcl_FindPopupFromItemId( const PopupMenu* pPopupMenu, sal_uInt16 nItemId )
220 {
221     if ( pPopupMenu )
222     {
223         sal_uInt16 nCount = pPopupMenu->GetItemCount();
224         for ( sal_uInt16 i = 0; i < nCount; i++ )
225         {
226             sal_uInt16 nId = pPopupMenu->GetItemId( i );
227             if ( nId == nItemId )
228                 return pPopupMenu;
229             else
230             {
231                 const PopupMenu* pResult( 0 );
232 
233                 const PopupMenu* pSubPopup = pPopupMenu->GetPopupMenu( i );
234                 if ( pPopupMenu )
235                     pResult = lcl_FindPopupFromItemId( pSubPopup, nItemId );
236                 if ( pResult != 0 )
237                     return pResult;
238             }
239         }
240     }
241 
242     return NULL;
243 }
244 
lcl_GetItemCommandRecursive(const PopupMenu * pPopupMenu,sal_uInt16 nItemId)245 static ::rtl::OUString lcl_GetItemCommandRecursive( const PopupMenu* pPopupMenu, sal_uInt16 nItemId )
246 {
247     const PopupMenu* pPopup = lcl_FindPopupFromItemId( pPopupMenu, nItemId );
248     if ( pPopup )
249         return pPopup->GetItemCommand( nItemId );
250     else
251         return ::rtl::OUString();
252 }
253 
254 /*************************************************************************/
255 
ContextMenuHelper(const uno::Reference<frame::XFrame> & xFrame,bool bAutoRefresh)256 ContextMenuHelper::ContextMenuHelper(
257     const uno::Reference< frame::XFrame >& xFrame,
258     bool bAutoRefresh ) :
259     m_xWeakFrame( xFrame ),
260     m_aSelf( RTL_CONSTASCII_USTRINGPARAM( "_self" )),
261     m_bAutoRefresh( bAutoRefresh ),
262     m_bUICfgMgrAssociated( false )
263 {
264 }
265 
~ContextMenuHelper()266 ContextMenuHelper::~ContextMenuHelper()
267 {
268 }
269 
270 void
completeAndExecute(const Point & aPos,PopupMenu & rPopupMenu)271 ContextMenuHelper::completeAndExecute(
272     const Point& aPos,
273     PopupMenu& rPopupMenu )
274 {
275     vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
276 
277     associateUIConfigurationManagers();
278     completeMenuProperties( &rPopupMenu );
279     executePopupMenu( aPos, &rPopupMenu );
280     resetAssociations();
281 }
282 
283 void
completeAndExecute(const Point & aPos,const uno::Reference<awt::XPopupMenu> & xPopupMenu)284 ContextMenuHelper::completeAndExecute(
285     const Point& aPos,
286     const uno::Reference< awt::XPopupMenu >& xPopupMenu )
287 {
288     vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
289 
290     VCLXMenu* pXMenu = VCLXMenu::GetImplementation( xPopupMenu );
291     if ( pXMenu )
292     {
293         PopupMenu* pPopupMenu = dynamic_cast< PopupMenu* >( pXMenu->GetMenu() );
294         // as dynamic_cast can return zero check pointer
295         if ( pPopupMenu )
296         {
297             associateUIConfigurationManagers();
298             completeMenuProperties( pPopupMenu );
299             executePopupMenu( aPos, pPopupMenu );
300             resetAssociations();
301         }
302     }
303 }
304 
305 uno::Reference< awt::XPopupMenu >
create(const::rtl::OUString &)306 ContextMenuHelper::create(
307     const ::rtl::OUString& /*aPopupMenuResourceId*/ )
308 {
309     // NOT IMPLEMENTED YET!
310     return uno::Reference< awt::XPopupMenu >();
311 }
312 
313 bool
createAndExecute(const Point &,const::rtl::OUString &)314 ContextMenuHelper::createAndExecute(
315     const Point& /*aPos*/,
316     const ::rtl::OUString& /*aPopupMenuResourceId*/ )
317 {
318     // NOT IMPLEMENTED YET!
319     return false;
320 }
321 
322 // private member
323 
324 void
executePopupMenu(const Point & rPos,PopupMenu * pMenu)325 ContextMenuHelper::executePopupMenu(
326     const Point& rPos,
327     PopupMenu* pMenu )
328 {
329     if ( pMenu )
330     {
331         uno::Reference< frame::XFrame > xFrame( m_xWeakFrame );
332         if ( xFrame.is() )
333         {
334             uno::Reference< awt::XWindow > xWindow( xFrame->getContainerWindow() );
335             if ( xWindow.is() )
336             {
337                 Window* pParent = VCLUnoHelper::GetWindow( xWindow );
338                 sal_uInt16 nResult = pMenu->Execute( pParent, rPos );
339 
340                 if ( nResult > 0 )
341                 {
342                     ::rtl::OUString aCommand = lcl_GetItemCommandRecursive( pMenu, nResult );
343                     if ( aCommand.getLength() > 0 )
344                         dispatchCommand( xFrame, aCommand );
345                 }
346             }
347         }
348     }
349 }
350 
351 bool
dispatchCommand(const uno::Reference<::frame::XFrame> & rFrame,const::rtl::OUString & aCommandURL)352 ContextMenuHelper::dispatchCommand(
353     const uno::Reference< ::frame::XFrame >& rFrame,
354     const ::rtl::OUString& aCommandURL )
355 {
356     if ( !m_xURLTransformer.is() )
357     {
358         m_xURLTransformer = uno::Reference< util::XURLTransformer >(
359             ::comphelper::getProcessServiceFactory()->createInstance(
360                 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
361                     "com.sun.star.util.URLTransformer" ))),
362             uno::UNO_QUERY );
363     }
364 
365     util::URL aTargetURL;
366     uno::Reference< frame::XDispatch > xDispatch;
367     if ( m_xURLTransformer.is() )
368     {
369         aTargetURL.Complete = aCommandURL;
370         m_xURLTransformer->parseStrict( aTargetURL );
371 
372         uno::Reference< frame::XDispatchProvider > xDispatchProvider(
373             rFrame, uno::UNO_QUERY );
374         if ( xDispatchProvider.is() )
375         {
376             try
377             {
378                 xDispatch = xDispatchProvider->queryDispatch( aTargetURL, m_aSelf, 0 );
379             }
380             catch ( uno::RuntimeException& )
381             {
382                 throw;
383             }
384             catch ( uno::Exception& )
385             {
386             }
387         }
388     }
389 
390     if ( xDispatch.is() )
391     {
392         ExecuteInfo* pExecuteInfo = new ExecuteInfo;
393         pExecuteInfo->xDispatch    = xDispatch;
394         pExecuteInfo->aTargetURL   = aTargetURL;
395         pExecuteInfo->aArgs        = m_aDefaultArgs;
396 
397         Application::PostUserEvent( STATIC_LINK(0, ContextMenuHelper , ExecuteHdl_Impl), pExecuteInfo );
398         return true;
399     }
400 
401     return false;
402 }
403 
404 // retrieves and stores references to our user-interface
405 // configuration managers, like image manager, ui command
406 // description manager.
407 bool
associateUIConfigurationManagers()408 ContextMenuHelper::associateUIConfigurationManagers()
409 {
410     uno::Reference< frame::XFrame > xFrame( m_xWeakFrame );
411     if ( !m_bUICfgMgrAssociated && xFrame.is() )
412     {
413         // clear current state
414         m_xDocImageMgr.clear();
415         m_xModuleImageMgr.clear();
416         m_xUICommandLabels.clear();
417 
418         try
419         {
420             uno::Reference < frame::XController > xController;
421             uno::Reference < frame::XModel > xModel;
422             xController = xFrame->getController();
423             if ( xController.is() )
424                 xModel = xController->getModel();
425 
426             if ( xModel.is() )
427             {
428                 // retrieve document image manager form model
429                 uno::Reference< ui::XUIConfigurationManagerSupplier > xSupplier( xModel, uno::UNO_QUERY );
430                 if ( xSupplier.is() )
431                 {
432                     uno::Reference< ui::XUIConfigurationManager > xDocUICfgMgr(
433                         xSupplier->getUIConfigurationManager(), uno::UNO_QUERY );
434                     m_xDocImageMgr = uno::Reference< ui::XImageManager >(
435                         xDocUICfgMgr->getImageManager(), uno::UNO_QUERY );
436                 }
437             }
438 
439             uno::Reference< frame::XModuleManager > xModuleManager(
440                 ::comphelper::getProcessServiceFactory()->createInstance(
441                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
442                         "com.sun.star.frame.ModuleManager" ))),
443                 uno::UNO_QUERY );
444 
445             uno::Reference< ui::XImageManager > xModuleImageManager;
446             rtl::OUString                       aModuleId;
447             if ( xModuleManager.is() )
448             {
449                 // retrieve module image manager
450                 aModuleId = xModuleManager->identify( xFrame );
451 
452                 uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModuleCfgMgrSupplier(
453                     ::comphelper::getProcessServiceFactory()->createInstance(
454                         rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
455                             "com.sun.star.ui.ModuleUIConfigurationManagerSupplier" ))),
456                         uno::UNO_QUERY );
457                 if ( xModuleCfgMgrSupplier.is() )
458                 {
459                     uno::Reference< ui::XUIConfigurationManager > xUICfgMgr(
460                         xModuleCfgMgrSupplier->getUIConfigurationManager( aModuleId ));
461                     if ( xUICfgMgr.is() )
462                     {
463                         m_xModuleImageMgr = uno::Reference< ui::XImageManager >(
464                             xUICfgMgr->getImageManager(), uno::UNO_QUERY );
465                     }
466                 }
467             }
468 
469             uno::Reference< container::XNameAccess > xNameAccess(
470                 ::comphelper::getProcessServiceFactory()->createInstance(
471                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
472                         "com.sun.star.frame.UICommandDescription" ))),
473                     uno::UNO_QUERY );
474             if ( xNameAccess.is() )
475             {
476                 try
477                 {
478                     uno::Any a = xNameAccess->getByName( aModuleId );
479                     a >>= m_xUICommandLabels;
480                 }
481                 catch ( container::NoSuchElementException& )
482                 {
483                 }
484             }
485         }
486         catch ( uno::RuntimeException& )
487         {
488             throw;
489         }
490         catch ( uno::Exception& )
491         {
492             m_bUICfgMgrAssociated = true;
493             return false;
494         }
495         m_bUICfgMgrAssociated = true;
496     }
497 
498     return true;
499 }
500 
501 Image
getImageFromCommandURL(const::rtl::OUString & aCmdURL,bool bHiContrast) const502 ContextMenuHelper::getImageFromCommandURL(
503     const ::rtl::OUString& aCmdURL,
504     bool                   bHiContrast ) const
505 {
506     Image     aImage;
507     sal_Int16 nImageType( ui::ImageType::COLOR_NORMAL|
508                           ui::ImageType::SIZE_DEFAULT );
509     if ( bHiContrast )
510         nImageType |= ui::ImageType::COLOR_HIGHCONTRAST;
511 
512     uno::Sequence< uno::Reference< graphic::XGraphic > > aGraphicSeq;
513     uno::Sequence< ::rtl::OUString > aImageCmdSeq( 1 );
514     aImageCmdSeq[0] = aCmdURL;
515 
516     if ( m_xDocImageMgr.is() )
517     {
518         try
519         {
520             aGraphicSeq = m_xDocImageMgr->getImages( nImageType, aImageCmdSeq );
521             uno::Reference< graphic::XGraphic > xGraphic = aGraphicSeq[0];
522             aImage = Image( xGraphic );
523 
524             if ( !!aImage )
525                 return aImage;
526         }
527         catch ( uno::RuntimeException& )
528         {
529             throw;
530         }
531         catch ( uno::Exception& )
532         {
533         }
534     }
535 
536     if ( m_xModuleImageMgr.is() )
537     {
538         try
539         {
540             aGraphicSeq = m_xModuleImageMgr->getImages( nImageType, aImageCmdSeq );
541             uno::Reference< ::com::sun::star::graphic::XGraphic > xGraphic = aGraphicSeq[0];
542 	    aImage = Image( xGraphic );
543 
544             if ( !!aImage )
545                 return aImage;
546         }
547         catch ( uno::RuntimeException& )
548         {
549             throw;
550         }
551         catch ( uno::Exception& )
552         {
553         }
554     }
555 
556     return aImage;
557 }
558 
559 rtl::OUString
getLabelFromCommandURL(const::rtl::OUString & aCmdURL) const560 ContextMenuHelper::getLabelFromCommandURL(
561     const ::rtl::OUString& aCmdURL ) const
562 {
563     ::rtl::OUString aLabel;
564 
565     if ( m_xUICommandLabels.is() )
566     {
567         try
568         {
569             if ( aCmdURL.getLength() > 0 )
570             {
571                 rtl::OUString aStr;
572                 uno::Sequence< beans::PropertyValue > aPropSeq;
573                 uno::Any a( m_xUICommandLabels->getByName( aCmdURL ));
574                 if ( a >>= aPropSeq )
575                 {
576                     for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ )
577                     {
578                         if ( aPropSeq[i].Name.equalsAscii( "Label" ))
579                         {
580                             aPropSeq[i].Value >>= aStr;
581                             break;
582                         }
583                     }
584                 }
585                 aLabel = aStr;
586             }
587         }
588         catch ( uno::RuntimeException& )
589         {
590         }
591         catch ( uno::Exception& )
592         {
593         }
594     }
595 
596     return aLabel;
597 }
598 
599 void
completeMenuProperties(Menu * pMenu)600 ContextMenuHelper::completeMenuProperties(
601     Menu* pMenu )
602 {
603     // Retrieve some settings necessary to display complete context
604     // menu correctly.
605     const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
606 	bool  bShowMenuImages( rSettings.GetUseImagesInMenus() );
607 	bool  bIsHiContrast( rSettings.GetHighContrastMode() );
608 
609     if ( pMenu )
610     {
611         uno::Reference< frame::XFrame > xFrame( m_xWeakFrame );
612         uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, uno::UNO_QUERY );
613 
614         if ( !m_xURLTransformer.is() )
615         {
616             m_xURLTransformer = uno::Reference< util::XURLTransformer >(
617                 ::comphelper::getProcessServiceFactory()->createInstance(
618                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
619                         "com.sun.star.util.URLTransformer" ))),
620                 uno::UNO_QUERY );
621         }
622 
623         for ( sal_uInt16 nPos = 0; nPos < pMenu->GetItemCount(); nPos++ )
624 	    {
625 		    sal_uInt16 nId        = pMenu->GetItemId( nPos );
626 		    PopupMenu* pPopupMenu = pMenu->GetPopupMenu( nId );
627             if ( pPopupMenu )
628                 completeMenuProperties( pPopupMenu );
629             if ( pMenu->GetItemType( nPos ) != MENUITEM_SEPARATOR )
630 		    {
631                 ::rtl::OUString aCmdURL( pMenu->GetItemCommand( nId ));
632 
633                 if ( bShowMenuImages )
634 			    {
635 				    Image aImage;
636                     if ( aCmdURL.getLength() > 0 )
637 					    aImage = getImageFromCommandURL( aCmdURL, bIsHiContrast );
638                     pMenu->SetItemImage( nId, aImage );
639 			    }
640 			    else
641 				    pMenu->SetItemImage( nId, Image() );
642 
643                 if ( pMenu->GetItemText( nId ).Len() == 0 )
644                 {
645                     ::rtl::OUString aLabel( getLabelFromCommandURL( aCmdURL ));
646                     pMenu->SetItemText( nId, aLabel );
647                 }
648 
649                 // Use helper to retrieve state of the command URL
650 				StateEventHelper* pHelper = new StateEventHelper(
651 													xDispatchProvider,
652 													m_xURLTransformer,
653 													aCmdURL );
654 
655 				uno::Reference< frame::XStatusListener > xHelper( pHelper );
656                 pMenu->EnableItem( nId, pHelper->isCommandEnabled() );
657 		    }
658 	    }
659     }
660 }
661 
662 
IMPL_STATIC_LINK_NOINSTANCE(ContextMenuHelper,ExecuteHdl_Impl,ExecuteInfo *,pExecuteInfo)663 IMPL_STATIC_LINK_NOINSTANCE( ContextMenuHelper, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
664 {
665     // Release solar mutex to prevent deadlocks with clipboard thread
666     const sal_uInt32 nRef = Application::ReleaseSolarMutex();
667     try
668     {
669         // Asynchronous execution as this can lead to our own destruction while we are
670         // on the stack. Stack unwinding would access the destroyed context menu.
671         pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
672     }
673     catch ( uno::Exception& )
674     {
675     }
676 
677     // Acquire solar mutex again
678     Application::AcquireSolarMutex( nRef );
679     delete pExecuteInfo;
680     return 0;
681 }
682 
683 } // namespace svt
684