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::util
;
50 using namespace ::com::sun::star::container
;
51 using namespace ::com::sun::star::beans
;
52 using ::com::sun::star::frame::XComponentLoader
;
54 class SfxFrameWindow_Impl
: public vcl::Window
56 DECL_LINK(ModalHierarchyHdl
, bool, void);
60 SfxFrameWindow_Impl( SfxFrame
* pF
, vcl::Window
& i_rContainerWindow
);
62 virtual void DataChanged( const DataChangedEvent
& rDCEvt
) override
;
63 virtual void StateChanged( StateChangedType nStateChange
) override
;
64 virtual bool PreNotify( NotifyEvent
& rNEvt
) override
;
65 virtual bool EventNotify( NotifyEvent
& rEvt
) override
;
66 virtual void Resize() override
;
67 virtual void GetFocus() override
;
68 virtual void dispose() override
;
72 SfxFrameWindow_Impl::SfxFrameWindow_Impl(SfxFrame
* pF
, vcl::Window
& i_rContainerWindow
)
73 : Window(&i_rContainerWindow
, WB_BORDER
| WB_CLIPCHILDREN
| WB_NODIALOGCONTROL
| WB_3DLOOK
)
76 i_rContainerWindow
.SetModalHierarchyHdl(LINK(this, SfxFrameWindow_Impl
, ModalHierarchyHdl
));
79 void SfxFrameWindow_Impl::dispose()
81 GetParent()->SetModalHierarchyHdl(Link
<bool, void>());
82 vcl::Window::dispose();
85 void SfxFrameWindow_Impl::DataChanged( const DataChangedEvent
& rDCEvt
)
87 Window::DataChanged( rDCEvt
);
88 // tdf#131613 the printers changing has no effect on window layout
89 if (rDCEvt
.GetType() == DataChangedEventType::PRINTER
)
91 SfxWorkWindow
*pWorkWin
= m_pFrame
->GetWorkWindow_Impl();
93 pWorkWin
->DataChanged_Impl();
96 bool SfxFrameWindow_Impl::EventNotify( NotifyEvent
& rNEvt
)
98 if ( m_pFrame
->IsClosing_Impl() || !m_pFrame
->GetFrameInterface().is() )
101 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
102 if ( !pView
|| !pView
->GetObjectShell() )
103 return Window::EventNotify( rNEvt
);
105 if ( rNEvt
.GetType() == NotifyEventType::GETFOCUS
)
107 if ( pView
->GetViewShell() && !pView
->GetViewShell()->GetUIActiveIPClient_Impl() && !m_pFrame
->IsInPlace() )
109 SAL_INFO("sfx", "SfxFrame: GotFocus");
110 pView
->MakeActive_Impl( false );
113 // if focus was on an external window, the clipboard content might have been changed
114 pView
->GetBindings().Invalidate( SID_PASTE
);
115 pView
->GetBindings().Invalidate( SID_PASTE_SPECIAL
);
118 else if( rNEvt
.GetType() == NotifyEventType::KEYINPUT
)
120 if ( pView
->GetViewShell()->KeyInput( *rNEvt
.GetKeyEvent() ) )
124 return Window::EventNotify( rNEvt
);
127 IMPL_LINK(SfxFrameWindow_Impl
, ModalHierarchyHdl
, bool, bSetModal
, void)
129 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
130 if (!pView
|| !pView
->GetObjectShell())
132 pView
->SetModalMode(bSetModal
);
135 bool SfxFrameWindow_Impl::PreNotify( NotifyEvent
& rNEvt
)
137 NotifyEventType nType
= rNEvt
.GetType();
138 if ( nType
== NotifyEventType::KEYINPUT
|| nType
== NotifyEventType::KEYUP
)
140 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
141 SfxViewShell
* pShell
= pView
? pView
->GetViewShell() : nullptr;
142 if ( pShell
&& pShell
->HasKeyListeners_Impl() && pShell
->HandleNotifyEvent_Impl( rNEvt
) )
145 else if ( nType
== NotifyEventType::MOUSEBUTTONUP
|| nType
== NotifyEventType::MOUSEBUTTONDOWN
)
147 vcl::Window
* pWindow
= rNEvt
.GetWindow();
148 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
149 SfxViewShell
* pShell
= pView
? pView
->GetViewShell() : nullptr;
151 if ( pWindow
== pShell
->GetWindow() || pShell
->GetWindow()->IsChild( pWindow
) )
152 if ( pShell
->HasMouseClickListeners_Impl() && pShell
->HandleNotifyEvent_Impl( rNEvt
) )
156 if ( nType
== NotifyEventType::MOUSEBUTTONDOWN
)
158 vcl::Window
* pWindow
= rNEvt
.GetWindow();
159 const MouseEvent
* pMEvent
= rNEvt
.GetMouseEvent();
160 Point aPos
= pWindow
->OutputToScreenPixel( pMEvent
->GetPosPixel() );
161 SfxWorkWindow
*pWorkWin
= m_pFrame
->GetWorkWindow_Impl();
163 pWorkWin
->EndAutoShow_Impl( aPos
);
166 return Window::PreNotify( rNEvt
);
169 void SfxFrameWindow_Impl::GetFocus()
171 if ( m_pFrame
&& !m_pFrame
->IsClosing_Impl() &&
172 m_pFrame
->GetCurrentViewFrame() &&
173 m_pFrame
->GetFrameInterface().is() )
174 m_pFrame
->GetCurrentViewFrame()->MakeActive_Impl( true );
177 void SfxFrameWindow_Impl::Resize()
179 if ( IsReallyVisible() || IsReallyShown() || GetOutputSizePixel().Width() )
183 void SfxFrameWindow_Impl::StateChanged( StateChangedType nStateChange
)
185 if ( nStateChange
== StateChangedType::InitShow
)
187 m_pFrame
->m_pImpl
->bHidden
= false;
188 if ( m_pFrame
->IsInPlace() )
189 // TODO/MBA: workaround for bug in LayoutManager: the final resize does not get through because the
190 // LayoutManager works asynchronously and between resize and time execution the DockingAcceptor was exchanged so that
191 // the resize event never is sent to the component
192 SetSizePixel( GetParent()->GetOutputSizePixel() );
195 SfxViewFrame
* pView
= m_pFrame
->GetCurrentViewFrame();
197 pView
->GetBindings().GetWorkWindow_Impl()->ShowChildren_Impl();
200 Window::StateChanged( nStateChange
);
203 void SfxFrameWindow_Impl::DoResize()
205 if ( !m_pFrame
->m_pImpl
->bLockResize
)
209 Reference
< XFrame
> SfxFrame::CreateBlankFrame()
211 Reference
< XFrame
> xFrame
;
214 Reference
< XDesktop2
> xDesktop
= Desktop::create( ::comphelper::getProcessComponentContext() );
215 xFrame
.set( xDesktop
->findFrame( "_blank", 0 ), UNO_SET_THROW
);
217 catch( const Exception
& )
219 DBG_UNHANDLED_EXCEPTION("sfx.view");
224 SfxFrame
* SfxFrame::CreateHidden( SfxObjectShell
const & rDoc
, vcl::Window
& rWindow
, SfxInterfaceId nViewId
)
226 SfxFrame
* pFrame
= nullptr;
229 // create and initialize new top level frame for this window
230 Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
231 Reference
< XDesktop2
> xDesktop
= Desktop::create( xContext
);
232 Reference
< XFrame2
> xFrame
= Frame::create( xContext
);
234 Reference
< awt::XWindow2
> xWin( VCLUnoHelper::GetInterface ( &rWindow
), uno::UNO_QUERY_THROW
);
235 xFrame
->initialize( xWin
);
236 xDesktop
->getFrames()->append( xFrame
);
238 if ( xWin
->isActive() )
241 // create load arguments
242 Sequence
< PropertyValue
> aLoadArgs
;
243 TransformItems( SID_OPENDOC
, *rDoc
.GetMedium()->GetItemSet(), aLoadArgs
);
245 ::comphelper::NamedValueCollection
aArgs( aLoadArgs
);
246 aArgs
.put( "Model", rDoc
.GetModel() );
247 aArgs
.put( "Hidden", true );
248 if ( nViewId
!= SFX_INTERFACE_NONE
)
249 aArgs
.put( "ViewId", static_cast<sal_uInt16
>(nViewId
) );
251 aLoadArgs
= aArgs
.getPropertyValues();
253 // load the doc into that frame
254 Reference
< XComponentLoader
> xLoader( xFrame
, UNO_QUERY_THROW
);
255 xLoader
->loadComponentFromURL(
262 for ( pFrame
= SfxFrame::GetFirst();
264 pFrame
= SfxFrame::GetNext( *pFrame
)
267 if ( pFrame
->GetFrameInterface() == xFrame
)
271 OSL_ENSURE( pFrame
, "SfxFrame::Create: load succeeded, but no SfxFrame was created during this!" );
273 catch( const Exception
& )
275 DBG_UNHANDLED_EXCEPTION("sfx.view");
281 SfxFrame
* SfxFrame::Create( const Reference
< XFrame
>& i_rFrame
)
283 // create a new TopFrame to an external XFrame object ( wrap controller )
284 ENSURE_OR_THROW( i_rFrame
.is(), "NULL frame not allowed" );
285 VclPtr
<vcl::Window
> pWindow
= VCLUnoHelper::GetWindow( i_rFrame
->getContainerWindow() );
286 ENSURE_OR_THROW( pWindow
, "frame without container window not allowed" );
288 SfxFrame
* pFrame
= new SfxFrame( *pWindow
);
289 pFrame
->SetFrameInterface_Impl( i_rFrame
);
293 SfxFrame::SfxFrame( vcl::Window
& i_rContainerWindow
)
294 :SvCompatWeakBase
<SfxFrame
>( this )
295 ,m_pWindow( nullptr )
299 m_pImpl
->bHidden
= false;
300 InsertTopFrame_Impl( this );
301 m_pImpl
->pExternalContainerWindow
= &i_rContainerWindow
;
303 m_pWindow
= VclPtr
<SfxFrameWindow_Impl
>::Create( this, i_rContainerWindow
);
305 // always show pWindow, which is the ComponentWindow of the XFrame we live in
306 // nowadays, since SfxFrames can be created with an XFrame only, hiding or showing the complete XFrame
307 // is not done at level of the container window, not at SFX level. Thus, the component window can
308 // always be visible.
312 void SfxFrame::SetPresentationMode( bool bSet
)
314 if ( GetCurrentViewFrame() )
315 GetCurrentViewFrame()->GetWindow().SetBorderStyle( bSet
? WindowBorderStyle::NOBORDER
: WindowBorderStyle::NORMAL
);
317 Reference
< css::beans::XPropertySet
> xPropSet( GetFrameInterface(), UNO_QUERY
);
318 Reference
< css::frame::XLayoutManager
> xLayoutManager
;
322 Any aValue
= xPropSet
->getPropertyValue("LayoutManager");
323 aValue
>>= xLayoutManager
;
326 if ( xLayoutManager
.is() )
327 xLayoutManager
->setVisible( !bSet
); // we don't want to have ui in presentation mode
329 SetMenuBarOn_Impl( !bSet
);
330 if ( GetWorkWindow_Impl() )
331 GetWorkWindow_Impl()->SetDockingAllowed( !bSet
);
332 if ( GetCurrentViewFrame() )
333 GetCurrentViewFrame()->GetDispatcher()->Update_Impl( true );
336 SystemWindow
* SfxFrame::GetSystemWindow() const
338 return GetTopWindow_Impl();
341 SystemWindow
* SfxFrame::GetTopWindow_Impl() const
343 if ( m_pImpl
->pExternalContainerWindow
->IsSystemWindow() )
344 return static_cast<SystemWindow
*>( m_pImpl
->pExternalContainerWindow
.get() );
350 void SfxFrame::LockResize_Impl( bool bLock
)
352 m_pImpl
->bLockResize
= bLock
;
355 void SfxFrame::SetMenuBarOn_Impl( bool bOn
)
357 m_pImpl
->bMenuBarOn
= bOn
;
359 Reference
< css::beans::XPropertySet
> xPropSet( GetFrameInterface(), UNO_QUERY
);
360 Reference
< css::frame::XLayoutManager
> xLayoutManager
;
364 Any aValue
= xPropSet
->getPropertyValue("LayoutManager");
365 aValue
>>= xLayoutManager
;
368 if ( xLayoutManager
.is() )
370 OUString
aMenuBarURL( "private:resource/menubar/menubar" );
373 xLayoutManager
->showElement( aMenuBarURL
);
375 xLayoutManager
->hideElement( aMenuBarURL
);
379 bool SfxFrame::IsMenuBarOn_Impl() const
381 return m_pImpl
->bMenuBarOn
;
384 void SfxFrame::PrepareForDoc_Impl( const SfxObjectShell
& i_rDoc
)
386 const ::comphelper::NamedValueCollection
aDocumentArgs( i_rDoc
.GetModel()->getArgs2( { "Hidden", "PluginMode" } ) );
389 OSL_ENSURE( !m_pImpl
->bHidden
, "when does this happen?" );
390 m_pImpl
->bHidden
= aDocumentArgs
.getOrDefault( "Hidden", m_pImpl
->bHidden
);
392 // update our descriptor
393 UpdateDescriptor( &i_rDoc
);
396 sal_Int16 nPluginMode
= aDocumentArgs
.getOrDefault( "PluginMode", sal_Int16( 0 ) );
397 if ( nPluginMode
&& ( nPluginMode
!= 2 ) )
398 m_pImpl
->bInPlace
= true;
401 bool SfxFrame::IsMarkedHidden_Impl() const
403 return m_pImpl
->bHidden
;
406 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */