Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / framework / source / services / frame.cxx
blob659578975a5eecc6cf8397d9d5e0e00beff33f82
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <utility>
24 #include <dispatch/dispatchprovider.hxx>
25 #include <dispatch/interceptionhelper.hxx>
26 #include <dispatch/windowcommanddispatch.hxx>
27 #include <loadenv/loadenv.hxx>
28 #include <helper/oframes.hxx>
29 #include <framework/framecontainer.hxx>
30 #include <framework/titlehelper.hxx>
31 #include <svtools/openfiledroptargetlistener.hxx>
32 #include <classes/taskcreator.hxx>
33 #include <loadenv/targethelper.hxx>
34 #include <framework/framelistanalyzer.hxx>
35 #include <helper/dockingareadefaultacceptor.hxx>
36 #include <dispatch/dispatchinformationprovider.hxx>
38 #include <pattern/window.hxx>
39 #include <properties.h>
40 #include <targets.h>
42 #include <com/sun/star/awt/Toolkit.hpp>
43 #include <com/sun/star/awt/XDevice.hpp>
44 #include <com/sun/star/awt/XTopWindow.hpp>
45 #include <com/sun/star/awt/PosSize.hpp>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 #include <com/sun/star/beans/PropertyExistException.hpp>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <com/sun/star/container/XIndexAccess.hpp>
51 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
52 #include <com/sun/star/frame/XFrame2.hpp>
53 #include <com/sun/star/frame/XModel.hpp>
54 #include <com/sun/star/frame/XTitleChangeBroadcaster.hpp>
55 #include <com/sun/star/frame/LayoutManager.hpp>
56 #include <com/sun/star/frame/XDesktop.hpp>
57 #include <com/sun/star/frame/FrameSearchFlag.hpp>
58 #include <com/sun/star/lang/DisposedException.hpp>
59 #include <com/sun/star/task/StatusIndicatorFactory.hpp>
60 #include <com/sun/star/task/theJobExecutor.hpp>
61 #include <com/sun/star/task/XJobExecutor.hpp>
62 #include <com/sun/star/util/CloseVetoException.hpp>
63 #include <com/sun/star/util/URLTransformer.hpp>
64 #include <com/sun/star/util/XURLTransformer.hpp>
65 #include <com/sun/star/util/XCloseable.hpp>
66 #include <com/sun/star/lang/XServiceInfo.hpp>
68 #include <cppuhelper/basemutex.hxx>
69 #include <cppuhelper/compbase.hxx>
70 #include <comphelper/multiinterfacecontainer3.hxx>
71 #include <comphelper/multicontainer2.hxx>
72 #include <cppuhelper/supportsservice.hxx>
73 #include <cppuhelper/weak.hxx>
74 #include <rtl/ref.hxx>
75 #include <sal/log.hxx>
76 #include <vcl/window.hxx>
77 #include <vcl/wrkwin.hxx>
78 #include <vcl/svapp.hxx>
80 #include <toolkit/helper/vclunohelper.hxx>
81 #include <unotools/moduleoptions.hxx>
82 #include <comphelper/diagnose_ex.hxx>
83 #include <unotools/cmdoptions.hxx>
84 #include <vcl/threadex.hxx>
85 #include <mutex>
87 using namespace framework;
89 namespace {
91 // This enum can be used to set different active states of frames
92 enum EActiveState
94 E_INACTIVE, // I am not a member of active path in tree and i don't have the focus.
95 E_ACTIVE, // I am in the middle of an active path in tree and i don't have the focus.
96 E_FOCUS // I have the focus now. I must a member of an active path!
99 /*-************************************************************************************************************
100 @short implements a normal frame of hierarchy
101 @descr An instance of these class can be a normal node in frame tree. A frame support influencing of his
102 subtree, find of subframes, activate- and deactivate-mechanism as well as
103 set/get of a frame window, component or controller.
104 *//*-*************************************************************************************************************/
105 class XFrameImpl:
106 private cppu::BaseMutex,
107 public cppu::PartialWeakComponentImplHelper<
108 css::lang::XServiceInfo, css::frame::XFrame2, css::awt::XWindowListener,
109 css::awt::XTopWindowListener, css::awt::XFocusListener,
110 css::document::XActionLockable, css::util::XCloseable,
111 css::frame::XComponentLoader, css::frame::XTitle,
112 css::frame::XTitleChangeBroadcaster, css::beans::XPropertySet,
113 css::beans::XPropertySetInfo>
115 public:
117 explicit XFrameImpl(css::uno::Reference< css::uno::XComponentContext > xContext);
119 /// Initialization function after having acquire()'d.
120 void initListeners();
122 virtual OUString SAL_CALL getImplementationName() override
124 return "com.sun.star.comp.framework.Frame";
127 virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
129 return cppu::supportsService(this, ServiceName);
132 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
134 return {"com.sun.star.frame.Frame"};
137 // XComponentLoader
139 virtual css::uno::Reference< css::lang::XComponent > SAL_CALL loadComponentFromURL(
140 const OUString& sURL,
141 const OUString& sTargetFrameName,
142 sal_Int32 nSearchFlags,
143 const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) override;
145 // XFramesSupplier
147 virtual css::uno::Reference < css::frame::XFrames > SAL_CALL getFrames() override;
148 virtual css::uno::Reference < css::frame::XFrame > SAL_CALL getActiveFrame() override;
149 virtual void SAL_CALL setActiveFrame(const css::uno::Reference < css::frame::XFrame > & xFrame) override;
151 // XFrame
153 virtual void SAL_CALL initialize(const css::uno::Reference < css::awt::XWindow > & xWindow) override;
154 virtual css::uno::Reference < css::awt::XWindow > SAL_CALL getContainerWindow() override;
155 virtual void SAL_CALL setCreator(const css::uno::Reference < css::frame::XFramesSupplier > & xCreator) override;
156 virtual css::uno::Reference < css::frame::XFramesSupplier > SAL_CALL getCreator() override;
157 virtual OUString SAL_CALL getName() override;
158 virtual void SAL_CALL setName(const OUString & sName) override;
159 virtual css::uno::Reference < css::frame::XFrame > SAL_CALL findFrame(
160 const OUString & sTargetFrameName,
161 sal_Int32 nSearchFlags) override;
162 virtual sal_Bool SAL_CALL isTop() override;
163 virtual void SAL_CALL activate() override;
164 virtual void SAL_CALL deactivate() override;
165 virtual sal_Bool SAL_CALL isActive() override;
166 virtual void SAL_CALL contextChanged() override;
167 virtual sal_Bool SAL_CALL setComponent(
168 const css::uno::Reference < css::awt::XWindow > & xComponentWindow,
169 const css::uno::Reference < css::frame::XController > & xController) override;
170 virtual css::uno::Reference < css::awt::XWindow > SAL_CALL getComponentWindow() override;
171 virtual css::uno::Reference < css::frame::XController > SAL_CALL getController() override;
172 virtual void SAL_CALL addFrameActionListener(const css::uno::Reference < css::frame::XFrameActionListener > & xListener) override;
173 virtual void SAL_CALL removeFrameActionListener(const css::uno::Reference < css::frame::XFrameActionListener > & xListener) override;
175 // XComponent
177 virtual void SAL_CALL disposing() override;
178 virtual void SAL_CALL addEventListener(const css::uno::Reference < css::lang::XEventListener > & xListener) override;
179 virtual void SAL_CALL removeEventListener(const css::uno::Reference < css::lang::XEventListener > & xListener) override;
181 // XStatusIndicatorFactory
183 virtual css::uno::Reference < css::task::XStatusIndicator > SAL_CALL createStatusIndicator() override;
185 // XDispatchProvider
187 virtual css::uno::Reference < css::frame::XDispatch > SAL_CALL queryDispatch(const css::util::URL & aURL,
188 const OUString & sTargetFrameName,
189 sal_Int32 nSearchFlags) override;
190 virtual css::uno::Sequence < css::uno::Reference < css::frame::XDispatch > > SAL_CALL queryDispatches(
191 const css::uno::Sequence < css::frame::DispatchDescriptor > & lDescriptor) override;
193 // XDispatchProviderInterception
195 virtual void SAL_CALL registerDispatchProviderInterceptor(
196 const css::uno::Reference < css::frame::XDispatchProviderInterceptor > & xInterceptor) override;
197 virtual void SAL_CALL releaseDispatchProviderInterceptor(
198 const css::uno::Reference < css::frame::XDispatchProviderInterceptor > & xInterceptor) override;
200 // XDispatchInformationProvider
202 virtual css::uno::Sequence < sal_Int16 > SAL_CALL getSupportedCommandGroups() override;
203 virtual css::uno::Sequence < css::frame::DispatchInformation > SAL_CALL getConfigurableDispatchInformation(sal_Int16 nCommandGroup) override;
205 // XWindowListener
206 // Attention: windowResized() and windowShown() are implement only! All other are empty!
208 virtual void SAL_CALL windowResized(const css::awt::WindowEvent & aEvent) override;
209 virtual void SAL_CALL windowMoved(const css::awt::WindowEvent & /*aEvent*/ ) override {};
210 virtual void SAL_CALL windowShown(const css::lang::EventObject & aEvent) override;
211 virtual void SAL_CALL windowHidden(const css::lang::EventObject & aEvent) override;
213 // XFocusListener
214 // Attention: focusLost() not implemented yet!
216 virtual void SAL_CALL focusGained(const css::awt::FocusEvent & aEvent) override;
217 virtual void SAL_CALL focusLost(const css::awt::FocusEvent & /*aEvent*/ ) override {};
219 // XTopWindowListener
220 // Attention: windowActivated(), windowDeactivated() and windowClosing() are implement only! All other are empty!
222 virtual void SAL_CALL windowActivated(const css::lang::EventObject & aEvent) override;
223 virtual void SAL_CALL windowDeactivated(const css::lang::EventObject & aEvent) override;
224 virtual void SAL_CALL windowOpened(const css::lang::EventObject & /*aEvent*/ ) override {};
225 virtual void SAL_CALL windowClosing(const css::lang::EventObject & aEvent) override;
226 virtual void SAL_CALL windowClosed(const css::lang::EventObject & /*aEvent*/ ) override {};
227 virtual void SAL_CALL windowMinimized(const css::lang::EventObject & /*aEvent*/ ) override {};
228 virtual void SAL_CALL windowNormalized(const css::lang::EventObject & /*aEvent*/ ) override {};
230 // XEventListener
232 virtual void SAL_CALL disposing(const css::lang::EventObject & aEvent) override;
234 // XActionLockable
236 virtual sal_Bool SAL_CALL isActionLocked() override;
237 virtual void SAL_CALL addActionLock() override;
238 virtual void SAL_CALL removeActionLock() override;
239 virtual void SAL_CALL setActionLocks(sal_Int16 nLock) override;
240 virtual sal_Int16 SAL_CALL resetActionLocks() override;
242 // XCloseable
244 virtual void SAL_CALL close(sal_Bool bDeliverOwnership) override;
246 // XCloseBroadcaster
248 virtual void SAL_CALL addCloseListener(const css::uno::Reference < css::util::XCloseListener > & xListener) override;
249 virtual void SAL_CALL removeCloseListener(const css::uno::Reference < css::util::XCloseListener > & xListener) override;
251 // XTitle
253 virtual OUString SAL_CALL getTitle() override;
254 virtual void SAL_CALL setTitle(const OUString & sTitle) override;
256 // XTitleChangeBroadcaster
258 virtual void SAL_CALL addTitleChangeListener(const css::uno::Reference < css::frame::XTitleChangeListener > & xListener) override;
259 virtual void SAL_CALL removeTitleChangeListener(const css::uno::Reference < css::frame::XTitleChangeListener > & xListenr) override;
261 // XFrame2 attributes
263 virtual css::uno::Reference < css::container::XNameContainer > SAL_CALL getUserDefinedAttributes() override;
265 virtual css::uno::Reference < css::frame::XDispatchRecorderSupplier > SAL_CALL getDispatchRecorderSupplier() override;
266 virtual void SAL_CALL setDispatchRecorderSupplier(const css::uno::Reference < css::frame::XDispatchRecorderSupplier > & ) override;
268 virtual css::uno::Reference < css::uno::XInterface > SAL_CALL getLayoutManager() override;
269 virtual void SAL_CALL setLayoutManager(const css::uno::Reference < css::uno::XInterface > & ) override;
271 // XPropertySet
272 virtual css::uno::Reference < css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override;
274 virtual void SAL_CALL setPropertyValue(const OUString & sProperty, const css::uno::Any & aValue) override;
276 virtual css::uno::Any SAL_CALL getPropertyValue(const OUString & sProperty) override;
278 virtual void SAL_CALL addPropertyChangeListener(
279 const OUString & sProperty,
280 const css::uno::Reference < css::beans::XPropertyChangeListener > & xListener) override;
282 virtual void SAL_CALL removePropertyChangeListener(
283 const OUString & sProperty,
284 const css::uno::Reference < css::beans::XPropertyChangeListener > & xListener) override;
286 virtual void SAL_CALL addVetoableChangeListener(
287 const OUString & sProperty,
288 const css::uno::Reference < css::beans::XVetoableChangeListener > & xListener) override;
290 virtual void SAL_CALL removeVetoableChangeListener(
291 const OUString & sProperty,
292 const css::uno::Reference < css::beans::XVetoableChangeListener > & xListener) override;
294 // XPropertySetInfo
295 virtual css::uno::Sequence < css::beans::Property > SAL_CALL getProperties() override;
297 virtual css::beans::Property SAL_CALL getPropertyByName(const OUString & sName) override;
299 virtual sal_Bool SAL_CALL hasPropertyByName(const OUString & sName) override;
302 private:
304 void impl_setPropertyValue(sal_Int32 nHandle,
305 const css::uno::Any& aValue);
307 css::uno::Any impl_getPropertyValue(sal_Int32 nHandle);
309 /** set a new owner for this helper.
311 * This owner is used as source for all broadcasted events.
312 * Further we hold it weak, because we don't wish to be disposed() .-)
314 void impl_setPropertyChangeBroadcaster(const css::uno::Reference< css::uno::XInterface >& xBroadcaster);
316 /** add a new property info to the set of supported ones.
318 * @param aProperty
319 * describes the new property.
321 * @throw [css::beans::PropertyExistException]
322 * if a property with the same name already exists.
324 * Note: The consistence of the whole set of properties is not checked here.
325 * Means e.g. ... a handle which exists more than once is not detected.
326 * The owner of this class has to be sure, that every new property does
327 * not clash with any existing one.
329 void impl_addPropertyInfo(const css::beans::Property& aProperty);
331 /** mark the object as "dead".
333 void impl_disablePropertySet();
335 bool impl_existsVeto(const css::beans::PropertyChangeEvent& aEvent);
337 void impl_notifyChangeListener(const css::beans::PropertyChangeEvent& aEvent);
339 /*-****************************************************************************************************
340 @short helper methods
341 @descr Follow methods are needed at different points of our code (more than ones!).
343 @attention Threadsafe methods are signed by "implts_..."!
344 *//*-*****************************************************************************************************/
346 // threadsafe
347 void implts_sendFrameActionEvent ( const css::frame::FrameAction& aAction );
348 void implts_resizeComponentWindow ( );
349 void implts_setIconOnWindow ( );
350 void implts_startWindowListening ( );
351 void implts_stopWindowListening ( );
352 void implts_checkSuicide ( );
353 void implts_forgetSubFrames ( );
355 // non threadsafe
356 void impl_checkMenuCloser ( );
357 void impl_setCloser ( const css::uno::Reference< css::frame::XFrame2 >& xFrame , bool bState );
359 void disableLayoutManager(const css::uno::Reference< css::frame::XLayoutManager2 >& xLayoutManager);
361 void checkDisposed() {
362 osl::MutexGuard g(rBHelper.rMutex);
363 if (rBHelper.bInDispose || rBHelper.bDisposed) {
364 throw css::lang::DisposedException("Frame disposed");
368 // variables
369 // -threadsafe by SolarMutex
371 /// reference to factory, which has create this instance
372 css::uno::Reference< css::uno::XComponentContext > m_xContext;
373 /// reference to factory helper to create status indicator objects
374 css::uno::Reference< css::task::XStatusIndicatorFactory > m_xIndicatorFactoryHelper;
375 /// points to an external set progress, which should be used instead of the internal one.
376 css::uno::WeakReference< css::task::XStatusIndicator > m_xIndicatorInterception;
377 /// helper for XDispatch/Provider and interception interfaces
378 rtl::Reference< InterceptionHelper > m_xDispatchHelper;
379 /// helper for XFrames, XIndexAccess and XElementAccess interfaces
380 css::uno::Reference< css::frame::XFrames > m_xFramesHelper;
381 /// container for ALL Listener
382 comphelper::OMultiTypeInterfaceContainerHelper2 m_aListenerContainer;
383 /// parent of this frame
384 css::uno::Reference< css::frame::XFramesSupplier > m_xParent;
385 /// containerwindow of this frame for embedded components
386 css::uno::Reference< css::awt::XWindow > m_xContainerWindow;
387 /// window of the actual component
388 css::uno::Reference< css::awt::XWindow > m_xComponentWindow;
389 /// controller of the actual frame
390 css::uno::Reference< css::frame::XController > m_xController;
391 /// listen to drag & drop
392 css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > m_xDropTargetListener;
393 /// state, if I am a member of active path in tree or I have the focus or...
394 EActiveState m_eActiveState;
395 /// name of this frame
396 OUString m_sName;
397 /// frame has no parent or the parent is a task or the desktop
398 bool m_bIsFrameTop;
399 /// due to FrameActionEvent
400 bool m_bConnected;
401 sal_Int16 m_nExternalLockCount;
402 /// is used for dispatch recording and will be set/get from outside. Frame provide it only!
403 css::uno::Reference< css::frame::XDispatchRecorderSupplier > m_xDispatchRecorderSupplier;
404 /// ref counted class to support disabling commands defined by configuration file
405 SvtCommandOptions m_aCommandOptions;
406 /// in case of CloseVetoException on method close() was thrown by ourself - we must close ourself later if no internal processes are running
407 bool m_bSelfClose;
408 /// indicates, if this frame is used in hidden mode or not
409 bool m_bIsHidden;
410 /// The container window has WindowExtendedStyle::DocHidden set.
411 bool m_bDocHidden = false;
412 /// is used to layout the child windows of the frame.
413 css::uno::Reference< css::frame::XLayoutManager2 > m_xLayoutManager;
414 css::uno::Reference< css::frame::XDispatchInformationProvider > m_xDispatchInfoHelper;
415 css::uno::Reference< css::frame::XTitle > m_xTitleHelper;
417 std::unique_ptr<WindowCommandDispatch> m_pWindowCommandDispatch;
419 typedef std::unordered_map<OUString, css::beans::Property> TPropInfoHash;
420 TPropInfoHash m_lProps;
422 comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XPropertyChangeListener, OUString> m_lSimpleChangeListener;
423 comphelper::OMultiTypeInterfaceContainerHelperVar3<css::beans::XVetoableChangeListener, OUString> m_lVetoChangeListener;
425 // hold it weak ... otherwise this helper has to be "killed" explicitly .-)
426 css::uno::WeakReference< css::uno::XInterface > m_xBroadcaster;
428 FrameContainer m_aChildFrameContainer; /// array of child frames
430 * URL of the file that is being loaded, when the load already started by we have no controller
431 * yet.
433 OUString m_aURL;
437 /*-****************************************************************************************************
438 @short standard constructor to create instance by factory
439 @descr This constructor initialize a new instance of this class by valid factory,
440 and will be set valid values on his member and baseclasses.
442 @attention a) Don't use your own reference during a UNO-Service-ctor! There is no guarantee, that you
443 will get over this. (e.g. using of your reference as parameter to initialize some member)
444 Do such things in DEFINE_INIT_SERVICE() method, which is called automatically after your ctor!!!
445 b) Baseclass OBroadcastHelper is a typedef in namespace cppu!
446 The microsoft compiler has some problems to handle it right BY using namespace explicitly ::cppu::OBroadcastHelper.
447 If we write it without a namespace or expand the typedef to OBroadcastHelperVar<...> -> it will be OK!?
448 I don't know why! (other compiler not tested .. but it works!)
450 @seealso method DEFINE_INIT_SERVICE()
452 @param xContext is the multi service manager, which creates this instance.
453 The value must be different from NULL!
454 @onerror ASSERT in debug version or nothing in release version.
455 *//*-*****************************************************************************************************/
456 XFrameImpl::XFrameImpl( css::uno::Reference< css::uno::XComponentContext > xContext )
457 : PartialWeakComponentImplHelper(m_aMutex)
458 // init member
459 , m_xContext (std::move( xContext ))
460 , m_aListenerContainer ( m_aMutex )
461 , m_eActiveState ( E_INACTIVE )
462 , m_bIsFrameTop ( true ) // I think we are top without a parent ... and there is no parent yet!
463 , m_bConnected ( false ) // There exist no component inside of use => sal_False, we are not connected!
464 , m_nExternalLockCount ( 0 )
465 , m_bSelfClose ( false ) // Important!
466 , m_bIsHidden ( true )
467 , m_lSimpleChangeListener ( m_aMutex )
468 , m_lVetoChangeListener ( m_aMutex )
472 void XFrameImpl::initListeners()
474 css::uno::Reference< css::uno::XInterface > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY_THROW);
476 // Initialize a new dispatchhelper-object to handle dispatches.
477 // We use these helper as slave for our interceptor helper ... not directly!
478 // But he is event listener on THIS instance!
479 rtl::Reference<DispatchProvider> xDispatchProvider = new DispatchProvider( m_xContext, this );
481 m_xDispatchInfoHelper = new DispatchInformationProvider(m_xContext, this);
483 // Initialize a new interception helper object to handle dispatches and implement an interceptor mechanism.
484 // Set created dispatch provider as slowest slave of it.
485 // Hold interception helper by reference only - not by pointer!
486 // So it's easier to destroy it.
487 m_xDispatchHelper = new InterceptionHelper( this, xDispatchProvider );
489 // Initialize a new XFrames-helper-object to handle XIndexAccess and XElementAccess.
490 // We hold member as reference ... not as pointer too!
491 // Attention: We share our frame container with this helper. Container is threadsafe himself ... So I think we can do that.
492 // But look on dispose() for right order of deinitialization.
493 m_xFramesHelper = new OFrames( this, &m_aChildFrameContainer );
495 // Initialize the drop target listener.
496 // We hold member as reference ... not as pointer too!
497 m_xDropTargetListener = new OpenFileDropTargetListener( m_xContext, this );
499 // Safe impossible cases
500 // We can't work without these helpers!
501 SAL_WARN_IF( !xDispatchProvider.is(), "fwk.frame", "XFrameImpl::XFrameImpl(): Slowest slave for dispatch- and interception helper "
502 "is not valid. XDispatchProvider, XDispatch, XDispatchProviderInterception are not full supported!" );
503 SAL_WARN_IF( !m_xDispatchHelper.is(), "fwk.frame", "XFrameImpl::XFrameImpl(): Interception helper is not valid. XDispatchProvider, "
504 "XDispatch, XDispatchProviderInterception are not full supported!" );
505 SAL_WARN_IF( !m_xFramesHelper.is(), "fwk.frame", "XFrameImpl::XFrameImpl(): Frames helper is not valid. XFrames, "
506 "XIndexAccess and XElementAccess are not supported!" );
507 SAL_WARN_IF( !m_xDropTargetListener.is(), "fwk.frame", "XFrameImpl::XFrameImpl(): DropTarget helper is not valid. "
508 "Drag and drop without functionality!" );
510 // establish notifies for changing of "disabled commands" configuration during runtime
511 m_aCommandOptions.EstablishFrameCallback(this);
513 // Create an initial layout manager
514 // Create layout manager and connect it to the newly created frame
515 m_xLayoutManager = css::frame::LayoutManager::create(m_xContext);
517 // set information about all supported properties
518 impl_setPropertyChangeBroadcaster(static_cast< css::frame::XFrame* >(this));
519 impl_addPropertyInfo(
520 css::beans::Property(
521 FRAME_PROPNAME_ASCII_DISPATCHRECORDERSUPPLIER,
522 FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER,
523 cppu::UnoType<css::frame::XDispatchRecorderSupplier>::get(),
524 css::beans::PropertyAttribute::TRANSIENT));
525 impl_addPropertyInfo(
526 css::beans::Property(
527 FRAME_PROPNAME_ASCII_INDICATORINTERCEPTION,
528 FRAME_PROPHANDLE_INDICATORINTERCEPTION,
529 cppu::UnoType<css::task::XStatusIndicator>::get(),
530 css::beans::PropertyAttribute::TRANSIENT));
531 impl_addPropertyInfo(
532 css::beans::Property(
533 FRAME_PROPNAME_ASCII_ISHIDDEN,
534 FRAME_PROPHANDLE_ISHIDDEN,
535 cppu::UnoType<bool>::get(),
536 css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY));
537 impl_addPropertyInfo(
538 css::beans::Property(
539 FRAME_PROPNAME_ASCII_LAYOUTMANAGER,
540 FRAME_PROPHANDLE_LAYOUTMANAGER,
541 cppu::UnoType<css::frame::XLayoutManager>::get(),
542 css::beans::PropertyAttribute::TRANSIENT));
543 impl_addPropertyInfo(
544 css::beans::Property(
545 FRAME_PROPNAME_ASCII_TITLE,
546 FRAME_PROPHANDLE_TITLE,
547 cppu::UnoType<OUString>::get(),
548 css::beans::PropertyAttribute::TRANSIENT));
549 impl_addPropertyInfo(css::beans::Property(FRAME_PROPNAME_ASCII_URL, FRAME_PROPHANDLE_URL,
550 cppu::UnoType<OUString>::get(),
551 css::beans::PropertyAttribute::TRANSIENT));
554 /*-************************************************************************************************************
555 @interface XComponentLoader
556 @short try to load given URL into a task
557 @descr You can give us some information about the content, which you will load into a frame.
558 We search or create this target for you, make a type detection of given URL and try to load it.
559 As result of this operation we return the new created component or nothing, if loading failed.
560 @param "sURL" , URL, which represent the content
561 @param "sTargetFrameName" , name of target frame or special value like "_self", "_blank" ...
562 @param "nSearchFlags" , optional arguments for frame search, if target is not a special one
563 @param "lArguments" , optional arguments for loading
564 @return A valid component reference, if loading was successful.
565 A null reference otherwise.
567 @onerror We return a null reference.
568 @threadsafe yes
569 *//*-*************************************************************************************************************/
570 css::uno::Reference< css::lang::XComponent > SAL_CALL XFrameImpl::loadComponentFromURL(
571 const OUString& sURL,
572 const OUString& sTargetFrameName,
573 sal_Int32 nSearchFlags,
574 const css::uno::Sequence< css::beans::PropertyValue >& lArguments )
576 checkDisposed();
578 css::uno::Reference< css::frame::XComponentLoader > xThis(this);
580 utl::MediaDescriptor aDescriptor(lArguments);
581 bool bOnMainThread = aDescriptor.getUnpackedValueOrDefault("OnMainThread", false);
583 if (bOnMainThread)
585 // Make sure that we own the solar mutex, otherwise later
586 // vcl::SolarThreadExecutor::execute() will release the solar mutex, even if it's owned by
587 // another thread, leading to an std::abort() at the end.
588 SolarMutexGuard g;
590 return vcl::solarthread::syncExecute(std::bind(&LoadEnv::loadComponentFromURL, xThis,
591 m_xContext, sURL, sTargetFrameName,
592 nSearchFlags, lArguments));
594 else
595 return LoadEnv::loadComponentFromURL(xThis, m_xContext, sURL, sTargetFrameName,
596 nSearchFlags, lArguments);
599 /*-****************************************************************************************************
600 @short return access to append or remove children on desktop
601 @descr We don't implement these interface directly. We use a helper class to do this.
602 If you wish to add or delete children to/from the container, call these method to get
603 a reference to the helper.
605 @seealso class OFrames
606 @return A reference to the helper which answer your queries.
608 @onerror A null reference is returned.
609 *//*-*****************************************************************************************************/
610 css::uno::Reference< css::frame::XFrames > SAL_CALL XFrameImpl::getFrames()
612 checkDisposed();
614 SolarMutexGuard g;
615 // Return access to all child frames to caller.
616 // Our childframe container is implemented in helper class OFrames and used as a reference m_xFramesHelper!
617 return m_xFramesHelper;
620 /*-****************************************************************************************************
621 @short get the current active child frame
622 @descr It must be a frameto. Direct children of a frame are frames only! No task or desktop is accepted.
623 We don't save this information directly in this class. We use our container-helper
624 to do that.
626 @seealso class OFrameContainer
627 @seealso method setActiveFrame()
628 @return A reference to our current active childframe, if anyone exist.
629 @return A null reference, if nobody is active.
631 @onerror A null reference is returned.
632 *//*-*****************************************************************************************************/
633 css::uno::Reference< css::frame::XFrame > SAL_CALL XFrameImpl::getActiveFrame()
635 checkDisposed();
637 SolarMutexGuard g;
638 // Return current active frame.
639 // This information is available on the container.
640 return m_aChildFrameContainer.getActive();
643 /*-****************************************************************************************************
644 @short set the new active direct child frame
645 @descr It must be a frame to. Direct children of frame are frames only! No task or desktop is accepted.
646 We don't save this information directly in this class. We use our container-helper
647 to do that.
649 @seealso class OFrameContainer
650 @seealso method getActiveFrame()
652 @param "xFrame", reference to new active child. It must be an already existing child!
653 @onerror An assertion is thrown and element is ignored, if given frame isn't already a child of us.
654 *//*-*****************************************************************************************************/
655 void SAL_CALL XFrameImpl::setActiveFrame( const css::uno::Reference< css::frame::XFrame >& xFrame )
657 checkDisposed();
659 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
660 SolarMutexResettableGuard aWriteLock;
662 // Copy necessary member for threadsafe access!
663 // m_aChildFrameContainer is threadsafe himself and he live if we live!!!
664 css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive();
665 EActiveState eActiveState = m_eActiveState;
667 aWriteLock.clear();
668 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
670 // Don't work, if "new" active frame isn't different from current one!
671 // (xFrame==NULL is allowed to UNSET it!)
672 if( xActiveChild != xFrame )
674 // ... otherwise set new and deactivate old one.
675 m_aChildFrameContainer.setActive( xFrame );
676 if (
677 ( eActiveState != E_INACTIVE ) &&
678 xActiveChild.is()
681 xActiveChild->deactivate();
685 if( xFrame.is() )
687 // If last active frame had focus ...
688 // ... reset state to ACTIVE and send right FrameActionEvent for focus lost.
689 if( eActiveState == E_FOCUS )
691 aWriteLock.reset();
692 eActiveState = E_ACTIVE;
693 m_eActiveState = eActiveState;
694 aWriteLock.clear();
695 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_DEACTIVATING );
698 // If last active frame was active ...
699 // but new one is not it ...
700 // ... set it as active one.
701 if ( eActiveState == E_ACTIVE && !xFrame->isActive() )
703 xFrame->activate();
706 else
707 // If this frame is active and has no active subframe anymore it is UI active too
708 if( eActiveState == E_ACTIVE )
710 aWriteLock.reset();
711 eActiveState = E_FOCUS;
712 m_eActiveState = eActiveState;
713 aWriteLock.clear();
714 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_ACTIVATED );
718 /*-****************************************************************************************************
719 initialize new created layout manager
721 void lcl_enableLayoutManager(const css::uno::Reference< css::frame::XLayoutManager2 >& xLayoutManager,
722 const css::uno::Reference< css::frame::XFrame >& xFrame )
724 // Provide container window to our layout manager implementation
725 xLayoutManager->attachFrame(xFrame);
727 xFrame->addFrameActionListener(xLayoutManager);
729 rtl::Reference<DockingAreaDefaultAcceptor> xDockingAreaAcceptor = new DockingAreaDefaultAcceptor(xFrame);
730 xLayoutManager->setDockingAreaAcceptor(xDockingAreaAcceptor);
733 /*-****************************************************************************************************
734 deinitialize layout manager
736 void XFrameImpl::disableLayoutManager(const css::uno::Reference< css::frame::XLayoutManager2 >& xLayoutManager)
738 removeFrameActionListener(xLayoutManager);
739 xLayoutManager->setDockingAreaAcceptor(css::uno::Reference< css::ui::XDockingAreaAcceptor >());
740 xLayoutManager->attachFrame(css::uno::Reference< css::frame::XFrame >());
743 /*-****************************************************************************************************
744 @short initialize frame instance
745 @descr A frame needs a window. This method set a new one ... but should called one times only!
746 We use this window to listen for window events and forward it to our set component.
747 It's used as parent of component window too.
749 @seealso method getContainerWindow()
750 @seealso method setComponent()
751 @seealso member m_xContainerWindow
753 @param "xWindow", reference to new container window - must be valid!
754 @onerror We do nothing.
755 *//*-*****************************************************************************************************/
756 void SAL_CALL XFrameImpl::initialize( const css::uno::Reference< css::awt::XWindow >& xWindow )
758 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
759 if (!xWindow.is())
760 throw css::uno::RuntimeException(
761 "XFrameImpl::initialize() called without a valid container window reference.",
762 static_cast< css::frame::XFrame* >(this));
764 checkDisposed();
766 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
767 SolarMutexResettableGuard aWriteLock;
769 // This must be the first call of this method!
770 // We should initialize our object and open it for working.
771 if ( m_xContainerWindow.is() )
772 throw css::uno::RuntimeException(
773 "XFrameImpl::initialized() is called more than once, which is not useful nor allowed.",
774 static_cast< css::frame::XFrame* >(this));
776 // Set the new window.
777 m_xContainerWindow = xWindow;
779 // if window is initially visible, we will never get a windowShowing event
780 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
781 if (pWindow)
783 if (pWindow->IsVisible())
784 m_bIsHidden = false;
785 m_bDocHidden
786 = static_cast<bool>(pWindow->GetExtendedStyle() & WindowExtendedStyle::DocHidden);
789 css::uno::Reference< css::frame::XLayoutManager2 > xLayoutManager = m_xLayoutManager;
791 // Release lock ... because we call some impl methods, which are threadsafe by himself.
792 // If we hold this lock - we will produce our own deadlock!
793 aWriteLock.clear();
794 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
796 // Avoid enabling the layout manager for hidden frames: it's expensive and
797 // provides little value.
798 if (xLayoutManager.is() && !m_bDocHidden)
799 lcl_enableLayoutManager(xLayoutManager, this);
801 // create progress helper
802 css::uno::Reference< css::frame::XFrame > xThis (this);
803 css::uno::Reference< css::task::XStatusIndicatorFactory > xIndicatorFactory =
804 css::task::StatusIndicatorFactory::createWithFrame(m_xContext, xThis,
805 false/*DisableReschedule*/, true/*AllowParentShow*/ );
807 // SAFE -> ----------------------------------
808 aWriteLock.reset();
809 m_xIndicatorFactoryHelper = xIndicatorFactory;
810 aWriteLock.clear();
811 // <- SAFE ----------------------------------
813 // Start listening for events after setting it on helper class ...
814 // So superfluous messages are filtered to NULL :-)
815 implts_startWindowListening();
817 m_pWindowCommandDispatch.reset(new WindowCommandDispatch(m_xContext, this));
819 // Initialize title functionality
820 m_xTitleHelper = new TitleHelper( m_xContext, xThis, nullptr );
823 /*-****************************************************************************************************
824 @short returns current set container window
825 @descr The ContainerWindow property is used as a container for the component
826 in this frame. So this object implements a container interface too.
827 The instantiation of the container window is done by the user of this class.
828 The frame is the owner of its container window.
830 @seealso method initialize()
831 @return A reference to current set containerwindow.
833 @onerror A null reference is returned.
834 *//*-*****************************************************************************************************/
835 css::uno::Reference< css::awt::XWindow > SAL_CALL XFrameImpl::getContainerWindow()
837 SolarMutexGuard g;
838 return m_xContainerWindow;
841 /*-****************************************************************************************************
842 @short set parent frame
843 @descr We need a parent to support some functionality! e.g. findFrame()
844 By the way we use the chance to set an internal information about our top state.
845 So we must not check this information during every isTop() call.
846 We are top, if our parent is the desktop instance or we haven't any parent.
848 @seealso getCreator()
849 @seealso findFrame()
850 @seealso isTop()
851 @seealso m_bIsFrameTop
853 @param xCreator
854 valid reference to our new owner frame, which should implement a supplier interface
856 @threadsafe yes
857 *//*-*****************************************************************************************************/
858 void SAL_CALL XFrameImpl::setCreator( const css::uno::Reference< css::frame::XFramesSupplier >& xCreator )
860 checkDisposed();
862 /* SAFE { */
864 SolarMutexGuard aWriteLock;
865 m_xParent = xCreator;
867 /* } SAFE */
869 css::uno::Reference< css::frame::XDesktop > xIsDesktop( xCreator, css::uno::UNO_QUERY );
870 m_bIsFrameTop = ( xIsDesktop.is() || ! xCreator.is() );
873 /*-****************************************************************************************************
874 @short returns current parent frame
875 @descr The Creator is the parent frame container. If it is NULL, the frame is the uppermost one.
877 @seealso method setCreator()
878 @return A reference to current set parent frame container.
880 @onerror A null reference is returned.
881 *//*-*****************************************************************************************************/
882 css::uno::Reference< css::frame::XFramesSupplier > SAL_CALL XFrameImpl::getCreator()
884 checkDisposed();
885 SolarMutexGuard g;
886 return m_xParent;
889 /*-****************************************************************************************************
890 @short returns current set name of frame
891 @descr This name is used to find target of findFrame() or queryDispatch() calls.
893 @seealso method setName()
894 @return Current set name of frame.
896 @onerror An empty string is returned.
897 *//*-*****************************************************************************************************/
898 OUString SAL_CALL XFrameImpl::getName()
900 SolarMutexGuard g;
901 return m_sName;
904 /*-****************************************************************************************************
905 @short set new name for frame
906 @descr This name is used to find target of findFrame() or queryDispatch() calls.
908 @attention Special names like "_blank", "_self" aren't allowed...
909 "_beamer" excepts this rule!
911 @seealso method getName()
913 @param "sName", new frame name.
914 @onerror We do nothing.
915 *//*-*****************************************************************************************************/
916 void SAL_CALL XFrameImpl::setName( const OUString& sName )
918 SolarMutexGuard g;
919 // Set new name... but look for invalid special target names!
920 // They are not allowed to set.
921 if (TargetHelper::isValidNameForFrame(sName))
922 m_sName = sName;
925 /*-****************************************************************************************************
926 @short search for frames
927 @descr This method searches for a frame with the specified name.
928 Frames may contain other frames (e.g. a frameset) and may
929 be contained in other frames. This hierarchy is searched by
930 this method.
931 First some special names are taken into account, i.e. "",
932 "_self", "_top", "_blank" etc. The nSearchFlags are ignored
933 when comparing these names with sTargetFrameName, further steps are
934 controlled by the search flags. If allowed, the name of the frame
935 itself is compared with the desired one, then ( again if allowed )
936 the method findFrame() is called for all children, for siblings
937 and as last for the parent frame.
938 If no frame with the given name is found until the top frames container,
939 a new top one is created, if this is allowed by a special
940 flag. The new frame also gets the desired name.
942 @param sTargetFrameName
943 special names (_blank, _self) or real name of target frame
944 @param nSearchFlags
945 optional flags which regulate search for non special target frames
947 @return A reference to found or may be new created frame.
948 @threadsafe yes
949 *//*-*****************************************************************************************************/
950 css::uno::Reference< css::frame::XFrame > SAL_CALL XFrameImpl::findFrame( const OUString& sTargetFrameName,
951 sal_Int32 nSearchFlags )
953 css::uno::Reference< css::frame::XFrame > xTarget;
955 // 0) Ignore wrong parameter!
956 // We don't support search for following special targets.
957 // If we reject this requests - we must not check for such names
958 // in following code again and again. If we do not so -wrong
959 // search results can occur!
961 if ( sTargetFrameName == SPECIALTARGET_DEFAULT ) // valid for dispatches - not for findFrame()!
963 return nullptr;
966 // I) check for special defined targets first which must be handled exclusive.
967 // force using of "if() else if() ..."
969 // get threadsafe some necessary member which are necessary for following functionality
970 /* SAFE { */
971 SolarMutexResettableGuard aReadLock;
972 css::uno::Reference< css::frame::XFrame > xParent = m_xParent;
973 bool bIsTopFrame = m_bIsFrameTop;
974 bool bIsTopWindow = WindowHelper::isTopWindow(m_xContainerWindow);
975 aReadLock.clear();
976 /* } SAFE */
978 // I.I) "_blank"
979 // Not allowed for a normal frame - but for the desktop.
980 // Use helper class to do so. It use the desktop automatically.
982 if ( sTargetFrameName==SPECIALTARGET_BLANK )
984 TaskCreator aCreator(m_xContext);
985 xTarget = aCreator.createTask(sTargetFrameName, utl::MediaDescriptor());
988 // I.II) "_parent"
989 // It doesn't matter if we have a valid parent or not. User ask for him and get it.
990 // An empty result is a valid result too.
992 else if ( sTargetFrameName==SPECIALTARGET_PARENT )
994 xTarget = xParent;
997 // I.III) "_top"
998 // If we are not the top frame in this hierarchy, we must forward request to our parent.
999 // Otherwise we must return ourself.
1001 else if ( sTargetFrameName==SPECIALTARGET_TOP )
1003 if (bIsTopFrame)
1004 xTarget = this;
1005 else if (xParent.is()) // If we are not top - the parent MUST exist. But may it's better to check it again .-)
1006 xTarget = xParent->findFrame(SPECIALTARGET_TOP,0);
1009 // I.IV) "_self", ""
1010 // This mean this frame in every case.
1012 else if (
1013 ( sTargetFrameName==SPECIALTARGET_SELF ) ||
1014 ( sTargetFrameName.isEmpty() )
1017 xTarget = this;
1020 // I.V) "_beamer"
1021 // This is a special sub frame of any task. We must return it if we found it on our direct children
1022 // or create it there if it not already exists.
1023 // Note: Such beamer exists for task(top) frames only!
1025 else if ( sTargetFrameName==SPECIALTARGET_BEAMER )
1027 // We are a task => search or create the beamer
1028 if (bIsTopWindow)
1030 xTarget = m_aChildFrameContainer.searchOnDirectChildrens(SPECIALTARGET_BEAMER);
1031 if ( ! xTarget.is() )
1033 /* TODO
1034 Creation not supported yet!
1035 Wait for new layout manager service because we can't plug it
1036 inside already opened document of this frame...
1040 // We aren't a task => forward request to our parent or ignore it.
1041 else if (xParent.is())
1042 xTarget = xParent->findFrame(SPECIALTARGET_BEAMER,0);
1045 else
1048 // II) otherwise use optional given search flags
1049 // force using of combinations of such flags. means no "else" part of use if() statements.
1050 // But we ust break further searches if target was already found.
1051 // Order of using flags is fix: SELF - CHILDREN - SIBLINGS - PARENT
1052 // TASK and CREATE are handled special.
1054 // get threadsafe some necessary member which are necessary for following functionality
1055 /* SAFE { */
1056 aReadLock.reset();
1057 OUString sOwnName = m_sName;
1058 aReadLock.clear();
1059 /* } SAFE */
1061 // II.I) SELF
1062 // Check for right name. If it's the searched one return ourself - otherwise
1063 // ignore this flag.
1065 if (
1066 (nSearchFlags & css::frame::FrameSearchFlag::SELF) &&
1067 (sOwnName == sTargetFrameName )
1070 xTarget = this;
1073 // II.II) CHILDREN
1074 // Search on all children for the given target name.
1075 // An empty name value can't occur here - because it must be already handled as "_self"
1076 // before. Used helper function of container doesn't create any frame.
1077 // It makes a deep search only.
1079 if (
1080 ( ! xTarget.is() ) &&
1081 (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
1084 xTarget = m_aChildFrameContainer.searchOnAllChildrens(sTargetFrameName);
1087 // II.III) TASKS
1088 // This is a special flag. It regulate search on this task tree only or allow search on
1089 // all other ones (which are sibling trees of us) too.
1090 // Upper search must stop at this frame if we are the topest one and the TASK flag is not set
1091 // or we can ignore it if we have no valid parent.
1093 if (
1094 ( bIsTopFrame && (nSearchFlags & css::frame::FrameSearchFlag::TASKS) ) ||
1095 ( ! bIsTopFrame )
1099 // II.III.I) SIBLINGS
1100 // Search on all our direct siblings - means all children of our parent.
1101 // Use this flag in combination with TASK. We must suppress such upper search if
1102 // user has not set it and if we are a top frame.
1103 // Attention: Don't forward this request to our parent as a findFrame() call.
1104 // In such case we must protect us against recursive calls.
1105 // Use snapshot of our parent. But don't use queryFrames() of XFrames interface.
1106 // Because it's return all siblings and all her children including our children too
1107 // if we call it with the CHILDREN flag. We don't need that - we need the direct container
1108 // items of our parent only to start searches there. So we must use the container interface
1109 // XIndexAccess instead of XFrames.
1111 if (
1112 ( ! xTarget.is() ) &&
1113 (nSearchFlags & css::frame::FrameSearchFlag::SIBLINGS) &&
1114 ( xParent.is() ) // search on siblings is impossible without a parent
1117 css::uno::Reference< css::frame::XFramesSupplier > xSupplier( xParent, css::uno::UNO_QUERY );
1118 if (xSupplier.is())
1120 css::uno::Reference< css::container::XIndexAccess > xContainer = xSupplier->getFrames();
1121 if (xContainer.is())
1123 sal_Int32 nCount = xContainer->getCount();
1124 for( sal_Int32 i=0; i<nCount; ++i )
1126 css::uno::Reference< css::frame::XFrame > xSibling;
1127 if (
1128 // control unpacking
1129 ( !(xContainer->getByIndex(i)>>=xSibling) ) ||
1130 // check for valid items
1131 ( ! xSibling.is() ) ||
1132 // ignore ourself! (We are a part of this container too - but search on our children was already done.)
1133 ( xSibling==static_cast< ::cppu::OWeakObject* >(this) )
1136 continue;
1139 // Don't allow upper search here! Use right flags to regulate it.
1140 // And allow deep search on children only - if it was allowed for us too.
1141 sal_Int32 nRightFlags = css::frame::FrameSearchFlag::SELF;
1142 if (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
1143 nRightFlags |= css::frame::FrameSearchFlag::CHILDREN;
1144 xTarget = xSibling->findFrame(sTargetFrameName, nRightFlags );
1145 // perform search be breaking further search if a result exist.
1146 if (xTarget.is())
1147 break;
1153 // II.III.II) PARENT
1154 // Forward search to our parent (if he exists.)
1155 // To prevent us against recursive and superfluous calls (which can occur if we allow him
1156 // to search on his children too) we must change used search flags.
1158 if (
1159 ( ! xTarget.is() ) &&
1160 (nSearchFlags & css::frame::FrameSearchFlag::PARENT) &&
1161 ( xParent.is() )
1164 if (xParent->getName() == sTargetFrameName)
1165 xTarget = xParent;
1166 else
1168 sal_Int32 nRightFlags = nSearchFlags & ~css::frame::FrameSearchFlag::CHILDREN;
1169 xTarget = xParent->findFrame(sTargetFrameName, nRightFlags);
1174 // II.IV) CREATE
1175 // If we haven't found any valid target frame by using normal flags - but user allowed us to create
1176 // a new one ... we should do that. Used TaskCreator use Desktop instance automatically as parent!
1178 if (
1179 ( ! xTarget.is() ) &&
1180 (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
1183 TaskCreator aCreator(m_xContext);
1184 xTarget = aCreator.createTask(sTargetFrameName, utl::MediaDescriptor());
1188 return xTarget;
1191 /*-****************************************************************************************************
1192 @descr Returns sal_True, if this frame is a "top frame", otherwise sal_False.
1193 The "m_bIsFrameTop" member must be set in the ctor or setCreator() method.
1194 A top frame is a member of the top frame container or a member of the
1195 task frame container. Both containers can create new frames if the findFrame()
1196 method of their css::frame::XFrame interface is called with a frame name not yet known.
1198 @seealso ctor
1199 @seealso method setCreator()
1200 @seealso method findFrame()
1201 @return true, if is it a top frame ... false otherwise.
1203 @onerror No error should occur!
1204 *//*-*****************************************************************************************************/
1205 sal_Bool SAL_CALL XFrameImpl::isTop()
1207 checkDisposed();
1208 SolarMutexGuard g;
1209 // This information is set in setCreator().
1210 // We are top, if our parent is a task or the desktop or if no parent exist!
1211 return m_bIsFrameTop;
1214 /*-****************************************************************************************************
1215 @short activate frame in hierarchy
1216 @descr This feature is used to mark active paths in our frame hierarchy.
1217 You can be a listener for this event to react for it ... change some internal states or something else.
1219 @seealso method deactivate()
1220 @seealso method isActivate()
1221 @seealso enum EActiveState
1222 @seealso listener mechanism
1223 *//*-*****************************************************************************************************/
1224 void SAL_CALL XFrameImpl::activate()
1226 checkDisposed();
1228 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1229 SolarMutexResettableGuard aWriteLock;
1231 // Copy necessary member and free the lock.
1232 // It's not necessary for m_aChildFrameContainer ... because
1233 // he is threadsafe himself and live if we live.
1234 css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive();
1235 css::uno::Reference< css::frame::XFramesSupplier > xParent = m_xParent;
1236 css::uno::Reference< css::frame::XFrame > xThis(this);
1237 EActiveState eState = m_eActiveState;
1239 aWriteLock.clear();
1240 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1242 // 1) If I am not active before...
1243 if( eState == E_INACTIVE )
1245 // ... do it then.
1246 aWriteLock.reset();
1247 eState = E_ACTIVE;
1248 m_eActiveState = eState;
1249 aWriteLock.clear();
1250 // Deactivate sibling path and forward activation to parent ... if any parent exist!
1251 if( xParent.is() )
1253 // Every time set THIS frame as active child of parent and activate it.
1254 // We MUST have a valid path from bottom to top as active path!
1255 // But we must deactivate the old active sibling path first.
1257 // Attention: Deactivation of an active path, deactivate the whole path ... from bottom to top!
1258 // But we wish to deactivate founded sibling-tree only.
1259 // [ see deactivate() / step 4) for further information! ]
1261 xParent->setActiveFrame( xThis );
1263 // Then we can activate from here to top.
1264 // Attention: We are ACTIVE now. And the parent will call activate() at us!
1265 // But we do nothing then! We are already activated.
1266 xParent->activate();
1268 // It's necessary to send event NOW - not before.
1269 // Activation goes from bottom to top!
1270 // That's the reason to activate parent first and send event now.
1271 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_ACTIVATED );
1274 // 2) I was active before or current activated and there is a path from here to bottom, who CAN be active.
1275 // But our direct child of path is not active yet.
1276 // (It can be, if activation occur in the middle of a current path!)
1277 // In these case we activate path to bottom to set focus on right frame!
1278 if ( eState == E_ACTIVE && xActiveChild.is() && !xActiveChild->isActive() )
1280 xActiveChild->activate();
1283 // 3) I was active before or current activated. But if I have no active child => I will get the focus!
1284 if ( eState == E_ACTIVE && !xActiveChild.is() )
1286 aWriteLock.reset();
1287 eState = E_FOCUS;
1288 m_eActiveState = eState;
1289 aWriteLock.clear();
1290 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_ACTIVATED );
1294 /*-****************************************************************************************************
1295 @short deactivate frame in hierarchy
1296 @descr This feature is used to deactivate paths in our frame hierarchy.
1297 You can be a listener for this event to react for it... change some internal states or something else.
1299 @seealso method activate()
1300 @seealso method isActivate()
1301 @seealso enum EActiveState
1302 @seealso listener mechanism
1303 *//*-*****************************************************************************************************/
1304 void SAL_CALL XFrameImpl::deactivate()
1306 checkDisposed();
1308 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1309 SolarMutexResettableGuard aWriteLock;
1311 // Copy necessary member and free the lock.
1312 css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive();
1313 css::uno::Reference< css::frame::XFramesSupplier > xParent = m_xParent;
1314 css::uno::Reference< css::frame::XFrame > xThis(this);
1315 EActiveState eState = m_eActiveState;
1317 aWriteLock.clear();
1318 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1320 // Work only, if there something to do!
1321 if( eState == E_INACTIVE )
1322 return;
1325 // 1) Deactivate all active children.
1326 if ( xActiveChild.is() && xActiveChild->isActive() )
1328 xActiveChild->deactivate();
1331 // 2) If I have the focus - I will lost it now.
1332 if( eState == E_FOCUS )
1334 // Set new state INACTIVE(!) and send message to all listener.
1335 // Don't set ACTIVE as new state. This frame is deactivated for next time - due to activate().
1336 aWriteLock.reset();
1337 eState = E_ACTIVE;
1338 m_eActiveState = eState;
1339 aWriteLock.clear();
1340 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_DEACTIVATING );
1343 // 3) If I am active - I will be deactivated now.
1344 if( eState == E_ACTIVE )
1346 // Set new state and send message to all listener.
1347 aWriteLock.reset();
1348 eState = E_INACTIVE;
1349 m_eActiveState = eState;
1350 aWriteLock.clear();
1351 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_DEACTIVATING );
1354 // 4) If there is a path from here to my parent...
1355 // ... I am on the top or in the middle of deactivated subtree and action was started here.
1356 // I must deactivate all frames from here to top, which are members of current path.
1357 // Stop, if THESE frame not the active frame of our parent!
1358 if ( xParent.is() && xParent->getActiveFrame() == xThis )
1360 // We MUST break the path - otherwise we will get the focus - not our parent! ...
1361 // Attention: Our parent don't call us again - WE ARE NOT ACTIVE YET!
1362 // [ see step 3 and condition "if ( m_eActiveState!=INACTIVE ) ..." in this method! ]
1363 xParent->deactivate();
1367 /*-****************************************************************************************************
1368 @short returns active state
1369 @descr Call it to get information about current active state of this frame.
1371 @seealso method activate()
1372 @seealso method deactivate()
1373 @seealso enum EActiveState
1374 @return true if active, false otherwise.
1376 @onerror No error should occur.
1377 *//*-*****************************************************************************************************/
1378 sal_Bool SAL_CALL XFrameImpl::isActive()
1380 checkDisposed();
1381 SolarMutexGuard g;
1382 return m_eActiveState == E_ACTIVE || m_eActiveState == E_FOCUS;
1385 /*-****************************************************************************************************
1386 @short ???
1387 *//*-*****************************************************************************************************/
1388 void SAL_CALL XFrameImpl::contextChanged()
1390 // Sometimes called during closing object...
1391 // Impl-method is threadsafe himself!
1392 // Send event to all listener for frame actions.
1393 implts_sendFrameActionEvent( css::frame::FrameAction_CONTEXT_CHANGED );
1396 /*-****************************************************************************************************
1397 @short set new component inside the frame
1398 @descr A frame is a container for a component. Use this method to set, change or release it!
1399 We accept null references! The xComponentWindow will be a child of our container window
1400 and get all window events from us.
1402 @attention (a) A current set component can disagree with the suspend() request!
1403 We don't set the new one and return with false then.
1404 (b) It's possible to set:
1405 (b1) a simple component here which supports the window only - no controller;
1406 (b2) a full featured component which supports window and controller;
1407 (b3) or both to NULL if outside code which to forget this component.
1409 @seealso method getComponentWindow()
1410 @seealso method getController()
1412 @param xComponentWindow
1413 valid reference to new component window which will be a child of internal container window
1414 May <NULL/> for releasing.
1415 @param xController
1416 reference to new component controller
1417 (may <NULL/> for releasing or setting of a simple component)
1419 @return <TRUE/> if operation was successful, <FALSE/> otherwise.
1421 @onerror We return <FALSE/>.
1422 @threadsafe yes
1423 *//*-*****************************************************************************************************/
1424 sal_Bool SAL_CALL XFrameImpl::setComponent(const css::uno::Reference< css::awt::XWindow >& xComponentWindow,
1425 const css::uno::Reference< css::frame::XController >& xController )
1428 // Ignore this HACK of sfx2!
1429 // He call us with a valid controller without a valid window... that's not allowed!
1430 if ( xController.is() && ! xComponentWindow.is() )
1431 return true;
1433 checkDisposed();
1435 // Get threadsafe some copies of used members.
1436 /* SAFE { */
1437 SolarMutexClearableGuard aReadLock;
1438 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
1439 css::uno::Reference< css::awt::XWindow > xOldComponentWindow = m_xComponentWindow;
1440 css::uno::Reference< css::frame::XController > xOldController = m_xController;
1441 VclPtr<vcl::Window> pOwnWindow = VCLUnoHelper::GetWindow( xContainerWindow );
1442 bool bHadFocus = pOwnWindow != nullptr && pOwnWindow->HasChildPathFocus();
1443 bool bWasConnected = m_bConnected;
1444 aReadLock.clear();
1445 /* } SAFE */
1447 // stop listening on old window
1448 // May it produce some trouble.
1449 // But don't forget to listen on new window again ... or reactivate listening
1450 // if we reject this setComponent() request and leave this method without changing the old window.
1451 implts_stopWindowListening();
1453 // Notify all listener, that this component (if current one exist) will be unloaded.
1454 if (bWasConnected)
1455 implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_DETACHING );
1457 // otherwise release old component first
1458 // Always release controller before releasing window,
1459 // because controller may want to access its window!
1460 // But check for real changes - may the new controller is the old one.
1461 if (
1462 (xOldController.is() ) &&
1463 (xOldController != xController)
1466 /* ATTENTION
1467 Don't suspend the old controller here. Because the outside caller must do that
1468 by definition. We have to dispose it here only.
1471 // Before we dispose this controller we should hide it inside this frame instance.
1472 // We hold it alive for next calls by using xOldController!
1473 /* SAFE {*/
1475 SolarMutexGuard aWriteLock;
1476 m_xController = nullptr;
1478 if (m_xDispatchHelper)
1480 rtl::Reference<DispatchProvider> pDispatchProvider = m_xDispatchHelper->GetSlave();
1481 if (pDispatchProvider)
1483 pDispatchProvider->ClearProtocolHandlers();
1487 /* } SAFE */
1489 if (xOldController.is())
1493 xOldController->dispose();
1495 catch(const css::lang::DisposedException&)
1498 xOldController = nullptr;
1501 // Now it's time to release the component window.
1502 // If controller wasn't released successfully - this code line shouldn't be reached.
1503 // Because in case of "suspend()==false" we return immediately with false ...
1504 // see before
1505 // Check for real changes too.
1506 if (
1507 (xOldComponentWindow.is() ) &&
1508 (xOldComponentWindow != xComponentWindow)
1511 /* SAFE { */
1513 SolarMutexGuard aWriteLock;
1514 m_xComponentWindow = nullptr;
1516 /* } SAFE */
1518 if (xOldComponentWindow.is())
1522 xOldComponentWindow->dispose();
1524 catch(const css::lang::DisposedException&)
1528 xOldComponentWindow = nullptr;
1531 // Now it's time to set the new component ...
1532 // By the way - find out our new "load state" - means if we have a valid component inside.
1533 /* SAFE { */
1534 SolarMutexResettableGuard aWriteLock;
1535 m_xComponentWindow = xComponentWindow;
1536 m_xController = xController;
1538 // Clear the URL on the frame itself, now that the controller has it.
1539 m_aURL.clear();
1541 m_bConnected = (m_xComponentWindow.is() || m_xController.is());
1542 bool bIsConnected = m_bConnected;
1543 aWriteLock.clear();
1544 /* } SAFE */
1546 // notifies all interest listener, that current component was changed or a new one was loaded
1547 if (bIsConnected && bWasConnected)
1548 implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_REATTACHED );
1549 else if (bIsConnected && !bWasConnected)
1550 implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_ATTACHED );
1552 // A new component window doesn't know anything about current active/focus states.
1553 // Set this information on it!
1554 if ( bHadFocus && xComponentWindow.is() )
1556 xComponentWindow->setFocus();
1559 // If it was a new component window - we must resize it to fill out
1560 // our container window.
1561 implts_resizeComponentWindow();
1562 // New component should change our current icon ...
1563 implts_setIconOnWindow();
1564 // OK - start listening on new window again - or do nothing if it is an empty one.
1565 implts_startWindowListening();
1567 /* SAFE { */
1568 aWriteLock.reset();
1569 impl_checkMenuCloser();
1570 aWriteLock.clear();
1571 /* } SAFE */
1573 return true;
1576 /*-****************************************************************************************************
1577 @short returns current set component window
1578 @descr Frames are used to display components. The actual displayed component is
1579 held by the m_xComponentWindow property. If the component implements only a
1580 XComponent interface, the communication between the frame and the
1581 component is very restricted. Better integration is achievable through a
1582 XController interface.
1583 If the component wants other objects to be able to get information about its
1584 ResourceDescriptor it has to implement a XModel interface.
1585 This frame is the owner of the component window.
1587 @seealso method setComponent()
1588 @return css::uno::Reference to current set component window.
1590 @onerror A null reference is returned.
1591 *//*-*****************************************************************************************************/
1592 css::uno::Reference< css::awt::XWindow > SAL_CALL XFrameImpl::getComponentWindow()
1594 checkDisposed();
1595 SolarMutexGuard g;
1596 return m_xComponentWindow;
1599 /*-****************************************************************************************************
1600 @short returns current set controller
1601 @descr Frames are used to display components. The actual displayed component is
1602 held by the m_xComponentWindow property. If the component implements only a
1603 XComponent interface, the communication between the frame and the
1604 component is very restricted. Better integration is achievable through a
1605 XController interface.
1606 If the component wants other objects to be able to get information about its
1607 ResourceDescriptor it has to implement a XModel interface.
1608 This frame is the owner of the component window.
1610 @seealso method setComponent()
1611 @return css::uno::Reference to current set controller.
1613 @onerror A null reference is returned.
1614 *//*-*****************************************************************************************************/
1615 css::uno::Reference< css::frame::XController > SAL_CALL XFrameImpl::getController()
1617 SolarMutexGuard g;
1618 return m_xController;
1621 /*-****************************************************************************************************
1622 @short add/remove listener for activate/deactivate/contextChanged events
1623 @seealso method activate()
1624 @seealso method deactivate()
1625 @seealso method contextChanged()
1627 @param "xListener" reference to your listener object
1628 @onerror Listener is ignored.
1629 *//*-*****************************************************************************************************/
1630 void SAL_CALL XFrameImpl::addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener )
1632 checkDisposed();
1633 m_aListenerContainer.addInterface( cppu::UnoType<css::frame::XFrameActionListener>::get(), xListener );
1636 void SAL_CALL XFrameImpl::removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener )
1638 m_aListenerContainer.removeInterface( cppu::UnoType<css::frame::XFrameActionListener>::get(), xListener );
1641 /*-****************************************************************************************************
1642 @short support two way mechanism to release a frame
1643 @descr This method ask internal component (controller) if he accept this close request.
1644 In case of <TRUE/> nothing will be happen (from point of caller of this close method).
1645 In case of <FALSE/> a CloseVetoException is thrown. After such exception given parameter
1646 <var>bDeliverOwnership</var> regulate which will be the new owner of this instance.
1648 @attention It's the replacement for XTask::close() which is marked as obsolete method.
1650 @param bDeliverOwnership
1651 If parameter is set to <FALSE/> the original caller will be the owner after thrown
1652 veto exception and must try to close this frame at later time again. Otherwise the
1653 source of thrown exception is the right one. May it will be the frame himself.
1655 @throws CloseVetoException
1656 if any internal things will not be closed
1658 @threadsafe yes
1659 *//*-*****************************************************************************************************/
1660 void SAL_CALL XFrameImpl::close( sal_Bool bDeliverOwnership )
1662 checkDisposed();
1664 // At the end of this method may we must dispose ourself...
1665 // and may nobody from outside hold a reference to us...
1666 // then it's a good idea to do that by ourself.
1667 css::uno::Reference< css::uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) );
1669 // Check any close listener before we look for currently running internal processes.
1670 // Because if a listener disagree with this close() request - we have time to finish this
1671 // internal operations too...
1672 // Note: container is threadsafe himself.
1673 css::lang::EventObject aSource (static_cast< ::cppu::OWeakObject*>(this));
1674 comphelper::OInterfaceContainerHelper2* pContainer = m_aListenerContainer.getContainer( cppu::UnoType<css::util::XCloseListener>::get());
1675 if (pContainer!=nullptr)
1677 comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
1678 while (pIterator.hasMoreElements())
1682 static_cast<css::util::XCloseListener*>(pIterator.next())->queryClosing( aSource, bDeliverOwnership );
1684 catch( const css::uno::RuntimeException& )
1686 pIterator.remove();
1691 // Ok - no listener disagreed with this close() request
1692 // check if this frame is used for any load process currently
1693 if (isActionLocked())
1695 if (bDeliverOwnership)
1697 SolarMutexGuard g;
1698 m_bSelfClose = true;
1701 throw css::util::CloseVetoException("Frame in use for loading document...",static_cast< ::cppu::OWeakObject*>(this));
1704 if ( ! setComponent(nullptr,nullptr) )
1705 throw css::util::CloseVetoException("Component couldn't be detached...",static_cast< ::cppu::OWeakObject*>(this));
1707 // If closing is allowed... inform all listeners and dispose this frame!
1708 pContainer = m_aListenerContainer.getContainer( cppu::UnoType<css::util::XCloseListener>::get());
1709 if (pContainer!=nullptr)
1711 comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
1712 while (pIterator.hasMoreElements())
1716 static_cast<css::util::XCloseListener*>(pIterator.next())->notifyClosing( aSource );
1718 catch( const css::uno::RuntimeException& )
1720 pIterator.remove();
1725 /* SAFE { */
1727 SolarMutexGuard aWriteLock;
1728 m_bIsHidden = true;
1730 /* } SAFE */
1731 impl_checkMenuCloser();
1733 dispose();
1736 /*-****************************************************************************************************
1737 @short be a listener for close events!
1738 @descr Adds/remove a CloseListener at this frame instance. If the close() method is called on
1739 this object, the such listener are informed and can disagree with that by throwing
1740 a CloseVetoException.
1742 @seealso XFrameImpl::close()
1744 @param xListener
1745 reference to your listener object
1747 @onerror Listener is ignored.
1749 @threadsafe yes
1750 *//*-*****************************************************************************************************/
1751 void SAL_CALL XFrameImpl::addCloseListener( const css::uno::Reference< css::util::XCloseListener >& xListener )
1753 checkDisposed();
1754 m_aListenerContainer.addInterface( cppu::UnoType<css::util::XCloseListener>::get(), xListener );
1757 void SAL_CALL XFrameImpl::removeCloseListener( const css::uno::Reference< css::util::XCloseListener >& xListener )
1759 m_aListenerContainer.removeInterface( cppu::UnoType<css::util::XCloseListener>::get(), xListener );
1762 OUString SAL_CALL XFrameImpl::getTitle()
1764 checkDisposed();
1766 // SAFE ->
1767 SolarMutexClearableGuard aReadLock;
1768 css::uno::Reference< css::frame::XTitle > xTitle(m_xTitleHelper, css::uno::UNO_SET_THROW);
1769 aReadLock.clear();
1770 // <- SAFE
1772 return xTitle->getTitle();
1775 void SAL_CALL XFrameImpl::setTitle( const OUString& sTitle )
1777 checkDisposed();
1779 // SAFE ->
1780 SolarMutexClearableGuard aReadLock;
1781 css::uno::Reference< css::frame::XTitle > xTitle(m_xTitleHelper, css::uno::UNO_SET_THROW);
1782 aReadLock.clear();
1783 // <- SAFE
1785 xTitle->setTitle(sTitle);
1788 void SAL_CALL XFrameImpl::addTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener)
1790 checkDisposed();
1792 // SAFE ->
1793 SolarMutexClearableGuard aReadLock;
1794 css::uno::Reference< css::frame::XTitleChangeBroadcaster > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW);
1795 aReadLock.clear();
1796 // <- SAFE
1798 xTitle->addTitleChangeListener(xListener);
1801 void SAL_CALL XFrameImpl::removeTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener )
1803 checkDisposed();
1805 // SAFE ->
1806 SolarMutexClearableGuard aReadLock;
1807 css::uno::Reference< css::frame::XTitleChangeBroadcaster > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW);
1808 aReadLock.clear();
1809 // <- SAFE
1811 xTitle->removeTitleChangeListener(xListener);
1814 css::uno::Reference<css::container::XNameContainer> SAL_CALL XFrameImpl::getUserDefinedAttributes()
1816 // optional attribute
1817 return nullptr;
1820 css::uno::Reference<css::frame::XDispatchRecorderSupplier> SAL_CALL XFrameImpl::getDispatchRecorderSupplier()
1822 SolarMutexGuard g;
1823 return m_xDispatchRecorderSupplier;
1826 void SAL_CALL XFrameImpl::setDispatchRecorderSupplier(const css::uno::Reference<css::frame::XDispatchRecorderSupplier>& p)
1828 checkDisposed();
1829 SolarMutexGuard g;
1830 m_xDispatchRecorderSupplier.set(p);
1833 css::uno::Reference<css::uno::XInterface> SAL_CALL XFrameImpl::getLayoutManager()
1835 SolarMutexGuard g;
1836 return m_xLayoutManager;
1839 void SAL_CALL XFrameImpl::setLayoutManager(const css::uno::Reference<css::uno::XInterface>& p1)
1841 checkDisposed();
1842 SolarMutexGuard g;
1844 css::uno::Reference<css::frame::XLayoutManager2> xOldLayoutManager = m_xLayoutManager;
1845 css::uno::Reference<css::frame::XLayoutManager2> xNewLayoutManager(p1, css::uno::UNO_QUERY);
1847 if (xOldLayoutManager != xNewLayoutManager)
1849 m_xLayoutManager = xNewLayoutManager;
1850 if (xOldLayoutManager.is())
1851 disableLayoutManager(xOldLayoutManager);
1852 if (xNewLayoutManager.is() && !m_bDocHidden)
1853 lcl_enableLayoutManager(xNewLayoutManager, this);
1857 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL XFrameImpl::getPropertySetInfo()
1859 checkDisposed();
1860 return css::uno::Reference< css::beans::XPropertySetInfo >(this);
1863 void SAL_CALL XFrameImpl::setPropertyValue(const OUString& sProperty,
1864 const css::uno::Any& aValue )
1866 // TODO look for e.g. readonly props and reject setProp() call!
1868 checkDisposed();
1870 // SAFE ->
1871 SolarMutexGuard g;
1873 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1874 if (pIt == m_lProps.end())
1875 throw css::beans::UnknownPropertyException(sProperty);
1877 css::beans::Property aPropInfo = pIt->second;
1879 css::uno::Any aCurrentValue = impl_getPropertyValue(aPropInfo.Handle);
1881 bool bWillBeChanged = (aCurrentValue != aValue);
1882 if (! bWillBeChanged)
1883 return;
1885 css::beans::PropertyChangeEvent aEvent;
1886 aEvent.PropertyName = aPropInfo.Name;
1887 aEvent.Further = false;
1888 aEvent.PropertyHandle = aPropInfo.Handle;
1889 aEvent.OldValue = aCurrentValue;
1890 aEvent.NewValue = aValue;
1891 aEvent.Source.set(m_xBroadcaster.get(), css::uno::UNO_QUERY);
1893 if (impl_existsVeto(aEvent))
1894 throw css::beans::PropertyVetoException();
1896 impl_setPropertyValue(aPropInfo.Handle, aValue);
1898 impl_notifyChangeListener(aEvent);
1901 css::uno::Any SAL_CALL XFrameImpl::getPropertyValue(const OUString& sProperty)
1903 checkDisposed();
1905 // SAFE ->
1906 SolarMutexGuard aReadLock;
1908 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1909 if (pIt == m_lProps.end())
1910 throw css::beans::UnknownPropertyException(sProperty);
1912 css::beans::Property aPropInfo = pIt->second;
1914 return impl_getPropertyValue(aPropInfo.Handle);
1917 void SAL_CALL XFrameImpl::addPropertyChangeListener(
1918 const OUString& sProperty,
1919 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener)
1921 checkDisposed();
1923 // SAFE ->
1925 SolarMutexGuard aReadLock;
1927 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1928 if (pIt == m_lProps.end())
1929 throw css::beans::UnknownPropertyException(sProperty);
1931 // <- SAFE
1933 m_lSimpleChangeListener.addInterface(sProperty, xListener);
1936 void SAL_CALL XFrameImpl::removePropertyChangeListener(
1937 const OUString& sProperty,
1938 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener)
1940 // SAFE ->
1942 SolarMutexGuard aReadLock;
1944 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1945 if (pIt == m_lProps.end())
1946 throw css::beans::UnknownPropertyException(sProperty);
1948 // <- SAFE
1950 m_lSimpleChangeListener.removeInterface(sProperty, xListener);
1953 void SAL_CALL XFrameImpl::addVetoableChangeListener(
1954 const OUString& sProperty,
1955 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener)
1957 checkDisposed();
1959 // SAFE ->
1961 SolarMutexGuard aReadLock;
1963 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1964 if (pIt == m_lProps.end())
1965 throw css::beans::UnknownPropertyException(sProperty);
1967 // <- SAFE
1969 m_lVetoChangeListener.addInterface(sProperty, xListener);
1972 void SAL_CALL XFrameImpl::removeVetoableChangeListener(
1973 const OUString& sProperty,
1974 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener)
1976 // SAFE ->
1978 SolarMutexGuard aReadLock;
1980 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1981 if (pIt == m_lProps.end())
1982 throw css::beans::UnknownPropertyException(sProperty);
1984 // <- SAFE
1986 m_lVetoChangeListener.removeInterface(sProperty, xListener);
1989 css::uno::Sequence< css::beans::Property > SAL_CALL XFrameImpl::getProperties()
1991 checkDisposed();
1993 SolarMutexGuard g;
1995 sal_Int32 c = static_cast<sal_Int32>(m_lProps.size());
1996 css::uno::Sequence< css::beans::Property > lProps(c);
1997 auto lPropsRange = asNonConstRange(lProps);
1998 for (auto const& elem : m_lProps)
2000 lPropsRange[--c] = elem.second;
2003 return lProps;
2006 css::beans::Property SAL_CALL XFrameImpl::getPropertyByName(const OUString& sName)
2008 checkDisposed();
2010 SolarMutexGuard g;
2012 TPropInfoHash::const_iterator pIt = m_lProps.find(sName);
2013 if (pIt == m_lProps.end())
2014 throw css::beans::UnknownPropertyException(sName);
2016 return pIt->second;
2019 sal_Bool SAL_CALL XFrameImpl::hasPropertyByName(const OUString& sName)
2021 checkDisposed();
2023 SolarMutexGuard g;
2025 TPropInfoHash::iterator pIt = m_lProps.find(sName);
2026 bool bExist = (pIt != m_lProps.end());
2028 return bExist;
2031 /*-****************************************************************************************************/
2032 void XFrameImpl::implts_forgetSubFrames()
2034 // SAFE ->
2035 SolarMutexClearableGuard aReadLock;
2036 css::uno::Reference< css::container::XIndexAccess > xContainer(m_xFramesHelper, css::uno::UNO_QUERY_THROW);
2037 aReadLock.clear();
2038 // <- SAFE
2040 sal_Int32 c = xContainer->getCount();
2041 sal_Int32 i = 0;
2043 for (i=0; i<c; ++i)
2047 css::uno::Reference< css::frame::XFrame > xFrame;
2048 xContainer->getByIndex(i) >>= xFrame;
2049 if (xFrame.is())
2050 xFrame->setCreator(css::uno::Reference< css::frame::XFramesSupplier >());
2052 catch(const css::uno::Exception&)
2054 // Ignore errors here.
2055 // Nobody can guarantee a stable index in multi threaded environments .-)
2059 SolarMutexGuard g;
2060 m_xFramesHelper.clear(); // clear uno reference
2061 m_aChildFrameContainer.clear(); // clear container content
2064 /*-****************************************************************************************************
2065 @short destroy instance
2066 @descr The owner of this object calls the dispose method if the object
2067 should be destroyed. All other objects and components, that are registered
2068 as an EventListener are forced to release their references to this object.
2069 Furthermore this frame is removed from its parent frame container to release
2070 this reference. The reference attributes are disposed and released also.
2072 @attention Look for globale description at beginning of file too!
2073 (DisposedException, FairRWLock ..., initialize, dispose)
2075 @seealso method initialize()
2076 @seealso baseclass FairRWLockBase!
2077 *//*-*****************************************************************************************************/
2078 void SAL_CALL XFrameImpl::disposing()
2080 // We should hold a reference to ourself ...
2081 // because our owner dispose us and release our reference ...
2082 // May be we will die before we could finish this method ...
2083 css::uno::Reference< css::frame::XFrame > xThis(this);
2085 SAL_INFO("fwk.frame", "[Frame] " << m_sName << " send dispose event to listener");
2087 // First operation should be... "stop all listening for window events on our container window".
2088 // These events are superfluous but can make trouble!
2089 // We will die, die and die...
2090 implts_stopWindowListening();
2092 css::uno::Reference<css::frame::XLayoutManager2> layoutMgr;
2094 SolarMutexGuard g;
2095 layoutMgr = m_xLayoutManager;
2097 if (layoutMgr.is()) {
2098 disableLayoutManager(layoutMgr);
2101 std::unique_ptr<WindowCommandDispatch> disp;
2103 SolarMutexGuard g;
2104 std::swap(disp, m_pWindowCommandDispatch);
2106 disp.reset();
2108 // Send message to all listener and forget her references.
2109 css::lang::EventObject aEvent( xThis );
2110 m_aListenerContainer.disposeAndClear( aEvent );
2112 // set "end of live" for our property set helper
2113 impl_disablePropertySet();
2115 // interception/dispatch chain must be destructed explicitly
2116 // Otherwise some dispatches and/or interception objects won't die.
2117 css::uno::Reference< css::lang::XEventListener > xDispatchHelper;
2119 SolarMutexGuard g;
2120 xDispatchHelper = m_xDispatchHelper;
2122 xDispatchHelper->disposing(aEvent);
2123 xDispatchHelper.clear();
2125 // Don't show any dialogs, errors or something else any more!
2126 // If somewhere called dispose() without close() before - normally no dialogs
2127 // should exist. Otherwise it's the problem of the outside caller.
2128 // Note:
2129 // (a) Do it after stopWindowListening(). May that force some active/deactivate
2130 // notifications which we don't need here really.
2131 // (b) Don't forget to save the old value of IsDialogCancelEnabled() to
2132 // restore it afterwards (to not kill headless mode).
2133 DialogCancelMode old = Application::GetDialogCancelMode();
2134 Application::SetDialogCancelMode( DialogCancelMode::Silent );
2136 // We should be alone for ever and further dispose calls are rejected by lines before ...
2137 // I hope it :-)
2139 // Free references of our frame tree.
2140 // Force parent container to forget this frame too ...
2141 // ( It's contained in m_xParent and so no css::lang::XEventListener for m_xParent! )
2142 // It's important to do that before we free some other internal structures.
2143 // Because if our parent gets an activate and found us as last possible active frame
2144 // he try to deactivate us ... and we run into some trouble (DisposedExceptions!).
2145 css::uno::Reference<css::frame::XFramesSupplier> parent;
2147 SolarMutexGuard g;
2148 std::swap(parent, m_xParent);
2150 if( parent.is() )
2152 parent->getFrames()->remove( xThis );
2155 /* } SAFE */
2156 // Forget our internal component and her window first.
2157 // So we can release our container window later without problems.
2158 // Because this container window is the parent of the component window ...
2159 // Note: Dispose it hard - because suspending must be done inside close() call!
2160 // But try to dispose the controller first before you destroy the window.
2161 // Because the window is used by the controller too ...
2162 css::uno::Reference< css::lang::XComponent > xDisposableCtrl;
2163 css::uno::Reference< css::lang::XComponent > xDisposableComp;
2165 SolarMutexGuard g;
2166 xDisposableCtrl = m_xController;
2167 xDisposableComp = m_xComponentWindow;
2169 if (xDisposableCtrl.is())
2170 xDisposableCtrl->dispose();
2171 if (xDisposableComp.is())
2172 xDisposableComp->dispose();
2174 impl_checkMenuCloser();
2176 css::uno::Reference<css::awt::XWindow> contWin;
2178 SolarMutexGuard g;
2179 std::swap(contWin, m_xContainerWindow);
2181 if( contWin.is() )
2183 contWin->setVisible( false );
2184 // All VclComponents are XComponents; so call dispose before discarding
2185 // a css::uno::Reference< XVclComponent >, because this frame is the owner of the window
2186 contWin->dispose();
2189 /*ATTENTION
2190 Clear container after successful removing from parent container ...
2191 because our parent could be the desktop which stand in dispose too!
2192 If we have already cleared our own container we lost our child before this could be
2193 remove himself at this instance ...
2194 Release m_xFramesHelper after that ... it's the same problem between parent and child!
2195 "m_xParent->getFrames()->remove( xThis );" needs this helper ...
2196 Otherwise we get a null reference and could finish removing successfully.
2197 => You see: Order of calling operations is important!!!
2199 implts_forgetSubFrames();
2202 SolarMutexGuard g;
2204 // Release some other references.
2205 // This calls should be easy ... I hope it :-)
2206 m_xDispatchHelper.clear();
2207 m_xDropTargetListener.clear();
2208 m_xDispatchRecorderSupplier.clear();
2209 m_xLayoutManager.clear();
2210 m_xIndicatorFactoryHelper.clear();
2212 // It's important to set default values here!
2213 // If may be later somewhere change the disposed-behaviour of this implementation
2214 // and doesn't throw any DisposedExceptions we must guarantee best matching default values ...
2215 m_eActiveState = E_INACTIVE;
2216 m_sName.clear();
2217 m_bIsFrameTop = false;
2218 m_bConnected = false;
2219 m_nExternalLockCount = 0;
2220 m_bSelfClose = false;
2221 m_bIsHidden = true;
2224 // Don't forget it restore old value -
2225 // otherwise no dialogs can be shown anymore in other frames.
2226 Application::SetDialogCancelMode( old );
2229 /*-****************************************************************************************************
2230 @short Be a listener for dispose events!
2231 @descr Adds/remove an EventListener to this object. If the dispose method is called on
2232 this object, the disposing method of the listener is called.
2233 @param "xListener" reference to your listener object.
2234 @onerror Listener is ignored.
2235 *//*-*****************************************************************************************************/
2236 void SAL_CALL XFrameImpl::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
2238 checkDisposed();
2239 m_aListenerContainer.addInterface( cppu::UnoType<css::lang::XEventListener>::get(), xListener );
2242 void SAL_CALL XFrameImpl::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
2244 m_aListenerContainer.removeInterface( cppu::UnoType<css::lang::XEventListener>::get(), xListener );
2247 /*-****************************************************************************************************
2248 @short create new status indicator
2249 @descr Use returned status indicator to show progresses and some text information.
2250 All created objects share the same dialog! Only the last one can show his information.
2252 @seealso class StatusIndicatorFactory
2253 @seealso class StatusIndicator
2254 @return A reference to created object.
2256 @onerror We return a null reference.
2257 *//*-*****************************************************************************************************/
2258 css::uno::Reference< css::task::XStatusIndicator > SAL_CALL XFrameImpl::createStatusIndicator()
2260 checkDisposed();
2262 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2263 SolarMutexClearableGuard aReadLock;
2265 // Make snapshot of necessary member and define default return value.
2266 css::uno::Reference< css::task::XStatusIndicator > xExternal(m_xIndicatorInterception.get(), css::uno::UNO_QUERY);
2267 css::uno::Reference< css::task::XStatusIndicatorFactory > xFactory = m_xIndicatorFactoryHelper;
2269 aReadLock.clear();
2270 /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
2272 // Was set from outside to intercept any progress activities!
2273 if (xExternal.is())
2274 return xExternal;
2276 // Or use our own factory as fallback, to create such progress.
2277 if (xFactory.is())
2278 return xFactory->createStatusIndicator();
2280 return css::uno::Reference< css::task::XStatusIndicator >();
2283 /*-****************************************************************************************************
2284 @short search for target to load URL
2285 @descr This method searches for a dispatch for the specified DispatchDescriptor.
2286 The FrameSearchFlags and the FrameName of the DispatchDescriptor are
2287 treated as described for findFrame.
2289 @seealso method findFrame()
2290 @seealso method queryDispatches()
2291 @seealso method set/getName()
2292 @seealso class TargetFinder
2294 @param "aURL" , URL for loading
2295 @param "sTargetFrameName" , name of target frame
2296 @param "nSearchFlags" , additional flags to regulate search if sTargetFrameName is not clear
2297 @return css::uno::Reference to dispatch handler.
2299 @onerror A null reference is returned.
2300 *//*-*****************************************************************************************************/
2301 css::uno::Reference< css::frame::XDispatch > SAL_CALL XFrameImpl::queryDispatch( const css::util::URL& aURL,
2302 const OUString& sTargetFrameName,
2303 sal_Int32 nSearchFlags)
2305 // Don't check incoming parameter here! Our helper do it for us and it is not a good idea to do it more than once!
2307 checkDisposed();
2309 // Remove uno and cmd protocol part as we want to support both of them. We store only the command part
2310 // in our hash map. All other protocols are stored with the protocol part.
2311 OUString aCommand( aURL.Main );
2312 if ( aURL.Protocol.equalsIgnoreAsciiCase(".uno:") )
2313 aCommand = aURL.Path;
2315 // Make std::unordered_map lookup if the current URL is in the disabled list
2316 if ( m_aCommandOptions.LookupDisabled( aCommand ) )
2317 return css::uno::Reference< css::frame::XDispatch >();
2318 else
2320 // We use a helper to support these interface and an interceptor mechanism.
2321 css::uno::Reference<css::frame::XDispatchProvider> disp;
2323 SolarMutexGuard g;
2324 disp = m_xDispatchHelper;
2326 if (!disp.is()) {
2327 throw css::lang::DisposedException("Frame disposed");
2329 return disp->queryDispatch( aURL, sTargetFrameName, nSearchFlags );
2333 /*-****************************************************************************************************
2334 @short handle more than ones dispatches at same call
2335 @descr Returns a sequence of dispatches. For details see the queryDispatch method.
2336 For failed dispatches we return empty items in list!
2338 @seealso method queryDispatch()
2340 @param "lDescriptor" list of dispatch arguments for queryDispatch()!
2341 @return List of dispatch references. Some elements can be NULL!
2343 @onerror An empty list is returned.
2344 *//*-*****************************************************************************************************/
2345 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL XFrameImpl::queryDispatches(
2346 const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
2348 // Don't check incoming parameter here! Our helper do it for us and it is not a good idea to do it more than ones!
2350 checkDisposed();
2352 // We use a helper to support these interface and an interceptor mechanism.
2353 css::uno::Reference<css::frame::XDispatchProvider> disp;
2355 SolarMutexGuard g;
2356 disp = m_xDispatchHelper;
2358 if (!disp.is()) {
2359 throw css::lang::DisposedException("Frame disposed");
2361 return disp->queryDispatches( lDescriptor );
2364 /*-****************************************************************************************************
2365 @short register/unregister interceptor for dispatch calls
2366 @descr If you wish to handle some dispatches by himself ... you should be
2367 an interceptor for it. Please see class OInterceptionHelper for further information.
2369 @seealso class OInterceptionHelper
2371 @param "xInterceptor", reference to your interceptor implementation.
2372 @onerror Interceptor is ignored.
2373 *//*-*****************************************************************************************************/
2374 void SAL_CALL XFrameImpl::registerDispatchProviderInterceptor(
2375 const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor )
2377 // We use a helper to support these interface and an interceptor mechanism.
2378 // This helper is threadsafe himself and check incoming parameter too.
2379 // I think we don't need any lock here!
2381 checkDisposed();
2383 css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper;
2385 SolarMutexGuard g;
2386 xInterceptionHelper = m_xDispatchHelper;
2388 if (xInterceptionHelper.is()) {
2389 xInterceptionHelper->registerDispatchProviderInterceptor( xInterceptor );
2393 void SAL_CALL XFrameImpl::releaseDispatchProviderInterceptor(
2394 const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor )
2396 // We use a helper to support these interface and an interceptor mechanism.
2397 // This helper is threadsafe himself and check incoming parameter too.
2398 // I think we don't need any lock here!
2400 // Sometimes we are called during our dispose() method
2402 css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper;
2404 SolarMutexGuard g;
2405 xInterceptionHelper = m_xDispatchHelper;
2407 if (xInterceptionHelper.is()) {
2408 xInterceptionHelper->releaseDispatchProviderInterceptor( xInterceptor );
2412 /*-****************************************************************************************************
2413 @short provides information about all possible dispatch functions
2414 inside the current frame environment
2415 *//*-*****************************************************************************************************/
2416 css::uno::Sequence< sal_Int16 > SAL_CALL XFrameImpl::getSupportedCommandGroups()
2418 return m_xDispatchInfoHelper->getSupportedCommandGroups();
2421 css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL XFrameImpl::getConfigurableDispatchInformation(
2422 sal_Int16 nCommandGroup)
2424 return m_xDispatchInfoHelper->getConfigurableDispatchInformation(nCommandGroup);
2427 /*-****************************************************************************************************
2428 @short notifications for window events
2429 @descr We are a listener on our container window to forward it to our component window.
2431 @seealso method setComponent()
2432 @seealso member m_xContainerWindow
2433 @seealso member m_xComponentWindow
2435 @param "aEvent" describe source of detected event
2436 *//*-*****************************************************************************************************/
2437 void SAL_CALL XFrameImpl::windowResized( const css::awt::WindowEvent& )
2439 // Part of dispose-mechanism
2441 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2442 // Impl-method is threadsafe!
2443 // If we have a current component window - we must resize it!
2444 implts_resizeComponentWindow();
2447 void SAL_CALL XFrameImpl::focusGained( const css::awt::FocusEvent& )
2449 // Part of dispose() mechanism
2451 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2452 SolarMutexClearableGuard aReadLock;
2453 // Make snapshot of member!
2454 css::uno::Reference< css::awt::XWindow > xComponentWindow = m_xComponentWindow;
2455 aReadLock.clear();
2456 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
2458 if( xComponentWindow.is() )
2460 xComponentWindow->setFocus();
2464 /*-****************************************************************************************************
2465 @short notifications for window events
2466 @descr We are a listener on our container window to forward it to our component window ...
2467 but a XTopWindowListener we are only if we are a top frame!
2469 @seealso method setComponent()
2470 @seealso member m_xContainerWindow
2471 @seealso member m_xComponentWindow
2473 @param "aEvent" describe source of detected event
2474 *//*-*****************************************************************************************************/
2475 void SAL_CALL XFrameImpl::windowActivated( const css::lang::EventObject& )
2477 checkDisposed();
2479 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2480 SolarMutexClearableGuard aReadLock;
2481 // Make snapshot of member!
2482 EActiveState eState = m_eActiveState;
2483 aReadLock.clear();
2484 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
2485 // Activate the new active path from here to top.
2486 if( eState == E_INACTIVE )
2488 setActiveFrame( css::uno::Reference< css::frame::XFrame >() );
2489 activate();
2493 void SAL_CALL XFrameImpl::windowDeactivated( const css::lang::EventObject& )
2495 // Sometimes called during dispose()
2497 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2498 SolarMutexClearableGuard aReadLock;
2500 css::uno::Reference< css::frame::XFrame > xParent = m_xParent;
2501 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
2502 EActiveState eActiveState = m_eActiveState;
2504 aReadLock.clear();
2506 if( eActiveState == E_INACTIVE )
2507 return;
2509 // Deactivation is always done implicitly by activation of another frame.
2510 // Only if no activation is done, deactivations have to be processed if the activated window
2511 // is a parent window of the last active Window!
2512 SolarMutexClearableGuard aSolarGuard;
2513 vcl::Window* pFocusWindow = Application::GetFocusWindow();
2514 if ( !xContainerWindow.is() || !xParent.is() ||
2515 css::uno::Reference< css::frame::XDesktop >( xParent, css::uno::UNO_QUERY ).is()
2517 return;
2519 css::uno::Reference< css::awt::XWindow > xParentWindow = xParent->getContainerWindow();
2520 VclPtr<vcl::Window> pParentWindow = VCLUnoHelper::GetWindow( xParentWindow );
2521 //#i70261#: dialogs opened from an OLE object will cause a deactivate on the frame of the OLE object
2522 // on Solaris/Linux at that time pFocusWindow is still NULL because the focus handling is different; right after
2523 // the deactivation the focus will be set into the dialog!
2524 // currently I see no case where a sub frame could get a deactivate with pFocusWindow being NULL permanently
2525 // so for now this case is omitted from handled deactivations
2526 if( pFocusWindow && pParentWindow->IsChild( pFocusWindow ) )
2528 css::uno::Reference< css::frame::XFramesSupplier > xSupplier( xParent, css::uno::UNO_QUERY );
2529 if( xSupplier.is() )
2531 aSolarGuard.clear();
2532 xSupplier->setActiveFrame( css::uno::Reference< css::frame::XFrame >() );
2537 void SAL_CALL XFrameImpl::windowClosing( const css::lang::EventObject& )
2539 checkDisposed();
2541 // deactivate this frame ...
2542 deactivate();
2544 // ... and try to close it
2545 // But do it asynchronous inside the main thread.
2546 // VCL has no fun to do such things outside his main thread :-(
2547 // Note: The used dispatch make it asynchronous for us .-)
2549 /*ATTENTION!
2550 Don't try to suspend the controller here! Because it's done inside used dispatch().
2551 Otherwise the dialog "would you save your changes?" will be shown more than once ...
2554 css::util::URL aURL;
2555 aURL.Complete = ".uno:CloseFrame";
2556 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
2557 xParser->parseStrict(aURL);
2559 css::uno::Reference< css::frame::XDispatch > xCloser = queryDispatch(aURL, SPECIALTARGET_SELF, 0);
2560 if (xCloser.is())
2561 xCloser->dispatch(aURL, css::uno::Sequence< css::beans::PropertyValue >());
2563 // Attention: If this dispatch works synchronous ... and fulfill its job ...
2564 // this line of code will never be reached ...
2565 // Or if it will be reached it will be for sure that all your member are gone .-)
2568 /*-****************************************************************************************************
2569 @short react for a show event for the internal container window
2570 @descr Normally we don't need this information really. But we can use it to
2571 implement the special feature "trigger first visible task".
2573 Algorithm: - first we have to check if we are a top (task) frame
2574 It's not enough to be a top frame! Because we MUST have the desktop as parent.
2575 But frames without a parent are top too. So it's not possible to check isTop() here!
2576 We have to look for the type of our parent.
2577 - if we are a task frame, then we have to check if we are the first one.
2578 We use a static variable to do so. They will be reset to afterwards be sure
2579 that further calls of this method doesn't do anything then.
2580 - Then we have to trigger the right event string on the global job executor.
2582 @seealso css::task::JobExecutor
2584 @param aEvent
2585 describes the source of this event
2586 We are not interested on this information. We are interested on the visible state only.
2588 @threadsafe yes
2589 *//*-*****************************************************************************************************/
2590 void SAL_CALL XFrameImpl::windowShown( const css::lang::EventObject& )
2592 static std::mutex aFirstVisibleLock;
2594 /* SAFE { */
2595 SolarMutexClearableGuard aReadLock;
2596 css::uno::Reference< css::frame::XDesktop > xDesktopCheck( m_xParent, css::uno::UNO_QUERY );
2597 m_bIsHidden = false;
2598 aReadLock.clear();
2599 /* } SAFE */
2601 impl_checkMenuCloser();
2603 if (!xDesktopCheck.is())
2604 return;
2606 static bool bFirstVisibleTask = true;
2607 std::unique_lock aGuard(aFirstVisibleLock);
2608 bool bMustBeTriggered = bFirstVisibleTask;
2609 bFirstVisibleTask = false;
2610 aGuard.unlock();
2612 if (bMustBeTriggered)
2614 css::uno::Reference< css::task::XJobExecutor > xExecutor
2615 = css::task::theJobExecutor::get( m_xContext );
2616 xExecutor->trigger( "onFirstVisibleTask" );
2620 void SAL_CALL XFrameImpl::windowHidden( const css::lang::EventObject& )
2622 /* SAFE { */
2624 SolarMutexGuard aReadLock;
2625 m_bIsHidden = true;
2627 /* } SAFE */
2629 impl_checkMenuCloser();
2632 /*-****************************************************************************************************
2633 @short called by dispose of our windows!
2634 @descr This object is forced to release all references to the interfaces given
2635 by the parameter source. We are a listener at our container window and
2636 should listen for his disposing.
2638 @seealso XWindowListener
2639 @seealso XTopWindowListener
2640 @seealso XFocusListener
2641 *//*-*****************************************************************************************************/
2642 void SAL_CALL XFrameImpl::disposing( const css::lang::EventObject& aEvent )
2644 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2645 SolarMutexResettableGuard aWriteLock;
2647 if( aEvent.Source == m_xContainerWindow )
2649 // NECESSARY: Impl-method is threadsafe by himself!
2650 aWriteLock.clear();
2651 implts_stopWindowListening();
2652 aWriteLock.reset();
2653 m_xContainerWindow.clear();
2657 /*-************************************************************************************************************
2658 @interface com.sun.star.document.XActionLockable
2659 @short implement locking of frame/task from outside
2660 @descr Sometimes we have problems to decide if closing of task is allowed. Because; frame/task
2661 could be used for pending loading jobs. So you can lock this object from outside and
2662 prevent instance against closing during using! But - don't do it in a wrong or expensive manner.
2663 Otherwise task couldn't die anymore!!!
2665 @seealso interface XActionLockable
2666 @seealso method BaseDispatcher::implts_loadIt()
2667 @seealso method Desktop::loadComponentFromURL()
2668 @return true if frame/task is locked
2669 false otherwise
2670 @threadsafe yes
2671 *//*-*************************************************************************************************************/
2672 sal_Bool SAL_CALL XFrameImpl::isActionLocked()
2674 SolarMutexGuard g;
2675 return( m_nExternalLockCount!=0);
2678 void SAL_CALL XFrameImpl::addActionLock()
2680 SolarMutexGuard g;
2681 ++m_nExternalLockCount;
2684 void SAL_CALL XFrameImpl::removeActionLock()
2687 SolarMutexGuard g;
2688 SAL_WARN_IF( m_nExternalLockCount<=0, "fwk.frame", "XFrameImpl::removeActionLock(): Frame is not locked! "
2689 "Possible multithreading problem detected." );
2690 --m_nExternalLockCount;
2693 implts_checkSuicide();
2696 void SAL_CALL XFrameImpl::setActionLocks( sal_Int16 nLock )
2698 SolarMutexGuard g;
2699 // Attention: If somewhere called resetActionLocks() before and get e.g. 5 locks ...
2700 // and tried to set these 5 ones here after his operations ...
2701 // we can't ignore set requests during these two calls!
2702 // So we must add(!) these 5 locks here.
2703 m_nExternalLockCount = m_nExternalLockCount + nLock;
2706 sal_Int16 SAL_CALL XFrameImpl::resetActionLocks()
2708 sal_Int16 nCurrentLocks = 0;
2710 SolarMutexGuard g;
2711 nCurrentLocks = m_nExternalLockCount;
2712 m_nExternalLockCount = 0;
2715 // Attention:
2716 // external lock count is 0 here every time... but if
2717 // member m_bSelfClose is set to true too... we call our own close()/dispose().
2718 // See close() for further information
2719 implts_checkSuicide();
2721 return nCurrentLocks;
2724 void XFrameImpl::impl_setPropertyValue(sal_Int32 nHandle,
2725 const css::uno::Any& aValue)
2728 /* There is no need to lock any mutex here. Because we share the
2729 solar mutex with our base class. And we said to our base class: "don't release it on calling us" .-)
2732 /* Attention: You can use nHandle only, if you are sure that all supported
2733 properties has a unique handle. That must be guaranteed
2734 inside method initListeners()!
2736 switch (nHandle)
2738 case FRAME_PROPHANDLE_TITLE :
2740 OUString sExternalTitle;
2741 aValue >>= sExternalTitle;
2742 setTitle (sExternalTitle);
2744 break;
2746 case FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER :
2747 aValue >>= m_xDispatchRecorderSupplier;
2748 break;
2750 case FRAME_PROPHANDLE_LAYOUTMANAGER :
2752 css::uno::Reference< css::frame::XLayoutManager2 > xOldLayoutManager = m_xLayoutManager;
2753 css::uno::Reference< css::frame::XLayoutManager2 > xNewLayoutManager;
2754 aValue >>= xNewLayoutManager;
2756 if (xOldLayoutManager != xNewLayoutManager)
2758 m_xLayoutManager = xNewLayoutManager;
2759 if (xOldLayoutManager.is())
2760 disableLayoutManager(xOldLayoutManager);
2761 if (xNewLayoutManager.is() && !m_bDocHidden)
2762 lcl_enableLayoutManager(xNewLayoutManager, this);
2765 break;
2767 case FRAME_PROPHANDLE_INDICATORINTERCEPTION :
2769 css::uno::Reference< css::task::XStatusIndicator > xProgress;
2770 aValue >>= xProgress;
2771 m_xIndicatorInterception = xProgress;
2773 break;
2775 case FRAME_PROPHANDLE_URL:
2777 aValue >>= m_aURL;
2779 break;
2780 default :
2781 SAL_INFO("fwk.frame", "XFrameImpl::setFastPropertyValue_NoBroadcast(): Invalid handle detected!" );
2782 break;
2786 css::uno::Any XFrameImpl::impl_getPropertyValue(sal_Int32 nHandle)
2788 /* There is no need to lock any mutex here. Because we share the
2789 solar mutex with our base class. And we said to our base class: "don't release it on calling us" .-)
2792 /* Attention: You can use nHandle only, if you are sure that all supported
2793 properties has a unique handle. That must be guaranteed
2794 inside method initListeners()!
2796 css::uno::Any aValue;
2797 switch (nHandle)
2799 case FRAME_PROPHANDLE_TITLE :
2800 aValue <<= getTitle ();
2801 break;
2803 case FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER :
2804 aValue <<= m_xDispatchRecorderSupplier;
2805 break;
2807 case FRAME_PROPHANDLE_ISHIDDEN :
2808 aValue <<= m_bIsHidden;
2809 break;
2811 case FRAME_PROPHANDLE_LAYOUTMANAGER :
2812 aValue <<= m_xLayoutManager;
2813 break;
2815 case FRAME_PROPHANDLE_INDICATORINTERCEPTION :
2817 css::uno::Reference< css::task::XStatusIndicator > xProgress(m_xIndicatorInterception.get(),
2818 css::uno::UNO_QUERY);
2819 aValue <<= xProgress;
2821 break;
2823 case FRAME_PROPHANDLE_URL:
2825 aValue <<= m_aURL;
2827 break;
2828 default :
2829 SAL_INFO("fwk.frame", "XFrameImpl::getFastPropertyValue(): Invalid handle detected!" );
2830 break;
2833 return aValue;
2836 void XFrameImpl::impl_setPropertyChangeBroadcaster(const css::uno::Reference< css::uno::XInterface >& xBroadcaster)
2838 SolarMutexGuard g;
2839 m_xBroadcaster = xBroadcaster;
2842 void XFrameImpl::impl_addPropertyInfo(const css::beans::Property& aProperty)
2844 SolarMutexGuard g;
2846 TPropInfoHash::const_iterator pIt = m_lProps.find(aProperty.Name);
2847 if (pIt != m_lProps.end())
2848 throw css::beans::PropertyExistException();
2850 m_lProps[aProperty.Name] = aProperty;
2853 void XFrameImpl::impl_disablePropertySet()
2855 SolarMutexGuard g;
2857 css::uno::Reference< css::uno::XInterface > xThis(static_cast< css::beans::XPropertySet* >(this), css::uno::UNO_QUERY);
2858 css::lang::EventObject aEvent(xThis);
2860 m_lSimpleChangeListener.disposeAndClear(aEvent);
2861 m_lVetoChangeListener.disposeAndClear(aEvent);
2862 m_lProps.clear();
2865 bool XFrameImpl::impl_existsVeto(const css::beans::PropertyChangeEvent& aEvent)
2867 /* Don't use the lock here!
2868 The used helper is threadsafe and it lives for the whole lifetime of
2869 our own object.
2871 ::comphelper::OInterfaceContainerHelper3<css::beans::XVetoableChangeListener>* pVetoListener = m_lVetoChangeListener.getContainer(aEvent.PropertyName);
2872 if (! pVetoListener)
2873 return false;
2875 ::comphelper::OInterfaceIteratorHelper3 pListener(*pVetoListener);
2876 while (pListener.hasMoreElements())
2880 pListener.next()->vetoableChange(aEvent);
2882 catch(const css::uno::RuntimeException&)
2883 { pListener.remove(); }
2884 catch(const css::beans::PropertyVetoException&)
2885 { return true; }
2888 return false;
2891 void XFrameImpl::impl_notifyChangeListener(const css::beans::PropertyChangeEvent& aEvent)
2893 /* Don't use the lock here!
2894 The used helper is threadsafe and it lives for the whole lifetime of
2895 our own object.
2897 ::comphelper::OInterfaceContainerHelper3<css::beans::XPropertyChangeListener>* pSimpleListener = m_lSimpleChangeListener.getContainer(aEvent.PropertyName);
2898 if (! pSimpleListener)
2899 return;
2901 ::comphelper::OInterfaceIteratorHelper3 pListener(*pSimpleListener);
2902 while (pListener.hasMoreElements())
2906 pListener.next()->propertyChange(aEvent);
2908 catch(const css::uno::RuntimeException&)
2909 { pListener.remove(); }
2913 /*-****************************************************************************************************
2914 @short send frame action event to our listener
2915 @descr This method is threadsafe AND can be called by our dispose method too!
2916 @param "aAction", describe the event for sending
2917 *//*-*****************************************************************************************************/
2918 void XFrameImpl::implts_sendFrameActionEvent( const css::frame::FrameAction& aAction )
2920 // Sometimes used by dispose()
2922 // Log information about order of events to file!
2923 // (only activated in debug version!)
2924 SAL_INFO( "fwk.frame",
2925 "[Frame] " << m_sName << " send event " <<
2926 (aAction == css::frame::FrameAction_COMPONENT_ATTACHED ? OUString("COMPONENT ATTACHED") :
2927 (aAction == css::frame::FrameAction_COMPONENT_DETACHING ? OUString("COMPONENT DETACHING") :
2928 (aAction == css::frame::FrameAction_COMPONENT_REATTACHED ? OUString("COMPONENT REATTACHED") :
2929 (aAction == css::frame::FrameAction_FRAME_ACTIVATED ? OUString("FRAME ACTIVATED") :
2930 (aAction == css::frame::FrameAction_FRAME_DEACTIVATING ? OUString("FRAME DEACTIVATING") :
2931 (aAction == css::frame::FrameAction_CONTEXT_CHANGED ? OUString("CONTEXT CHANGED") :
2932 (aAction == css::frame::FrameAction_FRAME_UI_ACTIVATED ? OUString("FRAME UI ACTIVATED") :
2933 (aAction == css::frame::FrameAction_FRAME_UI_DEACTIVATING ? OUString("FRAME UI DEACTIVATING") :
2934 (aAction == css::frame::FrameAction::FrameAction_MAKE_FIXED_SIZE ? OUString("MAKE_FIXED_SIZE") :
2935 OUString("*invalid*")))))))))));
2937 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2938 // Send css::frame::FrameAction event to all listener.
2939 // Get container for right listener.
2940 // FOLLOW LINES ARE THREADSAFE!!!
2941 // ( OInterfaceContainerHelper2 is synchronized with m_aListenerContainer! )
2942 comphelper::OInterfaceContainerHelper2* pContainer = m_aListenerContainer.getContainer(
2943 cppu::UnoType<css::frame::XFrameActionListener>::get());
2945 if( pContainer == nullptr )
2946 return;
2948 // Build action event.
2949 css::frame::FrameActionEvent aFrameActionEvent( static_cast< ::cppu::OWeakObject* >(this), this, aAction );
2951 // Get iterator for access to listener.
2952 comphelper::OInterfaceIteratorHelper2 aIterator( *pContainer );
2953 // Send message to all listener.
2954 while( aIterator.hasMoreElements() )
2958 static_cast<css::frame::XFrameActionListener*>(aIterator.next())->frameAction( aFrameActionEvent );
2960 catch( const css::uno::RuntimeException& )
2962 aIterator.remove();
2967 /*-****************************************************************************************************
2968 @short helper to resize our component window
2969 @descr A frame contains 2 windows - a container ~ and a component window.
2970 This method resize inner component window to full size of outer container window.
2971 This method is threadsafe AND can be called by our dispose method too!
2972 *//*-*****************************************************************************************************/
2973 void XFrameImpl::implts_resizeComponentWindow()
2975 // usually the LayoutManager does the resizing
2976 // in case there is no LayoutManager resizing has to be done here
2977 if ( m_xLayoutManager.is() )
2978 return;
2980 css::uno::Reference< css::awt::XWindow > xComponentWindow( getComponentWindow() );
2981 if( !xComponentWindow.is() )
2982 return;
2984 css::uno::Reference< css::awt::XDevice > xDevice( getContainerWindow(), css::uno::UNO_QUERY );
2986 // Convert relative size to output size.
2987 css::awt::Rectangle aRectangle = getContainerWindow()->getPosSize();
2988 css::awt::DeviceInfo aInfo = xDevice->getInfo();
2989 css::awt::Size aSize( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset,
2990 aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
2992 // Resize our component window.
2993 xComponentWindow->setPosSize( 0, 0, aSize.Width, aSize.Height, css::awt::PosSize::POSSIZE );
2996 /*-****************************************************************************************************
2997 @short helper to set icon on our container window (if it is a system window!)
2998 @descr We use our internal set controller (if it exist) to specify which factory he represented.
2999 This information can be used to find right icon. But our controller can say it us directly
3000 too ... we should ask his optional property set first ...
3002 @seealso method Window::SetIcon()
3003 @onerror We do nothing.
3004 *//*-*****************************************************************************************************/
3005 void XFrameImpl::implts_setIconOnWindow()
3007 checkDisposed();
3009 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3010 // Make snapshot of necessary members and release lock.
3011 SolarMutexClearableGuard aReadLock;
3012 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
3013 css::uno::Reference< css::frame::XController > xController = m_xController;
3014 aReadLock.clear();
3015 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
3017 if( !(xContainerWindow.is() && xController.is()) )
3018 return;
3021 // a) set default value to an invalid one. So we can start further searches for right icon id, if
3022 // first steps failed!
3023 // We must reset it to any fallback value - if no search step returns a valid result.
3024 sal_Int32 nIcon = -1;
3026 // b) try to find information on controller propertyset directly
3027 // Don't forget to catch possible exceptions - because these property is an optional one!
3028 css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY );
3029 if( xSet.is() )
3033 css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(),
3034 css::uno::UNO_SET_THROW );
3035 if ( xPSI->hasPropertyByName( "IconId" ) )
3036 xSet->getPropertyValue( "IconId" ) >>= nIcon;
3038 catch( css::uno::Exception& )
3040 DBG_UNHANDLED_EXCEPTION("fwk");
3044 // c) if b) failed... analyze argument list of currently loaded document inside the frame to find the filter.
3045 // He can be used to detect right factory - and these can be used to match factory to icon...
3046 if( nIcon == -1 )
3048 css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
3049 if( xModel.is() )
3051 SvtModuleOptions::EFactory eFactory = SvtModuleOptions::ClassifyFactoryByModel(xModel);
3052 if (eFactory != SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
3053 nIcon = SvtModuleOptions().GetFactoryIcon( eFactory );
3057 // d) if all steps failed - use fallback!
3058 if( nIcon == -1 )
3060 nIcon = 0;
3063 // e) set icon on container window now
3064 // Don't forget SolarMutex! We use vcl directly :-(
3065 // Check window pointer for right WorkWindow class too!!!
3066 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3068 SolarMutexGuard aSolarGuard;
3069 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
3071 ( pWindow != nullptr ) &&
3072 ( pWindow->GetType() == WindowType::WORKWINDOW )
3075 WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow.get());
3076 pWorkWindow->SetIcon( static_cast<sal_uInt16>(nIcon) );
3079 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
3082 /*-************************************************************************************************************
3083 @short helper to start/stop listening for window events on container window
3084 @descr If we get a new container window, we must set it on internal member ...
3085 and stop listening at old one ... and start listening on new one!
3086 But sometimes (in dispose() call!) it's necessary to stop listening without starting
3087 on new connections. So we split this functionality to make it easier at use.
3089 @seealso method initialize()
3090 @seealso method dispose()
3091 @onerror We do nothing!
3092 @threadsafe yes
3093 *//*-*************************************************************************************************************/
3094 void XFrameImpl::implts_startWindowListening()
3096 checkDisposed();
3098 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3099 // Make snapshot of necessary member!
3100 SolarMutexClearableGuard aReadLock;
3101 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
3102 css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > xDragDropListener = m_xDropTargetListener;
3103 css::uno::Reference< css::awt::XWindowListener > xWindowListener(this);
3104 css::uno::Reference< css::awt::XFocusListener > xFocusListener(this);
3105 css::uno::Reference< css::awt::XTopWindowListener > xTopWindowListener(this);
3106 aReadLock.clear();
3107 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
3109 if( !xContainerWindow.is() )
3110 return;
3112 xContainerWindow->addWindowListener( xWindowListener);
3113 xContainerWindow->addFocusListener ( xFocusListener );
3115 css::uno::Reference< css::awt::XTopWindow > xTopWindow( xContainerWindow, css::uno::UNO_QUERY );
3116 if( xTopWindow.is() )
3118 xTopWindow->addTopWindowListener( xTopWindowListener );
3120 css::uno::Reference< css::awt::XToolkit2 > xToolkit = css::awt::Toolkit::create( m_xContext );
3121 css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget = xToolkit->getDropTarget( xContainerWindow );
3122 if( xDropTarget.is() )
3124 xDropTarget->addDropTargetListener( xDragDropListener );
3125 xDropTarget->setActive( true );
3130 void XFrameImpl::implts_stopWindowListening()
3132 // Sometimes used by dispose()
3134 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3135 // Make snapshot of necessary member!
3136 SolarMutexClearableGuard aReadLock;
3137 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
3138 css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > xDragDropListener = m_xDropTargetListener;
3139 css::uno::Reference< css::awt::XWindowListener > xWindowListener(this);
3140 css::uno::Reference< css::awt::XFocusListener > xFocusListener(this);
3141 css::uno::Reference< css::awt::XTopWindowListener > xTopWindowListener(this);
3142 aReadLock.clear();
3143 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
3145 if( !xContainerWindow.is() )
3146 return;
3148 xContainerWindow->removeWindowListener( xWindowListener);
3149 xContainerWindow->removeFocusListener ( xFocusListener );
3151 css::uno::Reference< css::awt::XTopWindow > xTopWindow( xContainerWindow, css::uno::UNO_QUERY );
3152 if( !xTopWindow.is() )
3153 return;
3155 xTopWindow->removeTopWindowListener( xTopWindowListener );
3157 css::uno::Reference< css::awt::XToolkit2 > xToolkit = css::awt::Toolkit::create( m_xContext );
3158 css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget =
3159 xToolkit->getDropTarget( xContainerWindow );
3160 if( xDropTarget.is() )
3162 xDropTarget->removeDropTargetListener( xDragDropListener );
3163 xDropTarget->setActive( false );
3167 /*-****************************************************************************************************
3168 @short helper to force broken close() request again
3169 @descr If we self disagree with a close() request, and detect that all external locks are gone ...
3170 then we must try to close this frame again.
3172 @seealso XCloseable::close()
3173 @seealso XFrameImpl::close()
3174 @seealso XFrameImpl::removeActionLock()
3175 @seealso XFrameImpl::resetActionLock()
3176 @seealso m_bSelfClose
3177 @seealso m_nExternalLockCount
3179 @threadsafe yes
3180 *//*-*****************************************************************************************************/
3181 void XFrameImpl::implts_checkSuicide()
3183 /* SAFE */
3184 SolarMutexClearableGuard aReadLock;
3185 // in case of lock==0 and safed state of previous close() request m_bSelfClose
3186 // we must force close() again. Because we had disagreed with that before.
3187 bool bSuicide = (m_nExternalLockCount==0 && m_bSelfClose);
3188 m_bSelfClose = false;
3189 aReadLock.clear();
3190 /* } SAFE */
3191 // force close and deliver ownership to source of possible thrown veto exception
3192 // Attention: Because this method is not designed to throw such exception we must suppress
3193 // it for outside code!
3196 if (bSuicide)
3197 close(true);
3199 catch(const css::util::CloseVetoException&)
3201 catch(const css::lang::DisposedException&)
3205 /** little helper to enable/disable the menu closer at the menubar of the given frame.
3207 @param xFrame
3208 we use its layout manager to set/reset a special callback.
3209 Its existence regulate visibility of this closer item.
3211 @param bState
3212 <TRUE/> enable; <FALSE/> disable this state
3215 void XFrameImpl::impl_setCloser( /*IN*/ const css::uno::Reference< css::frame::XFrame2 >& xFrame ,
3216 /*IN*/ bool bState )
3218 // Note: If start module is not installed - no closer has to be shown!
3219 if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::STARTMODULE))
3220 return;
3224 css::uno::Reference< css::beans::XPropertySet > xFrameProps(xFrame, css::uno::UNO_QUERY_THROW);
3225 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
3226 xFrameProps->getPropertyValue(FRAME_PROPNAME_ASCII_LAYOUTMANAGER) >>= xLayoutManager;
3227 css::uno::Reference< css::beans::XPropertySet > xLayoutProps(xLayoutManager, css::uno::UNO_QUERY_THROW);
3228 xLayoutProps->setPropertyValue(LAYOUTMANAGER_PROPNAME_MENUBARCLOSER, css::uno::Any(bState));
3230 catch(const css::uno::RuntimeException&)
3231 { throw; }
3232 catch(const css::uno::Exception&)
3236 /** it checks, which of the top level task frames must have the special menu closer for
3237 switching to the backing window mode.
3239 It analyze the current list of visible top level frames. Only the last real document
3240 frame can have this symbol. Not the help frame nor the backing task itself.
3241 Here we do anything related to this closer. We remove it from the old frame and set it
3242 for the new one.
3245 void XFrameImpl::impl_checkMenuCloser()
3247 /* SAFE { */
3248 SolarMutexClearableGuard aReadLock;
3250 // only top frames, which are part of our desktop hierarchy, can
3251 // do so! By the way - we need the desktop instance to have access
3252 // to all other top level frames too.
3253 css::uno::Reference< css::frame::XDesktop > xDesktop (m_xParent, css::uno::UNO_QUERY);
3254 css::uno::Reference< css::frame::XFramesSupplier > xTaskSupplier(xDesktop , css::uno::UNO_QUERY);
3255 if ( !xDesktop.is() || !xTaskSupplier.is() )
3256 return;
3258 aReadLock.clear();
3259 /* } SAFE */
3261 // analyze the list of current open tasks
3262 // Suppress search for other views to the same model ...
3263 // It's not needed here and can be very expensive.
3264 FrameListAnalyzer aAnalyzer(
3265 xTaskSupplier,
3266 this,
3267 FrameAnalyzerFlags::Hidden | FrameAnalyzerFlags::Help | FrameAnalyzerFlags::BackingComponent);
3269 // specify the new frame, which must have this special state...
3270 css::uno::Reference< css::frame::XFrame2 > xNewCloserFrame;
3272 // a)
3273 // If there exist at least one other frame - there are two frames currently open.
3274 // But we can enable this closer only, if one of these two tasks includes the help module.
3275 // The "other frame" couldn't be the help. Because then it wouldn't be part of this "other list".
3276 // In such case it will be separated to the reference aAnalyzer.m_xHelp!
3277 // But we must check, if we include ourself the help...
3278 // Check aAnalyzer.m_bReferenceIsHelp!
3279 if (
3280 (aAnalyzer.m_lOtherVisibleFrames.size()==1) &&
3282 (aAnalyzer.m_bReferenceIsHelp ) ||
3283 (aAnalyzer.m_bReferenceIsHidden)
3287 // others[0] can't be the backing component!
3288 // Because it's set at the special member aAnalyzer.m_xBackingComponent ... :-)
3289 xNewCloserFrame.set( aAnalyzer.m_lOtherVisibleFrames[0], css::uno::UNO_QUERY_THROW );
3292 // b)
3293 // There is no other frame... means no other document frame. The help module
3294 // will be handled separately and must(!) be ignored here... excepting if we include ourself the help.
3295 else if (
3296 (aAnalyzer.m_lOtherVisibleFrames.empty()) &&
3297 (!aAnalyzer.m_bReferenceIsHelp) &&
3298 (!aAnalyzer.m_bReferenceIsHidden) &&
3299 (!aAnalyzer.m_bReferenceIsBacking)
3302 xNewCloserFrame = this;
3305 // Look for necessary actions ...
3306 // Only if the closer state must be moved from one frame to another one
3307 // or must be enabled/disabled at all.
3308 SolarMutexGuard aGuard;
3309 // Holds the only frame, which must show the special closer menu item (can be NULL!)
3310 static css::uno::WeakReference< css::frame::XFrame2 > s_xCloserFrame;
3311 css::uno::Reference< css::frame::XFrame2 > xCloserFrame (s_xCloserFrame.get(), css::uno::UNO_QUERY);
3312 if (xCloserFrame!=xNewCloserFrame)
3314 if (xCloserFrame.is())
3315 impl_setCloser(xCloserFrame, false);
3316 if (xNewCloserFrame.is())
3317 impl_setCloser(xNewCloserFrame, true);
3318 s_xCloserFrame = xNewCloserFrame;
3324 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
3325 com_sun_star_comp_framework_Frame_get_implementation(
3326 css::uno::XComponentContext *context,
3327 css::uno::Sequence<css::uno::Any> const &)
3329 rtl::Reference<XFrameImpl> inst = new XFrameImpl(context);
3330 css::uno::XInterface *acquired_inst = cppu::acquire(inst.get());
3332 inst->initListeners();
3334 return acquired_inst;
3337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */