/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sfx2.hxx" #include "impframe.hxx" #include "objshimp.hxx" #include "sfx2/sfxhelp.hxx" #include "workwin.hxx" #include "sfx2/app.hxx" #include "sfx2/bindings.hxx" #include "sfx2/dispatch.hxx" #include "sfx2/docfac.hxx" #include "sfx2/docfile.hxx" #include "sfx2/event.hxx" #include "sfx2/objface.hxx" #include "sfx2/request.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::frame; using namespace ::com::sun::star::util; using namespace ::com::sun::star::container; using namespace ::com::sun::star::beans; using ::com::sun::star::lang::XMultiServiceFactory; using ::com::sun::star::lang::XComponent; using ::com::sun::star::frame::XComponentLoader; //------------------------------------------------------------------------ class SfxFrameWindow_Impl : public Window { public: SfxFrame* pFrame; SfxFrameWindow_Impl( SfxFrame* pF, Window& i_rContainerWindow ); ~SfxFrameWindow_Impl( ); virtual void DataChanged( const DataChangedEvent& rDCEvt ); virtual void StateChanged( StateChangedType nStateChange ); virtual long PreNotify( NotifyEvent& rNEvt ); virtual long Notify( NotifyEvent& rEvt ); virtual void Resize(); virtual void GetFocus(); void DoResize(); DECL_LINK( CloserHdl, void* ); }; SfxFrameWindow_Impl::SfxFrameWindow_Impl( SfxFrame* pF, Window& i_rContainerWindow ) : Window( &i_rContainerWindow, WB_BORDER | WB_CLIPCHILDREN | WB_NODIALOGCONTROL | WB_3DLOOK ) , pFrame( pF ) { } SfxFrameWindow_Impl::~SfxFrameWindow_Impl( ) { } void SfxFrameWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt ) { Window::DataChanged( rDCEvt ); SfxWorkWindow *pWorkWin = pFrame->GetWorkWindow_Impl(); if ( pWorkWin ) pWorkWin->DataChanged_Impl( rDCEvt ); } long SfxFrameWindow_Impl::Notify( NotifyEvent& rNEvt ) { if ( pFrame->IsClosing_Impl() || !pFrame->GetFrameInterface().is() ) return sal_False; SfxViewFrame* pView = pFrame->GetCurrentViewFrame(); if ( !pView || !pView->GetObjectShell() ) return Window::Notify( rNEvt ); if ( rNEvt.GetType() == EVENT_GETFOCUS ) { if ( pView->GetViewShell() && !pView->GetViewShell()->GetUIActiveIPClient_Impl() && !pFrame->IsInPlace() ) { DBG_TRACE("SfxFrame: GotFocus"); pView->MakeActive_Impl( sal_False ); } // TODO/LATER: do we still need this code? Window* pWindow = rNEvt.GetWindow(); rtl::OString sHelpId; while ( !sHelpId.getLength() && pWindow ) { sHelpId = pWindow->GetHelpId(); pWindow = pWindow->GetParent(); } if ( sHelpId.getLength() ) SfxHelp::OpenHelpAgent( pFrame, sHelpId ); // if focus was on an external window, the clipboard content might have been changed pView->GetBindings().Invalidate( SID_PASTE ); pView->GetBindings().Invalidate( SID_PASTE_SPECIAL ); return sal_True; } else if( rNEvt.GetType() == EVENT_KEYINPUT ) { if ( pView->GetViewShell()->KeyInput( *rNEvt.GetKeyEvent() ) ) return sal_True; } else if ( rNEvt.GetType() == EVENT_EXECUTEDIALOG /*|| rNEvt.GetType() == EVENT_INPUTDISABLE*/ ) { pView->SetModalMode( sal_True ); return sal_True; } else if ( rNEvt.GetType() == EVENT_ENDEXECUTEDIALOG /*|| rNEvt.GetType() == EVENT_INPUTENABLE*/ ) { //EnableInput( sal_True, sal_True ); pView->SetModalMode( sal_False ); return sal_True; } return Window::Notify( rNEvt ); } long SfxFrameWindow_Impl::PreNotify( NotifyEvent& rNEvt ) { sal_uInt16 nType = rNEvt.GetType(); if ( nType == EVENT_KEYINPUT || nType == EVENT_KEYUP ) { SfxViewFrame* pView = pFrame->GetCurrentViewFrame(); SfxViewShell* pShell = pView ? pView->GetViewShell() : NULL; if ( pShell && pShell->HasKeyListeners_Impl() && pShell->HandleNotifyEvent_Impl( rNEvt ) ) return sal_True; } else if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN ) { Window* pWindow = rNEvt.GetWindow(); SfxViewFrame* pView = pFrame->GetCurrentViewFrame(); SfxViewShell* pShell = pView ? pView->GetViewShell() : NULL; if ( pShell ) if ( pWindow == pShell->GetWindow() || pShell->GetWindow()->IsChild( pWindow ) ) if ( pShell->HasMouseClickListeners_Impl() && pShell->HandleNotifyEvent_Impl( rNEvt ) ) return sal_True; } if ( nType == EVENT_MOUSEBUTTONDOWN ) { Window* pWindow = rNEvt.GetWindow(); const MouseEvent* pMEvent = rNEvt.GetMouseEvent(); Point aPos = pWindow->OutputToScreenPixel( pMEvent->GetPosPixel() ); SfxWorkWindow *pWorkWin = pFrame->GetWorkWindow_Impl(); if ( pWorkWin ) pWorkWin->EndAutoShow_Impl( aPos ); } return Window::PreNotify( rNEvt ); } void SfxFrameWindow_Impl::GetFocus() { if ( pFrame && !pFrame->IsClosing_Impl() && pFrame->GetCurrentViewFrame() && pFrame->GetFrameInterface().is() ) pFrame->GetCurrentViewFrame()->MakeActive_Impl( sal_True ); } void SfxFrameWindow_Impl::Resize() { if ( IsReallyVisible() || IsReallyShown() || GetOutputSizePixel().Width() ) DoResize(); } void SfxFrameWindow_Impl::StateChanged( StateChangedType nStateChange ) { if ( nStateChange == STATE_CHANGE_INITSHOW ) { pFrame->pImp->bHidden = sal_False; if ( pFrame->IsInPlace() ) // TODO/MBA: workaround for bug in LayoutManager: the final resize does not get through because the // LayoutManager works asynchronously and between resize and time execution the DockingAcceptor was exchanged so that // the resize event never is sent to the component SetSizePixel( GetParent()->GetOutputSizePixel() ); DoResize(); SfxViewFrame* pView = pFrame->GetCurrentViewFrame(); if ( pView ) pView->GetBindings().GetWorkWindow_Impl()->ShowChilds_Impl(); } Window::StateChanged( nStateChange ); } void SfxFrameWindow_Impl::DoResize() { if ( !pFrame->pImp->bLockResize ) pFrame->Resize(); } Reference < XFrame > SfxFrame::CreateBlankFrame() { Reference < XFrame > xFrame; try { ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); Reference < XFrame > xDesktop( aContext.createComponent( "com.sun.star.frame.Desktop" ), UNO_QUERY_THROW ); xFrame.set( xDesktop->findFrame( DEFINE_CONST_UNICODE("_blank"), 0 ), UNO_SET_THROW ); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } return xFrame; } SfxFrame* SfxFrame::Create( SfxObjectShell& rDoc, Window& rWindow, sal_uInt16 nViewId, bool bHidden ) { SfxFrame* pFrame = NULL; try { // create and initialize new top level frame for this window ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); Reference < XFramesSupplier > xDesktop( aContext.createComponent( "com.sun.star.frame.Desktop" ), UNO_QUERY_THROW ); Reference < XFrame > xFrame( aContext.createComponent( "com.sun.star.frame.Frame"), UNO_QUERY_THROW ); Reference< awt::XWindow2 > xWin( VCLUnoHelper::GetInterface ( &rWindow ), uno::UNO_QUERY_THROW ); xFrame->initialize( xWin.get() ); xDesktop->getFrames()->append( xFrame ); if ( xWin->isActive() ) xFrame->activate(); // create load arguments Sequence< PropertyValue > aLoadArgs; TransformItems( SID_OPENDOC, *rDoc.GetMedium()->GetItemSet(), aLoadArgs ); ::comphelper::NamedValueCollection aArgs( aLoadArgs ); aArgs.put( "Model", rDoc.GetModel() ); aArgs.put( "Hidden", bHidden ); if ( nViewId ) aArgs.put( "ViewId", nViewId ); aLoadArgs = aArgs.getPropertyValues(); // load the doc into that frame ::rtl::OUString sLoaderURL( RTL_CONSTASCII_USTRINGPARAM( "private:object" ) ); Reference< XComponentLoader > xLoader( xFrame, UNO_QUERY_THROW ); xLoader->loadComponentFromURL( sLoaderURL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), 0, aLoadArgs ); for ( pFrame = SfxFrame::GetFirst(); pFrame; pFrame = SfxFrame::GetNext( *pFrame ) ) { if ( pFrame->GetFrameInterface() == xFrame ) break; } OSL_ENSURE( pFrame, "SfxFrame::Create: load succeeded, but no SfxFrame was created during this!" ); } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } return pFrame; } SfxFrame* SfxFrame::Create( const Reference < XFrame >& i_rFrame ) { // create a new TopFrame to an external XFrame object ( wrap controller ) ENSURE_OR_THROW( i_rFrame.is(), "NULL frame not allowed" ); Window* pWindow = VCLUnoHelper::GetWindow( i_rFrame->getContainerWindow() ); ENSURE_OR_THROW( pWindow, "frame without container window not allowed" ); SfxFrame* pFrame = new SfxFrame( *pWindow, false ); pFrame->SetFrameInterface_Impl( i_rFrame ); return pFrame; } SfxFrame::SfxFrame( Window& i_rContainerWindow, bool i_bHidden ) :pParentFrame( NULL ) ,pChildArr( NULL ) ,pImp( NULL ) ,pWindow( NULL ) { Construct_Impl(); pImp->bHidden = i_bHidden; InsertTopFrame_Impl( this ); pImp->pExternalContainerWindow = &i_rContainerWindow; pWindow = new SfxFrameWindow_Impl( this, i_rContainerWindow ); // always show pWindow, which is the ComponentWindow of the XFrame we live in // nowadays, since SfxFrames can be created with an XFrame only, hiding or showing the complete XFrame // is not done at level of the container window, not at SFX level. Thus, the component window can // always be visible. pWindow->Show(); } void SfxFrame::SetPresentationMode( sal_Bool bSet ) { if ( GetCurrentViewFrame() ) GetCurrentViewFrame()->GetWindow().SetBorderStyle( bSet ? WINDOW_BORDER_NOBORDER : WINDOW_BORDER_NORMAL ); Reference< com::sun::star::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY ); Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; if ( xPropSet.is() ) { Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))); aValue >>= xLayoutManager; } if ( xLayoutManager.is() ) xLayoutManager->setVisible( !bSet ); // we don't want to have ui in presentation mode SetMenuBarOn_Impl( !bSet ); if ( GetWorkWindow_Impl() ) GetWorkWindow_Impl()->SetDockingAllowed( !bSet ); if ( GetCurrentViewFrame() ) GetCurrentViewFrame()->GetDispatcher()->Update_Impl( sal_True ); } SystemWindow* SfxFrame::GetSystemWindow() const { return GetTopWindow_Impl(); } SystemWindow* SfxFrame::GetTopWindow_Impl() const { if ( pImp->pExternalContainerWindow->IsSystemWindow() ) return (SystemWindow*) pImp->pExternalContainerWindow; else return NULL; } Window& SfxFrame::GetWindow() const { return *pWindow; } sal_Bool SfxFrame::Close() { delete this; return sal_True; } void SfxFrame::LockResize_Impl( sal_Bool bLock ) { pImp->bLockResize = bLock; } IMPL_LINK( SfxFrameWindow_Impl, CloserHdl, void*, EMPTYARG ) { if ( pFrame && !pFrame->PrepareClose_Impl( sal_True ) ) return 0L; if ( pFrame ) pFrame->GetCurrentViewFrame()->GetBindings().Execute( SID_CLOSEWIN, 0, 0, SFX_CALLMODE_ASYNCHRON ); return 0L; } void SfxFrame::SetMenuBarOn_Impl( sal_Bool bOn ) { pImp->bMenuBarOn = bOn; Reference< com::sun::star::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY ); Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; if ( xPropSet.is() ) { Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))); aValue >>= xLayoutManager; } if ( xLayoutManager.is() ) { rtl::OUString aMenuBarURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" )); if ( bOn ) xLayoutManager->showElement( aMenuBarURL ); else xLayoutManager->hideElement( aMenuBarURL ); } } sal_Bool SfxFrame::IsMenuBarOn_Impl() const { return pImp->bMenuBarOn; } void SfxFrame::PositionWindow_Impl( const Rectangle& rWinArea ) const { Window *pWin = pImp->pExternalContainerWindow; // Groesse setzen const Size aAppWindow( pImp->pExternalContainerWindow->GetDesktopRectPixel().GetSize() ); Point aPos( rWinArea.TopLeft() ); Size aSz( rWinArea.GetSize() ); if ( aSz.Width() && aSz.Height() ) { aPos.X() = Min(aPos.X(), long(aAppWindow.Width() - aSz.Width() + aSz.Width() / 2) ); aPos.Y() = Min(aPos.Y(), long( aAppWindow.Height() - aSz.Height() + aSz.Height() / 2) ); if ( aPos.X() + aSz.Width() < aAppWindow.Width() + aSz.Width() / 2 && aPos.Y() + aSz.Height() < aAppWindow.Height() + aSz.Height() / 2 ) { pWin->SetPosPixel( aPos ); pWin->SetOutputSizePixel( aSz ); } } } void SfxFrame::PrepareForDoc_Impl( SfxObjectShell& i_rDoc ) { const ::comphelper::NamedValueCollection aDocumentArgs( i_rDoc.GetModel()->getArgs() ); // hidden? OSL_ENSURE( !pImp->bHidden, "when does this happen?" ); pImp->bHidden = aDocumentArgs.getOrDefault( "Hidden", pImp->bHidden ); // update our descriptor UpdateDescriptor( &i_rDoc ); // plugin mode sal_Int16 nPluginMode = aDocumentArgs.getOrDefault( "PluginMode", sal_Int16( 0 ) ); if ( nPluginMode && ( nPluginMode != 2 ) ) SetInPlace_Impl( sal_True ); } bool SfxFrame::IsMarkedHidden_Impl() const { return pImp->bHidden; }