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 .
20 #include <docholder.hxx>
21 #include <embeddoc.hxx>
22 #include <intercept.hxx>
23 #include <syswinwrapper.hxx>
24 #include <iipaobj.hxx>
27 #if !defined WIN32_LEAN_AND_MEAN
28 # define WIN32_LEAN_AND_MEAN
32 #include <com/sun/star/awt/XTopWindow.hpp>
33 #include <com/sun/star/awt/PosSize.hpp>
34 #include <com/sun/star/awt/XView.hpp>
35 #include <com/sun/star/awt/Toolkit.hpp>
36 #include <com/sun/star/awt/XSystemChildFactory.hpp>
37 #include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
38 #include <com/sun/star/awt/XSystemDependentMenuPeer.hpp>
39 #include <com/sun/star/awt/WindowAttribute.hpp>
40 #include <com/sun/star/awt/XWindow.hpp>
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/bridge/XBridgeSupplier2.hpp>
43 #include <com/sun/star/bridge/ModelDependent.hpp>
44 #include <com/sun/star/container/XNameAccess.hpp>
45 #include <com/sun/star/document/MacroExecMode.hpp>
46 #include <com/sun/star/embed/EmbedMapUnits.hpp>
47 #include <com/sun/star/embed/XVisualObject.hpp>
48 #include <com/sun/star/frame/TerminationVetoException.hpp>
49 #include <com/sun/star/frame/XComponentLoader.hpp>
50 #include <com/sun/star/frame/Frame.hpp>
51 #include <com/sun/star/frame/XModel.hpp>
52 #include <com/sun/star/frame/Desktop.hpp>
53 #include <com/sun/star/frame/XStatusListener.hpp>
54 #include <com/sun/star/lang/SystemDependent.hpp>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/task/InteractionHandler.hpp>
57 #include <com/sun/star/ui/XUIElement.hpp>
58 #include <com/sun/star/util/CloseVetoException.hpp>
59 #include <com/sun/star/util/XCloseBroadcaster.hpp>
60 #include <com/sun/star/util/XCloseable.hpp>
61 #include <com/sun/star/util/XModifyBroadcaster.hpp>
62 #include <comphelper/processfactory.hxx>
63 #include <comphelper/propertyvalue.hxx>
64 #include <o3tl/any.hxx>
65 #include <o3tl/unit_conversion.hxx>
66 #include <osl/diagnose.h>
67 #include <rtl/process.h>
68 #include <rtl/ref.hxx>
70 using namespace ::com::sun::star
;
72 // add mutex locking ???
74 DocumentHolder::DocumentHolder(
75 const uno::Reference
<lang::XMultiServiceFactory
>& xFactory
,
76 const ::rtl::Reference
< EmbeddedDocumentInstanceAccess_Impl
>& xOleAccess
)
78 m_bAllowInPlace(true),
79 m_pIOleIPSite(nullptr),
80 m_pIOleIPFrame(nullptr),
81 m_pIOleIPUIWindow(nullptr),
82 m_pCHatchWin(nullptr),
83 m_xOleAccess( xOleAccess
),
84 m_xFactory( xFactory
),
85 m_bOnDeactivate(false),
86 m_hWndxWinParent(nullptr),
87 m_hWndxWinCont(nullptr),
88 m_nMenuHandle(nullptr),
89 m_nMenuShared(nullptr),
91 m_nMacroExecMode( document::MacroExecMode::USE_CONFIG
),
94 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create(comphelper::getComponentContext(m_xFactory
));
95 xDesktop
->addTerminateListener( static_cast<frame::XTerminateListener
*>(this) );
99 DocumentHolder::~DocumentHolder()
103 ClearInterceptorInternally();
107 void DocumentHolder::LoadDocInFrame( bool bPluginMode
)
109 uno::Reference
<frame::XComponentLoader
> xComponentLoader(
110 m_xFrame
,uno::UNO_QUERY
);
111 if( xComponentLoader
.is() && m_xDocument
.is() )
113 uno::Reference
< task::XInteractionHandler2
> xHandler(
114 task::InteractionHandler::createWithParent(comphelper::getComponentContext(m_xFactory
), nullptr) );
116 sal_Int32 nLen
= bPluginMode
? 6 : 5;
117 uno::Sequence
<beans::PropertyValue
> aSeq( nLen
);
118 auto pSeq
= aSeq
.getArray();
119 pSeq
[0] = beans::PropertyValue(
122 uno::Any(uno::Reference
<uno::XInterface
>(m_xDocument
, uno::UNO_QUERY
)),
123 beans::PropertyState_DIRECT_VALUE
);
125 pSeq
[1] = beans::PropertyValue(
129 beans::PropertyState_DIRECT_VALUE
);
131 pSeq
[2] = beans::PropertyValue(
135 beans::PropertyState_DIRECT_VALUE
);
139 pSeq
[3] = beans::PropertyValue(
142 uno::Any(sal_Int16(3)),
143 beans::PropertyState_DIRECT_VALUE
);
146 pSeq
[nLen
-2] = beans::PropertyValue(
147 "InteractionHandler",
150 beans::PropertyState_DIRECT_VALUE
);
152 pSeq
[nLen
-1] = beans::PropertyValue(
153 "MacroExecutionMode",
155 uno::Any(m_nMacroExecMode
),
156 beans::PropertyState_DIRECT_VALUE
);
158 xComponentLoader
->loadComponentFromURL(
164 const uno::Sequence
< beans::PropertyValue
> aResArgs
= m_xDocument
->getArgs();
165 for ( beans::PropertyValue
const & prop
: aResArgs
)
166 if ( prop
.Name
== "MacroExecutionMode" )
168 prop
.Value
>>= m_nMacroExecMode
;
174 void DocumentHolder::OnPosRectChanged(LPRECT lpRect
) const
176 lpRect
->left
+= m_aBorder
.left
;
177 lpRect
->right
-= m_aBorder
.right
;
178 lpRect
->top
+= m_aBorder
.top
;
179 lpRect
->bottom
-= m_aBorder
.bottom
;
181 m_pIOleIPSite
->OnPosRectChange(lpRect
);
185 void DocumentHolder::DisableInplaceActivation(BOOL b
)
187 m_bAllowInPlace
= ! b
;
190 BOOL
DocumentHolder::isActive() const
192 return m_pIOleIPSite
!= nullptr;
195 HRESULT
DocumentHolder::InPlaceActivate(
196 LPOLECLIENTSITE pActiveSite
,
199 m_bOnDeactivate
= false;
208 OLEINPLACEFRAMEINFO frameInfo
;
210 if (nullptr==pActiveSite
)
211 return ResultFromScode(E_INVALIDARG
);
213 if (nullptr!=m_pIOleIPSite
)
221 if ( !m_xDocument
.is() )
224 //1. Initialization, obtaining interfaces, OnInPlaceActivate.
225 hr
=pActiveSite
->QueryInterface(
227 reinterpret_cast<void**>(&m_pIOleIPSite
));
232 hr
=m_pIOleIPSite
->CanInPlaceActivate();
236 m_pIOleIPSite
->Release();
237 m_pIOleIPSite
=nullptr;
238 return ResultFromScode(E_FAIL
);
241 m_pIOleIPSite
->OnInPlaceActivate();
243 //2. Get the site window
244 //3. and determine container frame and
245 // document window for tools and menus, as well
246 // as frameInfo for accelerators
247 m_pIOleIPSite
->GetWindow(&hWndSite
);
249 frameInfo
.cb
=sizeof(OLEINPLACEFRAMEINFO
);
250 m_pIOleIPSite
->GetWindowContext(
251 &m_pIOleIPFrame
,&m_pIOleIPUIWindow
,&rcPos
,&rcClip
,&frameInfo
);
253 // initialize the office as, with hwnd as parentwindow
255 uno::Sequence
<sal_Int8
> aProcessIdent(16);
256 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8
*>(aProcessIdent
.getArray()));
260 if(!m_xEditWindow
.is())
261 { // determine XWindow and window handle of parent
262 HWND
hWndxWinParent(nullptr);
263 uno::Reference
<awt::XWindow
> xWin
;
265 uno::Reference
<awt::XToolkit2
> xToolkit
=
266 awt::Toolkit::create(comphelper::getComponentContext(m_xFactory
));
268 // create system window wrapper for hwnd
270 m_pCHatchWin
= new winwrap::CHatchWin(
273 if(m_pCHatchWin
->Init(hWndSite
,/*ID_HATCHWINDOW*/2000, nullptr)) {
274 m_pCHatchWin
->RectsSet(&rcPos
,&rcClip
); //set visible area
275 hWndxWinParent
= m_pCHatchWin
->Window();
276 ShowWindow(hWndxWinParent
,SW_SHOW
); //Make visible.
279 // no success initializing hatch window
281 m_pCHatchWin
= nullptr;
282 hWndxWinParent
= hWndSite
;
286 xToolkit
->createSystemChild(
287 uno::Any(reinterpret_cast<sal_Int64
>(hWndxWinParent
)),
289 lang::SystemDependent::SYSTEM_WIN32
),
294 m_pCHatchWin
? HATCHWIN_BORDERWIDTHDEFAULT
: 0,
295 m_pCHatchWin
? HATCHWIN_BORDERWIDTHDEFAULT
: 0,
296 rcPos
.right
-rcPos
.left
,
297 rcPos
.bottom
- rcPos
.top
,
298 awt::PosSize::POSSIZE
);
299 xWin
->setVisible(true);
301 m_xEditWindow
= xWin
;
302 m_hWndxWinParent
= hWndxWinParent
;
308 if(m_hWndxWinParent
) {
309 SetParent(m_hWndxWinParent
,hWndSite
);
310 ShowWindow(m_hWndxWinParent
,SW_SHOW
); //Make visible.
313 if ( !m_xFrame
.is() )
314 // initially set size to "empty", this guarantees that the final resize
315 // is always executed (will be done by "SetObjectRects" after getting internal border)
316 m_xEditWindow
->setPosSize(
321 awt::PosSize::POSSIZE
);
322 m_xEditWindow
->setVisible(true);
325 if(m_xContainerWindow
.is()) {
329 m_pIOleIPFrame
->GetWindow(&hWndCont
);
330 SetParent(m_hWndxWinCont
,hWndCont
);
331 ShowWindow(m_hWndxWinCont
,SW_SHOW
);
334 m_xContainerWindow
->setVisible(true);
338 m_xFrame
->activate();
340 // create frame and initialize it with the created window
341 m_xFrame
= frame::Frame::create( comphelper::getComponentContext(m_xFactory
) );
342 m_xFrame
->initialize(m_xEditWindow
);
344 m_xFrame
->registerDispatchProviderInterceptor( CreateNewInterceptor() );
346 m_xLayoutManager
.set( m_xFrame
->getLayoutManager(), uno::UNO_QUERY
);
348 if(m_xLayoutManager
.is())
349 m_xLayoutManager
->setDockingAreaAcceptor(this);
351 // load the model into the frame
352 LoadDocInFrame( true );
354 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create(comphelper::getComponentContext(m_xFactory
));
355 xDesktop
->getFrames()->append(m_xFrame
);
357 // determine the menuhandle to get menuitems.
358 if(m_xLayoutManager
.is()) {
359 uno::Reference
< css::ui::XUIElement
> xUIEl(
360 m_xLayoutManager
->getElement(
361 "private:resource/menubar/menubar"));
362 OSL_ENSURE(xUIEl
.is(),"no menubar");
363 uno::Reference
<awt::XSystemDependentMenuPeer
> xSDMP(
364 xUIEl
->getRealInterface(),
366 aAny
= xSDMP
->getMenuHandle(
367 aProcessIdent
,lang::SystemDependent::SYSTEM_WIN32
);
370 m_nMenuHandle
= reinterpret_cast<HMENU
>(tmp
);
371 m_xLayoutManager
->hideElement(
372 "private:resource/menubar/menubar" );
376 // TODO/cd: Workaround for status indicator bug. It always makes the
377 // document window visible, when someone tries to use the status
378 // indicator. As we save our document when we get the deactivation
379 // from OLE this conflict to hide floating windows.
380 if(m_xLayoutManager
.is())
381 m_xLayoutManager
->setVisible(true);
383 // get document border and resize rects according to border
384 GetDocumentBorder( &m_aBorder
);
385 SetObjectRects( &rcPos
, &rcClip
);
387 if ( m_xOleAccess
.is() )
389 LockedEmbedDocument_Impl aDocLock
= m_xOleAccess
->GetEmbedDocument();
390 if ( aDocLock
.GetEmbedDocument() )
391 aDocLock
.GetEmbedDocument()->ShowObject();
394 // setTitle(m_aDocumentNamePart);
398 m_pIOleIPSite
->DiscardUndoState();
400 catch( const uno::Exception
& )
409 void DocumentHolder::InPlaceDeactivate()
411 m_bOnDeactivate
= true;
414 if(m_xFrame
.is()) m_xFrame
->deactivate();
416 if(m_xEditWindow
.is()) {
417 m_xEditWindow
->setVisible(false);
418 ShowWindow(m_hWndxWinParent
,SW_HIDE
);
419 SetParent(m_hWndxWinParent
,nullptr);
422 if(m_xContainerWindow
.is()) {
423 m_xContainerWindow
->setVisible(false);
424 ShowWindow(m_hWndxWinCont
,SW_HIDE
);
425 SetParent(m_hWndxWinCont
,nullptr);
428 // TODO/cd: Workaround for status indicator bug. It always makes the
429 // document window visible, when someone tries to use the status
430 // indicator. As we save our document when we get the deactivation
431 // from OLE this conflict to hide floating windows.
432 if (m_xLayoutManager
.is())
433 m_xLayoutManager
->setVisible(false);
435 if (nullptr!=m_pIOleIPSite
)
436 m_pIOleIPSite
->OnInPlaceDeactivate();
438 if(m_pIOleIPFrame
) m_pIOleIPFrame
->Release(); m_pIOleIPFrame
= nullptr;
439 if(m_pIOleIPUIWindow
) m_pIOleIPUIWindow
->Release(); m_pIOleIPUIWindow
= nullptr;
440 if(m_pIOleIPSite
) m_pIOleIPSite
->Release(); m_pIOleIPSite
= nullptr;
442 if ( m_xOleAccess
.is() )
444 LockedEmbedDocument_Impl aDocLock
= m_xOleAccess
->GetEmbedDocument();
445 if ( aDocLock
.GetEmbedDocument() )
447 aDocLock
.GetEmbedDocument()->SaveObject();
455 HRESULT
DocumentHolder::UIActivate()
457 // 1. Call IOleInPlaceSite::UIActivate
458 if (nullptr!=m_pIOleIPSite
)
459 m_pIOleIPSite
->OnUIActivate();
461 //2. Critical for accelerators to work initially.
462 SetFocus(m_pCHatchWin
->Window());
463 // if(m_xEditWindow.is()) m_xEditWindow->setFocus();
465 //3. Set the active object
467 OLECHAR starOffice
[] = {'S','t','a','r','O','f','f','i','c','e',0};
468 CComPtr
< IOleInPlaceActiveObject
> pObj
= new CIIAObj( this );
470 if (nullptr!=m_pIOleIPFrame
)
471 m_pIOleIPFrame
->SetActiveObject(
474 if (nullptr!=m_pIOleIPUIWindow
)
475 m_pIOleIPUIWindow
->SetActiveObject(
478 //4. Create the shared menu.
484 void DocumentHolder::UIDeactivate()
486 //1. Remove the shared menu.
487 InPlaceMenuDestroy();
489 if (nullptr!=m_pIOleIPFrame
)
490 m_pIOleIPFrame
->SetActiveObject(nullptr, nullptr);
492 if (nullptr!=m_pIOleIPUIWindow
)
493 m_pIOleIPUIWindow
->SetActiveObject(nullptr, nullptr);
495 //3. Call IOleInPlaceSite::OnUIDeactivate
496 if (nullptr!=m_pIOleIPSite
)
497 m_pIOleIPSite
->OnUIDeactivate(FALSE
);
502 static void CopyToOLEMenu(HMENU hOrig
,WORD origPos
,HMENU hDest
,WORD destPos
)
504 HMENU
subMenu(nullptr);
507 subMenu
= GetSubMenu(hOrig
,origPos
);
508 GetMenuStringW(hOrig
,origPos
,buffer
,256,MF_BYPOSITION
);
509 InsertMenuW(hDest
,destPos
,MF_BYPOSITION
| MF_POPUP
,
510 reinterpret_cast<UINT_PTR
>(subMenu
),buffer
);
512 MENUITEMINFOW mi
= {};
513 mi
.cbSize
= sizeof(mi
);
514 mi
.fMask
= MIIM_DATA
;
515 if(GetMenuItemInfoW(hOrig
,origPos
,TRUE
,&mi
))
516 SetMenuItemInfoW(hDest
,destPos
,TRUE
,&mi
);
519 BOOL
DocumentHolder::InPlaceMenuCreate()
522 OLEMENUGROUPWIDTHS mgw
;
524 for (UINT i
=0; i
<6; i
++)
527 //We already have popup menu handles in m_pFR->m_phMenu[]
529 //Create the new shared menu and let container do its thing
531 m_pIOleIPFrame
->InsertMenus(hMenu
,&mgw
);
533 int count
= GetMenuItemCount(m_nMenuHandle
);
536 // start with 1, because we don't include "File"
537 WORD pos
= static_cast<WORD
>(mgw
.width
[0]);
538 CopyToOLEMenu(m_nMenuHandle
,1,hMenu
,pos
);
541 // insert object menu here
542 pos
= static_cast<WORD
>(mgw
.width
[0] + mgw
.width
[1] + mgw
.width
[2]);
543 for(WORD i
= 2; i
< help
-1; ++i
,++pos
)
544 CopyToOLEMenu(m_nMenuHandle
,i
,hMenu
,pos
);
545 mgw
.width
[3] = help
- 3;
548 pos
= static_cast<WORD
>(mgw
.width
[0] + mgw
.width
[1] + mgw
.width
[2] +
549 mgw
.width
[3] + mgw
.width
[4]);
550 CopyToOLEMenu(m_nMenuHandle
,WORD(help
),hMenu
,pos
);
553 m_nMenuShared
= hMenu
;
554 m_nOLEMenu
= OleCreateMenuDescriptor(m_nMenuShared
,&mgw
);
556 uno::Reference
<awt::XSystemDependentWindowPeer
> xSysDepWin(m_xContainerWindow
,uno::UNO_QUERY
);
557 if(xSysDepWin
.is()) {
558 uno::Sequence
<sal_Int8
> aProcessIdent(16);
559 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8
*>(aProcessIdent
.getArray()));
560 uno::Any aAny
= xSysDepWin
->getWindowHandle(aProcessIdent
,lang::SystemDependent::SYSTEM_WIN32
);
563 HWND aHwnd
= reinterpret_cast<HWND
>(tmp
);
564 m_pIOleIPFrame
->SetMenu(
565 m_nMenuShared
,m_nOLEMenu
,aHwnd
);
568 m_pIOleIPFrame
->SetMenu(
569 m_nMenuShared
,m_nOLEMenu
,::GetWindow(m_hWndxWinParent
,GW_CHILD
));
573 BOOL
DocumentHolder::InPlaceMenuDestroy()
575 if( nullptr == m_nMenuShared
)
578 m_pIOleIPFrame
->SetMenu(nullptr,nullptr,nullptr);
580 OleDestroyMenuDescriptor(m_nOLEMenu
);
581 m_nOLEMenu
= nullptr;
585 void DocumentHolder::OpenIntoWindow()
590 BOOL
DocumentHolder::Undo()
597 void DocumentHolder::FreeOffice()
599 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create(comphelper::getComponentContext(m_xFactory
));
600 xDesktop
->removeTerminateListener(
601 static_cast<frame::XTerminateListener
*>(this) );
604 void DocumentHolder::DisconnectFrameDocument( bool bComplete
)
608 uno::Reference
< util::XModifyBroadcaster
> xModifiable( m_xDocument
, uno::UNO_QUERY_THROW
);
609 xModifiable
->removeModifyListener( static_cast<util::XModifyListener
*>(this) );
611 catch( const uno::Exception
& )
616 uno::Reference
< util::XCloseBroadcaster
> xBroadcaster(
617 m_xDocument
, uno::UNO_QUERY_THROW
);
618 xBroadcaster
->removeCloseListener( static_cast<util::XCloseListener
*>(this) );
620 catch( const uno::Exception
& )
625 uno::Reference
< util::XCloseBroadcaster
> xBroadcaster(
626 m_xFrame
, uno::UNO_QUERY_THROW
);
627 xBroadcaster
->removeCloseListener( static_cast<util::XCloseListener
*>(this) );
629 catch( const uno::Exception
& )
635 m_pIDispatch
= nullptr;
640 void DocumentHolder::CloseDocument()
642 DisconnectFrameDocument();
644 uno::Reference
< util::XCloseable
> xCloseable(
645 m_xDocument
, uno::UNO_QUERY
);
647 if ( xCloseable
.is() )
651 xCloseable
->close( true );
653 catch( const uno::Exception
& )
657 m_pIDispatch
= nullptr;
662 void DocumentHolder::CloseFrame()
666 uno::Reference
< util::XCloseBroadcaster
> xBroadcaster(
667 m_xFrame
, uno::UNO_QUERY_THROW
);
668 xBroadcaster
->removeCloseListener( static_cast<util::XCloseListener
*>(this) );
670 catch( const uno::Exception
& )
673 uno::Reference
<util::XCloseable
> xCloseable(
674 m_xFrame
,uno::UNO_QUERY
);
677 xCloseable
->close(true);
679 catch( const uno::Exception
& ) {
681 else if (m_xFrame
.is())
687 void DocumentHolder::SetDocument( const uno::Reference
< frame::XModel
>& xDoc
, bool bLink
)
689 if ( m_xDocument
.is() )
695 uno::Reference
< util::XCloseBroadcaster
> xBroadcaster(
696 m_xDocument
, uno::UNO_QUERY
);
698 if ( xBroadcaster
.is() )
699 xBroadcaster
->addCloseListener( static_cast<util::XCloseListener
*>(this) );
701 if ( m_xDocument
.is() && !m_bLink
)
703 // set the document mode to embedded
704 uno::Sequence
< beans::PropertyValue
> aSeq
{ comphelper::makePropertyValue("SetEmbedded",
706 m_xDocument
->attachResource(OUString(),aSeq
);
710 bool DocumentHolder::ExecuteSuspendCloseFrame()
712 if ( m_xFrame
.is() && m_xFactory
.is() )
716 uno::Reference
< frame::XController
> xController
= m_xFrame
->getController();
717 if ( xController
.is() )
719 if ( !xController
->suspend( true ) )
725 uno::Reference
<util::XCloseable
> xCloseable( m_xFrame
, uno::UNO_QUERY
);
726 if ( xCloseable
.is() )
727 xCloseable
->close(true);
733 catch( const util::CloseVetoException
& )
735 // should be called if the frame could not be closed
736 xController
->suspend( false );
740 catch( uno::Exception
& )
750 uno::Reference
< frame::XFrame2
> DocumentHolder::DocumentFrame()
754 uno::Reference
<frame::XDesktop2
> xDesktop
= frame::Desktop::create(comphelper::getComponentContext(m_xFactory
));
756 // the frame will be registered on desktop here, later when the document
757 // is loaded into the frame in ::show() method the terminate listener will be removed
758 // this is so only for outplace activation
759 m_xFrame
.set( xDesktop
->findFrame( "_blank", 0 ), uno::UNO_QUERY
);
761 uno::Reference
< util::XCloseBroadcaster
> xBroadcaster(
762 m_xFrame
, uno::UNO_QUERY
);
764 if ( xBroadcaster
.is() )
766 xBroadcaster
->addCloseListener( static_cast<util::XCloseListener
*>(this) );
767 FreeOffice(); // the frame is part of the desktop
774 m_xFrame
->registerDispatchProviderInterceptor( CreateNewInterceptor() );
781 uno::Reference
< frame::XDispatchProviderInterceptor
> DocumentHolder::CreateNewInterceptor()
783 ::osl::MutexGuard
aGuard( m_aMutex
);
785 ClearInterceptorInternally();
787 uno::Reference
< frame::XDispatchProviderInterceptor
> xInterceptor( m_pInterceptor
= new Interceptor( m_xOleAccess
, this, m_bLink
) );
788 m_xInterceptorLocker
= xInterceptor
;
792 void DocumentHolder::ClearInterceptorInternally()
794 ::osl::MutexGuard
aGuard( m_aMutex
);
795 uno::Reference
< frame::XDispatchProviderInterceptor
> xInterceptor( m_xInterceptorLocker
);
796 if ( xInterceptor
.is() && m_pInterceptor
)
797 m_pInterceptor
->DisconnectDocHolder();
799 m_xInterceptorLocker
.clear();
800 m_pInterceptor
.clear();
803 void DocumentHolder::ClearInterceptor()
805 ::osl::MutexGuard
aGuard( m_aMutex
);
806 m_xInterceptorLocker
.clear();
807 m_pInterceptor
.clear();
811 void DocumentHolder::show()
817 m_xFrame
->activate();
818 uno::Reference
<awt::XTopWindow
> xTopWindow(
819 m_xFrame
->getContainerWindow(),uno::UNO_QUERY
);
821 xTopWindow
->toFront();
823 else if( DocumentFrame().is() )
825 LoadDocInFrame( false );
827 // get rid of second closer if it is there
828 uno::Reference
< beans::XPropertySet
> xLMProps( m_xFrame
->getLayoutManager(), uno::UNO_QUERY
);
831 xLMProps
->setPropertyValue("MenuBarCloser",
832 uno::Any( uno::Reference
< frame::XStatusListener
>() ) );
839 uno::Reference
< util::XModifyBroadcaster
> xModifiable( m_xDocument
, uno::UNO_QUERY_THROW
);
840 xModifiable
->addModifyListener( static_cast<util::XModifyListener
*>(this) );
842 catch( const uno::Exception
& )
847 setTitle(m_aDocumentNamePart
);
850 catch( const uno::Exception
& )
852 OSL_FAIL( "Can not show the frame!" );
857 void DocumentHolder::resizeWin( const SIZEL
& rNewSize
)
859 LockedEmbedDocument_Impl aDocLock
;
861 if ( m_xOleAccess
.is() )
862 aDocLock
= m_xOleAccess
->GetEmbedDocument();
864 if ( m_xFrame
.is() && aDocLock
.GetEmbedDocument() )
866 uno::Reference
< awt::XWindow
> xWindow
= m_xFrame
->getContainerWindow();
867 uno::Reference
< awt::XView
> xView( xWindow
, uno::UNO_QUERY
);
869 if ( xWindow
.is() && xView
.is() )
872 xView
->setZoom( fScale
, fScale
);
875 GetExtent( &aOldSize
);
877 if ( aOldSize
.cx
!= rNewSize
.cx
|| aOldSize
.cy
!= rNewSize
.cy
)
879 HDC hdc
= GetDC( nullptr );
880 SetMapMode( hdc
, MM_HIMETRIC
);
883 aOldOffset
.x
= aOldSize
.cx
;
884 aOldOffset
.y
= aOldSize
.cy
;
885 LPtoDP( hdc
, &aOldOffset
, 1 );
888 aNewOffset
.x
= rNewSize
.cx
;
889 aNewOffset
.y
= rNewSize
.cy
;
890 LPtoDP( hdc
, &aNewOffset
, 1 );
892 ReleaseDC( nullptr, hdc
);
894 awt::Rectangle aWinRect
= xWindow
->getPosSize();
896 sal_Int32 aWidthDelta
= aWinRect
.Width
- aOldOffset
.x
;
897 sal_Int32 aHeightDelta
= aWinRect
.Height
- aOldOffset
.y
;
899 if ( aWidthDelta
> 0 && aHeightDelta
> 0 )
900 xWindow
->setPosSize(0,
902 aNewOffset
.x
+ aWidthDelta
,
903 aNewOffset
.y
+ aHeightDelta
,
904 awt::PosSize::SIZE
);
910 void DocumentHolder::setTitle(const OUString
& aDocumentName
)
914 if(m_aFilterName
.getLength() == 0)
916 OUString aFilterName
;
917 uno::Sequence
<beans::PropertyValue
> aSeq
;
920 aSeq
= m_xDocument
->getArgs();
921 for (beans::PropertyValue
const& prop
: aSeq
)
923 if(prop
.Name
== "FilterName")
925 prop
.Value
>>= aFilterName
;
931 if(aFilterName
.getLength())
933 uno::Reference
<container::XNameAccess
> xNameAccess(
934 m_xFactory
->createInstance("com.sun.star.document.FilterFactory"),
937 if(xNameAccess
.is() &&
938 (xNameAccess
->getByName(aFilterName
) >>= aSeq
))
940 for (beans::PropertyValue
const& prop
: aSeq
)
941 if(prop
.Name
== "UIName")
943 prop
.Value
>>= m_aFilterName
;
948 catch(const uno::Exception
& ) {
949 // nothing better to do here
950 m_aFilterName
= aFilterName
;
955 OUString
aTotalName(m_aFilterName
+ " (" + aDocumentName
+ ")");
957 m_xFrame
->setTitle( aTotalName
);
959 catch( const uno::Exception
& ) {
963 m_aDocumentNamePart
= aDocumentName
;
967 ::osl::ClearableMutexGuard
aGuard( m_aMutex
);
969 rtl::Reference
<Interceptor
> pTmpInter
;
970 uno::Reference
< frame::XDispatchProviderInterceptor
> xLock( m_xInterceptorLocker
);
971 if ( xLock
.is() && m_pInterceptor
)
972 pTmpInter
= m_pInterceptor
;
977 pTmpInter
->generateFeatureStateEvent();
982 void DocumentHolder::setContainerName(const OUString
& aContainerName
)
984 m_aContainerName
= aContainerName
;
988 void DocumentHolder::hide()
990 if(m_xFrame
.is()) m_xFrame
->deactivate();
993 // after hiding the window it is always allowed to InPlaceActivate it
994 m_bAllowInPlace
= true;
997 IDispatch
* DocumentHolder::GetIDispatch()
999 if ( !m_pIDispatch
&& m_xDocument
.is() )
1001 uno::Reference
< bridge::XBridgeSupplier2
> xSupplier(
1002 m_xFactory
->createInstance( "com.sun.star.bridge.OleBridgeSupplier2" ), uno::UNO_QUERY
);
1004 if ( xSupplier
.is() )
1006 uno::Sequence
< sal_Int8
> aProcId( 16 );
1007 rtl_getGlobalProcessId( reinterpret_cast<sal_uInt8
*>(aProcId
.getArray()) );
1010 uno::Any anyResult
= xSupplier
->createBridge(
1011 uno::Any( m_xDocument
),
1013 bridge::ModelDependent::UNO
,
1014 bridge::ModelDependent::OLE
);
1016 if ( auto var
= o3tl::tryAccess
<sal_uIntPtr
>(anyResult
) )
1018 VARIANT
* pVariant
= reinterpret_cast<VARIANT
*>(*var
);
1019 if ( pVariant
->vt
== VT_DISPATCH
)
1020 m_pIDispatch
= pVariant
->pdispVal
;
1022 VariantClear( pVariant
);
1023 CoTaskMemFree( pVariant
);
1026 catch ( const uno::Exception
& )
1031 return m_pIDispatch
;
1034 HRESULT
DocumentHolder::GetDocumentBorder( RECT
*pRect
)
1036 if ( pRect
&& m_xDocument
.is() )
1038 const uno::Sequence
< beans::PropertyValue
> aArgs
= m_xDocument
->getArgs();
1039 for ( beans::PropertyValue
const & prop
: aArgs
)
1040 if ( prop
.Name
== "DocumentBorder" )
1042 uno::Sequence
< sal_Int32
> aRect
;
1043 if ( ( prop
.Value
>>= aRect
) && aRect
.getLength() == 4 )
1045 pRect
->left
= aRect
[0];
1046 pRect
->top
= aRect
[1];
1047 pRect
->right
= aRect
[2];
1048 pRect
->bottom
= aRect
[3];
1060 HRESULT
DocumentHolder::SetExtent( const SIZEL
*pSize
)
1064 uno::Reference
< embed::XVisualObject
> xVisObj( m_xDocument
, uno::UNO_QUERY
);
1069 awt::Size
aNewSize( pSize
->cx
, pSize
->cy
);
1071 sal_Int32 aMapMode
= xVisObj
->getMapUnit( DVASPECT_CONTENT
);
1073 // TODO/LATER: in future UNO API should be used for the conversion, currently there is no
1074 if ( aMapMode
== embed::EmbedMapUnits::TWIP
)
1076 // conversion from ONE_100TH_MM
1077 aNewSize
.Width
= o3tl::toTwips(aNewSize
.Width
, o3tl::Length::mm100
);
1078 aNewSize
.Height
= o3tl::toTwips(aNewSize
.Height
, o3tl::Length::mm100
);
1082 xVisObj
->setVisualAreaSize( DVASPECT_CONTENT
, aNewSize
);
1086 catch( const uno::Exception
& )
1094 HRESULT
DocumentHolder::GetExtent( SIZEL
*pSize
)
1098 uno::Reference
< embed::XVisualObject
> xVisObj( m_xDocument
, uno::UNO_QUERY
);
1103 awt::Size aDocSize
= xVisObj
->getVisualAreaSize( DVASPECT_CONTENT
);
1105 sal_Int32 aMapMode
= xVisObj
->getMapUnit( DVASPECT_CONTENT
);
1107 // TODO/LATER: in future UNO API should be used for the conversion, currently there is no
1108 if ( aMapMode
== embed::EmbedMapUnits::TWIP
)
1110 // conversion to ONE_100TH_MM
1111 aDocSize
.Width
= o3tl::convert(aDocSize
.Width
, o3tl::Length::twip
, o3tl::Length::mm100
);
1112 aDocSize
.Height
= o3tl::convert(aDocSize
.Height
, o3tl::Length::twip
, o3tl::Length::mm100
);
1115 pSize
->cx
= aDocSize
.Width
;
1116 pSize
->cy
= aDocSize
.Height
;
1120 catch( const uno::Exception
& )
1129 HRESULT
DocumentHolder::SetContRects(LPCRECT aRect
)
1131 if(m_xContainerWindow
.is()) {
1133 if(m_pIOleIPFrame
) {
1134 m_pIOleIPFrame
->GetBorder(&wi
);
1135 m_xContainerWindow
->setPosSize(
1139 awt::PosSize::POSSIZE
);
1142 m_xContainerWindow
->setPosSize(
1144 aRect
->right
- aRect
->left
,
1145 aRect
->bottom
- aRect
->top
,
1146 awt::PosSize::POSSIZE
);
1155 HRESULT
DocumentHolder::SetObjectRects(LPCRECT aRect
, LPCRECT aClip
)
1158 rect
.left
-= m_aBorder
.left
;
1159 rect
.right
+= m_aBorder
.right
;
1160 rect
.top
-= m_aBorder
.top
;
1161 rect
.bottom
+= m_aBorder
.bottom
;
1163 clip
.left
-= m_aBorder
.left
;
1164 clip
.right
+= m_aBorder
.right
;
1165 clip
.top
-= m_aBorder
.top
;
1166 clip
.bottom
+= m_aBorder
.bottom
;
1169 m_pCHatchWin
->RectsSet(&rect
, &clip
);
1170 if(m_xEditWindow
.is()) {
1171 m_xEditWindow
->setVisible(false);
1172 m_xEditWindow
->setPosSize(
1173 m_pCHatchWin
? HATCHWIN_BORDERWIDTHDEFAULT
: 0,
1174 m_pCHatchWin
? HATCHWIN_BORDERWIDTHDEFAULT
: 0,
1175 rect
.right
- rect
.left
,
1176 rect
.bottom
- rect
.top
,
1177 awt::PosSize::POSSIZE
);
1178 m_xEditWindow
->setVisible(true);
1184 css::uno::Reference
< css::awt::XWindow
> SAL_CALL
DocumentHolder::getContainerWindow()
1186 if(m_xContainerWindow
.is())
1187 return m_xContainerWindow
;
1189 uno::Reference
<awt::XWindow
> xWin
;
1191 uno::Reference
<awt::XToolkit2
> xToolkit
= awt::Toolkit::create( comphelper::getComponentContext(m_xFactory
) );
1193 if(m_pIOleIPFrame
) {
1195 m_pIOleIPFrame
->GetWindow(&hWnd
);
1197 uno::Sequence
<sal_Int8
> aProcessIdent(16);
1198 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8
*>(aProcessIdent
.getArray()));
1201 xToolkit
->createSystemChild(
1202 uno::Any(reinterpret_cast<sal_Int64
>(hWnd
)),
1204 lang::SystemDependent::SYSTEM_WIN32
),
1208 if(xWin
.is() && m_pIOleIPFrame
->GetBorder(&wi
) == NOERROR
) {
1209 xWin
->setVisible(true);
1214 awt::PosSize::POSSIZE
);
1216 uno::Reference
<awt::XSystemDependentWindowPeer
> xSysWin(
1217 xWin
,uno::UNO_QUERY
);
1219 uno::Any aAny
= xSysWin
->getWindowHandle(
1220 aProcessIdent
,lang::SystemDependent::SYSTEM_WIN32
);
1223 SetContainerWindowHandle(reinterpret_cast<HWND
>(tmp
));
1228 m_xContainerWindow
= xWin
;
1233 sal_Bool SAL_CALL
DocumentHolder::requestDockingAreaSpace( const css::awt::Rectangle
& RequestedSpace
)
1240 RequestedSpace
.X
,RequestedSpace
.Y
,
1241 RequestedSpace
.Width
,RequestedSpace
.Height
);
1242 if( m_pIOleIPFrame
)
1243 return m_pIOleIPFrame
->RequestBorderSpace(&bw
) == NOERROR
;
1249 void SAL_CALL
DocumentHolder::setDockingAreaSpace( const css::awt::Rectangle
& BorderSpace
)
1256 BorderSpace
.X
,BorderSpace
.Y
,
1257 BorderSpace
.Width
,BorderSpace
.Height
);
1258 if( m_pIOleIPFrame
) {
1260 GetClientRect(m_hWndxWinCont
,&aRect
);
1261 HRGN hrgn1
= CreateRectRgn(
1263 aRect
.right
,BorderSpace
.Y
);
1264 HRGN hrgn2
= CreateRectRgn(aRect
.right
-BorderSpace
.Width
,0,aRect
.right
,aRect
.bottom
);
1265 CombineRgn(hrgn1
,hrgn1
,hrgn2
,RGN_OR
);
1266 DeleteObject(hrgn2
);
1267 hrgn2
= CreateRectRgn(0,aRect
.bottom
-BorderSpace
.Height
,aRect
.right
,aRect
.bottom
);
1268 CombineRgn(hrgn1
,hrgn1
,hrgn2
,RGN_OR
);
1269 DeleteObject(hrgn2
);
1270 hrgn2
= CreateRectRgn(0,0,BorderSpace
.X
,aRect
.bottom
);
1271 CombineRgn(hrgn1
,hrgn1
,hrgn2
,RGN_OR
);
1272 DeleteObject(hrgn2
);
1274 SetWindowRgn(m_hWndxWinCont
,hrgn1
,true);
1275 // not:: DeleteObject(hrgn1);
1276 m_pIOleIPFrame
->SetBorderSpace(&bw
);
1281 void SAL_CALL
DocumentHolder::disposing( const css::lang::EventObject
& aSource
)
1283 if ( m_xDocument
.is() && m_xDocument
== aSource
.Source
)
1285 m_pIDispatch
= nullptr;
1286 m_xDocument
.clear();
1289 if( m_xFrame
.is() && m_xFrame
== aSource
.Source
)
1295 DocumentHolder::queryClosing(
1296 const lang::EventObject
& aSource
,
1297 sal_Bool
/*bGetsOwnership*/
1301 && ((m_xDocument
.is() && m_xDocument
== aSource
.Source
)
1302 || (m_xFrame
.is() && m_xFrame
== aSource
.Source
)))
1303 throw util::CloseVetoException();
1308 DocumentHolder::notifyClosing(
1309 const lang::EventObject
& aSource
)
1313 uno::Reference
< util::XCloseBroadcaster
> xEventBroadcaster(
1314 aSource
.Source
, uno::UNO_QUERY_THROW
);
1315 xEventBroadcaster
->removeCloseListener( static_cast<util::XCloseListener
*>(this) );
1317 catch( const uno::Exception
& )
1320 if ( m_xDocument
.is() && m_xDocument
== aSource
.Source
)
1322 // can happen only in case of links
1323 m_pIDispatch
= nullptr;
1324 m_xDocument
.clear();
1327 LockedEmbedDocument_Impl aDocLock
= m_xOleAccess
->GetEmbedDocument();
1328 if ( aDocLock
.GetEmbedDocument() )
1329 aDocLock
.GetEmbedDocument()->OLENotifyClosing();
1331 else if( m_xFrame
.is() && m_xFrame
== aSource
.Source
)
1336 DocumentHolder::queryTermination(
1337 const lang::EventObject
& /*aSource*/
1340 if ( m_xDocument
.is() )
1341 throw frame::TerminationVetoException();
1345 DocumentHolder::notifyTermination(
1346 const lang::EventObject
& aSource
1349 OSL_ENSURE( !m_xDocument
.is(), "Just a disaster..." );
1350 uno::Reference
< frame::XDesktop
> xDesktop(
1351 aSource
.Source
, uno::UNO_QUERY
);
1353 if ( xDesktop
.is() )
1354 xDesktop
->removeTerminateListener( static_cast<frame::XTerminateListener
*>(this) );
1358 void SAL_CALL
DocumentHolder::modified( const lang::EventObject
& /*aEvent*/ )
1360 if ( m_xOleAccess
.is() )
1362 LockedEmbedDocument_Impl aDocLock
= m_xOleAccess
->GetEmbedDocument();
1363 if ( aDocLock
.GetEmbedDocument() )
1364 aDocLock
.GetEmbedDocument()->notify();
1368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */