1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #ifndef INCLUDED_FRAMEWORK_INC_SERVICES_DESKTOP_HXX 21 #define INCLUDED_FRAMEWORK_INC_SERVICES_DESKTOP_HXX 22 23 #include <sal/config.h> 24 25 #include <memory> 26 #include <vector> 27 28 #include <classes/framecontainer.hxx> 29 #include <threadhelp/transactionbase.hxx> 30 31 #include <com/sun/star/frame/XUntitledNumbers.hpp> 32 #include <com/sun/star/frame/XController.hpp> 33 #include <com/sun/star/frame/XDesktop2.hpp> 34 #include <com/sun/star/frame/XTerminateListener.hpp> 35 #include <com/sun/star/frame/XTask.hpp> 36 #include <com/sun/star/frame/XFramesSupplier.hpp> 37 #include <com/sun/star/frame/XFrames.hpp> 38 #include <com/sun/star/lang/XServiceInfo.hpp> 39 #include <com/sun/star/frame/XDispatchProvider.hpp> 40 #include <com/sun/star/frame/XTasksSupplier.hpp> 41 #include <com/sun/star/container/XEnumerationAccess.hpp> 42 #include <com/sun/star/frame/XDispatchResultListener.hpp> 43 #include <com/sun/star/lang/XEventListener.hpp> 44 #include <com/sun/star/lang/XComponent.hpp> 45 #include <com/sun/star/task/XInteractionHandler.hpp> 46 #include <com/sun/star/frame/XDispatchRecorderSupplier.hpp> 47 #include <com/sun/star/uno/XComponentContext.hpp> 48 49 #include <cppuhelper/basemutex.hxx> 50 #include <cppuhelper/compbase.hxx> 51 #include <cppuhelper/propshlp.hxx> 52 #include <unotools/cmdoptions.hxx> 53 54 namespace framework{ 55 56 enum ELoadState 57 { 58 E_NOTSET , 59 E_SUCCESSFUL , 60 E_FAILED , 61 E_INTERACTION 62 }; 63 64 /*-************************************************************************************************************ 65 @short implement the topframe of frame tree 66 @descr This is the root of the frame tree. The desktop has no window, is not visible but he is the logical 67 "masternode" to build the hierarchy. 68 69 @implements XInterface 70 XTypeProvider 71 XServiceInfo 72 XDesktop 73 XComponentLoader 74 XTasksSupplier 75 XDispatchProvider 76 XFramesSupplier 77 XFrame 78 XComponent 79 XPropertySet 80 XFastPropertySet 81 XMultiPropertySet 82 XDispatchResultListener 83 XEventListener 84 XInteractionHandler 85 86 @devstatus ready to use 87 @threadsafe yes 88 *//*-*************************************************************************************************************/ 89 typedef cppu::WeakComponentImplHelper< 90 css::lang::XServiceInfo , 91 css::frame::XDesktop2 , 92 css::frame::XTasksSupplier , 93 css::frame::XDispatchResultListener , // => XEventListener 94 css::task::XInteractionHandler , 95 css::frame::XUntitledNumbers > Desktop_BASE; 96 97 class Desktop : private cppu::BaseMutex, 98 private TransactionBase, 99 public Desktop_BASE, 100 public cppu::OPropertySetHelper 101 { 102 // internal used types, const etcpp. 103 private: 104 105 /** used temporary to know which listener was already called or not. */ 106 typedef ::std::vector< css::uno::Reference< css::frame::XTerminateListener > > TTerminateListenerList; 107 108 // public methods 109 public: 110 111 // constructor / destructor 112 Desktop( const css::uno::Reference< css::uno::XComponentContext >& xContext ); 113 virtual ~Desktop( ) override; 114 115 void constructorInit(); 116 117 // XServiceInfo 118 virtual OUString SAL_CALL getImplementationName() override; 119 120 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override; 121 122 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; 123 124 // XInterface acquire()125 virtual void SAL_CALL acquire() throw () override 126 { OWeakObject::acquire(); } release()127 virtual void SAL_CALL release() throw () override 128 { OWeakObject::release(); } 129 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& type) override; 130 131 // XTypeProvider 132 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override; 133 134 /** 135 @interface XDesktop 136 137 @short try to shutdown these desktop environment. 138 139 @descr Will try to close all frames. If at least one frame could 140 not be closed successfully termination will be stopped. 141 142 Registered termination listener will be taken into account 143 also. As special feature some of our registered listener 144 are well known by its UNO implementation name. They are handled 145 different to all other listener. 146 147 Btw: Desktop.terminate() was designed in the past to be used 148 within an UI based environment. So it's allowed e.g. to 149 call XController.suspend() here. If UI isn't an option ... please 150 use XCloseable.close() at these desktop implementation. 151 ... if it will be supported in the future .-)) 152 153 @seealso XTerminateListener 154 @seealso XTerminateListener2 155 156 @return true if all open frames could be closed and no listener threw 157 a veto exception; false otherwise. 158 159 @onerror False will be returned. 160 @threadsafe yes 161 */ 162 virtual sal_Bool SAL_CALL terminate() override; 163 164 /** 165 @interface XDesktop 166 167 @short add a listener for termination events 168 169 @descr Additional to adding normal listener these method was implemented special. 170 Every listener will be asked for its uno implementation name. 171 Some of them are well known... and the corresponding listener won't be added 172 to the container of "normal listener". Those listener will be set as special 173 member. 174 see e.g. member m_xSfxTerminator 175 176 @seealso terminate() 177 178 @param xListener 179 the listener for registration. 180 181 @threadsafe yes 182 */ 183 virtual void SAL_CALL addTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener ) override; 184 185 /** 186 @interface XDesktop 187 188 @short remove a listener from this container. 189 190 @descr Additional to removing normal listener these method was implemented special. 191 Every listener will be asked for its uno implementation name. 192 Some of them are well known... and the corresponding listener was set as special member. 193 Now those special member will be reset also. 194 see e.g. member m_xSfxTerminator 195 196 @seealso terminate() 197 198 @param xListener 199 the listener for deregistration. 200 201 @threadsafe yes 202 */ 203 virtual void SAL_CALL removeTerminateListener( const css::uno::Reference< css::frame::XTerminateListener >& xListener ) override; 204 205 virtual css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL getComponents ( ) override; 206 virtual css::uno::Reference< css::lang::XComponent > SAL_CALL getCurrentComponent ( ) override; 207 virtual css::uno::Reference< css::frame::XFrame > SAL_CALL getCurrentFrame ( ) override; 208 209 // XComponentLoader 210 virtual css::uno::Reference< css::lang::XComponent > SAL_CALL loadComponentFromURL ( const OUString& sURL , 211 const OUString& sTargetFrameName , 212 sal_Int32 nSearchFlags , 213 const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) override; 214 215 // XTasksSupplier 216 virtual css::uno::Reference< css::container::XEnumerationAccess > SAL_CALL getTasks ( ) override; 217 virtual css::uno::Reference< css::frame::XTask > SAL_CALL getActiveTask ( ) override; 218 219 // XDispatchProvider 220 virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch ( const css::util::URL& aURL , 221 const OUString& sTargetFrameName , 222 sal_Int32 nSearchFlags ) override; 223 virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches ( const css::uno::Sequence< css::frame::DispatchDescriptor >& lQueries ) override; 224 225 // XDispatchProviderInterception 226 virtual void SAL_CALL registerDispatchProviderInterceptor( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor) override; 227 virtual void SAL_CALL releaseDispatchProviderInterceptor ( const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor) override; 228 229 // XFramesSupplier 230 virtual css::uno::Reference< css::frame::XFrames > SAL_CALL getFrames ( ) override; 231 virtual css::uno::Reference< css::frame::XFrame > SAL_CALL getActiveFrame ( ) override; 232 virtual void SAL_CALL setActiveFrame ( const css::uno::Reference< css::frame::XFrame >& xFrame ) override; 233 234 // XFrame 235 // Attention: findFrame() is implemented only! Other methods make no sense for our desktop! 236 virtual css::uno::Reference< css::frame::XFrame > SAL_CALL findFrame ( const OUString& sTargetFrameName , 237 sal_Int32 nSearchFlags ) override; 238 virtual void SAL_CALL initialize ( const css::uno::Reference< css::awt::XWindow >& xWindow ) override; 239 virtual css::uno::Reference< css::awt::XWindow > SAL_CALL getContainerWindow ( ) override; 240 virtual void SAL_CALL setCreator ( const css::uno::Reference< css::frame::XFramesSupplier >& xCreator ) override; 241 virtual css::uno::Reference< css::frame::XFramesSupplier > SAL_CALL getCreator ( ) override; 242 virtual OUString SAL_CALL getName ( ) override; 243 virtual void SAL_CALL setName ( const OUString& sName ) override; 244 virtual sal_Bool SAL_CALL isTop ( ) override; 245 virtual void SAL_CALL activate ( ) override; 246 virtual void SAL_CALL deactivate ( ) override; 247 virtual sal_Bool SAL_CALL isActive ( ) override; 248 virtual sal_Bool SAL_CALL setComponent ( const css::uno::Reference< css::awt::XWindow >& xComponentWindow , 249 const css::uno::Reference< css::frame::XController >& xController ) override; 250 virtual css::uno::Reference< css::awt::XWindow > SAL_CALL getComponentWindow ( ) override; 251 virtual css::uno::Reference< css::frame::XController > SAL_CALL getController ( ) override; 252 virtual void SAL_CALL contextChanged ( ) override; 253 virtual void SAL_CALL addFrameActionListener ( const css::uno::Reference< css::frame::XFrameActionListener >& xListener ) override; 254 virtual void SAL_CALL removeFrameActionListener ( const css::uno::Reference< css::frame::XFrameActionListener >& xListener ) override; 255 256 // XComponent 257 virtual void SAL_CALL disposing() override; 258 virtual void SAL_CALL addEventListener ( const css::uno::Reference< css::lang::XEventListener >& xListener ) override; 259 virtual void SAL_CALL removeEventListener ( const css::uno::Reference< css::lang::XEventListener >& xListener ) override; 260 261 // XDispatchResultListener 262 virtual void SAL_CALL dispatchFinished ( const css::frame::DispatchResultEvent& aEvent ) override; 263 264 // XEventListener 265 virtual void SAL_CALL disposing ( const css::lang::EventObject& aSource ) override; 266 267 // XInteractionHandler 268 virtual void SAL_CALL handle ( const css::uno::Reference< css::task::XInteractionRequest >& xRequest ) override; 269 270 // css.frame.XUntitledNumbers 271 virtual ::sal_Int32 SAL_CALL leaseNumber( const css::uno::Reference< css::uno::XInterface >& xComponent ) override; 272 273 // css.frame.XUntitledNumbers 274 virtual void SAL_CALL releaseNumber( ::sal_Int32 nNumber ) override; 275 276 // css.frame.XUntitledNumbers 277 virtual void SAL_CALL releaseNumberForComponent( const css::uno::Reference< css::uno::XInterface >& xComponent ) override; 278 279 // css.frame.XUntitledNumbers 280 virtual OUString SAL_CALL getUntitledPrefix() override; 281 282 // we need this wrapped terminate()-call to terminate even the QuickStarter 283 // non-virtual and non-UNO for now 284 /// @throws css::uno::RuntimeException 285 bool terminateQuickstarterToo(); 286 287 // protected methods 288 289 protected: 290 291 // OPropertySetHelper 292 virtual sal_Bool SAL_CALL convertFastPropertyValue ( css::uno::Any& aConvertedValue , 293 css::uno::Any& aOldValue , 294 sal_Int32 nHandle , 295 const css::uno::Any& aValue ) override; 296 virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle , 297 const css::uno::Any& aValue ) override; 298 using cppu::OPropertySetHelper::getFastPropertyValue; 299 virtual void SAL_CALL getFastPropertyValue ( css::uno::Any& aValue , 300 sal_Int32 nHandle ) const override; 301 virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper ( ) override; 302 virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo ( ) override; 303 304 305 private: 306 307 css::uno::Reference< css::lang::XComponent > impl_getFrameComponent ( const css::uno::Reference< css::frame::XFrame >& xFrame ) const; 308 309 /** calls queryTermination() on every registered termination listener. 310 * 311 * Note: Only normal termination listener (registered in list m_aListenerContainer 312 * will be recognized here. Special listener like quick starter, pipe or others 313 * has to be handled explicitly ! 314 * 315 * @param [out] lCalledListener 316 * every called listener will be returned here. 317 * Those list will be used to inform all called listener 318 * about cancel this termination request. 319 * 320 * @param [out] bVeto 321 * will be true if at least one listener threw a veto exception; 322 * false otherwise. 323 * 324 * @see impl_sendCancelTerminationEvent() 325 */ 326 void impl_sendQueryTerminationEvent(TTerminateListenerList& lCalledListener, 327 bool& bVeto ); 328 329 /** calls cancelTermination() on every termination listener 330 * where queryTermination() was called before. 331 * 332 * Note: Only normal termination listener (registered in list m_aListenerContainer 333 * will be recognized here. Special listener like quick starter, pipe or others 334 * has to be handled explicitly ! 335 * 336 * @param [in] lCalledListener 337 * every listener in this list was called within its method 338 * queryTermination() before. 339 * 340 * @see impl_sendQueryTerminationEvent() 341 */ 342 void impl_sendCancelTerminationEvent(const TTerminateListenerList& lCalledListener); 343 344 /** calls notifyTermination() on the clipboard listener 345 * 346 * The system clipboard may decide that it wants copies 347 * in several formats of the clipboard content requiring 348 * nearly all the services 349 * 350 */ 351 void impl_sendTerminateToClipboard(); 352 353 /** calls notifyTermination() on every registered termination listener. 354 * 355 * Note: Only normal termination listener (registered in list m_aListenerContainer 356 * will be recognized here. Special listener like quick starter, pipe or others 357 * has to be handled explicitly ! 358 */ 359 void impl_sendNotifyTerminationEvent(); 360 361 /** try to close all open frames. 362 * 363 * Iterates over all child frames and try to close them. 364 * Given parameter bAllowUI enable/disable showing any UI 365 * (which mostly occur on calling XController->suspend()). 366 * 367 * This method doesn't stop if one frame could not be closed. 368 * It will ignore such frames and try all other ones. 369 * But it returns false in such case - true otherwise. 370 * 371 * @param bAllowUI 372 * enable/disable showing of UI. 373 * 374 * @return true if all frames could be closed; false otherwise. 375 */ 376 bool impl_closeFrames(bool bAllowUI); 377 378 private: 379 380 /** check flag to protect us against dispose before terminate! 381 * see dispose() for further information! 382 */ 383 bool m_bIsTerminated; 384 385 /** when true, the call came from session manager 386 * the method is Desktop::terminateQuickstarterToo() 387 * this the only one place where set this to true 388 * In this case, when one frame break, not make 389 * question for other, the break of shutdown or logout 390 * can be only once. 391 * In Desktop::impl_closeFrames would be test and break 392 * the loop and reset to false 393 */ 394 bool m_bSession; 395 396 css::uno::Reference< css::uno::XComponentContext > m_xContext; /// reference to factory, which has create this instance 397 FrameContainer m_aChildTaskContainer; /// array of child tasks (children of desktop are tasks; and tasks are also frames - But pure frames are not accepted!) 398 ::cppu::OMultiTypeInterfaceContainerHelper m_aListenerContainer; /// container for ALL Listener 399 css::uno::Reference< css::frame::XFrames > m_xFramesHelper; /// helper for XFrames, XIndexAccess, XElementAccess and implementation of a childcontainer! 400 css::uno::Reference< css::frame::XDispatchProvider > m_xDispatchHelper; /// helper to dispatch something for new tasks, created by "_blank"! 401 ELoadState m_eLoadState; /// hold information about state of asynchron loading of component for loadComponentFromURL()! 402 bool m_bSuspendQuickstartVeto; /// don't ask quickstart for a veto 403 std::unique_ptr<SvtCommandOptions> m_xCommandOptions; /// ref counted class to support disabling commands defined by configuration file 404 OUString m_sName; 405 OUString m_sTitle; 406 css::uno::Reference< css::frame::XDispatchRecorderSupplier > m_xDispatchRecorderSupplier; 407 408 /** special terminate listener to close pipe and block external requests 409 * during/after termination process is/was running 410 */ 411 css::uno::Reference< css::frame::XTerminateListener > m_xPipeTerminator; 412 413 /** special terminate listener shown inside system tray (quick starter) 414 * Will hinder the office on shutdown ... but wish to allow closing 415 * of open documents. And because that's different to a normal terminate listener 416 * it has to be handled special .-) 417 */ 418 css::uno::Reference< css::frame::XTerminateListener > m_xQuickLauncher; 419 420 /** special terminate listener active when a macro is executing. 421 * Because basic runs Application::Yield internally the application may quit 422 * while running inside the internal basic event loop. So all the basic 423 * infrastructure may be deleted while the call is executing, leading to 424 * a variant of crashes. So this special terminate listener will 425 * veto the current quit attempt, stop basic execution, which will 426 * cause the inner event loop to quit, and on return to the outer normal 427 * application event loop then resend the quit attempt. 428 * So these implementation must be a special terminate listener too .-( 429 */ 430 css::uno::Reference< css::frame::XTerminateListener > m_xStarBasicQuitGuard; 431 432 /** special terminate listener which loads images asynchronous for current open documents. 433 * Because internally it uses blocking system APIs... it can't be guaranteed that 434 * running jobs can be cancelled successfully if the corresponding document will be closed... 435 * it will not hinder those documents on closing. Instead it let all jobs running... 436 * but at least on terminate we have to wait for all those blocked requests. 437 * So these implementation must be a special terminate listener too .-( 438 */ 439 css::uno::Reference< css::frame::XTerminateListener > m_xSWThreadManager; 440 441 /** special terminate listener shutting down the SfxApplication. 442 * Because these desktop instance closes documents and informs listener 443 * only... it does not really shutdown the whole application. 444 * 445 * Btw: that wouldn't be possible by design... because Desktop.terminate() 446 * has to return a boolean value about success... it can't really shutdown the 447 * process .-) 448 * 449 * So we uses a trick: a special listener (exactly these one here) listen for notifyTermination() 450 * and shutdown the process asynchronous. But desktop has to make this special 451 * notification as really last one ... Otherwise it can happen that asynchronous 452 * shutdown will be faster then all other code around Desktop.terminate() .-)) 453 */ 454 css::uno::Reference< css::frame::XTerminateListener > m_xSfxTerminator; 455 456 css::uno::Reference< css::frame::XUntitledNumbers > m_xTitleNumberGenerator; 457 458 std::vector<css::uno::Reference<css::frame::XTerminateListener>> m_xComponentDllListeners; 459 460 }; // class Desktop 461 462 } // namespace framework 463 464 #endif // INCLUDED_FRAMEWORK_INC_SERVICES_DESKTOP_HXX 465 466 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 467