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