1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include "impframe.hxx"
22 #include <workwin.hxx>
24 #include <sfx2/bindings.hxx>
25 #include <sfx2/dispatch.hxx>
26 #include <sfx2/docfile.hxx>
27 #include <sfx2/sfxsids.hrc>
28 #include <sfx2/sfxuno.hxx>
29 #include <sfx2/viewsh.hxx>
31 #include <com/sun/star/awt/XWindow2.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/frame/Desktop.hpp>
34 #include <com/sun/star/frame/XComponentLoader.hpp>
35 #include <com/sun/star/frame/Frame.hpp>
36 #include <com/sun/star/frame/XLayoutManager.hpp>
38 #include <comphelper/namedvaluecollection.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <comphelper/diagnose_ex.hxx>
42 #include <vcl/event.hxx>
43 #include <vcl/syswin.hxx>
44 #include <sal/log.hxx>
46 using namespace ::com::sun::star
;
47 using namespace ::com::sun::star::uno
;
48 using namespace ::com::sun::star::frame
;
49 using namespace ::com::sun::star::beans
;
50 using ::com::sun::star::frame::XComponentLoader
;
52 class SfxFrameWindow_Impl
: public vcl::Window
54 DECL_LINK(ModalHierarchyHdl
, bool, void);
58 SfxFrameWindow_Impl( SfxFrame
* pF
, vcl::Window
& i_rContainerWindow
);
60 virtual void DataChanged( const DataChangedEvent
& rDCEvt
) override
;
61 virtual void StateChanged( StateChangedType nStateChange
) override
;
62 virtual bool PreNotify( NotifyEvent
& rNEvt
) override
;
63 virtual bool EventNotify( NotifyEvent
& rEvt
) override
;
64 virtual void Resize() override
;
65 virtual void GetFocus() override
;
66 virtual void dispose() override
;
70 SfxFrameWindow_Impl::SfxFrameWindow_Impl(SfxFrame
* pF
, vcl::Window
& i_rContainerWindow
)
71 : Window(&i_rContainerWindow
, WB_BORDER
| WB_CLIPCHILDREN
| WB_NODIALOGCONTROL
| WB_3DLOOK
)
74 i_rContainerWindow
.SetModalHierarchyHdl(LINK(this, SfxFrameWindow_Impl
, ModalHierarchyHdl
));
77 void SfxFrameWindow_Impl::dispose()
79 GetParent()->SetModalHierarchyHdl(Link
<bool, void>());
80 vcl::Window::dispose();
83 void SfxFrameWindow_Impl::DataChanged( const DataChangedEvent
& rDCEvt
)
85 Window::DataChanged( rDCEvt
);
86 // tdf#131613 the printers changing has no effect on window layout
87 if (rDCEvt
.GetType() == DataChangedEventType::PRINTER
)
89 SfxWorkWindow
*pWorkWin
= m_pFrame
->GetWorkWindow_Impl();
91 pWorkWin
->DataChanged_Impl();
94 bool SfxFrameWindow_Impl::EventNotify( NotifyEvent
& rNEvt
)
96 if ( m_pFrame
->IsClosing_Impl() || !m_pFrame
->GetFrameInterface().is() )
99 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
100 if ( !pView
|| !pView
->GetObjectShell() )
101 return Window::EventNotify( rNEvt
);
103 if ( rNEvt
.GetType() == NotifyEventType::GETFOCUS
)
105 if ( pView
->GetViewShell() && !pView
->GetViewShell()->GetUIActiveIPClient_Impl() && !m_pFrame
->IsInPlace() )
107 SAL_INFO("sfx", "SfxFrame: GotFocus");
108 pView
->MakeActive_Impl( false );
111 // if focus was on an external window, the clipboard content might have been changed
112 pView
->GetBindings().Invalidate( SID_PASTE
);
113 pView
->GetBindings().Invalidate( SID_PASTE_SPECIAL
);
116 else if( rNEvt
.GetType() == NotifyEventType::KEYINPUT
)
118 if ( pView
->GetViewShell()->KeyInput( *rNEvt
.GetKeyEvent() ) )
122 return Window::EventNotify( rNEvt
);
125 IMPL_LINK(SfxFrameWindow_Impl
, ModalHierarchyHdl
, bool, bSetModal
, void)
127 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
128 if (!pView
|| !pView
->GetObjectShell())
130 pView
->SetModalMode(bSetModal
);
133 bool SfxFrameWindow_Impl::PreNotify( NotifyEvent
& rNEvt
)
135 NotifyEventType nType
= rNEvt
.GetType();
136 if ( nType
== NotifyEventType::KEYINPUT
|| nType
== NotifyEventType::KEYUP
)
138 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
139 SfxViewShell
* pShell
= pView
? pView
->GetViewShell() : nullptr;
140 if ( pShell
&& pShell
->HasKeyListeners_Impl() && pShell
->HandleNotifyEvent_Impl( rNEvt
) )
143 else if ( nType
== NotifyEventType::MOUSEBUTTONUP
|| nType
== NotifyEventType::MOUSEBUTTONDOWN
)
145 vcl::Window
* pWindow
= rNEvt
.GetWindow();
146 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
147 SfxViewShell
* pShell
= pView
? pView
->GetViewShell() : nullptr;
149 if ( pWindow
== pShell
->GetWindow() || pShell
->GetWindow()->IsChild( pWindow
) )
150 if ( pShell
->HasMouseClickListeners_Impl() && pShell
->HandleNotifyEvent_Impl( rNEvt
) )
154 if ( nType
== NotifyEventType::MOUSEBUTTONDOWN
)
156 vcl::Window
* pWindow
= rNEvt
.GetWindow();
157 const MouseEvent
* pMEvent
= rNEvt
.GetMouseEvent();
158 Point aPos
= pWindow
->OutputToScreenPixel( pMEvent
->GetPosPixel() );
159 SfxWorkWindow
*pWorkWin
= m_pFrame
->GetWorkWindow_Impl();
161 pWorkWin
->EndAutoShow_Impl( aPos
);
164 return Window::PreNotify( rNEvt
);
167 void SfxFrameWindow_Impl::GetFocus()
169 if ( m_pFrame
&& !m_pFrame
->IsClosing_Impl() &&
170 m_pFrame
->GetCurrentViewFrame() &&
171 m_pFrame
->GetFrameInterface().is() )
172 m_pFrame
->GetCurrentViewFrame()->MakeActive_Impl( true );
175 void SfxFrameWindow_Impl::Resize()
177 if ( IsReallyVisible() || IsReallyShown() || GetOutputSizePixel().Width() )
181 void SfxFrameWindow_Impl::StateChanged( StateChangedType nStateChange
)
183 if ( nStateChange
== StateChangedType::InitShow
)
185 m_pFrame
->m_pImpl
->bHidden
= false;
186 if ( m_pFrame
->IsInPlace() )
187 // TODO/MBA: workaround for bug in LayoutManager: the final resize does not get through because the
188 // LayoutManager works asynchronously and between resize and time execution the DockingAcceptor was exchanged so that
189 // the resize event never is sent to the component
190 SetSizePixel( GetParent()->GetOutputSizePixel() );
193 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
195 pView
->GetBindings().GetWorkWindow_Impl()->ShowChildren_Impl();
198 Window::StateChanged( nStateChange
);
201 void SfxFrameWindow_Impl::DoResize()
203 if ( !m_pFrame
->m_pImpl
->bLockResize
)
207 Reference
< XFrame
> SfxFrame::CreateBlankFrame()
209 Reference
< XFrame
> xFrame
;
212 Reference
< XDesktop2
> xDesktop
= Desktop::create( ::comphelper::getProcessComponentContext() );
213 xFrame
.set( xDesktop
->findFrame( u
"_blank"_ustr
, 0 ), UNO_SET_THROW
);
215 catch( const Exception
& )
217 DBG_UNHANDLED_EXCEPTION("sfx.view");
222 SfxFrame
* SfxFrame::CreateHidden( SfxObjectShell
const & rDoc
, vcl::Window
& rWindow
, SfxInterfaceId nViewId
)
224 SfxFrame
* pFrame
= nullptr;
227 // create and initialize new top level frame for this window
228 const Reference
< XComponentContext
>& xContext( ::comphelper::getProcessComponentContext() );
229 Reference
< XDesktop2
> xDesktop
= Desktop::create( xContext
);
230 Reference
< XFrame2
> xFrame
= Frame::create( xContext
);
232 Reference
< awt::XWindow2
> xWin( VCLUnoHelper::GetInterface ( &rWindow
), uno::UNO_QUERY_THROW
);
233 xFrame
->initialize( xWin
);
234 xDesktop
->getFrames()->append( xFrame
);
236 if ( xWin
->isActive() )
239 // create load arguments
240 Sequence
< PropertyValue
> aLoadArgs
;
241 TransformItems( SID_OPENDOC
, rDoc
.GetMedium()->GetItemSet(), aLoadArgs
);
243 ::comphelper::NamedValueCollection
aArgs( aLoadArgs
);
244 aArgs
.put( u
"Model"_ustr
, rDoc
.GetModel() );
245 aArgs
.put( u
"Hidden"_ustr
, true );
246 if ( nViewId
!= SFX_INTERFACE_NONE
)
247 aArgs
.put( u
"ViewId"_ustr
, static_cast<sal_uInt16
>(nViewId
) );
249 aLoadArgs
= aArgs
.getPropertyValues();
251 // load the doc into that frame
252 Reference
< XComponentLoader
> xLoader( xFrame
, UNO_QUERY_THROW
);
253 xLoader
->loadComponentFromURL(
254 u
"private:object"_ustr
,
260 for ( pFrame
= SfxFrame::GetFirst();
262 pFrame
= SfxFrame::GetNext( *pFrame
)
265 if ( pFrame
->GetFrameInterface() == xFrame
)
269 OSL_ENSURE( pFrame
, "SfxFrame::Create: load succeeded, but no SfxFrame was created during this!" );
271 catch( const Exception
& )
273 DBG_UNHANDLED_EXCEPTION("sfx.view");
279 SfxFrame
* SfxFrame::Create( const Reference
< XFrame
>& i_rFrame
)
281 // create a new TopFrame to an external XFrame object ( wrap controller )
282 ENSURE_OR_THROW( i_rFrame
.is(), "NULL frame not allowed" );
283 VclPtr
<vcl::Window
> pWindow
= VCLUnoHelper::GetWindow( i_rFrame
->getContainerWindow() );
284 ENSURE_OR_THROW( pWindow
, "frame without container window not allowed" );
286 SfxFrame
* pFrame
= new SfxFrame( *pWindow
);
287 pFrame
->SetFrameInterface_Impl( i_rFrame
);
291 SfxFrame::SfxFrame( vcl::Window
& i_rContainerWindow
)
292 :SvCompatWeakBase
<SfxFrame
>( this )
293 ,m_pWindow( nullptr )
297 m_pImpl
->bHidden
= false;
298 InsertTopFrame_Impl( this );
299 m_pImpl
->pExternalContainerWindow
= &i_rContainerWindow
;
301 m_pWindow
= VclPtr
<SfxFrameWindow_Impl
>::Create( this, i_rContainerWindow
);
303 // always show pWindow, which is the ComponentWindow of the XFrame we live in
304 // nowadays, since SfxFrames can be created with an XFrame only, hiding or showing the complete XFrame
305 // is not done at level of the container window, not at SFX level. Thus, the component window can
306 // always be visible.
310 void SfxFrame::SetPresentationMode( bool bSet
)
312 if ( GetCurrentViewFrame() )
313 GetCurrentViewFrame()->GetWindow().SetBorderStyle( bSet
? WindowBorderStyle::NOBORDER
: WindowBorderStyle::NORMAL
);
315 Reference
< css::beans::XPropertySet
> xPropSet( GetFrameInterface(), UNO_QUERY
);
316 Reference
< css::frame::XLayoutManager
> xLayoutManager
;
320 Any aValue
= xPropSet
->getPropertyValue(u
"LayoutManager"_ustr
);
321 aValue
>>= xLayoutManager
;
324 if ( xLayoutManager
.is() )
325 xLayoutManager
->setVisible( !bSet
); // we don't want to have ui in presentation mode
327 SetMenuBarOn_Impl( !bSet
);
328 if ( GetWorkWindow_Impl() )
329 GetWorkWindow_Impl()->SetDockingAllowed( !bSet
);
330 if ( GetCurrentViewFrame() )
331 GetCurrentViewFrame()->GetDispatcher()->Update_Impl( true );
334 SystemWindow
* SfxFrame::GetSystemWindow() const
336 return GetTopWindow_Impl();
339 SystemWindow
* SfxFrame::GetTopWindow_Impl() const
341 if ( m_pImpl
->pExternalContainerWindow
->IsSystemWindow() )
342 return static_cast<SystemWindow
*>( m_pImpl
->pExternalContainerWindow
.get() );
348 void SfxFrame::LockResize_Impl( bool bLock
)
350 m_pImpl
->bLockResize
= bLock
;
353 void SfxFrame::SetMenuBarOn_Impl( bool bOn
)
355 m_pImpl
->bMenuBarOn
= bOn
;
357 Reference
< css::beans::XPropertySet
> xPropSet( GetFrameInterface(), UNO_QUERY
);
358 Reference
< css::frame::XLayoutManager
> xLayoutManager
;
362 Any aValue
= xPropSet
->getPropertyValue(u
"LayoutManager"_ustr
);
363 aValue
>>= xLayoutManager
;
366 if ( xLayoutManager
.is() )
368 OUString
aMenuBarURL( u
"private:resource/menubar/menubar"_ustr
);
371 xLayoutManager
->showElement( aMenuBarURL
);
373 xLayoutManager
->hideElement( aMenuBarURL
);
377 bool SfxFrame::IsMenuBarOn_Impl() const
379 return m_pImpl
->bMenuBarOn
;
382 void SfxFrame::PrepareForDoc_Impl( const SfxObjectShell
& i_rDoc
)
384 const ::comphelper::NamedValueCollection
aDocumentArgs( i_rDoc
.GetModel()->getArgs2( { u
"Hidden"_ustr
, u
"PluginMode"_ustr
} ) );
387 OSL_ENSURE( !m_pImpl
->bHidden
, "when does this happen?" );
388 m_pImpl
->bHidden
= aDocumentArgs
.getOrDefault( u
"Hidden"_ustr
, m_pImpl
->bHidden
);
390 // update our descriptor
391 UpdateDescriptor( &i_rDoc
);
394 sal_Int16 nPluginMode
= aDocumentArgs
.getOrDefault( u
"PluginMode"_ustr
, sal_Int16( 0 ) );
395 if ( nPluginMode
&& ( nPluginMode
!= 2 ) )
396 m_pImpl
->bInPlace
= true;
399 bool SfxFrame::IsMarkedHidden_Impl() const
401 return m_pImpl
->bHidden
;
404 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */