Avoid potential negative array index access to cached text.
[LibreOffice.git] / framework / source / services / frame.cxx
blob34024b45f5ad309e27d7377ce5f9b5d02d066bb8
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);
804 css::uno::Reference< css::task::XStatusIndicatorFactory > xIndicatorFactory =
805 css::task::StatusIndicatorFactory::createWithFrame(m_xContext, xThis,
806 false/*DisableReschedule*/, true/*AllowParentShow*/ );
808 // SAFE -> ----------------------------------
809 aWriteLock.reset();
810 m_xIndicatorFactoryHelper = std::move(xIndicatorFactory);
811 aWriteLock.clear();
812 // <- SAFE ----------------------------------
815 // Start listening for events after setting it on helper class ...
816 // So superfluous messages are filtered to NULL :-)
817 implts_startWindowListening();
819 m_pWindowCommandDispatch.reset(new WindowCommandDispatch(m_xContext, this));
821 // Initialize title functionality
822 m_xTitleHelper = new TitleHelper( m_xContext, xThis, nullptr );
825 /*-****************************************************************************************************
826 @short returns current set container window
827 @descr The ContainerWindow property is used as a container for the component
828 in this frame. So this object implements a container interface too.
829 The instantiation of the container window is done by the user of this class.
830 The frame is the owner of its container window.
832 @seealso method initialize()
833 @return A reference to current set containerwindow.
835 @onerror A null reference is returned.
836 *//*-*****************************************************************************************************/
837 css::uno::Reference< css::awt::XWindow > SAL_CALL XFrameImpl::getContainerWindow()
839 SolarMutexGuard g;
840 return m_xContainerWindow;
843 /*-****************************************************************************************************
844 @short set parent frame
845 @descr We need a parent to support some functionality! e.g. findFrame()
846 By the way we use the chance to set an internal information about our top state.
847 So we must not check this information during every isTop() call.
848 We are top, if our parent is the desktop instance or we haven't any parent.
850 @seealso getCreator()
851 @seealso findFrame()
852 @seealso isTop()
853 @seealso m_bIsFrameTop
855 @param xCreator
856 valid reference to our new owner frame, which should implement a supplier interface
858 @threadsafe yes
859 *//*-*****************************************************************************************************/
860 void SAL_CALL XFrameImpl::setCreator( const css::uno::Reference< css::frame::XFramesSupplier >& xCreator )
862 checkDisposed();
864 /* SAFE { */
866 SolarMutexGuard aWriteLock;
867 m_xParent = xCreator;
869 /* } SAFE */
871 css::uno::Reference< css::frame::XDesktop > xIsDesktop( xCreator, css::uno::UNO_QUERY );
872 m_bIsFrameTop = ( xIsDesktop.is() || ! xCreator.is() );
875 /*-****************************************************************************************************
876 @short returns current parent frame
877 @descr The Creator is the parent frame container. If it is NULL, the frame is the uppermost one.
879 @seealso method setCreator()
880 @return A reference to current set parent frame container.
882 @onerror A null reference is returned.
883 *//*-*****************************************************************************************************/
884 css::uno::Reference< css::frame::XFramesSupplier > SAL_CALL XFrameImpl::getCreator()
886 checkDisposed();
887 SolarMutexGuard g;
888 return m_xParent;
891 /*-****************************************************************************************************
892 @short returns current set name of frame
893 @descr This name is used to find target of findFrame() or queryDispatch() calls.
895 @seealso method setName()
896 @return Current set name of frame.
898 @onerror An empty string is returned.
899 *//*-*****************************************************************************************************/
900 OUString SAL_CALL XFrameImpl::getName()
902 SolarMutexGuard g;
903 return m_sName;
906 /*-****************************************************************************************************
907 @short set new name for frame
908 @descr This name is used to find target of findFrame() or queryDispatch() calls.
910 @attention Special names like "_blank", "_self" aren't allowed...
911 "_beamer" excepts this rule!
913 @seealso method getName()
915 @param "sName", new frame name.
916 @onerror We do nothing.
917 *//*-*****************************************************************************************************/
918 void SAL_CALL XFrameImpl::setName( const OUString& sName )
920 SolarMutexGuard g;
921 // Set new name... but look for invalid special target names!
922 // They are not allowed to set.
923 if (TargetHelper::isValidNameForFrame(sName))
924 m_sName = sName;
927 /*-****************************************************************************************************
928 @short search for frames
929 @descr This method searches for a frame with the specified name.
930 Frames may contain other frames (e.g. a frameset) and may
931 be contained in other frames. This hierarchy is searched by
932 this method.
933 First some special names are taken into account, i.e. "",
934 "_self", "_top", "_blank" etc. The nSearchFlags are ignored
935 when comparing these names with sTargetFrameName, further steps are
936 controlled by the search flags. If allowed, the name of the frame
937 itself is compared with the desired one, then ( again if allowed )
938 the method findFrame() is called for all children, for siblings
939 and as last for the parent frame.
940 If no frame with the given name is found until the top frames container,
941 a new top one is created, if this is allowed by a special
942 flag. The new frame also gets the desired name.
944 @param sTargetFrameName
945 special names (_blank, _self) or real name of target frame
946 @param nSearchFlags
947 optional flags which regulate search for non special target frames
949 @return A reference to found or may be new created frame.
950 @threadsafe yes
951 *//*-*****************************************************************************************************/
952 css::uno::Reference< css::frame::XFrame > SAL_CALL XFrameImpl::findFrame( const OUString& sTargetFrameName,
953 sal_Int32 nSearchFlags )
955 css::uno::Reference< css::frame::XFrame > xTarget;
957 // 0) Ignore wrong parameter!
958 // We don't support search for following special targets.
959 // If we reject this requests - we must not check for such names
960 // in following code again and again. If we do not so -wrong
961 // search results can occur!
963 if ( sTargetFrameName == SPECIALTARGET_DEFAULT ) // valid for dispatches - not for findFrame()!
965 return nullptr;
968 // I) check for special defined targets first which must be handled exclusive.
969 // force using of "if() else if() ..."
971 // get threadsafe some necessary member which are necessary for following functionality
972 /* SAFE { */
973 SolarMutexResettableGuard aReadLock;
974 css::uno::Reference< css::frame::XFrame > xParent = m_xParent;
975 bool bIsTopFrame = m_bIsFrameTop;
976 bool bIsTopWindow = WindowHelper::isTopWindow(m_xContainerWindow);
977 aReadLock.clear();
978 /* } SAFE */
980 // I.I) "_blank"
981 // Not allowed for a normal frame - but for the desktop.
982 // Use helper class to do so. It use the desktop automatically.
984 if ( sTargetFrameName==SPECIALTARGET_BLANK )
986 TaskCreator aCreator(m_xContext);
987 xTarget = aCreator.createTask(sTargetFrameName, utl::MediaDescriptor());
990 // I.II) "_parent"
991 // It doesn't matter if we have a valid parent or not. User ask for him and get it.
992 // An empty result is a valid result too.
994 else if ( sTargetFrameName==SPECIALTARGET_PARENT )
996 xTarget = xParent;
999 // I.III) "_top"
1000 // If we are not the top frame in this hierarchy, we must forward request to our parent.
1001 // Otherwise we must return ourself.
1003 else if ( sTargetFrameName==SPECIALTARGET_TOP )
1005 if (bIsTopFrame)
1006 xTarget = this;
1007 else if (xParent.is()) // If we are not top - the parent MUST exist. But may it's better to check it again .-)
1008 xTarget = xParent->findFrame(SPECIALTARGET_TOP,0);
1011 // I.IV) "_self", ""
1012 // This mean this frame in every case.
1014 else if (
1015 ( sTargetFrameName==SPECIALTARGET_SELF ) ||
1016 ( sTargetFrameName.isEmpty() )
1019 xTarget = this;
1022 // I.V) "_beamer"
1023 // This is a special sub frame of any task. We must return it if we found it on our direct children
1024 // or create it there if it not already exists.
1025 // Note: Such beamer exists for task(top) frames only!
1027 else if ( sTargetFrameName==SPECIALTARGET_BEAMER )
1029 // We are a task => search or create the beamer
1030 if (bIsTopWindow)
1032 xTarget = m_aChildFrameContainer.searchOnDirectChildrens(SPECIALTARGET_BEAMER);
1033 if ( ! xTarget.is() )
1035 /* TODO
1036 Creation not supported yet!
1037 Wait for new layout manager service because we can't plug it
1038 inside already opened document of this frame...
1042 // We aren't a task => forward request to our parent or ignore it.
1043 else if (xParent.is())
1044 xTarget = xParent->findFrame(SPECIALTARGET_BEAMER,0);
1047 else
1050 // II) otherwise use optional given search flags
1051 // force using of combinations of such flags. means no "else" part of use if() statements.
1052 // But we ust break further searches if target was already found.
1053 // Order of using flags is fix: SELF - CHILDREN - SIBLINGS - PARENT
1054 // TASK and CREATE are handled special.
1056 // get threadsafe some necessary member which are necessary for following functionality
1057 /* SAFE { */
1058 aReadLock.reset();
1059 OUString sOwnName = m_sName;
1060 aReadLock.clear();
1061 /* } SAFE */
1063 // II.I) SELF
1064 // Check for right name. If it's the searched one return ourself - otherwise
1065 // ignore this flag.
1067 if (
1068 (nSearchFlags & css::frame::FrameSearchFlag::SELF) &&
1069 (sOwnName == sTargetFrameName )
1072 xTarget = this;
1075 // II.II) CHILDREN
1076 // Search on all children for the given target name.
1077 // An empty name value can't occur here - because it must be already handled as "_self"
1078 // before. Used helper function of container doesn't create any frame.
1079 // It makes a deep search only.
1081 if (
1082 ( ! xTarget.is() ) &&
1083 (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
1086 xTarget = m_aChildFrameContainer.searchOnAllChildrens(sTargetFrameName);
1089 // II.III) TASKS
1090 // This is a special flag. It regulate search on this task tree only or allow search on
1091 // all other ones (which are sibling trees of us) too.
1092 // Upper search must stop at this frame if we are the topest one and the TASK flag is not set
1093 // or we can ignore it if we have no valid parent.
1095 if (
1096 ( bIsTopFrame && (nSearchFlags & css::frame::FrameSearchFlag::TASKS) ) ||
1097 ( ! bIsTopFrame )
1101 // II.III.I) SIBLINGS
1102 // Search on all our direct siblings - means all children of our parent.
1103 // Use this flag in combination with TASK. We must suppress such upper search if
1104 // user has not set it and if we are a top frame.
1105 // Attention: Don't forward this request to our parent as a findFrame() call.
1106 // In such case we must protect us against recursive calls.
1107 // Use snapshot of our parent. But don't use queryFrames() of XFrames interface.
1108 // Because it's return all siblings and all her children including our children too
1109 // if we call it with the CHILDREN flag. We don't need that - we need the direct container
1110 // items of our parent only to start searches there. So we must use the container interface
1111 // XIndexAccess instead of XFrames.
1113 if (
1114 ( ! xTarget.is() ) &&
1115 (nSearchFlags & css::frame::FrameSearchFlag::SIBLINGS) &&
1116 ( xParent.is() ) // search on siblings is impossible without a parent
1119 css::uno::Reference< css::frame::XFramesSupplier > xSupplier( xParent, css::uno::UNO_QUERY );
1120 if (xSupplier.is())
1122 css::uno::Reference< css::container::XIndexAccess > xContainer = xSupplier->getFrames();
1123 if (xContainer.is())
1125 sal_Int32 nCount = xContainer->getCount();
1126 for( sal_Int32 i=0; i<nCount; ++i )
1128 css::uno::Reference< css::frame::XFrame > xSibling;
1129 if (
1130 // control unpacking
1131 ( !(xContainer->getByIndex(i)>>=xSibling) ) ||
1132 // check for valid items
1133 ( ! xSibling.is() ) ||
1134 // ignore ourself! (We are a part of this container too - but search on our children was already done.)
1135 ( xSibling==static_cast< ::cppu::OWeakObject* >(this) )
1138 continue;
1141 // Don't allow upper search here! Use right flags to regulate it.
1142 // And allow deep search on children only - if it was allowed for us too.
1143 sal_Int32 nRightFlags = css::frame::FrameSearchFlag::SELF;
1144 if (nSearchFlags & css::frame::FrameSearchFlag::CHILDREN)
1145 nRightFlags |= css::frame::FrameSearchFlag::CHILDREN;
1146 xTarget = xSibling->findFrame(sTargetFrameName, nRightFlags );
1147 // perform search be breaking further search if a result exist.
1148 if (xTarget.is())
1149 break;
1155 // II.III.II) PARENT
1156 // Forward search to our parent (if he exists.)
1157 // To prevent us against recursive and superfluous calls (which can occur if we allow him
1158 // to search on his children too) we must change used search flags.
1160 if (
1161 ( ! xTarget.is() ) &&
1162 (nSearchFlags & css::frame::FrameSearchFlag::PARENT) &&
1163 ( xParent.is() )
1166 if (xParent->getName() == sTargetFrameName)
1167 xTarget = xParent;
1168 else
1170 sal_Int32 nRightFlags = nSearchFlags & ~css::frame::FrameSearchFlag::CHILDREN;
1171 xTarget = xParent->findFrame(sTargetFrameName, nRightFlags);
1176 // II.IV) CREATE
1177 // If we haven't found any valid target frame by using normal flags - but user allowed us to create
1178 // a new one ... we should do that. Used TaskCreator use Desktop instance automatically as parent!
1180 if (
1181 ( ! xTarget.is() ) &&
1182 (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
1185 TaskCreator aCreator(m_xContext);
1186 xTarget = aCreator.createTask(sTargetFrameName, utl::MediaDescriptor());
1190 return xTarget;
1193 /*-****************************************************************************************************
1194 @descr Returns sal_True, if this frame is a "top frame", otherwise sal_False.
1195 The "m_bIsFrameTop" member must be set in the ctor or setCreator() method.
1196 A top frame is a member of the top frame container or a member of the
1197 task frame container. Both containers can create new frames if the findFrame()
1198 method of their css::frame::XFrame interface is called with a frame name not yet known.
1200 @seealso ctor
1201 @seealso method setCreator()
1202 @seealso method findFrame()
1203 @return true, if is it a top frame ... false otherwise.
1205 @onerror No error should occur!
1206 *//*-*****************************************************************************************************/
1207 sal_Bool SAL_CALL XFrameImpl::isTop()
1209 checkDisposed();
1210 SolarMutexGuard g;
1211 // This information is set in setCreator().
1212 // We are top, if our parent is a task or the desktop or if no parent exist!
1213 return m_bIsFrameTop;
1216 /*-****************************************************************************************************
1217 @short activate frame in hierarchy
1218 @descr This feature is used to mark active paths in our frame hierarchy.
1219 You can be a listener for this event to react for it ... change some internal states or something else.
1221 @seealso method deactivate()
1222 @seealso method isActivate()
1223 @seealso enum EActiveState
1224 @seealso listener mechanism
1225 *//*-*****************************************************************************************************/
1226 void SAL_CALL XFrameImpl::activate()
1228 checkDisposed();
1230 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1231 SolarMutexResettableGuard aWriteLock;
1233 // Copy necessary member and free the lock.
1234 // It's not necessary for m_aChildFrameContainer ... because
1235 // he is threadsafe himself and live if we live.
1236 css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive();
1237 css::uno::Reference< css::frame::XFramesSupplier > xParent = m_xParent;
1238 css::uno::Reference< css::frame::XFrame > xThis(this);
1239 EActiveState eState = m_eActiveState;
1241 aWriteLock.clear();
1242 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1244 // 1) If I am not active before...
1245 if( eState == E_INACTIVE )
1247 // ... do it then.
1248 aWriteLock.reset();
1249 eState = E_ACTIVE;
1250 m_eActiveState = eState;
1251 aWriteLock.clear();
1252 // Deactivate sibling path and forward activation to parent ... if any parent exist!
1253 if( xParent.is() )
1255 // Every time set THIS frame as active child of parent and activate it.
1256 // We MUST have a valid path from bottom to top as active path!
1257 // But we must deactivate the old active sibling path first.
1259 // Attention: Deactivation of an active path, deactivate the whole path ... from bottom to top!
1260 // But we wish to deactivate founded sibling-tree only.
1261 // [ see deactivate() / step 4) for further information! ]
1263 xParent->setActiveFrame( xThis );
1265 // Then we can activate from here to top.
1266 // Attention: We are ACTIVE now. And the parent will call activate() at us!
1267 // But we do nothing then! We are already activated.
1268 xParent->activate();
1270 // It's necessary to send event NOW - not before.
1271 // Activation goes from bottom to top!
1272 // That's the reason to activate parent first and send event now.
1273 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_ACTIVATED );
1276 // 2) I was active before or current activated and there is a path from here to bottom, who CAN be active.
1277 // But our direct child of path is not active yet.
1278 // (It can be, if activation occur in the middle of a current path!)
1279 // In these case we activate path to bottom to set focus on right frame!
1280 if ( eState == E_ACTIVE && xActiveChild.is() && !xActiveChild->isActive() )
1282 xActiveChild->activate();
1285 // 3) I was active before or current activated. But if I have no active child => I will get the focus!
1286 if ( eState == E_ACTIVE && !xActiveChild.is() )
1288 aWriteLock.reset();
1289 eState = E_FOCUS;
1290 m_eActiveState = eState;
1291 aWriteLock.clear();
1292 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_ACTIVATED );
1296 /*-****************************************************************************************************
1297 @short deactivate frame in hierarchy
1298 @descr This feature is used to deactivate paths in our frame hierarchy.
1299 You can be a listener for this event to react for it... change some internal states or something else.
1301 @seealso method activate()
1302 @seealso method isActivate()
1303 @seealso enum EActiveState
1304 @seealso listener mechanism
1305 *//*-*****************************************************************************************************/
1306 void SAL_CALL XFrameImpl::deactivate()
1308 checkDisposed();
1310 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1311 SolarMutexResettableGuard aWriteLock;
1313 // Copy necessary member and free the lock.
1314 css::uno::Reference< css::frame::XFrame > xActiveChild = m_aChildFrameContainer.getActive();
1315 css::uno::Reference< css::frame::XFramesSupplier > xParent = m_xParent;
1316 css::uno::Reference< css::frame::XFrame > xThis(this);
1317 EActiveState eState = m_eActiveState;
1319 aWriteLock.clear();
1320 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
1322 // Work only, if there something to do!
1323 if( eState == E_INACTIVE )
1324 return;
1327 // 1) Deactivate all active children.
1328 if ( xActiveChild.is() && xActiveChild->isActive() )
1330 xActiveChild->deactivate();
1333 // 2) If I have the focus - I will lost it now.
1334 if( eState == E_FOCUS )
1336 // Set new state INACTIVE(!) and send message to all listener.
1337 // Don't set ACTIVE as new state. This frame is deactivated for next time - due to activate().
1338 aWriteLock.reset();
1339 eState = E_ACTIVE;
1340 m_eActiveState = eState;
1341 aWriteLock.clear();
1342 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_UI_DEACTIVATING );
1345 // 3) If I am active - I will be deactivated now.
1346 if( eState == E_ACTIVE )
1348 // Set new state and send message to all listener.
1349 aWriteLock.reset();
1350 eState = E_INACTIVE;
1351 m_eActiveState = eState;
1352 aWriteLock.clear();
1353 implts_sendFrameActionEvent( css::frame::FrameAction_FRAME_DEACTIVATING );
1356 // 4) If there is a path from here to my parent...
1357 // ... I am on the top or in the middle of deactivated subtree and action was started here.
1358 // I must deactivate all frames from here to top, which are members of current path.
1359 // Stop, if THESE frame not the active frame of our parent!
1360 if ( xParent.is() && xParent->getActiveFrame() == xThis )
1362 // We MUST break the path - otherwise we will get the focus - not our parent! ...
1363 // Attention: Our parent don't call us again - WE ARE NOT ACTIVE YET!
1364 // [ see step 3 and condition "if ( m_eActiveState!=INACTIVE ) ..." in this method! ]
1365 xParent->deactivate();
1369 /*-****************************************************************************************************
1370 @short returns active state
1371 @descr Call it to get information about current active state of this frame.
1373 @seealso method activate()
1374 @seealso method deactivate()
1375 @seealso enum EActiveState
1376 @return true if active, false otherwise.
1378 @onerror No error should occur.
1379 *//*-*****************************************************************************************************/
1380 sal_Bool SAL_CALL XFrameImpl::isActive()
1382 checkDisposed();
1383 SolarMutexGuard g;
1384 return m_eActiveState == E_ACTIVE || m_eActiveState == E_FOCUS;
1387 /*-****************************************************************************************************
1388 @short ???
1389 *//*-*****************************************************************************************************/
1390 void SAL_CALL XFrameImpl::contextChanged()
1392 // Sometimes called during closing object...
1393 // Impl-method is threadsafe himself!
1394 // Send event to all listener for frame actions.
1395 implts_sendFrameActionEvent( css::frame::FrameAction_CONTEXT_CHANGED );
1398 /*-****************************************************************************************************
1399 @short set new component inside the frame
1400 @descr A frame is a container for a component. Use this method to set, change or release it!
1401 We accept null references! The xComponentWindow will be a child of our container window
1402 and get all window events from us.
1404 @attention (a) A current set component can disagree with the suspend() request!
1405 We don't set the new one and return with false then.
1406 (b) It's possible to set:
1407 (b1) a simple component here which supports the window only - no controller;
1408 (b2) a full featured component which supports window and controller;
1409 (b3) or both to NULL if outside code which to forget this component.
1411 @seealso method getComponentWindow()
1412 @seealso method getController()
1414 @param xComponentWindow
1415 valid reference to new component window which will be a child of internal container window
1416 May <NULL/> for releasing.
1417 @param xController
1418 reference to new component controller
1419 (may <NULL/> for releasing or setting of a simple component)
1421 @return <TRUE/> if operation was successful, <FALSE/> otherwise.
1423 @onerror We return <FALSE/>.
1424 @threadsafe yes
1425 *//*-*****************************************************************************************************/
1426 sal_Bool SAL_CALL XFrameImpl::setComponent(const css::uno::Reference< css::awt::XWindow >& xComponentWindow,
1427 const css::uno::Reference< css::frame::XController >& xController )
1430 // Ignore this HACK of sfx2!
1431 // He call us with a valid controller without a valid window... that's not allowed!
1432 if ( xController.is() && ! xComponentWindow.is() )
1433 return true;
1435 checkDisposed();
1437 // Get threadsafe some copies of used members.
1438 /* SAFE { */
1439 SolarMutexClearableGuard aReadLock;
1440 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
1441 css::uno::Reference< css::awt::XWindow > xOldComponentWindow = m_xComponentWindow;
1442 css::uno::Reference< css::frame::XController > xOldController = m_xController;
1443 VclPtr<vcl::Window> pOwnWindow = VCLUnoHelper::GetWindow( xContainerWindow );
1444 bool bHadFocus = pOwnWindow != nullptr && pOwnWindow->HasChildPathFocus();
1445 bool bWasConnected = m_bConnected;
1446 aReadLock.clear();
1447 /* } SAFE */
1449 // stop listening on old window
1450 // May it produce some trouble.
1451 // But don't forget to listen on new window again ... or reactivate listening
1452 // if we reject this setComponent() request and leave this method without changing the old window.
1453 implts_stopWindowListening();
1455 // Notify all listener, that this component (if current one exist) will be unloaded.
1456 if (bWasConnected)
1457 implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_DETACHING );
1459 // otherwise release old component first
1460 // Always release controller before releasing window,
1461 // because controller may want to access its window!
1462 // But check for real changes - may the new controller is the old one.
1463 if (
1464 (xOldController.is() ) &&
1465 (xOldController != xController)
1468 /* ATTENTION
1469 Don't suspend the old controller here. Because the outside caller must do that
1470 by definition. We have to dispose it here only.
1473 // Before we dispose this controller we should hide it inside this frame instance.
1474 // We hold it alive for next calls by using xOldController!
1475 /* SAFE {*/
1477 SolarMutexGuard aWriteLock;
1478 m_xController = nullptr;
1480 if (m_xDispatchHelper)
1482 rtl::Reference<DispatchProvider> pDispatchProvider = m_xDispatchHelper->GetSlave();
1483 if (pDispatchProvider)
1485 pDispatchProvider->ClearProtocolHandlers();
1489 /* } SAFE */
1491 if (xOldController.is())
1495 xOldController->dispose();
1497 catch(const css::lang::DisposedException&)
1500 xOldController = nullptr;
1503 // Now it's time to release the component window.
1504 // If controller wasn't released successfully - this code line shouldn't be reached.
1505 // Because in case of "suspend()==false" we return immediately with false ...
1506 // see before
1507 // Check for real changes too.
1508 if (
1509 (xOldComponentWindow.is() ) &&
1510 (xOldComponentWindow != xComponentWindow)
1513 /* SAFE { */
1515 SolarMutexGuard aWriteLock;
1516 m_xComponentWindow = nullptr;
1518 /* } SAFE */
1520 if (xOldComponentWindow.is())
1524 xOldComponentWindow->dispose();
1526 catch(const css::lang::DisposedException&)
1530 xOldComponentWindow = nullptr;
1533 // Now it's time to set the new component ...
1534 // By the way - find out our new "load state" - means if we have a valid component inside.
1535 /* SAFE { */
1536 SolarMutexResettableGuard aWriteLock;
1537 m_xComponentWindow = xComponentWindow;
1538 m_xController = xController;
1540 // Clear the URL on the frame itself, now that the controller has it.
1541 m_aURL.clear();
1543 m_bConnected = (m_xComponentWindow.is() || m_xController.is());
1544 bool bIsConnected = m_bConnected;
1545 aWriteLock.clear();
1546 /* } SAFE */
1548 // notifies all interest listener, that current component was changed or a new one was loaded
1549 if (bIsConnected && bWasConnected)
1550 implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_REATTACHED );
1551 else if (bIsConnected && !bWasConnected)
1552 implts_sendFrameActionEvent( css::frame::FrameAction_COMPONENT_ATTACHED );
1554 // A new component window doesn't know anything about current active/focus states.
1555 // Set this information on it!
1556 if ( bHadFocus && xComponentWindow.is() )
1558 xComponentWindow->setFocus();
1561 // If it was a new component window - we must resize it to fill out
1562 // our container window.
1563 implts_resizeComponentWindow();
1564 // New component should change our current icon ...
1565 implts_setIconOnWindow();
1566 // OK - start listening on new window again - or do nothing if it is an empty one.
1567 implts_startWindowListening();
1569 /* SAFE { */
1570 aWriteLock.reset();
1571 impl_checkMenuCloser();
1572 aWriteLock.clear();
1573 /* } SAFE */
1575 return true;
1578 /*-****************************************************************************************************
1579 @short returns current set component window
1580 @descr Frames are used to display components. The actual displayed component is
1581 held by the m_xComponentWindow property. If the component implements only a
1582 XComponent interface, the communication between the frame and the
1583 component is very restricted. Better integration is achievable through a
1584 XController interface.
1585 If the component wants other objects to be able to get information about its
1586 ResourceDescriptor it has to implement a XModel interface.
1587 This frame is the owner of the component window.
1589 @seealso method setComponent()
1590 @return css::uno::Reference to current set component window.
1592 @onerror A null reference is returned.
1593 *//*-*****************************************************************************************************/
1594 css::uno::Reference< css::awt::XWindow > SAL_CALL XFrameImpl::getComponentWindow()
1596 checkDisposed();
1597 SolarMutexGuard g;
1598 return m_xComponentWindow;
1601 /*-****************************************************************************************************
1602 @short returns current set controller
1603 @descr Frames are used to display components. The actual displayed component is
1604 held by the m_xComponentWindow property. If the component implements only a
1605 XComponent interface, the communication between the frame and the
1606 component is very restricted. Better integration is achievable through a
1607 XController interface.
1608 If the component wants other objects to be able to get information about its
1609 ResourceDescriptor it has to implement a XModel interface.
1610 This frame is the owner of the component window.
1612 @seealso method setComponent()
1613 @return css::uno::Reference to current set controller.
1615 @onerror A null reference is returned.
1616 *//*-*****************************************************************************************************/
1617 css::uno::Reference< css::frame::XController > SAL_CALL XFrameImpl::getController()
1619 SolarMutexGuard g;
1620 return m_xController;
1623 /*-****************************************************************************************************
1624 @short add/remove listener for activate/deactivate/contextChanged events
1625 @seealso method activate()
1626 @seealso method deactivate()
1627 @seealso method contextChanged()
1629 @param "xListener" reference to your listener object
1630 @onerror Listener is ignored.
1631 *//*-*****************************************************************************************************/
1632 void SAL_CALL XFrameImpl::addFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener )
1634 checkDisposed();
1635 m_aListenerContainer.addInterface( cppu::UnoType<css::frame::XFrameActionListener>::get(), xListener );
1638 void SAL_CALL XFrameImpl::removeFrameActionListener( const css::uno::Reference< css::frame::XFrameActionListener >& xListener )
1640 m_aListenerContainer.removeInterface( cppu::UnoType<css::frame::XFrameActionListener>::get(), xListener );
1643 /*-****************************************************************************************************
1644 @short support two way mechanism to release a frame
1645 @descr This method ask internal component (controller) if he accept this close request.
1646 In case of <TRUE/> nothing will be happen (from point of caller of this close method).
1647 In case of <FALSE/> a CloseVetoException is thrown. After such exception given parameter
1648 <var>bDeliverOwnership</var> regulate which will be the new owner of this instance.
1650 @attention It's the replacement for XTask::close() which is marked as obsolete method.
1652 @param bDeliverOwnership
1653 If parameter is set to <FALSE/> the original caller will be the owner after thrown
1654 veto exception and must try to close this frame at later time again. Otherwise the
1655 source of thrown exception is the right one. May it will be the frame himself.
1657 @throws CloseVetoException
1658 if any internal things will not be closed
1660 @threadsafe yes
1661 *//*-*****************************************************************************************************/
1662 void SAL_CALL XFrameImpl::close( sal_Bool bDeliverOwnership )
1664 checkDisposed();
1666 // At the end of this method may we must dispose ourself...
1667 // and may nobody from outside hold a reference to us...
1668 // then it's a good idea to do that by ourself.
1669 css::uno::Reference< css::uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >(this) );
1671 // Check any close listener before we look for currently running internal processes.
1672 // Because if a listener disagree with this close() request - we have time to finish this
1673 // internal operations too...
1674 // Note: container is threadsafe himself.
1675 css::lang::EventObject aSource (static_cast< ::cppu::OWeakObject*>(this));
1676 comphelper::OInterfaceContainerHelper2* pContainer = m_aListenerContainer.getContainer( cppu::UnoType<css::util::XCloseListener>::get());
1677 if (pContainer!=nullptr)
1679 comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
1680 while (pIterator.hasMoreElements())
1684 static_cast<css::util::XCloseListener*>(pIterator.next())->queryClosing( aSource, bDeliverOwnership );
1686 catch( const css::uno::RuntimeException& )
1688 pIterator.remove();
1693 // Ok - no listener disagreed with this close() request
1694 // check if this frame is used for any load process currently
1695 if (isActionLocked())
1697 if (bDeliverOwnership)
1699 SolarMutexGuard g;
1700 m_bSelfClose = true;
1703 throw css::util::CloseVetoException("Frame in use for loading document...",static_cast< ::cppu::OWeakObject*>(this));
1706 if ( ! setComponent(nullptr,nullptr) )
1707 throw css::util::CloseVetoException("Component couldn't be detached...",static_cast< ::cppu::OWeakObject*>(this));
1709 // If closing is allowed... inform all listeners and dispose this frame!
1710 pContainer = m_aListenerContainer.getContainer( cppu::UnoType<css::util::XCloseListener>::get());
1711 if (pContainer!=nullptr)
1713 comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
1714 while (pIterator.hasMoreElements())
1718 static_cast<css::util::XCloseListener*>(pIterator.next())->notifyClosing( aSource );
1720 catch( const css::uno::RuntimeException& )
1722 pIterator.remove();
1727 /* SAFE { */
1729 SolarMutexGuard aWriteLock;
1730 m_bIsHidden = true;
1732 /* } SAFE */
1733 impl_checkMenuCloser();
1735 dispose();
1738 /*-****************************************************************************************************
1739 @short be a listener for close events!
1740 @descr Adds/remove a CloseListener at this frame instance. If the close() method is called on
1741 this object, the such listener are informed and can disagree with that by throwing
1742 a CloseVetoException.
1744 @seealso XFrameImpl::close()
1746 @param xListener
1747 reference to your listener object
1749 @onerror Listener is ignored.
1751 @threadsafe yes
1752 *//*-*****************************************************************************************************/
1753 void SAL_CALL XFrameImpl::addCloseListener( const css::uno::Reference< css::util::XCloseListener >& xListener )
1755 checkDisposed();
1756 m_aListenerContainer.addInterface( cppu::UnoType<css::util::XCloseListener>::get(), xListener );
1759 void SAL_CALL XFrameImpl::removeCloseListener( const css::uno::Reference< css::util::XCloseListener >& xListener )
1761 m_aListenerContainer.removeInterface( cppu::UnoType<css::util::XCloseListener>::get(), xListener );
1764 OUString SAL_CALL XFrameImpl::getTitle()
1766 checkDisposed();
1768 // SAFE ->
1769 SolarMutexClearableGuard aReadLock;
1770 css::uno::Reference< css::frame::XTitle > xTitle(m_xTitleHelper, css::uno::UNO_SET_THROW);
1771 aReadLock.clear();
1772 // <- SAFE
1774 return xTitle->getTitle();
1777 void SAL_CALL XFrameImpl::setTitle( const OUString& sTitle )
1779 checkDisposed();
1781 // SAFE ->
1782 SolarMutexClearableGuard aReadLock;
1783 css::uno::Reference< css::frame::XTitle > xTitle(m_xTitleHelper, css::uno::UNO_SET_THROW);
1784 aReadLock.clear();
1785 // <- SAFE
1787 xTitle->setTitle(sTitle);
1790 void SAL_CALL XFrameImpl::addTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener)
1792 checkDisposed();
1794 // SAFE ->
1795 SolarMutexClearableGuard aReadLock;
1796 css::uno::Reference< css::frame::XTitleChangeBroadcaster > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW);
1797 aReadLock.clear();
1798 // <- SAFE
1800 xTitle->addTitleChangeListener(xListener);
1803 void SAL_CALL XFrameImpl::removeTitleChangeListener( const css::uno::Reference< css::frame::XTitleChangeListener >& xListener )
1805 checkDisposed();
1807 // SAFE ->
1808 SolarMutexClearableGuard aReadLock;
1809 css::uno::Reference< css::frame::XTitleChangeBroadcaster > xTitle(m_xTitleHelper, css::uno::UNO_QUERY_THROW);
1810 aReadLock.clear();
1811 // <- SAFE
1813 xTitle->removeTitleChangeListener(xListener);
1816 css::uno::Reference<css::container::XNameContainer> SAL_CALL XFrameImpl::getUserDefinedAttributes()
1818 // optional attribute
1819 return nullptr;
1822 css::uno::Reference<css::frame::XDispatchRecorderSupplier> SAL_CALL XFrameImpl::getDispatchRecorderSupplier()
1824 SolarMutexGuard g;
1825 return m_xDispatchRecorderSupplier;
1828 void SAL_CALL XFrameImpl::setDispatchRecorderSupplier(const css::uno::Reference<css::frame::XDispatchRecorderSupplier>& p)
1830 checkDisposed();
1831 SolarMutexGuard g;
1832 m_xDispatchRecorderSupplier.set(p);
1835 css::uno::Reference<css::uno::XInterface> SAL_CALL XFrameImpl::getLayoutManager()
1837 SolarMutexGuard g;
1838 return m_xLayoutManager;
1841 void SAL_CALL XFrameImpl::setLayoutManager(const css::uno::Reference<css::uno::XInterface>& p1)
1843 checkDisposed();
1844 SolarMutexGuard g;
1846 css::uno::Reference<css::frame::XLayoutManager2> xOldLayoutManager = m_xLayoutManager;
1847 css::uno::Reference<css::frame::XLayoutManager2> xNewLayoutManager(p1, css::uno::UNO_QUERY);
1849 if (xOldLayoutManager != xNewLayoutManager)
1851 m_xLayoutManager = xNewLayoutManager;
1852 if (xOldLayoutManager.is())
1853 disableLayoutManager(xOldLayoutManager);
1854 if (xNewLayoutManager.is() && !m_bDocHidden)
1855 lcl_enableLayoutManager(xNewLayoutManager, this);
1859 css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL XFrameImpl::getPropertySetInfo()
1861 checkDisposed();
1862 return css::uno::Reference< css::beans::XPropertySetInfo >(this);
1865 void SAL_CALL XFrameImpl::setPropertyValue(const OUString& sProperty,
1866 const css::uno::Any& aValue )
1868 // TODO look for e.g. readonly props and reject setProp() call!
1870 checkDisposed();
1872 // SAFE ->
1873 SolarMutexGuard g;
1875 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1876 if (pIt == m_lProps.end())
1877 throw css::beans::UnknownPropertyException(sProperty);
1879 css::beans::Property aPropInfo = pIt->second;
1881 css::uno::Any aCurrentValue = impl_getPropertyValue(aPropInfo.Handle);
1883 bool bWillBeChanged = (aCurrentValue != aValue);
1884 if (! bWillBeChanged)
1885 return;
1887 css::beans::PropertyChangeEvent aEvent;
1888 aEvent.PropertyName = aPropInfo.Name;
1889 aEvent.Further = false;
1890 aEvent.PropertyHandle = aPropInfo.Handle;
1891 aEvent.OldValue = aCurrentValue;
1892 aEvent.NewValue = aValue;
1893 aEvent.Source.set(m_xBroadcaster.get(), css::uno::UNO_QUERY);
1895 if (impl_existsVeto(aEvent))
1896 throw css::beans::PropertyVetoException();
1898 impl_setPropertyValue(aPropInfo.Handle, aValue);
1900 impl_notifyChangeListener(aEvent);
1903 css::uno::Any SAL_CALL XFrameImpl::getPropertyValue(const OUString& sProperty)
1905 checkDisposed();
1907 // SAFE ->
1908 SolarMutexGuard aReadLock;
1910 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1911 if (pIt == m_lProps.end())
1912 throw css::beans::UnknownPropertyException(sProperty);
1914 css::beans::Property aPropInfo = pIt->second;
1916 return impl_getPropertyValue(aPropInfo.Handle);
1919 void SAL_CALL XFrameImpl::addPropertyChangeListener(
1920 const OUString& sProperty,
1921 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener)
1923 checkDisposed();
1925 // SAFE ->
1927 SolarMutexGuard aReadLock;
1929 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1930 if (pIt == m_lProps.end())
1931 throw css::beans::UnknownPropertyException(sProperty);
1933 // <- SAFE
1935 m_lSimpleChangeListener.addInterface(sProperty, xListener);
1938 void SAL_CALL XFrameImpl::removePropertyChangeListener(
1939 const OUString& sProperty,
1940 const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener)
1942 // SAFE ->
1944 SolarMutexGuard aReadLock;
1946 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1947 if (pIt == m_lProps.end())
1948 throw css::beans::UnknownPropertyException(sProperty);
1950 // <- SAFE
1952 m_lSimpleChangeListener.removeInterface(sProperty, xListener);
1955 void SAL_CALL XFrameImpl::addVetoableChangeListener(
1956 const OUString& sProperty,
1957 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener)
1959 checkDisposed();
1961 // SAFE ->
1963 SolarMutexGuard aReadLock;
1965 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1966 if (pIt == m_lProps.end())
1967 throw css::beans::UnknownPropertyException(sProperty);
1969 // <- SAFE
1971 m_lVetoChangeListener.addInterface(sProperty, xListener);
1974 void SAL_CALL XFrameImpl::removeVetoableChangeListener(
1975 const OUString& sProperty,
1976 const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener)
1978 // SAFE ->
1980 SolarMutexGuard aReadLock;
1982 TPropInfoHash::const_iterator pIt = m_lProps.find(sProperty);
1983 if (pIt == m_lProps.end())
1984 throw css::beans::UnknownPropertyException(sProperty);
1986 // <- SAFE
1988 m_lVetoChangeListener.removeInterface(sProperty, xListener);
1991 css::uno::Sequence< css::beans::Property > SAL_CALL XFrameImpl::getProperties()
1993 checkDisposed();
1995 SolarMutexGuard g;
1997 sal_Int32 c = static_cast<sal_Int32>(m_lProps.size());
1998 css::uno::Sequence< css::beans::Property > lProps(c);
1999 auto lPropsRange = asNonConstRange(lProps);
2000 for (auto const& elem : m_lProps)
2002 lPropsRange[--c] = elem.second;
2005 return lProps;
2008 css::beans::Property SAL_CALL XFrameImpl::getPropertyByName(const OUString& sName)
2010 checkDisposed();
2012 SolarMutexGuard g;
2014 TPropInfoHash::const_iterator pIt = m_lProps.find(sName);
2015 if (pIt == m_lProps.end())
2016 throw css::beans::UnknownPropertyException(sName);
2018 return pIt->second;
2021 sal_Bool SAL_CALL XFrameImpl::hasPropertyByName(const OUString& sName)
2023 checkDisposed();
2025 SolarMutexGuard g;
2027 TPropInfoHash::iterator pIt = m_lProps.find(sName);
2028 bool bExist = (pIt != m_lProps.end());
2030 return bExist;
2033 /*-****************************************************************************************************/
2034 void XFrameImpl::implts_forgetSubFrames()
2036 // SAFE ->
2037 SolarMutexClearableGuard aReadLock;
2038 css::uno::Reference< css::container::XIndexAccess > xContainer(m_xFramesHelper, css::uno::UNO_QUERY_THROW);
2039 aReadLock.clear();
2040 // <- SAFE
2042 sal_Int32 c = xContainer->getCount();
2043 sal_Int32 i = 0;
2045 for (i=0; i<c; ++i)
2049 css::uno::Reference< css::frame::XFrame > xFrame;
2050 xContainer->getByIndex(i) >>= xFrame;
2051 if (xFrame.is())
2052 xFrame->setCreator(css::uno::Reference< css::frame::XFramesSupplier >());
2054 catch(const css::uno::Exception&)
2056 // Ignore errors here.
2057 // Nobody can guarantee a stable index in multi threaded environments .-)
2061 SolarMutexGuard g;
2062 m_xFramesHelper.clear(); // clear uno reference
2063 m_aChildFrameContainer.clear(); // clear container content
2066 /*-****************************************************************************************************
2067 @short destroy instance
2068 @descr The owner of this object calls the dispose method if the object
2069 should be destroyed. All other objects and components, that are registered
2070 as an EventListener are forced to release their references to this object.
2071 Furthermore this frame is removed from its parent frame container to release
2072 this reference. The reference attributes are disposed and released also.
2074 @attention Look for globale description at beginning of file too!
2075 (DisposedException, FairRWLock ..., initialize, dispose)
2077 @seealso method initialize()
2078 @seealso baseclass FairRWLockBase!
2079 *//*-*****************************************************************************************************/
2080 void SAL_CALL XFrameImpl::disposing()
2082 // We should hold a reference to ourself ...
2083 // because our owner dispose us and release our reference ...
2084 // May be we will die before we could finish this method ...
2085 css::uno::Reference< css::frame::XFrame > xThis(this);
2087 SAL_INFO("fwk.frame", "[Frame] " << m_sName << " send dispose event to listener");
2089 // First operation should be... "stop all listening for window events on our container window".
2090 // These events are superfluous but can make trouble!
2091 // We will die, die and die...
2092 implts_stopWindowListening();
2094 css::uno::Reference<css::frame::XLayoutManager2> layoutMgr;
2096 SolarMutexGuard g;
2097 layoutMgr = m_xLayoutManager;
2099 if (layoutMgr.is()) {
2100 disableLayoutManager(layoutMgr);
2103 std::unique_ptr<WindowCommandDispatch> disp;
2105 SolarMutexGuard g;
2106 std::swap(disp, m_pWindowCommandDispatch);
2108 disp.reset();
2110 // Send message to all listener and forget her references.
2111 css::lang::EventObject aEvent( xThis );
2112 m_aListenerContainer.disposeAndClear( aEvent );
2114 // set "end of live" for our property set helper
2115 impl_disablePropertySet();
2117 // interception/dispatch chain must be destructed explicitly
2118 // Otherwise some dispatches and/or interception objects won't die.
2119 css::uno::Reference< css::lang::XEventListener > xDispatchHelper;
2121 SolarMutexGuard g;
2122 xDispatchHelper = m_xDispatchHelper;
2124 xDispatchHelper->disposing(aEvent);
2125 xDispatchHelper.clear();
2127 // Don't show any dialogs, errors or something else any more!
2128 // If somewhere called dispose() without close() before - normally no dialogs
2129 // should exist. Otherwise it's the problem of the outside caller.
2130 // Note:
2131 // (a) Do it after stopWindowListening(). May that force some active/deactivate
2132 // notifications which we don't need here really.
2133 // (b) Don't forget to save the old value of IsDialogCancelEnabled() to
2134 // restore it afterwards (to not kill headless mode).
2135 DialogCancelMode old = Application::GetDialogCancelMode();
2136 Application::SetDialogCancelMode( DialogCancelMode::Silent );
2138 // We should be alone for ever and further dispose calls are rejected by lines before ...
2139 // I hope it :-)
2141 // Free references of our frame tree.
2142 // Force parent container to forget this frame too ...
2143 // ( It's contained in m_xParent and so no css::lang::XEventListener for m_xParent! )
2144 // It's important to do that before we free some other internal structures.
2145 // Because if our parent gets an activate and found us as last possible active frame
2146 // he try to deactivate us ... and we run into some trouble (DisposedExceptions!).
2147 css::uno::Reference<css::frame::XFramesSupplier> parent;
2149 SolarMutexGuard g;
2150 std::swap(parent, m_xParent);
2152 if( parent.is() )
2154 parent->getFrames()->remove( xThis );
2157 /* } SAFE */
2158 // Forget our internal component and her window first.
2159 // So we can release our container window later without problems.
2160 // Because this container window is the parent of the component window ...
2161 // Note: Dispose it hard - because suspending must be done inside close() call!
2162 // But try to dispose the controller first before you destroy the window.
2163 // Because the window is used by the controller too ...
2164 css::uno::Reference< css::lang::XComponent > xDisposableCtrl;
2165 css::uno::Reference< css::lang::XComponent > xDisposableComp;
2167 SolarMutexGuard g;
2168 xDisposableCtrl = m_xController;
2169 xDisposableComp = m_xComponentWindow;
2171 if (xDisposableCtrl.is())
2172 xDisposableCtrl->dispose();
2173 if (xDisposableComp.is())
2174 xDisposableComp->dispose();
2176 impl_checkMenuCloser();
2178 css::uno::Reference<css::awt::XWindow> contWin;
2180 SolarMutexGuard g;
2181 std::swap(contWin, m_xContainerWindow);
2183 if( contWin.is() )
2185 contWin->setVisible( false );
2186 // All VclComponents are XComponents; so call dispose before discarding
2187 // a css::uno::Reference< XVclComponent >, because this frame is the owner of the window
2188 contWin->dispose();
2191 /*ATTENTION
2192 Clear container after successful removing from parent container ...
2193 because our parent could be the desktop which stand in dispose too!
2194 If we have already cleared our own container we lost our child before this could be
2195 remove himself at this instance ...
2196 Release m_xFramesHelper after that ... it's the same problem between parent and child!
2197 "m_xParent->getFrames()->remove( xThis );" needs this helper ...
2198 Otherwise we get a null reference and could finish removing successfully.
2199 => You see: Order of calling operations is important!!!
2201 implts_forgetSubFrames();
2204 SolarMutexGuard g;
2206 // Release some other references.
2207 // This calls should be easy ... I hope it :-)
2208 m_xDispatchHelper.clear();
2209 m_xDropTargetListener.clear();
2210 m_xDispatchRecorderSupplier.clear();
2211 m_xLayoutManager.clear();
2212 m_xIndicatorFactoryHelper.clear();
2214 // It's important to set default values here!
2215 // If may be later somewhere change the disposed-behaviour of this implementation
2216 // and doesn't throw any DisposedExceptions we must guarantee best matching default values ...
2217 m_eActiveState = E_INACTIVE;
2218 m_sName.clear();
2219 m_bIsFrameTop = false;
2220 m_bConnected = false;
2221 m_nExternalLockCount = 0;
2222 m_bSelfClose = false;
2223 m_bIsHidden = true;
2226 // Don't forget it restore old value -
2227 // otherwise no dialogs can be shown anymore in other frames.
2228 Application::SetDialogCancelMode( old );
2231 /*-****************************************************************************************************
2232 @short Be a listener for dispose events!
2233 @descr Adds/remove an EventListener to this object. If the dispose method is called on
2234 this object, the disposing method of the listener is called.
2235 @param "xListener" reference to your listener object.
2236 @onerror Listener is ignored.
2237 *//*-*****************************************************************************************************/
2238 void SAL_CALL XFrameImpl::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
2240 checkDisposed();
2241 m_aListenerContainer.addInterface( cppu::UnoType<css::lang::XEventListener>::get(), xListener );
2244 void SAL_CALL XFrameImpl::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener )
2246 m_aListenerContainer.removeInterface( cppu::UnoType<css::lang::XEventListener>::get(), xListener );
2249 /*-****************************************************************************************************
2250 @short create new status indicator
2251 @descr Use returned status indicator to show progresses and some text information.
2252 All created objects share the same dialog! Only the last one can show his information.
2254 @seealso class StatusIndicatorFactory
2255 @seealso class StatusIndicator
2256 @return A reference to created object.
2258 @onerror We return a null reference.
2259 *//*-*****************************************************************************************************/
2260 css::uno::Reference< css::task::XStatusIndicator > SAL_CALL XFrameImpl::createStatusIndicator()
2262 checkDisposed();
2264 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2265 SolarMutexClearableGuard aReadLock;
2267 // Make snapshot of necessary member and define default return value.
2268 css::uno::Reference< css::task::XStatusIndicator > xExternal(m_xIndicatorInterception.get(), css::uno::UNO_QUERY);
2269 css::uno::Reference< css::task::XStatusIndicatorFactory > xFactory = m_xIndicatorFactoryHelper;
2271 aReadLock.clear();
2272 /* UNSAFE AREA ----------------------------------------------------------------------------------------- */
2274 // Was set from outside to intercept any progress activities!
2275 if (xExternal.is())
2276 return xExternal;
2278 // Or use our own factory as fallback, to create such progress.
2279 if (xFactory.is())
2280 return xFactory->createStatusIndicator();
2282 return css::uno::Reference< css::task::XStatusIndicator >();
2285 /*-****************************************************************************************************
2286 @short search for target to load URL
2287 @descr This method searches for a dispatch for the specified DispatchDescriptor.
2288 The FrameSearchFlags and the FrameName of the DispatchDescriptor are
2289 treated as described for findFrame.
2291 @seealso method findFrame()
2292 @seealso method queryDispatches()
2293 @seealso method set/getName()
2294 @seealso class TargetFinder
2296 @param "aURL" , URL for loading
2297 @param "sTargetFrameName" , name of target frame
2298 @param "nSearchFlags" , additional flags to regulate search if sTargetFrameName is not clear
2299 @return css::uno::Reference to dispatch handler.
2301 @onerror A null reference is returned.
2302 *//*-*****************************************************************************************************/
2303 css::uno::Reference< css::frame::XDispatch > SAL_CALL XFrameImpl::queryDispatch( const css::util::URL& aURL,
2304 const OUString& sTargetFrameName,
2305 sal_Int32 nSearchFlags)
2307 // 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!
2309 checkDisposed();
2311 // Remove uno and cmd protocol part as we want to support both of them. We store only the command part
2312 // in our hash map. All other protocols are stored with the protocol part.
2313 OUString aCommand( aURL.Main );
2314 if ( aURL.Protocol.equalsIgnoreAsciiCase(".uno:") )
2315 aCommand = aURL.Path;
2317 // Make std::unordered_map lookup if the current URL is in the disabled list
2318 if ( m_aCommandOptions.LookupDisabled( aCommand ) )
2319 return css::uno::Reference< css::frame::XDispatch >();
2320 else
2322 // We use a helper to support these interface and an interceptor mechanism.
2323 css::uno::Reference<css::frame::XDispatchProvider> disp;
2325 SolarMutexGuard g;
2326 disp = m_xDispatchHelper;
2328 if (!disp.is()) {
2329 throw css::lang::DisposedException("Frame disposed");
2331 return disp->queryDispatch( aURL, sTargetFrameName, nSearchFlags );
2335 /*-****************************************************************************************************
2336 @short handle more than ones dispatches at same call
2337 @descr Returns a sequence of dispatches. For details see the queryDispatch method.
2338 For failed dispatches we return empty items in list!
2340 @seealso method queryDispatch()
2342 @param "lDescriptor" list of dispatch arguments for queryDispatch()!
2343 @return List of dispatch references. Some elements can be NULL!
2345 @onerror An empty list is returned.
2346 *//*-*****************************************************************************************************/
2347 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL XFrameImpl::queryDispatches(
2348 const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
2350 // 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!
2352 checkDisposed();
2354 // We use a helper to support these interface and an interceptor mechanism.
2355 css::uno::Reference<css::frame::XDispatchProvider> disp;
2357 SolarMutexGuard g;
2358 disp = m_xDispatchHelper;
2360 if (!disp.is()) {
2361 throw css::lang::DisposedException("Frame disposed");
2363 return disp->queryDispatches( lDescriptor );
2366 /*-****************************************************************************************************
2367 @short register/unregister interceptor for dispatch calls
2368 @descr If you wish to handle some dispatches by himself ... you should be
2369 an interceptor for it. Please see class OInterceptionHelper for further information.
2371 @seealso class OInterceptionHelper
2373 @param "xInterceptor", reference to your interceptor implementation.
2374 @onerror Interceptor is ignored.
2375 *//*-*****************************************************************************************************/
2376 void SAL_CALL XFrameImpl::registerDispatchProviderInterceptor(
2377 const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor )
2379 // We use a helper to support these interface and an interceptor mechanism.
2380 // This helper is threadsafe himself and check incoming parameter too.
2381 // I think we don't need any lock here!
2383 checkDisposed();
2385 css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper;
2387 SolarMutexGuard g;
2388 xInterceptionHelper = m_xDispatchHelper;
2390 if (xInterceptionHelper.is()) {
2391 xInterceptionHelper->registerDispatchProviderInterceptor( xInterceptor );
2395 void SAL_CALL XFrameImpl::releaseDispatchProviderInterceptor(
2396 const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor )
2398 // We use a helper to support these interface and an interceptor mechanism.
2399 // This helper is threadsafe himself and check incoming parameter too.
2400 // I think we don't need any lock here!
2402 // Sometimes we are called during our dispose() method
2404 css::uno::Reference< css::frame::XDispatchProviderInterception > xInterceptionHelper;
2406 SolarMutexGuard g;
2407 xInterceptionHelper = m_xDispatchHelper;
2409 if (xInterceptionHelper.is()) {
2410 xInterceptionHelper->releaseDispatchProviderInterceptor( xInterceptor );
2414 /*-****************************************************************************************************
2415 @short provides information about all possible dispatch functions
2416 inside the current frame environment
2417 *//*-*****************************************************************************************************/
2418 css::uno::Sequence< sal_Int16 > SAL_CALL XFrameImpl::getSupportedCommandGroups()
2420 return m_xDispatchInfoHelper->getSupportedCommandGroups();
2423 css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL XFrameImpl::getConfigurableDispatchInformation(
2424 sal_Int16 nCommandGroup)
2426 return m_xDispatchInfoHelper->getConfigurableDispatchInformation(nCommandGroup);
2429 /*-****************************************************************************************************
2430 @short notifications for window events
2431 @descr We are a listener on our container window to forward it to our component window.
2433 @seealso method setComponent()
2434 @seealso member m_xContainerWindow
2435 @seealso member m_xComponentWindow
2437 @param "aEvent" describe source of detected event
2438 *//*-*****************************************************************************************************/
2439 void SAL_CALL XFrameImpl::windowResized( const css::awt::WindowEvent& )
2441 // Part of dispose-mechanism
2443 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2444 // Impl-method is threadsafe!
2445 // If we have a current component window - we must resize it!
2446 implts_resizeComponentWindow();
2449 void SAL_CALL XFrameImpl::focusGained( const css::awt::FocusEvent& )
2451 // Part of dispose() mechanism
2453 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2454 SolarMutexClearableGuard aReadLock;
2455 // Make snapshot of member!
2456 css::uno::Reference< css::awt::XWindow > xComponentWindow = m_xComponentWindow;
2457 aReadLock.clear();
2458 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
2460 if( xComponentWindow.is() )
2462 xComponentWindow->setFocus();
2466 /*-****************************************************************************************************
2467 @short notifications for window events
2468 @descr We are a listener on our container window to forward it to our component window ...
2469 but a XTopWindowListener we are only if we are a top frame!
2471 @seealso method setComponent()
2472 @seealso member m_xContainerWindow
2473 @seealso member m_xComponentWindow
2475 @param "aEvent" describe source of detected event
2476 *//*-*****************************************************************************************************/
2477 void SAL_CALL XFrameImpl::windowActivated( const css::lang::EventObject& )
2479 checkDisposed();
2481 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2482 SolarMutexClearableGuard aReadLock;
2483 // Make snapshot of member!
2484 EActiveState eState = m_eActiveState;
2485 aReadLock.clear();
2486 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
2487 // Activate the new active path from here to top.
2488 if( eState == E_INACTIVE )
2490 setActiveFrame( css::uno::Reference< css::frame::XFrame >() );
2491 activate();
2495 void SAL_CALL XFrameImpl::windowDeactivated( const css::lang::EventObject& )
2497 // Sometimes called during dispose()
2499 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2500 SolarMutexClearableGuard aReadLock;
2502 css::uno::Reference< css::frame::XFrame > xParent = m_xParent;
2503 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
2504 EActiveState eActiveState = m_eActiveState;
2506 aReadLock.clear();
2508 if( eActiveState == E_INACTIVE )
2509 return;
2511 // Deactivation is always done implicitly by activation of another frame.
2512 // Only if no activation is done, deactivations have to be processed if the activated window
2513 // is a parent window of the last active Window!
2514 SolarMutexClearableGuard aSolarGuard;
2515 vcl::Window* pFocusWindow = Application::GetFocusWindow();
2516 if ( !xContainerWindow.is() || !xParent.is() ||
2517 css::uno::Reference< css::frame::XDesktop >( xParent, css::uno::UNO_QUERY ).is()
2519 return;
2521 css::uno::Reference< css::awt::XWindow > xParentWindow = xParent->getContainerWindow();
2522 VclPtr<vcl::Window> pParentWindow = VCLUnoHelper::GetWindow( xParentWindow );
2523 //#i70261#: dialogs opened from an OLE object will cause a deactivate on the frame of the OLE object
2524 // on Solaris/Linux at that time pFocusWindow is still NULL because the focus handling is different; right after
2525 // the deactivation the focus will be set into the dialog!
2526 // currently I see no case where a sub frame could get a deactivate with pFocusWindow being NULL permanently
2527 // so for now this case is omitted from handled deactivations
2528 if( pFocusWindow && pParentWindow->IsChild( pFocusWindow ) )
2530 css::uno::Reference< css::frame::XFramesSupplier > xSupplier( xParent, css::uno::UNO_QUERY );
2531 if( xSupplier.is() )
2533 aSolarGuard.clear();
2534 xSupplier->setActiveFrame( css::uno::Reference< css::frame::XFrame >() );
2539 void SAL_CALL XFrameImpl::windowClosing( const css::lang::EventObject& )
2541 checkDisposed();
2543 // deactivate this frame ...
2544 deactivate();
2546 // ... and try to close it
2547 // But do it asynchronous inside the main thread.
2548 // VCL has no fun to do such things outside his main thread :-(
2549 // Note: The used dispatch make it asynchronous for us .-)
2551 /*ATTENTION!
2552 Don't try to suspend the controller here! Because it's done inside used dispatch().
2553 Otherwise the dialog "would you save your changes?" will be shown more than once ...
2556 css::util::URL aURL;
2557 aURL.Complete = ".uno:CloseFrame";
2558 css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
2559 xParser->parseStrict(aURL);
2561 css::uno::Reference< css::frame::XDispatch > xCloser = queryDispatch(aURL, SPECIALTARGET_SELF, 0);
2562 if (xCloser.is())
2563 xCloser->dispatch(aURL, css::uno::Sequence< css::beans::PropertyValue >());
2565 // Attention: If this dispatch works synchronous ... and fulfill its job ...
2566 // this line of code will never be reached ...
2567 // Or if it will be reached it will be for sure that all your member are gone .-)
2570 /*-****************************************************************************************************
2571 @short react for a show event for the internal container window
2572 @descr Normally we don't need this information really. But we can use it to
2573 implement the special feature "trigger first visible task".
2575 Algorithm: - first we have to check if we are a top (task) frame
2576 It's not enough to be a top frame! Because we MUST have the desktop as parent.
2577 But frames without a parent are top too. So it's not possible to check isTop() here!
2578 We have to look for the type of our parent.
2579 - if we are a task frame, then we have to check if we are the first one.
2580 We use a static variable to do so. They will be reset to afterwards be sure
2581 that further calls of this method doesn't do anything then.
2582 - Then we have to trigger the right event string on the global job executor.
2584 @seealso css::task::JobExecutor
2586 @param aEvent
2587 describes the source of this event
2588 We are not interested on this information. We are interested on the visible state only.
2590 @threadsafe yes
2591 *//*-*****************************************************************************************************/
2592 void SAL_CALL XFrameImpl::windowShown( const css::lang::EventObject& )
2594 static std::mutex aFirstVisibleLock;
2596 /* SAFE { */
2597 SolarMutexClearableGuard aReadLock;
2598 css::uno::Reference< css::frame::XDesktop > xDesktopCheck( m_xParent, css::uno::UNO_QUERY );
2599 m_bIsHidden = false;
2600 aReadLock.clear();
2601 /* } SAFE */
2603 impl_checkMenuCloser();
2605 if (!xDesktopCheck.is())
2606 return;
2608 static bool bFirstVisibleTask = true;
2609 std::unique_lock aGuard(aFirstVisibleLock);
2610 bool bMustBeTriggered = bFirstVisibleTask;
2611 bFirstVisibleTask = false;
2612 aGuard.unlock();
2614 if (bMustBeTriggered)
2616 css::uno::Reference< css::task::XJobExecutor > xExecutor
2617 = css::task::theJobExecutor::get( m_xContext );
2618 xExecutor->trigger( "onFirstVisibleTask" );
2622 void SAL_CALL XFrameImpl::windowHidden( const css::lang::EventObject& )
2624 /* SAFE { */
2626 SolarMutexGuard aReadLock;
2627 m_bIsHidden = true;
2629 /* } SAFE */
2631 impl_checkMenuCloser();
2634 /*-****************************************************************************************************
2635 @short called by dispose of our windows!
2636 @descr This object is forced to release all references to the interfaces given
2637 by the parameter source. We are a listener at our container window and
2638 should listen for his disposing.
2640 @seealso XWindowListener
2641 @seealso XTopWindowListener
2642 @seealso XFocusListener
2643 *//*-*****************************************************************************************************/
2644 void SAL_CALL XFrameImpl::disposing( const css::lang::EventObject& aEvent )
2646 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2647 SolarMutexResettableGuard aWriteLock;
2649 if( aEvent.Source == m_xContainerWindow )
2651 // NECESSARY: Impl-method is threadsafe by himself!
2652 aWriteLock.clear();
2653 implts_stopWindowListening();
2654 aWriteLock.reset();
2655 m_xContainerWindow.clear();
2659 /*-************************************************************************************************************
2660 @interface com.sun.star.document.XActionLockable
2661 @short implement locking of frame/task from outside
2662 @descr Sometimes we have problems to decide if closing of task is allowed. Because; frame/task
2663 could be used for pending loading jobs. So you can lock this object from outside and
2664 prevent instance against closing during using! But - don't do it in a wrong or expensive manner.
2665 Otherwise task couldn't die anymore!!!
2667 @seealso interface XActionLockable
2668 @seealso method BaseDispatcher::implts_loadIt()
2669 @seealso method Desktop::loadComponentFromURL()
2670 @return true if frame/task is locked
2671 false otherwise
2672 @threadsafe yes
2673 *//*-*************************************************************************************************************/
2674 sal_Bool SAL_CALL XFrameImpl::isActionLocked()
2676 SolarMutexGuard g;
2677 return( m_nExternalLockCount!=0);
2680 void SAL_CALL XFrameImpl::addActionLock()
2682 SolarMutexGuard g;
2683 ++m_nExternalLockCount;
2686 void SAL_CALL XFrameImpl::removeActionLock()
2689 SolarMutexGuard g;
2690 SAL_WARN_IF( m_nExternalLockCount<=0, "fwk.frame", "XFrameImpl::removeActionLock(): Frame is not locked! "
2691 "Possible multithreading problem detected." );
2692 --m_nExternalLockCount;
2695 implts_checkSuicide();
2698 void SAL_CALL XFrameImpl::setActionLocks( sal_Int16 nLock )
2700 SolarMutexGuard g;
2701 // Attention: If somewhere called resetActionLocks() before and get e.g. 5 locks ...
2702 // and tried to set these 5 ones here after his operations ...
2703 // we can't ignore set requests during these two calls!
2704 // So we must add(!) these 5 locks here.
2705 m_nExternalLockCount = m_nExternalLockCount + nLock;
2708 sal_Int16 SAL_CALL XFrameImpl::resetActionLocks()
2710 sal_Int16 nCurrentLocks = 0;
2712 SolarMutexGuard g;
2713 nCurrentLocks = m_nExternalLockCount;
2714 m_nExternalLockCount = 0;
2717 // Attention:
2718 // external lock count is 0 here every time... but if
2719 // member m_bSelfClose is set to true too... we call our own close()/dispose().
2720 // See close() for further information
2721 implts_checkSuicide();
2723 return nCurrentLocks;
2726 void XFrameImpl::impl_setPropertyValue(sal_Int32 nHandle,
2727 const css::uno::Any& aValue)
2730 /* There is no need to lock any mutex here. Because we share the
2731 solar mutex with our base class. And we said to our base class: "don't release it on calling us" .-)
2734 /* Attention: You can use nHandle only, if you are sure that all supported
2735 properties has a unique handle. That must be guaranteed
2736 inside method initListeners()!
2738 switch (nHandle)
2740 case FRAME_PROPHANDLE_TITLE :
2742 OUString sExternalTitle;
2743 aValue >>= sExternalTitle;
2744 setTitle (sExternalTitle);
2746 break;
2748 case FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER :
2749 aValue >>= m_xDispatchRecorderSupplier;
2750 break;
2752 case FRAME_PROPHANDLE_LAYOUTMANAGER :
2754 css::uno::Reference< css::frame::XLayoutManager2 > xOldLayoutManager = m_xLayoutManager;
2755 css::uno::Reference< css::frame::XLayoutManager2 > xNewLayoutManager;
2756 aValue >>= xNewLayoutManager;
2758 if (xOldLayoutManager != xNewLayoutManager)
2760 m_xLayoutManager = xNewLayoutManager;
2761 if (xOldLayoutManager.is())
2762 disableLayoutManager(xOldLayoutManager);
2763 if (xNewLayoutManager.is() && !m_bDocHidden)
2764 lcl_enableLayoutManager(xNewLayoutManager, this);
2767 break;
2769 case FRAME_PROPHANDLE_INDICATORINTERCEPTION :
2771 css::uno::Reference< css::task::XStatusIndicator > xProgress;
2772 aValue >>= xProgress;
2773 m_xIndicatorInterception = xProgress;
2775 break;
2777 case FRAME_PROPHANDLE_URL:
2779 aValue >>= m_aURL;
2781 break;
2782 default :
2783 SAL_INFO("fwk.frame", "XFrameImpl::setFastPropertyValue_NoBroadcast(): Invalid handle detected!" );
2784 break;
2788 css::uno::Any XFrameImpl::impl_getPropertyValue(sal_Int32 nHandle)
2790 /* There is no need to lock any mutex here. Because we share the
2791 solar mutex with our base class. And we said to our base class: "don't release it on calling us" .-)
2794 /* Attention: You can use nHandle only, if you are sure that all supported
2795 properties has a unique handle. That must be guaranteed
2796 inside method initListeners()!
2798 css::uno::Any aValue;
2799 switch (nHandle)
2801 case FRAME_PROPHANDLE_TITLE :
2802 aValue <<= getTitle ();
2803 break;
2805 case FRAME_PROPHANDLE_DISPATCHRECORDERSUPPLIER :
2806 aValue <<= m_xDispatchRecorderSupplier;
2807 break;
2809 case FRAME_PROPHANDLE_ISHIDDEN :
2810 aValue <<= m_bIsHidden;
2811 break;
2813 case FRAME_PROPHANDLE_LAYOUTMANAGER :
2814 aValue <<= m_xLayoutManager;
2815 break;
2817 case FRAME_PROPHANDLE_INDICATORINTERCEPTION :
2819 css::uno::Reference< css::task::XStatusIndicator > xProgress(m_xIndicatorInterception.get(),
2820 css::uno::UNO_QUERY);
2821 aValue <<= xProgress;
2823 break;
2825 case FRAME_PROPHANDLE_URL:
2827 aValue <<= m_aURL;
2829 break;
2830 default :
2831 SAL_INFO("fwk.frame", "XFrameImpl::getFastPropertyValue(): Invalid handle detected!" );
2832 break;
2835 return aValue;
2838 void XFrameImpl::impl_setPropertyChangeBroadcaster(const css::uno::Reference< css::uno::XInterface >& xBroadcaster)
2840 SolarMutexGuard g;
2841 m_xBroadcaster = xBroadcaster;
2844 void XFrameImpl::impl_addPropertyInfo(const css::beans::Property& aProperty)
2846 SolarMutexGuard g;
2848 TPropInfoHash::const_iterator pIt = m_lProps.find(aProperty.Name);
2849 if (pIt != m_lProps.end())
2850 throw css::beans::PropertyExistException();
2852 m_lProps[aProperty.Name] = aProperty;
2855 void XFrameImpl::impl_disablePropertySet()
2857 SolarMutexGuard g;
2859 css::uno::Reference< css::uno::XInterface > xThis(static_cast< css::beans::XPropertySet* >(this), css::uno::UNO_QUERY);
2860 css::lang::EventObject aEvent(xThis);
2862 m_lSimpleChangeListener.disposeAndClear(aEvent);
2863 m_lVetoChangeListener.disposeAndClear(aEvent);
2864 m_lProps.clear();
2867 bool XFrameImpl::impl_existsVeto(const css::beans::PropertyChangeEvent& aEvent)
2869 /* Don't use the lock here!
2870 The used helper is threadsafe and it lives for the whole lifetime of
2871 our own object.
2873 ::comphelper::OInterfaceContainerHelper3<css::beans::XVetoableChangeListener>* pVetoListener = m_lVetoChangeListener.getContainer(aEvent.PropertyName);
2874 if (! pVetoListener)
2875 return false;
2877 ::comphelper::OInterfaceIteratorHelper3 pListener(*pVetoListener);
2878 while (pListener.hasMoreElements())
2882 pListener.next()->vetoableChange(aEvent);
2884 catch(const css::uno::RuntimeException&)
2885 { pListener.remove(); }
2886 catch(const css::beans::PropertyVetoException&)
2887 { return true; }
2890 return false;
2893 void XFrameImpl::impl_notifyChangeListener(const css::beans::PropertyChangeEvent& aEvent)
2895 /* Don't use the lock here!
2896 The used helper is threadsafe and it lives for the whole lifetime of
2897 our own object.
2899 ::comphelper::OInterfaceContainerHelper3<css::beans::XPropertyChangeListener>* pSimpleListener = m_lSimpleChangeListener.getContainer(aEvent.PropertyName);
2900 if (! pSimpleListener)
2901 return;
2903 ::comphelper::OInterfaceIteratorHelper3 pListener(*pSimpleListener);
2904 while (pListener.hasMoreElements())
2908 pListener.next()->propertyChange(aEvent);
2910 catch(const css::uno::RuntimeException&)
2911 { pListener.remove(); }
2915 /*-****************************************************************************************************
2916 @short send frame action event to our listener
2917 @descr This method is threadsafe AND can be called by our dispose method too!
2918 @param "aAction", describe the event for sending
2919 *//*-*****************************************************************************************************/
2920 void XFrameImpl::implts_sendFrameActionEvent( const css::frame::FrameAction& aAction )
2922 // Sometimes used by dispose()
2924 // Log information about order of events to file!
2925 // (only activated in debug version!)
2926 SAL_INFO( "fwk.frame",
2927 "[Frame] " << m_sName << " send event " <<
2928 (aAction == css::frame::FrameAction_COMPONENT_ATTACHED ? OUString("COMPONENT ATTACHED") :
2929 (aAction == css::frame::FrameAction_COMPONENT_DETACHING ? OUString("COMPONENT DETACHING") :
2930 (aAction == css::frame::FrameAction_COMPONENT_REATTACHED ? OUString("COMPONENT REATTACHED") :
2931 (aAction == css::frame::FrameAction_FRAME_ACTIVATED ? OUString("FRAME ACTIVATED") :
2932 (aAction == css::frame::FrameAction_FRAME_DEACTIVATING ? OUString("FRAME DEACTIVATING") :
2933 (aAction == css::frame::FrameAction_CONTEXT_CHANGED ? OUString("CONTEXT CHANGED") :
2934 (aAction == css::frame::FrameAction_FRAME_UI_ACTIVATED ? OUString("FRAME UI ACTIVATED") :
2935 (aAction == css::frame::FrameAction_FRAME_UI_DEACTIVATING ? OUString("FRAME UI DEACTIVATING") :
2936 (aAction == css::frame::FrameAction::FrameAction_MAKE_FIXED_SIZE ? OUString("MAKE_FIXED_SIZE") :
2937 OUString("*invalid*")))))))))));
2939 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2940 // Send css::frame::FrameAction event to all listener.
2941 // Get container for right listener.
2942 // FOLLOW LINES ARE THREADSAFE!!!
2943 // ( OInterfaceContainerHelper2 is synchronized with m_aListenerContainer! )
2944 comphelper::OInterfaceContainerHelper2* pContainer = m_aListenerContainer.getContainer(
2945 cppu::UnoType<css::frame::XFrameActionListener>::get());
2947 if( pContainer == nullptr )
2948 return;
2950 // Build action event.
2951 css::frame::FrameActionEvent aFrameActionEvent( static_cast< ::cppu::OWeakObject* >(this), this, aAction );
2953 // Get iterator for access to listener.
2954 comphelper::OInterfaceIteratorHelper2 aIterator( *pContainer );
2955 // Send message to all listener.
2956 while( aIterator.hasMoreElements() )
2960 static_cast<css::frame::XFrameActionListener*>(aIterator.next())->frameAction( aFrameActionEvent );
2962 catch( const css::uno::RuntimeException& )
2964 aIterator.remove();
2969 /*-****************************************************************************************************
2970 @short helper to resize our component window
2971 @descr A frame contains 2 windows - a container ~ and a component window.
2972 This method resize inner component window to full size of outer container window.
2973 This method is threadsafe AND can be called by our dispose method too!
2974 *//*-*****************************************************************************************************/
2975 void XFrameImpl::implts_resizeComponentWindow()
2977 // usually the LayoutManager does the resizing
2978 // in case there is no LayoutManager resizing has to be done here
2979 if ( m_xLayoutManager.is() )
2980 return;
2982 css::uno::Reference< css::awt::XWindow > xComponentWindow( getComponentWindow() );
2983 if( !xComponentWindow.is() )
2984 return;
2986 css::uno::Reference< css::awt::XDevice > xDevice( getContainerWindow(), css::uno::UNO_QUERY );
2988 // Convert relative size to output size.
2989 css::awt::Rectangle aRectangle = getContainerWindow()->getPosSize();
2990 css::awt::DeviceInfo aInfo = xDevice->getInfo();
2991 css::awt::Size aSize( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset,
2992 aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
2994 // Resize our component window.
2995 xComponentWindow->setPosSize( 0, 0, aSize.Width, aSize.Height, css::awt::PosSize::POSSIZE );
2998 /*-****************************************************************************************************
2999 @short helper to set icon on our container window (if it is a system window!)
3000 @descr We use our internal set controller (if it exist) to specify which factory he represented.
3001 This information can be used to find right icon. But our controller can say it us directly
3002 too ... we should ask his optional property set first ...
3004 @seealso method Window::SetIcon()
3005 @onerror We do nothing.
3006 *//*-*****************************************************************************************************/
3007 void XFrameImpl::implts_setIconOnWindow()
3009 checkDisposed();
3011 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3012 // Make snapshot of necessary members and release lock.
3013 SolarMutexClearableGuard aReadLock;
3014 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
3015 css::uno::Reference< css::frame::XController > xController = m_xController;
3016 aReadLock.clear();
3017 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
3019 if( !(xContainerWindow.is() && xController.is()) )
3020 return;
3023 // a) set default value to an invalid one. So we can start further searches for right icon id, if
3024 // first steps failed!
3025 // We must reset it to any fallback value - if no search step returns a valid result.
3026 sal_Int32 nIcon = -1;
3028 // b) try to find information on controller propertyset directly
3029 // Don't forget to catch possible exceptions - because these property is an optional one!
3030 css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY );
3031 if( xSet.is() )
3035 css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(),
3036 css::uno::UNO_SET_THROW );
3037 if ( xPSI->hasPropertyByName( "IconId" ) )
3038 xSet->getPropertyValue( "IconId" ) >>= nIcon;
3040 catch( css::uno::Exception& )
3042 DBG_UNHANDLED_EXCEPTION("fwk");
3046 // c) if b) failed... analyze argument list of currently loaded document inside the frame to find the filter.
3047 // He can be used to detect right factory - and these can be used to match factory to icon...
3048 if( nIcon == -1 )
3050 css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
3051 if( xModel.is() )
3053 SvtModuleOptions::EFactory eFactory = SvtModuleOptions::ClassifyFactoryByModel(xModel);
3054 if (eFactory != SvtModuleOptions::EFactory::UNKNOWN_FACTORY)
3055 nIcon = SvtModuleOptions().GetFactoryIcon( eFactory );
3059 // d) if all steps failed - use fallback!
3060 if( nIcon == -1 )
3062 nIcon = 0;
3065 // e) set icon on container window now
3066 // Don't forget SolarMutex! We use vcl directly :-(
3067 // Check window pointer for right WorkWindow class too!!!
3068 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3070 SolarMutexGuard aSolarGuard;
3071 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xContainerWindow );
3073 ( pWindow != nullptr ) &&
3074 ( pWindow->GetType() == WindowType::WORKWINDOW )
3077 WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow.get());
3078 pWorkWindow->SetIcon( static_cast<sal_uInt16>(nIcon) );
3081 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
3084 /*-************************************************************************************************************
3085 @short helper to start/stop listening for window events on container window
3086 @descr If we get a new container window, we must set it on internal member ...
3087 and stop listening at old one ... and start listening on new one!
3088 But sometimes (in dispose() call!) it's necessary to stop listening without starting
3089 on new connections. So we split this functionality to make it easier at use.
3091 @seealso method initialize()
3092 @seealso method dispose()
3093 @onerror We do nothing!
3094 @threadsafe yes
3095 *//*-*************************************************************************************************************/
3096 void XFrameImpl::implts_startWindowListening()
3098 checkDisposed();
3100 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3101 // Make snapshot of necessary member!
3102 SolarMutexClearableGuard aReadLock;
3103 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
3104 css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > xDragDropListener = m_xDropTargetListener;
3105 css::uno::Reference< css::awt::XWindowListener > xWindowListener(this);
3106 css::uno::Reference< css::awt::XFocusListener > xFocusListener(this);
3107 css::uno::Reference< css::awt::XTopWindowListener > xTopWindowListener(this);
3108 aReadLock.clear();
3109 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
3111 if( !xContainerWindow.is() )
3112 return;
3114 xContainerWindow->addWindowListener( xWindowListener);
3115 xContainerWindow->addFocusListener ( xFocusListener );
3117 css::uno::Reference< css::awt::XTopWindow > xTopWindow( xContainerWindow, css::uno::UNO_QUERY );
3118 if( xTopWindow.is() )
3120 xTopWindow->addTopWindowListener( xTopWindowListener );
3122 css::uno::Reference< css::awt::XToolkit2 > xToolkit = css::awt::Toolkit::create( m_xContext );
3123 css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget = xToolkit->getDropTarget( xContainerWindow );
3124 if( xDropTarget.is() )
3126 xDropTarget->addDropTargetListener( xDragDropListener );
3127 xDropTarget->setActive( true );
3132 void XFrameImpl::implts_stopWindowListening()
3134 // Sometimes used by dispose()
3136 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3137 // Make snapshot of necessary member!
3138 SolarMutexClearableGuard aReadLock;
3139 css::uno::Reference< css::awt::XWindow > xContainerWindow = m_xContainerWindow;
3140 css::uno::Reference< css::datatransfer::dnd::XDropTargetListener > xDragDropListener = m_xDropTargetListener;
3141 css::uno::Reference< css::awt::XWindowListener > xWindowListener(this);
3142 css::uno::Reference< css::awt::XFocusListener > xFocusListener(this);
3143 css::uno::Reference< css::awt::XTopWindowListener > xTopWindowListener(this);
3144 aReadLock.clear();
3145 /* UNSAFE AREA --------------------------------------------------------------------------------------------- */
3147 if( !xContainerWindow.is() )
3148 return;
3150 xContainerWindow->removeWindowListener( xWindowListener);
3151 xContainerWindow->removeFocusListener ( xFocusListener );
3153 css::uno::Reference< css::awt::XTopWindow > xTopWindow( xContainerWindow, css::uno::UNO_QUERY );
3154 if( !xTopWindow.is() )
3155 return;
3157 xTopWindow->removeTopWindowListener( xTopWindowListener );
3159 css::uno::Reference< css::awt::XToolkit2 > xToolkit = css::awt::Toolkit::create( m_xContext );
3160 css::uno::Reference< css::datatransfer::dnd::XDropTarget > xDropTarget =
3161 xToolkit->getDropTarget( xContainerWindow );
3162 if( xDropTarget.is() )
3164 xDropTarget->removeDropTargetListener( xDragDropListener );
3165 xDropTarget->setActive( false );
3169 /*-****************************************************************************************************
3170 @short helper to force broken close() request again
3171 @descr If we self disagree with a close() request, and detect that all external locks are gone ...
3172 then we must try to close this frame again.
3174 @seealso XCloseable::close()
3175 @seealso XFrameImpl::close()
3176 @seealso XFrameImpl::removeActionLock()
3177 @seealso XFrameImpl::resetActionLock()
3178 @seealso m_bSelfClose
3179 @seealso m_nExternalLockCount
3181 @threadsafe yes
3182 *//*-*****************************************************************************************************/
3183 void XFrameImpl::implts_checkSuicide()
3185 /* SAFE */
3186 SolarMutexClearableGuard aReadLock;
3187 // in case of lock==0 and safed state of previous close() request m_bSelfClose
3188 // we must force close() again. Because we had disagreed with that before.
3189 bool bSuicide = (m_nExternalLockCount==0 && m_bSelfClose);
3190 m_bSelfClose = false;
3191 aReadLock.clear();
3192 /* } SAFE */
3193 // force close and deliver ownership to source of possible thrown veto exception
3194 // Attention: Because this method is not designed to throw such exception we must suppress
3195 // it for outside code!
3198 if (bSuicide)
3199 close(true);
3201 catch(const css::util::CloseVetoException&)
3203 catch(const css::lang::DisposedException&)
3207 /** little helper to enable/disable the menu closer at the menubar of the given frame.
3209 @param xFrame
3210 we use its layout manager to set/reset a special callback.
3211 Its existence regulate visibility of this closer item.
3213 @param bState
3214 <TRUE/> enable; <FALSE/> disable this state
3217 void XFrameImpl::impl_setCloser( /*IN*/ const css::uno::Reference< css::frame::XFrame2 >& xFrame ,
3218 /*IN*/ bool bState )
3220 // Note: If start module is not installed - no closer has to be shown!
3221 if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::EModule::STARTMODULE))
3222 return;
3226 css::uno::Reference< css::beans::XPropertySet > xFrameProps(xFrame, css::uno::UNO_QUERY_THROW);
3227 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
3228 xFrameProps->getPropertyValue(FRAME_PROPNAME_ASCII_LAYOUTMANAGER) >>= xLayoutManager;
3229 css::uno::Reference< css::beans::XPropertySet > xLayoutProps(xLayoutManager, css::uno::UNO_QUERY_THROW);
3230 xLayoutProps->setPropertyValue(LAYOUTMANAGER_PROPNAME_MENUBARCLOSER, css::uno::Any(bState));
3232 catch(const css::uno::RuntimeException&)
3233 { throw; }
3234 catch(const css::uno::Exception&)
3238 /** it checks, which of the top level task frames must have the special menu closer for
3239 switching to the backing window mode.
3241 It analyze the current list of visible top level frames. Only the last real document
3242 frame can have this symbol. Not the help frame nor the backing task itself.
3243 Here we do anything related to this closer. We remove it from the old frame and set it
3244 for the new one.
3247 void XFrameImpl::impl_checkMenuCloser()
3249 /* SAFE { */
3250 SolarMutexClearableGuard aReadLock;
3252 // only top frames, which are part of our desktop hierarchy, can
3253 // do so! By the way - we need the desktop instance to have access
3254 // to all other top level frames too.
3255 css::uno::Reference< css::frame::XDesktop > xDesktop (m_xParent, css::uno::UNO_QUERY);
3256 css::uno::Reference< css::frame::XFramesSupplier > xTaskSupplier(xDesktop , css::uno::UNO_QUERY);
3257 if ( !xDesktop.is() || !xTaskSupplier.is() )
3258 return;
3260 aReadLock.clear();
3261 /* } SAFE */
3263 // analyze the list of current open tasks
3264 // Suppress search for other views to the same model ...
3265 // It's not needed here and can be very expensive.
3266 FrameListAnalyzer aAnalyzer(
3267 xTaskSupplier,
3268 this,
3269 FrameAnalyzerFlags::Hidden | FrameAnalyzerFlags::Help | FrameAnalyzerFlags::BackingComponent);
3271 // specify the new frame, which must have this special state...
3272 css::uno::Reference< css::frame::XFrame2 > xNewCloserFrame;
3274 // a)
3275 // If there exist at least one other frame - there are two frames currently open.
3276 // But we can enable this closer only, if one of these two tasks includes the help module.
3277 // The "other frame" couldn't be the help. Because then it wouldn't be part of this "other list".
3278 // In such case it will be separated to the reference aAnalyzer.m_xHelp!
3279 // But we must check, if we include ourself the help...
3280 // Check aAnalyzer.m_bReferenceIsHelp!
3281 if (
3282 (aAnalyzer.m_lOtherVisibleFrames.size()==1) &&
3284 (aAnalyzer.m_bReferenceIsHelp ) ||
3285 (aAnalyzer.m_bReferenceIsHidden)
3289 // others[0] can't be the backing component!
3290 // Because it's set at the special member aAnalyzer.m_xBackingComponent ... :-)
3291 xNewCloserFrame.set( aAnalyzer.m_lOtherVisibleFrames[0], css::uno::UNO_QUERY_THROW );
3294 // b)
3295 // There is no other frame... means no other document frame. The help module
3296 // will be handled separately and must(!) be ignored here... excepting if we include ourself the help.
3297 else if (
3298 (aAnalyzer.m_lOtherVisibleFrames.empty()) &&
3299 (!aAnalyzer.m_bReferenceIsHelp) &&
3300 (!aAnalyzer.m_bReferenceIsHidden) &&
3301 (!aAnalyzer.m_bReferenceIsBacking)
3304 xNewCloserFrame = this;
3307 // Look for necessary actions ...
3308 // Only if the closer state must be moved from one frame to another one
3309 // or must be enabled/disabled at all.
3310 SolarMutexGuard aGuard;
3311 // Holds the only frame, which must show the special closer menu item (can be NULL!)
3312 static css::uno::WeakReference< css::frame::XFrame2 > s_xCloserFrame;
3313 css::uno::Reference< css::frame::XFrame2 > xCloserFrame (s_xCloserFrame.get(), css::uno::UNO_QUERY);
3314 if (xCloserFrame!=xNewCloserFrame)
3316 if (xCloserFrame.is())
3317 impl_setCloser(xCloserFrame, false);
3318 if (xNewCloserFrame.is())
3319 impl_setCloser(xNewCloserFrame, true);
3320 s_xCloserFrame = xNewCloserFrame;
3326 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
3327 com_sun_star_comp_framework_Frame_get_implementation(
3328 css::uno::XComponentContext *context,
3329 css::uno::Sequence<css::uno::Any> const &)
3331 rtl::Reference<XFrameImpl> inst = new XFrameImpl(context);
3332 css::uno::XInterface *acquired_inst = cppu::acquire(inst.get());
3334 inst->initListeners();
3336 return acquired_inst;
3339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */