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