sw a11y: clang-format SidebarWinAccessible code
[LibreOffice.git] / embedserv / source / embed / docholder.cxx
blob829db69b91d445d7809d0028e6a129453ee46c49
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 <docholder.hxx>
21 #include <embeddoc.hxx>
22 #include <intercept.hxx>
23 #include <syswinwrapper.hxx>
24 #include <iipaobj.hxx>
25 #include <common.h>
27 #if !defined WIN32_LEAN_AND_MEAN
28 # define WIN32_LEAN_AND_MEAN
29 #endif
30 #include <windows.h>
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),
90 m_nOLEMenu(nullptr),
91 m_nMacroExecMode( document::MacroExecMode::USE_CONFIG ),
92 m_bLink( false )
94 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(comphelper::getComponentContext(m_xFactory));
95 xDesktop->addTerminateListener( static_cast<frame::XTerminateListener*>(this) );
99 DocumentHolder::~DocumentHolder()
101 delete m_pCHatchWin;
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(
120 "Model",
122 uno::Any(uno::Reference<uno::XInterface>(m_xDocument, uno::UNO_QUERY)),
123 beans::PropertyState_DIRECT_VALUE);
125 pSeq[1] = beans::PropertyValue(
126 "ReadOnly",
128 uno::Any(false),
129 beans::PropertyState_DIRECT_VALUE);
131 pSeq[2] = beans::PropertyValue(
132 "NoAutoSave",
134 uno::Any(true),
135 beans::PropertyState_DIRECT_VALUE);
137 if ( bPluginMode )
139 pSeq[3] = beans::PropertyValue(
140 "PluginMode",
142 uno::Any(sal_Int16(3)),
143 beans::PropertyState_DIRECT_VALUE);
146 pSeq[nLen-2] = beans::PropertyValue(
147 "InteractionHandler",
149 uno::Any(xHandler),
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(
159 "private:object",
160 "_self",
162 aSeq);
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;
169 break;
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;
180 if(m_pIOleIPSite)
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,
197 BOOL fIncludeUI)
199 m_bOnDeactivate = false;
201 if(!m_bAllowInPlace)
202 return ERROR;
204 HRESULT hr;
205 HWND hWndSite;
206 RECT rcPos;
207 RECT rcClip;
208 OLEINPLACEFRAMEINFO frameInfo;
210 if (nullptr==pActiveSite)
211 return ResultFromScode(E_INVALIDARG);
213 if (nullptr!=m_pIOleIPSite)
215 if (fIncludeUI)
216 UIActivate();
218 return NOERROR;
221 if ( !m_xDocument.is() )
222 return ERROR;
224 //1. Initialization, obtaining interfaces, OnInPlaceActivate.
225 hr=pActiveSite->QueryInterface(
226 IID_IOleInPlaceSite,
227 reinterpret_cast<void**>(&m_pIOleIPSite));
229 if (FAILED(hr))
230 return hr;
232 hr=m_pIOleIPSite->CanInPlaceActivate();
234 if (NOERROR!=hr)
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
254 uno::Any aAny;
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
269 if( !m_pCHatchWin )
270 m_pCHatchWin = new winwrap::CHatchWin(
271 m_hInstance,this);
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.
278 else {
279 // no success initializing hatch window
280 delete m_pCHatchWin;
281 m_pCHatchWin = nullptr;
282 hWndxWinParent = hWndSite;
285 xWin.set(
286 xToolkit->createSystemChild(
287 uno::Any(reinterpret_cast<sal_Int64>(hWndxWinParent)),
288 aProcessIdent,
289 lang::SystemDependent::SYSTEM_WIN32),
290 uno::UNO_QUERY);
292 if(xWin.is()) {
293 xWin->setPosSize(
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;
304 else
305 return ERROR;
307 else {
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()) {
326 if(m_hWndxWinCont) {
327 if(m_pIOleIPFrame) {
328 HWND hWndCont;
329 m_pIOleIPFrame->GetWindow(&hWndCont);
330 SetParent(m_hWndxWinCont,hWndCont);
331 ShowWindow(m_hWndxWinCont,SW_SHOW);
334 m_xContainerWindow->setVisible(true);
337 if(m_xFrame.is())
338 m_xFrame->activate();
339 else {
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(),
365 uno::UNO_QUERY);
366 aAny = xSDMP->getMenuHandle(
367 aProcessIdent,lang::SystemDependent::SYSTEM_WIN32);
368 sal_Int64 tmp;
369 if( aAny >>= tmp )
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);
395 if (fIncludeUI)
396 hr=UIActivate();
398 m_pIOleIPSite->DiscardUndoState();
400 catch( const uno::Exception& )
402 hr = ERROR;
405 return hr;
409 void DocumentHolder::InPlaceDeactivate()
411 m_bOnDeactivate = true;
413 UIDeactivate();
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();
451 return;
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(
472 pObj, starOffice );
474 if (nullptr!=m_pIOleIPUIWindow)
475 m_pIOleIPUIWindow->SetActiveObject(
476 pObj, starOffice );
478 //4. Create the shared menu.
479 InPlaceMenuCreate();
481 return NOERROR;
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);
499 return;
502 static void CopyToOLEMenu(HMENU hOrig,WORD origPos,HMENU hDest,WORD destPos)
504 HMENU subMenu(nullptr);
505 wchar_t buffer[256];
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()
521 HMENU hMenu;
522 OLEMENUGROUPWIDTHS mgw;
524 for (UINT i=0; i<6; i++)
525 mgw.width[i]=0;
527 //We already have popup menu handles in m_pFR->m_phMenu[]
529 //Create the new shared menu and let container do its thing
530 hMenu=CreateMenu();
531 m_pIOleIPFrame->InsertMenus(hMenu,&mgw);
533 int count = GetMenuItemCount(m_nMenuHandle);
534 int help = count-1;
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);
539 mgw.width[1] = 1;
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;
547 // insert help menu
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);
551 mgw.width[5] = 1;
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);
561 sal_Int64 tmp;
562 aAny >>= tmp;
563 HWND aHwnd = reinterpret_cast<HWND>(tmp);
564 m_pIOleIPFrame->SetMenu(
565 m_nMenuShared,m_nOLEMenu,aHwnd);
567 else
568 m_pIOleIPFrame->SetMenu(
569 m_nMenuShared,m_nOLEMenu,::GetWindow(m_hWndxWinParent,GW_CHILD));
570 return TRUE;
573 BOOL DocumentHolder::InPlaceMenuDestroy()
575 if( nullptr == m_nMenuShared )
576 return TRUE;
578 m_pIOleIPFrame->SetMenu(nullptr,nullptr,nullptr);
580 OleDestroyMenuDescriptor(m_nOLEMenu);
581 m_nOLEMenu = nullptr;
582 return TRUE;
585 void DocumentHolder::OpenIntoWindow()
587 // not implemented
590 BOOL DocumentHolder::Undo()
592 // not implemented
593 return false;
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& )
632 if ( bComplete )
634 m_xFrame.clear();
635 m_pIDispatch = nullptr;
636 m_xDocument.clear();
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;
658 m_xDocument.clear();
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);
675 if(xCloseable.is())
676 try {
677 xCloseable->close(true);
679 catch( const uno::Exception& ) {
681 else if (m_xFrame.is())
682 m_xFrame->dispose();
684 m_xFrame.clear();
687 void DocumentHolder::SetDocument( const uno::Reference< frame::XModel >& xDoc, bool bLink )
689 if ( m_xDocument.is() )
690 CloseDocument();
692 m_xDocument = xDoc;
693 m_bLink = bLink;
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",
705 true) };
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 ) )
720 return false;
722 FreeOffice();
725 uno::Reference<util::XCloseable> xCloseable( m_xFrame, uno::UNO_QUERY );
726 if ( xCloseable.is() )
727 xCloseable->close(true);
728 else
730 m_xFrame->dispose();
733 catch( const util::CloseVetoException& )
735 // should be called if the frame could not be closed
736 xController->suspend( false );
740 catch( uno::Exception& )
744 m_xFrame.clear();
747 return true;
750 uno::Reference< frame::XFrame2 > DocumentHolder::DocumentFrame()
752 if(! m_xFrame.is() )
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
771 if( m_xFrame.is() )
773 // intercept
774 m_xFrame->registerDispatchProviderInterceptor( CreateNewInterceptor() );
777 return m_xFrame;
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;
789 return 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()
815 if(m_xFrame.is())
817 m_xFrame->activate();
818 uno::Reference<awt::XTopWindow> xTopWindow(
819 m_xFrame->getContainerWindow(),uno::UNO_QUERY);
820 if(xTopWindow.is())
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 );
829 if ( xLMProps.is() )
831 xLMProps->setPropertyValue("MenuBarCloser",
832 uno::Any( uno::Reference< frame::XStatusListener >() ) );
835 if ( !m_bLink )
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& )
846 if ( !m_bLink )
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() )
871 float fScale = 1;
872 xView->setZoom( fScale, fScale );
874 SIZEL aOldSize;
875 GetExtent( &aOldSize );
877 if ( aOldSize.cx != rNewSize.cx || aOldSize.cy != rNewSize.cy )
879 HDC hdc = GetDC( nullptr );
880 SetMapMode( hdc, MM_HIMETRIC );
882 POINT aOldOffset;
883 aOldOffset.x = aOldSize.cx;
884 aOldOffset.y = aOldSize.cy;
885 LPtoDP( hdc, &aOldOffset, 1 );
887 POINT aNewOffset;
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)
912 if(m_xFrame.is())
914 if(m_aFilterName.getLength() == 0)
916 OUString aFilterName;
917 uno::Sequence<beans::PropertyValue> aSeq;
918 if(m_xDocument.is())
920 aSeq = m_xDocument->getArgs();
921 for (beans::PropertyValue const& prop : aSeq)
923 if(prop.Name == "FilterName")
925 prop.Value >>= aFilterName;
926 break;
931 if(aFilterName.getLength())
933 uno::Reference<container::XNameAccess> xNameAccess(
934 m_xFactory->createInstance("com.sun.star.document.FilterFactory"),
935 uno::UNO_QUERY);
936 try {
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;
944 break;
948 catch(const uno::Exception& ) {
949 // nothing better to do here
950 m_aFilterName = aFilterName;
954 // set the title
955 OUString aTotalName(m_aFilterName + " (" + aDocumentName + ")");
956 try {
957 m_xFrame->setTitle( aTotalName );
959 catch( const uno::Exception& ) {
963 m_aDocumentNamePart = aDocumentName;
965 if(m_pInterceptor)
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;
974 aGuard.clear();
976 if ( pTmpInter )
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();
992 //todo: sendadvise
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()) );
1009 try {
1010 uno::Any anyResult = xSupplier->createBridge(
1011 uno::Any( m_xDocument ),
1012 aProcId,
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];
1050 return S_OK;
1053 break;
1057 return E_FAIL;
1060 HRESULT DocumentHolder::SetExtent( const SIZEL *pSize )
1062 if ( pSize )
1064 uno::Reference< embed::XVisualObject > xVisObj( m_xDocument, uno::UNO_QUERY );
1065 if ( xVisObj.is() )
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 );
1084 return S_OK;
1086 catch( const uno::Exception& )
1091 return E_FAIL;
1094 HRESULT DocumentHolder::GetExtent( SIZEL *pSize )
1096 if ( pSize )
1098 uno::Reference< embed::XVisualObject > xVisObj( m_xDocument, uno::UNO_QUERY );
1099 if ( xVisObj.is() )
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;
1118 return S_OK;
1120 catch( const uno::Exception& )
1125 return E_FAIL;
1129 HRESULT DocumentHolder::SetContRects(LPCRECT aRect)
1131 if(m_xContainerWindow.is()) {
1132 RECT wi = {};
1133 if(m_pIOleIPFrame) {
1134 m_pIOleIPFrame->GetBorder(&wi);
1135 m_xContainerWindow->setPosSize(
1136 0,0,
1137 wi.right - wi.left,
1138 wi.bottom - wi.top,
1139 awt::PosSize::POSSIZE);
1141 else
1142 m_xContainerWindow->setPosSize(
1143 0,0,
1144 aRect->right - aRect->left,
1145 aRect->bottom - aRect->top,
1146 awt::PosSize::POSSIZE);
1147 return NOERROR;
1149 else {
1150 return ERROR;
1155 HRESULT DocumentHolder::SetObjectRects(LPCRECT aRect, LPCRECT aClip)
1157 auto rect = *aRect;
1158 rect.left -= m_aBorder.left;
1159 rect.right += m_aBorder.right;
1160 rect.top -= m_aBorder.top;
1161 rect.bottom += m_aBorder.bottom;
1162 auto clip = *aClip;
1163 clip.left -= m_aBorder.left;
1164 clip.right += m_aBorder.right;
1165 clip.top -= m_aBorder.top;
1166 clip.bottom += m_aBorder.bottom;
1168 if(m_pCHatchWin)
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);
1180 return NOERROR;
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) {
1194 HWND hWnd;
1195 m_pIOleIPFrame->GetWindow(&hWnd);
1197 uno::Sequence<sal_Int8> aProcessIdent(16);
1198 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8*>(aProcessIdent.getArray()));
1200 xWin.set(
1201 xToolkit->createSystemChild(
1202 uno::Any(reinterpret_cast<sal_Int64>(hWnd)),
1203 aProcessIdent,
1204 lang::SystemDependent::SYSTEM_WIN32),
1205 uno::UNO_QUERY);
1207 RECT wi = {};
1208 if(xWin.is() && m_pIOleIPFrame->GetBorder(&wi) == NOERROR) {
1209 xWin->setVisible(true);
1210 xWin->setPosSize(
1211 0,0,
1212 wi.right-wi.left,
1213 wi.bottom - wi.top,
1214 awt::PosSize::POSSIZE);
1216 uno::Reference<awt::XSystemDependentWindowPeer> xSysWin(
1217 xWin,uno::UNO_QUERY);
1218 if(xSysWin.is()) {
1219 uno::Any aAny = xSysWin->getWindowHandle(
1220 aProcessIdent,lang::SystemDependent::SYSTEM_WIN32);
1221 sal_Int64 tmp;
1222 if( aAny >>= tmp )
1223 SetContainerWindowHandle(reinterpret_cast<HWND>(tmp));
1228 m_xContainerWindow= xWin;
1229 return xWin;
1233 sal_Bool SAL_CALL DocumentHolder::requestDockingAreaSpace( const css::awt::Rectangle& RequestedSpace )
1235 if(m_bOnDeactivate)
1236 return true;
1238 BORDERWIDTHS bw;
1239 SetRect(&bw,
1240 RequestedSpace.X,RequestedSpace.Y,
1241 RequestedSpace.Width,RequestedSpace.Height);
1242 if( m_pIOleIPFrame )
1243 return m_pIOleIPFrame->RequestBorderSpace(&bw) == NOERROR ;
1244 else
1245 return false;
1249 void SAL_CALL DocumentHolder::setDockingAreaSpace( const css::awt::Rectangle& BorderSpace )
1251 if(m_bOnDeactivate)
1252 return;
1254 BORDERWIDTHS bw;
1255 SetRect(&bw,
1256 BorderSpace.X,BorderSpace.Y,
1257 BorderSpace.Width,BorderSpace.Height);
1258 if( m_pIOleIPFrame ) {
1259 RECT aRect;
1260 GetClientRect(m_hWndxWinCont,&aRect);
1261 HRGN hrgn1 = CreateRectRgn(
1262 0,0,
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 )
1290 m_xFrame.clear();
1294 void SAL_CALL
1295 DocumentHolder::queryClosing(
1296 const lang::EventObject& aSource,
1297 sal_Bool /*bGetsOwnership*/
1300 if (!m_bLink
1301 && ((m_xDocument.is() && m_xDocument == aSource.Source)
1302 || (m_xFrame.is() && m_xFrame == aSource.Source)))
1303 throw util::CloseVetoException();
1307 void SAL_CALL
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();
1325 m_xFrame.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 )
1332 m_xFrame.clear();
1335 void SAL_CALL
1336 DocumentHolder::queryTermination(
1337 const lang::EventObject& /*aSource*/
1340 if ( m_xDocument.is() )
1341 throw frame::TerminationVetoException();
1344 void SAL_CALL
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: */