xref: /core/sfx2/source/view/viewsh.cxx (revision 2b196f3b)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <config_features.h>
21 
22 #include <sal/log.hxx>
23 #include <svl/stritem.hxx>
24 #include <svl/eitem.hxx>
25 #include <svl/whiter.hxx>
26 #include <vcl/toolbox.hxx>
27 #include <vcl/svapp.hxx>
28 #include <vcl/weld.hxx>
29 #include <svl/intitem.hxx>
30 #include <svtools/langhelp.hxx>
31 #include <com/sun/star/frame/XLayoutManager.hpp>
32 #include <com/sun/star/frame/ModuleManager.hpp>
33 #include <com/sun/star/io/IOException.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/embed/EmbedStates.hpp>
36 #include <com/sun/star/embed/EmbedMisc.hpp>
37 #include <com/sun/star/embed/XEmbeddedObject.hpp>
38 #include <com/sun/star/container/XContainerQuery.hpp>
39 #include <com/sun/star/frame/XStorable.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
41 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/datatransfer/clipboard/XClipboardListener.hpp>
44 #include <com/sun/star/datatransfer/clipboard/XClipboardNotifier.hpp>
45 #include <com/sun/star/view/XRenderable.hpp>
46 #include <com/sun/star/uno/Reference.hxx>
47 #include <cppuhelper/implbase.hxx>
48 
49 #include <tools/diagnose_ex.h>
50 #include <tools/urlobj.hxx>
51 #include <unotools/tempfile.hxx>
52 #include <svtools/soerr.hxx>
53 #include <tools/svborder.hxx>
54 
55 #include <framework/actiontriggerhelper.hxx>
56 #include <comphelper/lok.hxx>
57 #include <comphelper/namedvaluecollection.hxx>
58 #include <comphelper/processfactory.hxx>
59 #include <comphelper/sequenceashashmap.hxx>
60 #include <toolkit/helper/vclunohelper.hxx>
61 #include <vcl/settings.hxx>
62 #include <vcl/commandinfoprovider.hxx>
63 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
64 
65 #include <officecfg/Office/Common.hxx>
66 #include <officecfg/Setup.hxx>
67 #include <sfx2/app.hxx>
68 #include <sfx2/flatpak.hxx>
69 #include <sfx2/viewsh.hxx>
70 #include "viewimp.hxx"
71 #include <sfx2/sfxresid.hxx>
72 #include <sfx2/request.hxx>
73 #include <sfx2/printer.hxx>
74 #include <sfx2/docfile.hxx>
75 #include <sfx2/dispatch.hxx>
76 #include <sfx2/strings.hrc>
77 #include <sfx2/sfxbasecontroller.hxx>
78 #include <sfx2/mailmodelapi.hxx>
79 #include <bluthsndapi.hxx>
80 #include <sfx2/viewfrm.hxx>
81 #include <sfx2/event.hxx>
82 #include <sfx2/ipclient.hxx>
83 #include <sfx2/sfxsids.hrc>
84 #include <sfx2/objface.hxx>
85 #include <sfx2/lokhelper.hxx>
86 #include <openuriexternally.hxx>
87 #include <shellimpl.hxx>
88 
89 #include <vector>
90 #include <libxml/xmlwriter.h>
91 
92 using namespace ::com::sun::star;
93 using namespace ::com::sun::star::uno;
94 using namespace ::com::sun::star::frame;
95 using namespace ::com::sun::star::beans;
96 using namespace ::com::sun::star::util;
97 using namespace ::cppu;
98 
99 #define ShellClass_SfxViewShell
100 #include <sfxslots.hxx>
101 
102 
103 class SfxClipboardChangeListener : public ::cppu::WeakImplHelper<
104     datatransfer::clipboard::XClipboardListener >
105 {
106 public:
107     SfxClipboardChangeListener( SfxViewShell* pView, const uno::Reference< datatransfer::clipboard::XClipboardNotifier >& xClpbrdNtfr );
108 
109     // XEventListener
110     virtual void SAL_CALL disposing( const lang::EventObject& rEventObject ) override;
111 
112     // XClipboardListener
113     virtual void SAL_CALL changedContents( const datatransfer::clipboard::ClipboardEvent& rEventObject ) override;
114 
115     void DisconnectViewShell() { m_pViewShell = nullptr; }
116     void ChangedContents();
117 
118     enum AsyncExecuteCmd
119     {
120         ASYNCEXECUTE_CMD_DISPOSING,
121         ASYNCEXECUTE_CMD_CHANGEDCONTENTS
122     };
123 
124     struct AsyncExecuteInfo
125     {
126         AsyncExecuteInfo( AsyncExecuteCmd eCmd, SfxClipboardChangeListener* pListener ) :
127             m_eCmd( eCmd ), m_xListener( pListener ) {}
128 
129         AsyncExecuteCmd m_eCmd;
130         rtl::Reference<SfxClipboardChangeListener> m_xListener;
131     };
132 
133 private:
134     SfxViewShell* m_pViewShell;
135     uno::Reference< datatransfer::clipboard::XClipboardNotifier > m_xClpbrdNtfr;
136     uno::Reference< lang::XComponent > m_xCtrl;
137 
138     DECL_STATIC_LINK( SfxClipboardChangeListener, AsyncExecuteHdl_Impl, void*, void );
139 };
140 
141 SfxClipboardChangeListener::SfxClipboardChangeListener( SfxViewShell* pView, const uno::Reference< datatransfer::clipboard::XClipboardNotifier >& xClpbrdNtfr )
142   : m_pViewShell( nullptr ), m_xClpbrdNtfr( xClpbrdNtfr ), m_xCtrl(pView->GetController())
143 {
144     if ( m_xCtrl.is() )
145     {
146         m_xCtrl->addEventListener( uno::Reference < lang::XEventListener > ( static_cast < lang::XEventListener* >( this ) ) );
147         m_pViewShell = pView;
148     }
149     if ( m_xClpbrdNtfr.is() )
150     {
151         m_xClpbrdNtfr->addClipboardListener( uno::Reference< datatransfer::clipboard::XClipboardListener >(
152             static_cast< datatransfer::clipboard::XClipboardListener* >( this )));
153     }
154 }
155 
156 void SfxClipboardChangeListener::ChangedContents()
157 {
158     const SolarMutexGuard aGuard;
159     if (!m_pViewShell)
160         return;
161 
162     SfxBindings& rBind = m_pViewShell->GetViewFrame()->GetBindings();
163     rBind.Invalidate(SID_PASTE);
164     rBind.Invalidate(SID_PASTE_SPECIAL);
165     rBind.Invalidate(SID_CLIPBOARD_FORMAT_ITEMS);
166 
167     if (comphelper::LibreOfficeKit::isActive())
168     {
169         // In the future we might send the payload as well.
170         SfxLokHelper::notifyAllViews(LOK_CALLBACK_CLIPBOARD_CHANGED, "");
171     }
172 }
173 
174 IMPL_STATIC_LINK( SfxClipboardChangeListener, AsyncExecuteHdl_Impl, void*, p, void )
175 {
176     AsyncExecuteInfo* pAsyncExecuteInfo = static_cast<AsyncExecuteInfo*>(p);
177     if ( pAsyncExecuteInfo )
178     {
179         if ( pAsyncExecuteInfo->m_xListener.is() )
180         {
181             if ( pAsyncExecuteInfo->m_eCmd == ASYNCEXECUTE_CMD_DISPOSING )
182                 pAsyncExecuteInfo->m_xListener->DisconnectViewShell();
183             else if ( pAsyncExecuteInfo->m_eCmd == ASYNCEXECUTE_CMD_CHANGEDCONTENTS )
184                 pAsyncExecuteInfo->m_xListener->ChangedContents();
185         }
186     }
187     delete pAsyncExecuteInfo;
188 }
189 
190 void SAL_CALL SfxClipboardChangeListener::disposing( const lang::EventObject& /*rEventObject*/ )
191 {
192     // Either clipboard or ViewShell is going to be destroyed -> no interest in listening anymore
193     uno::Reference< lang::XComponent > xCtrl( m_xCtrl );
194     uno::Reference< datatransfer::clipboard::XClipboardNotifier > xNotify( m_xClpbrdNtfr );
195 
196     uno::Reference< datatransfer::clipboard::XClipboardListener > xThis( static_cast< datatransfer::clipboard::XClipboardListener* >( this ));
197     if ( xCtrl.is() )
198         xCtrl->removeEventListener( uno::Reference < lang::XEventListener > ( static_cast < lang::XEventListener* >( this )));
199     if ( xNotify.is() )
200         xNotify->removeClipboardListener( xThis );
201 
202     // Make asynchronous call to avoid locking SolarMutex which is the
203     // root for many deadlocks, especially in conjunction with the "Windows"
204     // based single thread apartment clipboard code!
205     AsyncExecuteInfo* pInfo = new AsyncExecuteInfo( ASYNCEXECUTE_CMD_DISPOSING, this );
206     Application::PostUserEvent( LINK( nullptr, SfxClipboardChangeListener, AsyncExecuteHdl_Impl ), pInfo );
207 }
208 
209 void SAL_CALL SfxClipboardChangeListener::changedContents( const datatransfer::clipboard::ClipboardEvent& )
210 {
211     // Make asynchronous call to avoid locking SolarMutex which is the
212     // root for many deadlocks, especially in conjunction with the "Windows"
213     // based single thread apartment clipboard code!
214     AsyncExecuteInfo* pInfo = new AsyncExecuteInfo( ASYNCEXECUTE_CMD_CHANGEDCONTENTS, this );
215     Application::PostUserEvent( LINK( nullptr, SfxClipboardChangeListener, AsyncExecuteHdl_Impl ), pInfo );
216 }
217 
218 sal_uInt32 SfxViewShell_Impl::m_nLastViewShellId = 0;
219 
220 SfxViewShell_Impl::SfxViewShell_Impl(SfxViewShellFlags const nFlags)
221 : aInterceptorContainer( aMutex )
222 ,   m_bHasPrintOptions(nFlags & SfxViewShellFlags::HAS_PRINTOPTIONS)
223 ,   m_nFamily(0xFFFF)   // undefined, default set by TemplateDialog
224 ,   m_pLibreOfficeKitViewCallback(nullptr)
225 ,   m_pLibreOfficeKitViewData(nullptr)
226 ,   m_bTiledSearching(false)
227 ,   m_nViewShellId(SfxViewShell_Impl::m_nLastViewShellId++)
228 ,   m_nDocId(-1)
229 {
230 }
231 
232 SfxViewShell_Impl::~SfxViewShell_Impl()
233 {
234 }
235 
236 std::vector< SfxInPlaceClient* > *SfxViewShell_Impl::GetIPClients_Impl( bool bCreate ) const
237 {
238     if (!mpIPClients && bCreate)
239         mpIPClients.reset(new std::vector< SfxInPlaceClient* >);
240     return mpIPClients.get();
241 }
242 
243 SFX_IMPL_SUPERCLASS_INTERFACE(SfxViewShell,SfxShell)
244 
245 void SfxViewShell::InitInterface_Impl()
246 {
247 }
248 
249 
250 /** search for a filter name dependent on type and module
251  */
252 static OUString impl_retrieveFilterNameFromTypeAndModule(
253     const css::uno::Reference< css::container::XContainerQuery >& rContainerQuery,
254     const OUString& rType,
255     const OUString& rModuleIdentifier,
256     const sal_Int32 nFlags )
257 {
258     // Retrieve filter from type
259     css::uno::Sequence< css::beans::NamedValue > aQuery {
260         { "Type", css::uno::makeAny( rType ) },
261         { "DocumentService", css::uno::makeAny( rModuleIdentifier ) }
262     };
263 
264     css::uno::Reference< css::container::XEnumeration > xEnumeration =
265         rContainerQuery->createSubSetEnumerationByProperties( aQuery );
266 
267     OUString aFoundFilterName;
268     while ( xEnumeration->hasMoreElements() )
269     {
270         ::comphelper::SequenceAsHashMap aFilterPropsHM( xEnumeration->nextElement() );
271         OUString aFilterName = aFilterPropsHM.getUnpackedValueOrDefault(
272             "Name",
273             OUString() );
274 
275         sal_Int32 nFilterFlags = aFilterPropsHM.getUnpackedValueOrDefault(
276             "Flags",
277             sal_Int32( 0 ) );
278 
279         if ( nFilterFlags & nFlags )
280         {
281             aFoundFilterName = aFilterName;
282             break;
283         }
284     }
285 
286     return aFoundFilterName;
287 }
288 
289 namespace {
290 
291 /** search for an internal typename, which map to the current app module
292     and map also to a "family" of file formats as e.g. PDF/MS Doc/OOo Doc.
293  */
294 enum ETypeFamily
295 {
296     E_MS_DOC,
297     E_OOO_DOC
298 };
299 
300 }
301 
302 static OUString impl_searchFormatTypeForApp(const css::uno::Reference< css::frame::XFrame >& xFrame     ,
303                                                   ETypeFamily                                eTypeFamily)
304 {
305     try
306     {
307         css::uno::Reference< css::uno::XComponentContext >  xContext      (::comphelper::getProcessComponentContext());
308         css::uno::Reference< css::frame::XModuleManager2 >  xModuleManager(css::frame::ModuleManager::create(xContext));
309 
310         OUString sModule = xModuleManager->identify(xFrame);
311         OUString sType   ;
312 
313         switch(eTypeFamily)
314         {
315             case E_MS_DOC:
316             {
317                 if ( sModule == "com.sun.star.text.TextDocument" )
318                     sType = "writer_MS_Word_2007";
319                 else
320                 if ( sModule == "com.sun.star.sheet.SpreadsheetDocument" )
321                     sType = "MS Excel 2007 XML";
322                 else
323                 if ( sModule == "com.sun.star.presentation.PresentationDocument" )
324                     sType = "MS PowerPoint 2007 XML";
325             }
326             break;
327 
328             case E_OOO_DOC:
329             {
330                 if ( sModule == "com.sun.star.text.TextDocument" )
331                     sType = "writer8";
332                 else
333                 if ( sModule == "com.sun.star.sheet.SpreadsheetDocument" )
334                     sType = "calc8";
335                 else
336                 if ( sModule == "com.sun.star.drawing.DrawingDocument" )
337                     sType = "draw8";
338                 else
339                 if ( sModule == "com.sun.star.presentation.PresentationDocument" )
340                     sType = "impress8";
341             }
342             break;
343         }
344 
345         return sType;
346     }
347     catch (const css::uno::RuntimeException&)
348     {
349         throw;
350     }
351     catch (const css::uno::Exception&)
352     {
353     }
354 
355     return OUString();
356 }
357 
358 void SfxViewShell::NewIPClient_Impl( SfxInPlaceClient *pIPClient )
359 {
360     pImpl->GetIPClients_Impl()->push_back(pIPClient);
361 }
362 
363 void SfxViewShell::IPClientGone_Impl( SfxInPlaceClient const *pIPClient )
364 {
365     std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl();
366 
367     auto it = std::find(pClients->begin(), pClients->end(), pIPClient);
368     if (it != pClients->end())
369         pClients->erase( it );
370 }
371 
372 
373 void SfxViewShell::ExecMisc_Impl( SfxRequest &rReq )
374 {
375     const sal_uInt16 nId = rReq.GetSlot();
376     switch( nId )
377     {
378         case SID_STYLE_FAMILY :
379         {
380             const SfxUInt16Item* pItem = rReq.GetArg<SfxUInt16Item>(nId);
381             if (pItem)
382             {
383                 pImpl->m_nFamily = pItem->GetValue();
384             }
385             break;
386         }
387         case SID_ACTIVATE_STYLE_APPLY:
388         {
389             uno::Reference< frame::XFrame > xFrame =
390                 GetViewFrame()->GetFrame().GetFrameInterface();
391 
392             Reference< beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
393             Reference< frame::XLayoutManager > xLayoutManager;
394             if ( xPropSet.is() )
395             {
396                 try
397                 {
398                     Any aValue = xPropSet->getPropertyValue("LayoutManager");
399                     aValue >>= xLayoutManager;
400                     if ( xLayoutManager.is() )
401                     {
402                         uno::Reference< ui::XUIElement > xElement = xLayoutManager->getElement( "private:resource/toolbar/textobjectbar" );
403                         if(!xElement.is())
404                         {
405                             xElement = xLayoutManager->getElement( "private:resource/toolbar/frameobjectbar" );
406                         }
407                         if(!xElement.is())
408                         {
409                             xElement = xLayoutManager->getElement( "private:resource/toolbar/oleobjectbar" );
410                         }
411                         if(xElement.is())
412                         {
413                             uno::Reference< awt::XWindow > xWin( xElement->getRealInterface(), uno::UNO_QUERY_THROW );
414                             VclPtr<vcl::Window> pWin = VCLUnoHelper::GetWindow( xWin );
415                             ToolBox* pTextToolbox = dynamic_cast< ToolBox* >( pWin.get() );
416                             if( pTextToolbox )
417                             {
418                                 ToolBox::ImplToolItems::size_type nItemCount = pTextToolbox->GetItemCount();
419                                 for( ToolBox::ImplToolItems::size_type nItem = 0; nItem < nItemCount; ++nItem )
420                                 {
421                                     sal_uInt16 nItemId = pTextToolbox->GetItemId( nItem );
422                                     const OUString& rCommand = pTextToolbox->GetItemCommand( nItemId );
423                                     if (rCommand == ".uno:StyleApply")
424                                     {
425                                         vcl::Window* pItemWin = pTextToolbox->GetItemWindow( nItemId );
426                                         if( pItemWin )
427                                             pItemWin->GrabFocus();
428                                         break;
429                                     }
430                                 }
431                             }
432                         }
433                     }
434                 }
435                 catch (const Exception&)
436                 {
437                 }
438             }
439             rReq.Done();
440         }
441         break;
442 
443         case SID_MAIL_SENDDOCASMS:
444         case SID_MAIL_SENDDOCASOOO:
445         case SID_MAIL_SENDDOCASPDF:
446         case SID_MAIL_SENDDOC:
447         case SID_MAIL_SENDDOCASFORMAT:
448         {
449             SfxObjectShell* pDoc = GetObjectShell();
450             if ( pDoc && pDoc->QueryHiddenInformation(
451                              HiddenWarningFact::WhenSaving, GetViewFrame()->GetWindow().GetFrameWeld() ) != RET_YES )
452                 break;
453 
454 
455             SfxMailModel  aModel;
456             OUString aDocType;
457 
458             const SfxStringItem* pMailRecipient = rReq.GetArg<SfxStringItem>(SID_MAIL_RECIPIENT);
459             if ( pMailRecipient )
460             {
461                 OUString aRecipient( pMailRecipient->GetValue() );
462                 OUString aMailToStr("mailto:");
463 
464                 if ( aRecipient.startsWith( aMailToStr ) )
465                     aRecipient = aRecipient.copy( aMailToStr.getLength() );
466                 aModel.AddToAddress( aRecipient );
467             }
468             const SfxStringItem* pMailDocType = rReq.GetArg<SfxStringItem>(SID_TYPE_NAME);
469             if ( pMailDocType )
470                 aDocType = pMailDocType->GetValue();
471 
472             uno::Reference < frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() );
473             SfxMailModel::SendMailResult eResult = SfxMailModel::SEND_MAIL_ERROR;
474 
475             if ( nId == SID_MAIL_SENDDOC )
476                 eResult = aModel.SaveAndSend( xFrame, OUString() );
477             else if ( nId == SID_MAIL_SENDDOCASPDF )
478                 eResult = aModel.SaveAndSend( xFrame, "pdf_Portable_Document_Format");
479             else if ( nId == SID_MAIL_SENDDOCASMS )
480             {
481                 aDocType = impl_searchFormatTypeForApp(xFrame, E_MS_DOC);
482                 if (!aDocType.isEmpty())
483                     eResult = aModel.SaveAndSend( xFrame, aDocType );
484             }
485             else if ( nId == SID_MAIL_SENDDOCASOOO )
486             {
487                 aDocType = impl_searchFormatTypeForApp(xFrame, E_OOO_DOC);
488                 if (!aDocType.isEmpty())
489                     eResult = aModel.SaveAndSend( xFrame, aDocType );
490             }
491 
492             if ( eResult == SfxMailModel::SEND_MAIL_ERROR )
493             {
494                 vcl::Window* pWin = SfxGetpApp()->GetTopWindow();
495                 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
496                                                                          VclMessageType::Info, VclButtonsType::Ok,
497                                                                          SfxResId(STR_ERROR_SEND_MAIL)));
498                 xBox->run();
499                 rReq.Ignore();
500             }
501             else
502                 rReq.Done();
503         }
504         break;
505 
506         case SID_BLUETOOTH_SENDDOC:
507         {
508             SfxBluetoothModel aModel;
509             SfxObjectShell* pDoc = GetObjectShell();
510             if ( pDoc && pDoc->QueryHiddenInformation(
511                             HiddenWarningFact::WhenSaving, GetViewFrame()->GetWindow().GetFrameWeld() ) != RET_YES )
512                 break;
513             uno::Reference < frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() );
514             SfxMailModel::SendMailResult eResult = aModel.SaveAndSend( xFrame );
515             if( eResult == SfxMailModel::SEND_MAIL_ERROR )
516             {
517                 vcl::Window* pWin = SfxGetpApp()->GetTopWindow();
518                 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
519                                                                          VclMessageType::Info, VclButtonsType::Ok,
520                                                                          SfxResId(STR_ERROR_SEND_MAIL)));
521                 xBox->run();
522                 rReq.Ignore();
523             }
524             else
525                 rReq.Done();
526         }
527         break;
528 
529         // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
530         case SID_WEBHTML:
531         {
532             const sal_Int32   FILTERFLAG_EXPORT    = 0x00000002;
533 
534             css::uno::Reference< lang::XMultiServiceFactory > xSMGR(::comphelper::getProcessServiceFactory(), css::uno::UNO_SET_THROW);
535             css::uno::Reference< uno::XComponentContext >     xContext(::comphelper::getProcessComponentContext(), css::uno::UNO_SET_THROW);
536             css::uno::Reference< css::frame::XFrame >         xFrame( pFrame->GetFrame().GetFrameInterface() );
537             css::uno::Reference< css::frame::XModel >         xModel;
538 
539             css::uno::Reference< css::frame::XModuleManager2 > xModuleManager( css::frame::ModuleManager::create(xContext) );
540 
541             OUString aModule;
542             try
543             {
544                 aModule = xModuleManager->identify( xFrame );
545             }
546             catch (const css::uno::RuntimeException&)
547             {
548                 throw;
549             }
550             catch (const css::uno::Exception&)
551             {
552             }
553 
554             if ( xFrame.is() )
555             {
556                 css::uno::Reference< css::frame::XController > xController = xFrame->getController();
557                 if ( xController.is() )
558                     xModel = xController->getModel();
559             }
560 
561             // We need at least a valid module name and model reference
562             css::uno::Reference< css::frame::XStorable > xStorable( xModel, css::uno::UNO_QUERY );
563             if ( xModel.is() && xStorable.is() )
564             {
565                 OUString aFilterName;
566                 OUString aTypeName( "generic_HTML" );
567                 OUString aFileName;
568 
569                 OUString aLocation = xStorable->getLocation();
570                 INetURLObject aFileObj( aLocation );
571 
572                 bool bPrivateProtocol = ( aFileObj.GetProtocol() == INetProtocol::PrivSoffice );
573                 bool bHasLocation = !aLocation.isEmpty() && !bPrivateProtocol;
574 
575                 css::uno::Reference< css::container::XContainerQuery > xContainerQuery(
576                     xSMGR->createInstance( "com.sun.star.document.FilterFactory" ),
577                     css::uno::UNO_QUERY_THROW );
578 
579                 // Retrieve filter from type
580                 sal_Int32 nFilterFlags = FILTERFLAG_EXPORT;
581                 aFilterName = impl_retrieveFilterNameFromTypeAndModule( xContainerQuery, aTypeName, aModule, nFilterFlags );
582                 if ( aFilterName.isEmpty() )
583                 {
584                     // Draw/Impress uses a different type. 2nd chance try to use alternative type name
585                     aFilterName = impl_retrieveFilterNameFromTypeAndModule(
586                         xContainerQuery, "graphic_HTML", aModule, nFilterFlags );
587                 }
588 
589                 // No filter found => error
590                 // No type and no location => error
591                 if ( aFilterName.isEmpty() ||  aTypeName.isEmpty())
592                 {
593                     rReq.Done();
594                     return;
595                 }
596 
597                 // Use provided save file name. If empty determine file name
598                 if ( !bHasLocation )
599                 {
600                     // Create a default file name with the correct extension
601                     aFileName = "webpreview";
602                 }
603                 else
604                 {
605                     // Determine file name from model
606                     INetURLObject aFObj( xStorable->getLocation() );
607                     aFileName = aFObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::NONE );
608                 }
609 
610                 OSL_ASSERT( !aFilterName.isEmpty() );
611                 OSL_ASSERT( !aFileName.isEmpty() );
612 
613                 // Creates a temporary directory to store our predefined file into it (for the
614                 // flatpak case, create it in XDG_CACHE_HOME instead of /tmp for technical reasons,
615                 // so that it can be accessed by the browser running outside the sandbox):
616                 OUString * parent = nullptr;
617                 if (flatpak::isFlatpak() && !flatpak::createTemporaryHtmlDirectory(&parent))
618                 {
619                     SAL_WARN("sfx.view", "cannot create Flatpak html temp dir");
620                 }
621                 ::utl::TempFile aTempDir( parent, true );
622 
623                 INetURLObject aFilePathObj( aTempDir.GetURL() );
624                 aFilePathObj.insertName( aFileName );
625                 aFilePathObj.setExtension( "htm" );
626 
627                 OUString aFileURL = aFilePathObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
628 
629                 css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 );
630                 aArgs[0].Name  = "FilterName";
631                 aArgs[0].Value <<= aFilterName;
632 
633                 // Store document in the html format
634                 try
635                 {
636                     xStorable->storeToURL( aFileURL, aArgs );
637                 }
638                 catch (const io::IOException&)
639                 {
640                     rReq.Done();
641                     return;
642                 }
643 
644                 sfx2::openUriExternally(aFileURL, true);
645                 rReq.Done(true);
646                 break;
647             }
648             else
649             {
650                 rReq.Done();
651                 return;
652             }
653         }
654     }
655 }
656 
657 
658 void SfxViewShell::GetState_Impl( SfxItemSet &rSet )
659 {
660 
661     SfxWhichIter aIter( rSet );
662     SfxObjectShell *pSh = GetViewFrame()->GetObjectShell();
663     for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() )
664     {
665         switch ( nSID )
666         {
667 
668             case SID_BLUETOOTH_SENDDOC:
669             case SID_MAIL_SENDDOC:
670             case SID_MAIL_SENDDOCASFORMAT:
671             case SID_MAIL_SENDDOCASMS:
672             case SID_MAIL_SENDDOCASOOO:
673             case SID_MAIL_SENDDOCASPDF:
674             {
675 #if HAVE_FEATURE_MACOSX_SANDBOX
676                 rSet.DisableItem(nSID);
677 #endif
678                 if (pSh && pSh->isExportLocked() && nSID != SID_MAIL_SENDDOC)
679                     rSet.DisableItem(nSID);
680                 break;
681             }
682             case SID_WEBHTML:
683             {
684                 if (pSh && pSh->isExportLocked())
685                     rSet.DisableItem(nSID);
686                 break;
687             }
688             // Printer functions
689             case SID_PRINTDOC:
690             case SID_PRINTDOCDIRECT:
691             case SID_SETUPPRINTER:
692             case SID_PRINTER_NAME:
693             {
694                 if (Application::GetSettings().GetMiscSettings().GetDisablePrinting()
695                     || (pSh && pSh->isPrintLocked()))
696                 {
697                     rSet.DisableItem(nSID);
698                     break;
699                 }
700 
701                 SfxPrinter *pPrinter = GetPrinter();
702 
703                 if ( SID_PRINTDOCDIRECT == nSID )
704                 {
705                     OUString aPrinterName;
706                     if ( pPrinter != nullptr )
707                         aPrinterName = pPrinter->GetName();
708                     else
709                         aPrinterName = Printer::GetDefaultPrinterName();
710                     if ( !aPrinterName.isEmpty() )
711                     {
712                         uno::Reference < frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() );
713 
714                         OUStringBuffer aBuffer( 60 );
715                         auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(".uno:PrintDefault",
716                             vcl::CommandInfoProvider::GetModuleIdentifier(xFrame));
717                         aBuffer.append(vcl::CommandInfoProvider::GetLabelForCommand(aProperties));
718                         aBuffer.append( " (" );
719                         aBuffer.append( aPrinterName );
720                         aBuffer.append(')');
721 
722                         rSet.Put( SfxStringItem( SID_PRINTDOCDIRECT, aBuffer.makeStringAndClear() ) );
723                     }
724                 }
725                 break;
726             }
727             case SID_STYLE_FAMILY :
728             {
729                 rSet.Put( SfxUInt16Item( SID_STYLE_FAMILY, pImpl->m_nFamily ) );
730                 break;
731             }
732         }
733     }
734 }
735 
736 
737 void SfxViewShell::SetZoomFactor( const Fraction &rZoomX,
738     const Fraction &rZoomY )
739 {
740     DBG_ASSERT( GetWindow(), "no window" );
741     MapMode aMap( GetWindow()->GetMapMode() );
742     aMap.SetScaleX( rZoomX );
743     aMap.SetScaleY( rZoomY );
744     GetWindow()->SetMapMode( aMap );
745 }
746 
747 
748 ErrCode SfxViewShell::DoVerb(long /*nVerb*/)
749 
750 /*  [Description]
751 
752     Virtual Method used to perform a Verb on a selected Object.
753     Since this Object is only known by the derived classes, they must override
754     DoVerb.
755 */
756 
757 {
758     return ERRCODE_SO_NOVERBS;
759 }
760 
761 
762 void SfxViewShell::OutplaceActivated( bool bActive )
763 {
764     if ( !bActive )
765         GetFrame()->GetFrame().Appear();
766 }
767 
768 
769 void SfxViewShell::UIActivating( SfxInPlaceClient* /*pClient*/ )
770 {
771     uno::Reference < frame::XFrame > xOwnFrame( pFrame->GetFrame().GetFrameInterface() );
772     uno::Reference < frame::XFramesSupplier > xParentFrame = xOwnFrame->getCreator();
773     if ( xParentFrame.is() )
774         xParentFrame->setActiveFrame( xOwnFrame );
775 
776     pFrame->GetBindings().HidePopups();
777     pFrame->GetDispatcher()->Update_Impl( true );
778 }
779 
780 
781 void SfxViewShell::UIDeactivated( SfxInPlaceClient* /*pClient*/ )
782 {
783     if ( !pFrame->GetFrame().IsClosing_Impl() || SfxViewFrame::Current() != pFrame )
784         pFrame->GetDispatcher()->Update_Impl( true );
785     pFrame->GetBindings().HidePopups(false);
786 
787     pFrame->GetBindings().InvalidateAll(true);
788 }
789 
790 
791 SfxInPlaceClient* SfxViewShell::FindIPClient
792 (
793     const uno::Reference < embed::XEmbeddedObject >& xObj,
794     vcl::Window*             pObjParentWin
795 )   const
796 {
797     std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
798     if ( !pClients )
799         return nullptr;
800 
801     if( !pObjParentWin )
802         pObjParentWin = GetWindow();
803     for (SfxInPlaceClient* pIPClient : *pClients)
804     {
805         if ( pIPClient->GetObject() == xObj && pIPClient->GetEditWin() == pObjParentWin )
806             return pIPClient;
807     }
808 
809     return nullptr;
810 }
811 
812 
813 SfxInPlaceClient* SfxViewShell::GetIPClient() const
814 {
815     return GetUIActiveClient();
816 }
817 
818 
819 SfxInPlaceClient* SfxViewShell::GetUIActiveIPClient_Impl() const
820 {
821     // this method is needed as long as SFX still manages the border space for ChildWindows (see SfxFrame::Resize)
822     std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
823     if ( !pClients )
824         return nullptr;
825 
826     for (SfxInPlaceClient* pIPClient : *pClients)
827     {
828         if ( pIPClient->IsUIActive() )
829             return pIPClient;
830     }
831 
832     return nullptr;
833 }
834 
835 SfxInPlaceClient* SfxViewShell::GetUIActiveClient() const
836 {
837     std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
838     if ( !pClients )
839         return nullptr;
840 
841     const bool bIsTiledRendering = comphelper::LibreOfficeKit::isActive();
842 
843     for (SfxInPlaceClient* pIPClient : *pClients)
844     {
845         if ( pIPClient->IsObjectUIActive() || ( bIsTiledRendering && pIPClient->IsObjectInPlaceActive() ) )
846             return pIPClient;
847     }
848 
849     return nullptr;
850 }
851 
852 
853 void SfxViewShell::Activate( bool bMDI )
854 {
855     if ( bMDI )
856     {
857         SfxObjectShell *pSh = GetViewFrame()->GetObjectShell();
858         if ( pSh->GetModel().is() )
859             pSh->GetModel()->setCurrentController( GetViewFrame()->GetFrame().GetController() );
860 
861         SetCurrentDocument();
862     }
863 }
864 
865 
866 void SfxViewShell::Deactivate(bool /*bMDI*/)
867 {
868 }
869 
870 
871 void SfxViewShell::Move()
872 
873 /*  [Description]
874 
875     This virtual Method is called when the window displayed in the
876     SfxViewShell gets a StarView-Move() notification.
877 
878     This base implementation does not have to be called.     .
879 
880     [Note]
881 
882     This Method can be used to cancel a selection, in order to catch the
883     mouse movement which is due to moving a window.
884 
885     For now the notification does not work In-Place.
886 */
887 
888 {
889 }
890 
891 
892 void SfxViewShell::OuterResizePixel
893 (
894     const Point&    /*rToolOffset*/,// Upper left corner Tools in Frame-Window
895     const Size&     /*rSize*/       // All available sizes.
896 )
897 
898 /*  [Description]
899 
900     Override this Method to be able to react to the size-change of
901     the View. Thus the View is defined as the Edit window and also the
902     attached Tools are defined (for example the ruler).
903 
904     The Edit window must not be changed either in size or position.
905 
906     The Vis-Area of SfxObjectShell, its scale and position can be changed
907     here. The main use is to change the size of the Vis-Area.
908 
909     If the Border is changed due to the new calculation then this has to be set
910     by <SfxViewShell::SetBorderPixel(const SvBorder&)>. The Positioning of Tools
911     is only allowed after the calling of 'SetBorderPixel'.
912 
913     [Example]
914 
915     void AppViewSh::OuterViewResizePixel( const Point &rOfs, const Size &rSz )
916     {
917         // Calculate Tool position and size externally, do not set!
918         // (due to the following Border calculation)
919         Point aHLinPos...; Size aHLinSz...;
920         ...
921 
922         // Calculate and Set a Border of Tools which matches rSize.
923         SvBorder aBorder...
924         SetBorderPixel( aBorder ); // Allow Positioning from here on.
925 
926         // Arrange Tools
927         pHLin->SetPosSizePixel( aHLinPos, aHLinSz );
928         ...
929     }
930 
931     [Cross-reference]
932 
933         <SfxViewShell::InnerResizePixel(const Point&,const Size& rSize)>
934 */
935 
936 {
937     SetBorderPixel( SvBorder() );
938 }
939 
940 
941 void SfxViewShell::InnerResizePixel
942 (
943     const Point&    /*rToolOffset*/,// Upper left corner Tools in Frame-Window
944     const Size&     /*rSize*/,      // All available sizes.
945     bool
946 )
947 
948 /*  [Description]
949 
950     Override this Method to be able to react to the size-change of
951     the Edit window.
952 
953     The Edit window must not be changed either in size or position.
954     Neither the Vis-Area of SfxObjectShell nor its scale or position are
955     allowed to be changed
956 
957     If the Border is changed due to the new calculation then is has to be set
958     by <SfxViewShell::SetBorderPixel(const SvBorder&)>.
959     The Positioning of Tools is only allowed after the calling of
960     'SetBorderPixel'.
961 
962 
963     [Note]
964 
965     void AppViewSh::InnerViewResizePixel( const Point &rOfs, const Size &rSz )
966     {
967         // Calculate Tool position and size internally, do not set!
968         // (due to the following Border calculation)
969         Point aHLinPos...; Size aHLinSz...;
970         ...
971 
972         // Calculate and Set a Border of Tools which matches rSize.
973         SvBorder aBorder...
974         SetBorderPixel( aBorder ); // Allow Positioning from here on.
975 
976         // Arrange Tools
977         pHLin->SetPosSizePixel( aHLinPos, aHLinSz );
978         ...
979     }
980 
981     [Cross-reference]
982 
983         <SfxViewShell::OuterResizePixel(const Point&,const Size& rSize)>
984 */
985 
986 {
987     SetBorderPixel( SvBorder() );
988 }
989 
990 
991 void SfxViewShell::InvalidateBorder()
992 {
993     DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" );
994 
995     GetViewFrame()->InvalidateBorderImpl( this );
996     if (pImpl->m_pController.is())
997     {
998         pImpl->m_pController->BorderWidthsChanged_Impl();
999     }
1000 }
1001 
1002 
1003 void SfxViewShell::SetBorderPixel( const SvBorder &rBorder )
1004 {
1005     DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" );
1006 
1007     GetViewFrame()->SetBorderPixelImpl( this, rBorder );
1008 
1009     // notify related controller that border size is changed
1010     if (pImpl->m_pController.is())
1011     {
1012         pImpl->m_pController->BorderWidthsChanged_Impl();
1013     }
1014 }
1015 
1016 
1017 const SvBorder& SfxViewShell::GetBorderPixel() const
1018 {
1019     DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" );
1020 
1021     return GetViewFrame()->GetBorderPixelImpl();
1022 }
1023 
1024 
1025 void SfxViewShell::SetWindow
1026 (
1027     vcl::Window*     pViewPort   // For example Null pointer in the Destructor.
1028 )
1029 
1030 /*  [Description]
1031 
1032     With this method the SfxViewShell is set in the data window. This is
1033     needed for the in-place container and for restoring the proper focus.
1034 
1035     Even in-place-active the conversion of the ViewPort Windows is forbidden.
1036 */
1037 
1038 {
1039     if( pWindow == pViewPort )
1040         return;
1041 
1042     // Disconnect existing IP-Clients if possible
1043     DisconnectAllClients();
1044 
1045     // Switch View-Port
1046     bool bHadFocus = pWindow && pWindow->HasChildPathFocus( true );
1047     pWindow = pViewPort;
1048 
1049     if( pWindow )
1050     {
1051         // Disable automatic GUI mirroring (right-to-left) for document windows
1052         pWindow->EnableRTL( false );
1053     }
1054 
1055     if ( bHadFocus && pWindow )
1056         pWindow->GrabFocus();
1057     //TODO/CLEANUP
1058     //Do we still need this Method?!
1059     //SfxGetpApp()->GrabFocus( pWindow );
1060 }
1061 
1062 
1063 SfxViewShell::SfxViewShell
1064 (
1065     SfxViewFrame*     pViewFrame,     /*  <SfxViewFrame>, which will be
1066                                           displayed in this View */
1067     SfxViewShellFlags nFlags          /*  See <SfxViewShell-Flags> */
1068 )
1069 
1070 :   SfxShell(this)
1071 ,   pImpl( new SfxViewShell_Impl(nFlags) )
1072 ,   pFrame(pViewFrame)
1073 ,   pWindow(nullptr)
1074 ,   bNoNewWindow( nFlags & SfxViewShellFlags::NO_NEWWINDOW )
1075 ,   mbPrinterSettingsModified(false)
1076 ,   maLOKLanguageTag(LANGUAGE_NONE)
1077 ,   maLOKLocale(LANGUAGE_NONE)
1078 ,   maLOKDeviceFormFactor(LOKDeviceFormFactor::UNKNOWN)
1079 {
1080     SetMargin( pViewFrame->GetMargin_Impl() );
1081 
1082     SetPool( &pViewFrame->GetObjectShell()->GetPool() );
1083     StartListening(*pViewFrame->GetObjectShell());
1084 
1085     // Insert into list
1086     SfxViewShellArr_Impl &rViewArr = SfxGetpApp()->GetViewShells_Impl();
1087     rViewArr.push_back(this);
1088 
1089     if (comphelper::LibreOfficeKit::isActive())
1090     {
1091         maLOKLanguageTag = SfxLokHelper::getDefaultLanguage();
1092         maLOKLocale = SfxLokHelper::getDefaultLanguage();
1093 
1094         maLOKDeviceFormFactor = SfxLokHelper::getDeviceFormFactor();
1095 
1096         vcl::Window* pFrameWin = pViewFrame->GetWindow().GetFrameWindow();
1097         if (pFrameWin && !pFrameWin->GetLOKNotifier())
1098             pFrameWin->SetLOKNotifier(this, true);
1099     }
1100 }
1101 
1102 
1103 SfxViewShell::~SfxViewShell()
1104 {
1105     // Remove from list
1106     const SfxViewShell *pThis = this;
1107     SfxViewShellArr_Impl &rViewArr = SfxGetpApp()->GetViewShells_Impl();
1108     SfxViewShellArr_Impl::iterator it = std::find( rViewArr.begin(), rViewArr.end(), pThis );
1109     rViewArr.erase( it );
1110 
1111     if ( pImpl->xClipboardListener.is() )
1112     {
1113         pImpl->xClipboardListener->DisconnectViewShell();
1114         pImpl->xClipboardListener = nullptr;
1115     }
1116 
1117     if (pImpl->m_pController.is())
1118     {
1119         pImpl->m_pController->ReleaseShell_Impl();
1120         pImpl->m_pController.clear();
1121     }
1122 
1123     vcl::Window* pFrameWin = GetViewFrame()->GetWindow().GetFrameWindow();
1124     if (pFrameWin && pFrameWin->GetLOKNotifier() == this)
1125         pFrameWin->ReleaseLOKNotifier();
1126 }
1127 
1128 bool SfxViewShell::PrepareClose
1129 (
1130     bool bUI     // TRUE: Allow Dialog and so on, FALSE: silent-mode
1131 )
1132 {
1133     if (GetViewFrame()->GetWindow().GetLOKNotifier() == this)
1134         GetViewFrame()->GetWindow().ReleaseLOKNotifier();
1135 
1136     SfxPrinter *pPrinter = GetPrinter();
1137     if ( pPrinter && pPrinter->IsPrinting() )
1138     {
1139         if ( bUI )
1140         {
1141             std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetViewFrame()->GetWindow().GetFrameWeld(),
1142                                                                      VclMessageType::Info, VclButtonsType::Ok,
1143                                                                      SfxResId(STR_CANT_CLOSE)));
1144             xBox->run();
1145         }
1146 
1147         return false;
1148     }
1149 
1150     if( GetViewFrame()->IsInModalMode() )
1151         return false;
1152 
1153     if( bUI && GetViewFrame()->GetDispatcher()->IsLocked() )
1154         return false;
1155 
1156     return true;
1157 }
1158 
1159 
1160 SfxViewShell* SfxViewShell::Current()
1161 {
1162     SfxViewFrame *pCurrent = SfxViewFrame::Current();
1163     return pCurrent ? pCurrent->GetViewShell() : nullptr;
1164 }
1165 
1166 
1167 SfxViewShell* SfxViewShell::Get( const Reference< XController>& i_rController )
1168 {
1169     if ( !i_rController.is() )
1170         return nullptr;
1171 
1172     for (   SfxViewShell* pViewShell = SfxViewShell::GetFirst( false );
1173             pViewShell;
1174             pViewShell = SfxViewShell::GetNext( *pViewShell, false )
1175         )
1176     {
1177         if ( pViewShell->GetController() == i_rController )
1178             return pViewShell;
1179     }
1180     return nullptr;
1181 }
1182 
1183 
1184 SdrView* SfxViewShell::GetDrawView() const
1185 
1186 /*  [Description]
1187 
1188     This virtual Method has to be overloaded by the sub classes, to be able
1189     make the Property-Editor available.
1190 
1191     The default implementation does always return zero.
1192 */
1193 
1194 {
1195     return nullptr;
1196 }
1197 
1198 
1199 OUString SfxViewShell::GetSelectionText
1200 (
1201     bool /*bCompleteWords*/ /*  FALSE (default)
1202                                 Only the actual selected text is returned.
1203 
1204                                 TRUE
1205                                 The selected text is expanded so that only
1206                                 whole words are returned. As word separators
1207                                 these are used: white spaces and punctuation
1208                                 ".,;" and single and double quotes.
1209                             */
1210 )
1211 
1212 /*  [Description]
1213 
1214     Override this Method to return a text that
1215     is included in the current selection. This is for example used when
1216     sending emails.
1217 
1218     When called with "CompleteWords == TRUE", it is for example sufficient
1219     with having the Cursor positioned somewhere within a URL in-order
1220     to have the entire URL returned.
1221 */
1222 
1223 {
1224     return OUString();
1225 }
1226 
1227 
1228 bool SfxViewShell::HasSelection( bool ) const
1229 
1230 /*  [Description]
1231 
1232     With this virtual Method can a for example a Dialog be queried, to
1233     check if something is selected in the current view. If the Parameter
1234     is <BOOL> TRUE then it is checked whether some text is selected.
1235 */
1236 
1237 {
1238     return false;
1239 }
1240 
1241 void SfxViewShell::AddSubShell( SfxShell& rShell )
1242 {
1243     pImpl->aArr.push_back(&rShell);
1244     SfxDispatcher *pDisp = pFrame->GetDispatcher();
1245     if ( pDisp->IsActive(*this) )
1246     {
1247         pDisp->Push(rShell);
1248         pDisp->Flush();
1249     }
1250 }
1251 
1252 void SfxViewShell::RemoveSubShell( SfxShell* pShell )
1253 {
1254     SfxDispatcher *pDisp = pFrame->GetDispatcher();
1255     if ( !pShell )
1256     {
1257         size_t nCount = pImpl->aArr.size();
1258         if ( pDisp->IsActive(*this) )
1259         {
1260             for(size_t n = nCount; n > 0; --n)
1261                 pDisp->Pop(*pImpl->aArr[n - 1]);
1262             pDisp->Flush();
1263         }
1264         pImpl->aArr.clear();
1265     }
1266     else
1267     {
1268         SfxShellArr_Impl::iterator i = std::find(pImpl->aArr.begin(), pImpl->aArr.end(), pShell);
1269         if(i != pImpl->aArr.end())
1270         {
1271             pImpl->aArr.erase(i);
1272             if(pDisp->IsActive(*this))
1273             {
1274                 pDisp->RemoveShell_Impl(*pShell);
1275                 pDisp->Flush();
1276             }
1277         }
1278     }
1279 }
1280 
1281 SfxShell* SfxViewShell::GetSubShell( sal_uInt16 nNo )
1282 {
1283     sal_uInt16 nCount = pImpl->aArr.size();
1284     if(nNo < nCount)
1285         return pImpl->aArr[nCount - nNo - 1];
1286     return nullptr;
1287 }
1288 
1289 void SfxViewShell::PushSubShells_Impl( bool bPush )
1290 {
1291     SfxDispatcher *pDisp = pFrame->GetDispatcher();
1292     if ( bPush )
1293     {
1294         for (auto const& elem : pImpl->aArr)
1295             pDisp->Push(*elem);
1296     }
1297     else if(!pImpl->aArr.empty())
1298     {
1299         SfxShell& rPopUntil = *pImpl->aArr[0];
1300         if ( pDisp->GetShellLevel( rPopUntil ) != USHRT_MAX )
1301             pDisp->Pop( rPopUntil, SfxDispatcherPopFlags::POP_UNTIL );
1302     }
1303 
1304     pDisp->Flush();
1305 }
1306 
1307 
1308 void SfxViewShell::WriteUserData( OUString&, bool )
1309 {
1310 }
1311 
1312 
1313 void SfxViewShell::ReadUserData(const OUString&, bool )
1314 {
1315 }
1316 
1317 void SfxViewShell::ReadUserDataSequence ( const uno::Sequence < beans::PropertyValue >& )
1318 {
1319 }
1320 
1321 void SfxViewShell::WriteUserDataSequence ( uno::Sequence < beans::PropertyValue >& )
1322 {
1323 }
1324 
1325 
1326 // returns the first shell of spec. type viewing the specified doc.
1327 SfxViewShell* SfxViewShell::GetFirst
1328 (
1329     bool          bOnlyVisible,
1330     const std::function< bool ( const SfxViewShell* ) >& isViewShell
1331 )
1332 {
1333     // search for a SfxViewShell of the specified type
1334     SfxViewShellArr_Impl &rShells = SfxGetpApp()->GetViewShells_Impl();
1335     SfxViewFrameArr_Impl &rFrames = SfxGetpApp()->GetViewFrames_Impl();
1336     for (SfxViewShell* pShell : rShells)
1337     {
1338         if ( pShell )
1339         {
1340             // sometimes dangling SfxViewShells exist that point to a dead SfxViewFrame
1341             // these ViewShells shouldn't be accessible anymore
1342             // a destroyed ViewFrame is not in the ViewFrame array anymore, so checking this array helps
1343             for (SfxViewFrame* pFrame : rFrames)
1344             {
1345                 if ( pFrame == pShell->GetViewFrame() )
1346                 {
1347                     // only ViewShells with a valid ViewFrame will be returned
1348                     if ( ( !bOnlyVisible || pFrame->IsVisible() ) && (!isViewShell || isViewShell(pShell)))
1349                         return pShell;
1350                     break;
1351                 }
1352             }
1353         }
1354     }
1355 
1356     return nullptr;
1357 }
1358 
1359 
1360 // returns the next shell of spec. type viewing the specified doc.
1361 
1362 SfxViewShell* SfxViewShell::GetNext
1363 (
1364     const SfxViewShell& rPrev,
1365     bool                bOnlyVisible,
1366     const std::function<bool ( const SfxViewShell* )>& isViewShell
1367 )
1368 {
1369     SfxViewShellArr_Impl &rShells = SfxGetpApp()->GetViewShells_Impl();
1370     SfxViewFrameArr_Impl &rFrames = SfxGetpApp()->GetViewFrames_Impl();
1371     size_t nPos;
1372     for ( nPos = 0; nPos < rShells.size(); ++nPos )
1373         if ( rShells[nPos] == &rPrev )
1374             break;
1375 
1376     for ( ++nPos; nPos < rShells.size(); ++nPos )
1377     {
1378         SfxViewShell *pShell = rShells[nPos];
1379         if ( pShell )
1380         {
1381             // sometimes dangling SfxViewShells exist that point to a dead SfxViewFrame
1382             // these ViewShells shouldn't be accessible anymore
1383             // a destroyed ViewFrame is not in the ViewFrame array anymore, so checking this array helps
1384             for (SfxViewFrame* pFrame : rFrames)
1385             {
1386                 if ( pFrame == pShell->GetViewFrame() )
1387                 {
1388                     // only ViewShells with a valid ViewFrame will be returned
1389                     if ( ( !bOnlyVisible || pFrame->IsVisible() ) && (!isViewShell || isViewShell(pShell)) )
1390                         return pShell;
1391                     break;
1392                 }
1393             }
1394         }
1395     }
1396 
1397     return nullptr;
1398 }
1399 
1400 
1401 void SfxViewShell::Notify( SfxBroadcaster& rBC,
1402                             const SfxHint& rHint )
1403 {
1404     const SfxEventHint* pEventHint = dynamic_cast<const SfxEventHint*>(&rHint);
1405     if ( !(pEventHint && pEventHint->GetEventId() == SfxEventHintId::LoadFinished) )
1406         return;
1407 
1408     if ( !GetController().is() )
1409         return;
1410 
1411     // avoid access to dangling ViewShells
1412     SfxViewFrameArr_Impl &rFrames = SfxGetpApp()->GetViewFrames_Impl();
1413     for (SfxViewFrame* frame : rFrames)
1414     {
1415         if ( frame == GetViewFrame() && &rBC == GetObjectShell() )
1416         {
1417             SfxItemSet* pSet = GetObjectShell()->GetMedium()->GetItemSet();
1418             const SfxUnoAnyItem* pItem = SfxItemSet::GetItem<SfxUnoAnyItem>(pSet, SID_VIEW_DATA, false);
1419             if ( pItem )
1420             {
1421                 pImpl->m_pController->restoreViewData( pItem->GetValue() );
1422                 pSet->ClearItem( SID_VIEW_DATA );
1423             }
1424             break;
1425         }
1426     }
1427 }
1428 
1429 bool SfxViewShell::ExecKey_Impl(const KeyEvent& aKey)
1430 {
1431     if (!pImpl->m_xAccExec)
1432     {
1433         pImpl->m_xAccExec = ::svt::AcceleratorExecute::createAcceleratorHelper();
1434         pImpl->m_xAccExec->init(::comphelper::getProcessComponentContext(),
1435             pFrame->GetFrame().GetFrameInterface());
1436     }
1437 
1438     return pImpl->m_xAccExec->execute(aKey.GetKeyCode());
1439 }
1440 
1441 void SfxViewShell::registerLibreOfficeKitViewCallback(LibreOfficeKitCallback pCallback, void* pData)
1442 {
1443     pImpl->m_pLibreOfficeKitViewCallback = pCallback;
1444     pImpl->m_pLibreOfficeKitViewData = pData;
1445 
1446     afterCallbackRegistered();
1447 
1448     if (!pCallback)
1449         return;
1450 
1451     // Ask other views to tell us about their cursors.
1452     SfxViewShell* pViewShell = SfxViewShell::GetFirst();
1453     while (pViewShell)
1454     {
1455         if (pViewShell->GetDocId() == GetDocId())
1456             pViewShell->NotifyCursor(this);
1457         pViewShell = SfxViewShell::GetNext(*pViewShell);
1458     }
1459 }
1460 
1461 void SfxViewShell::libreOfficeKitViewCallback(int nType, const char* pPayload) const
1462 {
1463     if (!comphelper::LibreOfficeKit::isActive())
1464         return;
1465 
1466     if (comphelper::LibreOfficeKit::isTiledPainting() && nType != LOK_CALLBACK_FORM_FIELD_BUTTON)
1467         return;
1468 
1469     if (pImpl->m_bTiledSearching)
1470     {
1471         switch (nType)
1472         {
1473         case LOK_CALLBACK_TEXT_SELECTION:
1474         case LOK_CALLBACK_TEXT_VIEW_SELECTION:
1475         case LOK_CALLBACK_TEXT_SELECTION_START:
1476         case LOK_CALLBACK_TEXT_SELECTION_END:
1477         case LOK_CALLBACK_GRAPHIC_SELECTION:
1478         case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION:
1479             return;
1480         }
1481     }
1482 
1483     if (pImpl->m_pLibreOfficeKitViewCallback)
1484         pImpl->m_pLibreOfficeKitViewCallback(nType, pPayload, pImpl->m_pLibreOfficeKitViewData);
1485     else
1486         SAL_INFO(
1487             "sfx.view",
1488             "SfxViewShell::libreOfficeKitViewCallback no callback set! Dropped payload of type "
1489             << lokCallbackTypeToString(nType) << ": [" << pPayload << ']');
1490 }
1491 
1492 void SfxViewShell::afterCallbackRegistered()
1493 {
1494 }
1495 
1496 vcl::Window* SfxViewShell::GetEditWindowForActiveOLEObj() const
1497 {
1498     vcl::Window* pEditWin = nullptr;
1499     SfxInPlaceClient* pIPClient = GetIPClient();
1500     if (pIPClient)
1501     {
1502         pEditWin = pIPClient->GetEditWin();
1503     }
1504     return pEditWin;
1505 }
1506 
1507 void SfxViewShell::SetLOKLanguageTag(const OUString& rBcp47LanguageTag)
1508 {
1509     LanguageTag aTag(rBcp47LanguageTag, true);
1510 
1511     css::uno::Sequence<OUString> inst(officecfg::Setup::Office::InstalledLocales::get()->getElementNames());
1512     LanguageTag aFallbackTag = LanguageTag(getInstalledLocaleForSystemUILanguage(inst, /* bRequestInstallIfMissing */ false, rBcp47LanguageTag), true).makeFallback();
1513 
1514     // If we want de-CH, and the de localisation is available, we don't want to use de-DE as then
1515     // the magic in Translate::get() won't turn ess-zet into double s. Possibly other similar cases?
1516     if (comphelper::LibreOfficeKit::isActive() && aTag.getLanguage() == aFallbackTag.getLanguage())
1517         maLOKLanguageTag = aTag;
1518     else
1519         maLOKLanguageTag = aFallbackTag;
1520 }
1521 
1522 void SfxViewShell::SetLOKLocale(const OUString& rBcp47LanguageTag)
1523 {
1524     maLOKLocale = LanguageTag(rBcp47LanguageTag, true).makeFallback();
1525 }
1526 
1527 void SfxViewShell::NotifyCursor(SfxViewShell* /*pViewShell*/) const
1528 {
1529 }
1530 
1531 void SfxViewShell::setTiledSearching(bool bTiledSearching)
1532 {
1533     pImpl->m_bTiledSearching = bTiledSearching;
1534 }
1535 
1536 int SfxViewShell::getPart() const
1537 {
1538     return 0;
1539 }
1540 
1541 ViewShellId SfxViewShell::GetViewShellId() const
1542 {
1543     return pImpl->m_nViewShellId;
1544 }
1545 
1546 void SfxViewShell::SetDocId(ViewShellDocId nId)
1547 {
1548     assert(static_cast<int>(pImpl->m_nDocId) == -1);
1549     pImpl->m_nDocId = nId;
1550 }
1551 
1552 ViewShellDocId SfxViewShell::GetDocId() const
1553 {
1554     return pImpl->m_nDocId;
1555 }
1556 
1557 void SfxViewShell::NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload)
1558 {
1559     SfxLokHelper::notifyOtherViews(this, nType, rKey, rPayload);
1560 }
1561 
1562 void SfxViewShell::NotifyOtherView(OutlinerViewShell* pOther, int nType, const OString& rKey, const OString& rPayload)
1563 {
1564     auto pOtherShell = dynamic_cast<SfxViewShell*>(pOther);
1565     if (!pOtherShell)
1566         return;
1567 
1568     SfxLokHelper::notifyOtherView(this, pOtherShell, nType, rKey, rPayload);
1569 }
1570 
1571 void SfxViewShell::dumpAsXml(xmlTextWriterPtr pWriter) const
1572 {
1573     xmlTextWriterStartElement(pWriter, BAD_CAST("SfxViewShell"));
1574     xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1575     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("id"), BAD_CAST(OString::number(static_cast<sal_Int32>(GetViewShellId())).getStr()));
1576     xmlTextWriterEndElement(pWriter);
1577 }
1578 
1579 bool SfxViewShell::KeyInput( const KeyEvent &rKeyEvent )
1580 
1581 /*  [Description]
1582 
1583     This Method executes the KeyEvent 'rKeyEvent' of the Keys (Accelerator)
1584     configured either direct or indirect (for example by the Application)
1585     in the SfxViewShell.
1586 
1587     [Return value]
1588 
1589     bool                    TRUE
1590                             The Key (Accelerator) is configured and the
1591                             associated Handler was called
1592 
1593                             FALSE
1594                             The Key (Accelerator) is not configured and
1595                             subsequently no Handler was called
1596 
1597     [Cross-reference]
1598 
1599     <SfxApplication::KeyInput(const KeyEvent&)>
1600 */
1601 {
1602     return ExecKey_Impl(rKeyEvent);
1603 }
1604 
1605 bool SfxViewShell::GlobalKeyInput_Impl( const KeyEvent &rKeyEvent )
1606 {
1607     return ExecKey_Impl(rKeyEvent);
1608 }
1609 
1610 
1611 void SfxViewShell::ShowCursor( bool /*bOn*/ )
1612 
1613 /*  [Description]
1614 
1615     Subclasses must override this Method so that SFx can switch the
1616     Cursor on and off, for example while a <SfxProgress> is running.
1617 */
1618 
1619 {
1620 }
1621 
1622 
1623 void SfxViewShell::ResetAllClients_Impl( SfxInPlaceClient const *pIP )
1624 {
1625 
1626     std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
1627     if ( !pClients )
1628         return;
1629 
1630     for (SfxInPlaceClient* pIPClient : *pClients)
1631     {
1632         if( pIPClient != pIP )
1633             pIPClient->ResetObject();
1634     }
1635 }
1636 
1637 
1638 void SfxViewShell::DisconnectAllClients()
1639 {
1640     std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
1641     if ( !pClients )
1642         return;
1643 
1644     for ( size_t n = 0; n < pClients->size(); )
1645         // clients will remove themselves from the list
1646         delete pClients->at( n );
1647 }
1648 
1649 
1650 void SfxViewShell::QueryObjAreaPixel( tools::Rectangle& ) const
1651 {
1652 }
1653 
1654 
1655 void SfxViewShell::VisAreaChanged()
1656 {
1657     std::vector< SfxInPlaceClient* > *pClients = pImpl->GetIPClients_Impl(false);
1658     if ( !pClients )
1659         return;
1660 
1661     for (SfxInPlaceClient* pIPClient : *pClients)
1662     {
1663         if ( pIPClient->IsObjectInPlaceActive() )
1664             // client is active, notify client that the VisArea might have changed
1665             pIPClient->VisAreaChanged();
1666     }
1667 }
1668 
1669 
1670 void SfxViewShell::CheckIPClient_Impl(
1671         SfxInPlaceClient const *const pIPClient, const tools::Rectangle& rVisArea)
1672 {
1673     if ( GetObjectShell()->IsInClose() )
1674         return;
1675 
1676     bool bAlwaysActive =
1677         ( ( pIPClient->GetObjectMiscStatus() & embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY ) != 0 );
1678     bool bActiveWhenVisible =
1679         ( pIPClient->GetObjectMiscStatus() & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE ) != 0;
1680 
1681     // this method is called when a client is created
1682     if (pIPClient->IsObjectInPlaceActive())
1683         return;
1684 
1685     // object in client is currently not active
1686     // check if the object wants to be activated always or when it becomes at least partially visible
1687     // TODO/LATER: maybe we should use the scaled area instead of the ObjArea?!
1688     if (bAlwaysActive || (bActiveWhenVisible && rVisArea.IsOver(pIPClient->GetObjArea())))
1689     {
1690         try
1691         {
1692             pIPClient->GetObject()->changeState( embed::EmbedStates::INPLACE_ACTIVE );
1693         }
1694         catch (const uno::Exception&)
1695         {
1696             TOOLS_WARN_EXCEPTION("sfx.view", "SfxViewShell::CheckIPClient_Impl");
1697         }
1698     }
1699 }
1700 
1701 
1702 SfxObjectShell* SfxViewShell::GetObjectShell()
1703 {
1704     return pFrame ? pFrame->GetObjectShell() : nullptr;
1705 }
1706 
1707 
1708 Reference< XModel > SfxViewShell::GetCurrentDocument() const
1709 {
1710     Reference< XModel > xDocument;
1711 
1712     const SfxObjectShell* pDocShell( const_cast< SfxViewShell* >( this )->GetObjectShell() );
1713     OSL_ENSURE( pDocShell, "SfxViewFrame::GetCurrentDocument: no DocShell!?" );
1714     if ( pDocShell )
1715         xDocument = pDocShell->GetModel();
1716     return xDocument;
1717 }
1718 
1719 
1720 void SfxViewShell::SetCurrentDocument() const
1721 {
1722     uno::Reference< frame::XModel > xDocument( GetCurrentDocument() );
1723     if ( xDocument.is() )
1724         SfxObjectShell::SetCurrentComponent( xDocument );
1725 }
1726 
1727 
1728 const Size& SfxViewShell::GetMargin() const
1729 {
1730     return pImpl->aMargin;
1731 }
1732 
1733 
1734 void SfxViewShell::SetMargin( const Size& rSize )
1735 {
1736     // the default margin was verified using www.apple.com !!
1737     Size aMargin = rSize;
1738     if ( aMargin.Width() == -1 )
1739         aMargin.setWidth( DEFAULT_MARGIN_WIDTH );
1740     if ( aMargin.Height() == -1 )
1741         aMargin.setHeight( DEFAULT_MARGIN_HEIGHT );
1742 
1743     if ( aMargin != pImpl->aMargin )
1744     {
1745         pImpl->aMargin = aMargin;
1746         MarginChanged();
1747     }
1748 }
1749 
1750 void SfxViewShell::MarginChanged()
1751 {
1752 }
1753 
1754 void SfxViewShell::JumpToMark( const OUString& rMark )
1755 {
1756     SfxStringItem aMarkItem( SID_JUMPTOMARK, rMark );
1757     GetViewFrame()->GetDispatcher()->ExecuteList(
1758         SID_JUMPTOMARK,
1759         SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
1760         { &aMarkItem });
1761 }
1762 
1763 void SfxViewShell::SetController( SfxBaseController* pController )
1764 {
1765     pImpl->m_pController = pController;
1766 
1767     // there should be no old listener, but if there is one, it should be disconnected
1768     if (  pImpl->xClipboardListener.is() )
1769         pImpl->xClipboardListener->DisconnectViewShell();
1770 
1771     pImpl->xClipboardListener = new SfxClipboardChangeListener( this, GetClipboardNotifier() );
1772 }
1773 
1774 Reference < XController > SfxViewShell::GetController() const
1775 {
1776     return pImpl->m_pController.get();
1777 }
1778 
1779 SfxBaseController* SfxViewShell::GetBaseController_Impl() const
1780 {
1781     return pImpl->m_pController.get();
1782 }
1783 
1784 void SfxViewShell::AddContextMenuInterceptor_Impl( const uno::Reference< ui::XContextMenuInterceptor >& xInterceptor )
1785 {
1786     pImpl->aInterceptorContainer.addInterface( xInterceptor );
1787 }
1788 
1789 void SfxViewShell::RemoveContextMenuInterceptor_Impl( const uno::Reference< ui::XContextMenuInterceptor >& xInterceptor )
1790 {
1791     pImpl->aInterceptorContainer.removeInterface( xInterceptor );
1792 }
1793 
1794 static void Change( Menu* pMenu, SfxViewShell* pView )
1795 {
1796     SfxDispatcher *pDisp = pView->GetViewFrame()->GetDispatcher();
1797     sal_uInt16 nCount = pMenu->GetItemCount();
1798     for ( sal_uInt16 nPos=0; nPos<nCount; ++nPos )
1799     {
1800         sal_uInt16 nId = pMenu->GetItemId(nPos);
1801         OUString aCmd = pMenu->GetItemCommand(nId);
1802         PopupMenu* pPopup = pMenu->GetPopupMenu(nId);
1803         if ( pPopup )
1804         {
1805             Change( pPopup, pView );
1806         }
1807         else if ( nId < 5000 )
1808         {
1809             if ( aCmd.startsWith(".uno:") )
1810             {
1811                 for (sal_uInt16 nIdx=0;;)
1812                 {
1813                     SfxShell *pShell=pDisp->GetShell(nIdx++);
1814                     if (pShell == nullptr)
1815                         break;
1816                     const SfxInterface *pIFace = pShell->GetInterface();
1817                     const SfxSlot* pSlot = pIFace->GetSlot( aCmd );
1818                     if ( pSlot )
1819                     {
1820                         pMenu->InsertItem( pSlot->GetSlotId(), pMenu->GetItemText( nId ),
1821                             pMenu->GetItemBits( nId ), OString(), nPos );
1822                         pMenu->SetItemCommand( pSlot->GetSlotId(), aCmd );
1823                         pMenu->RemoveItem( nPos+1 );
1824                         break;
1825                     }
1826                 }
1827             }
1828         }
1829     }
1830 }
1831 
1832 
1833 bool SfxViewShell::TryContextMenuInterception( Menu& rIn, const OUString& rMenuIdentifier, VclPtr<Menu>& rpOut, ui::ContextMenuExecuteEvent aEvent )
1834 {
1835     rpOut = nullptr;
1836     bool bModified = false;
1837 
1838     // create container from menu
1839     aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu(
1840         &rIn, &rMenuIdentifier );
1841 
1842     // get selection from controller
1843     aEvent.Selection.set( GetController(), uno::UNO_QUERY );
1844 
1845     // call interceptors
1846     ::comphelper::OInterfaceIteratorHelper2 aIt( pImpl->aInterceptorContainer );
1847     while( aIt.hasMoreElements() )
1848     {
1849         try
1850         {
1851             ui::ContextMenuInterceptorAction eAction;
1852             {
1853                 SolarMutexReleaser rel;
1854                 eAction = static_cast<ui::XContextMenuInterceptor*>(aIt.next())->notifyContextMenuExecute( aEvent );
1855             }
1856             switch ( eAction )
1857             {
1858                 case ui::ContextMenuInterceptorAction_CANCELLED :
1859                     // interceptor does not want execution
1860                     return false;
1861                 case ui::ContextMenuInterceptorAction_EXECUTE_MODIFIED :
1862                     // interceptor wants his modified menu to be executed
1863                     bModified = true;
1864                     break;
1865                 case ui::ContextMenuInterceptorAction_CONTINUE_MODIFIED :
1866                     // interceptor has modified menu, but allows for calling other interceptors
1867                     bModified = true;
1868                     continue;
1869                 case ui::ContextMenuInterceptorAction_IGNORED :
1870                     // interceptor is indifferent
1871                     continue;
1872                 default:
1873                     OSL_FAIL("Wrong return value of ContextMenuInterceptor!");
1874                     continue;
1875             }
1876         }
1877         catch (...)
1878         {
1879             aIt.remove();
1880         }
1881 
1882         break;
1883     }
1884 
1885     if ( bModified )
1886     {
1887         // container was modified, create a new window out of it
1888         rpOut = VclPtr<PopupMenu>::Create();
1889         ::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer( rpOut, aEvent.ActionTriggerContainer );
1890 
1891         Change( rpOut, this );
1892     }
1893 
1894     return true;
1895 }
1896 
1897 bool SfxViewShell::TryContextMenuInterception( Menu& rMenu, const OUString& rMenuIdentifier, css::ui::ContextMenuExecuteEvent aEvent )
1898 {
1899     bool bModified = false;
1900 
1901     // create container from menu
1902     aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu( &rMenu, &rMenuIdentifier );
1903 
1904     // get selection from controller
1905     aEvent.Selection = css::uno::Reference< css::view::XSelectionSupplier >( GetController(), css::uno::UNO_QUERY );
1906 
1907     // call interceptors
1908     ::comphelper::OInterfaceIteratorHelper2 aIt( pImpl->aInterceptorContainer );
1909     while( aIt.hasMoreElements() )
1910     {
1911         try
1912         {
1913             css::ui::ContextMenuInterceptorAction eAction;
1914             {
1915                 SolarMutexReleaser rel;
1916                 eAction = static_cast< css::ui::XContextMenuInterceptor* >( aIt.next() )->notifyContextMenuExecute( aEvent );
1917             }
1918             switch ( eAction )
1919             {
1920                 case css::ui::ContextMenuInterceptorAction_CANCELLED:
1921                     // interceptor does not want execution
1922                     return false;
1923                 case css::ui::ContextMenuInterceptorAction_EXECUTE_MODIFIED:
1924                     // interceptor wants his modified menu to be executed
1925                     bModified = true;
1926                     break;
1927                 case css::ui::ContextMenuInterceptorAction_CONTINUE_MODIFIED:
1928                     // interceptor has modified menu, but allows for calling other interceptors
1929                     bModified = true;
1930                     continue;
1931                 case css::ui::ContextMenuInterceptorAction_IGNORED:
1932                     // interceptor is indifferent
1933                     continue;
1934                 default:
1935                     SAL_WARN( "sfx.view", "Wrong return value of ContextMenuInterceptor!" );
1936                     continue;
1937             }
1938         }
1939         catch (...)
1940         {
1941             aIt.remove();
1942         }
1943 
1944         break;
1945     }
1946 
1947     if ( bModified )
1948     {
1949         rMenu.Clear();
1950         ::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer( &rMenu, aEvent.ActionTriggerContainer );
1951     }
1952 
1953     return true;
1954 }
1955 
1956 bool SfxViewShell::HandleNotifyEvent_Impl( NotifyEvent const & rEvent )
1957 {
1958     if (pImpl->m_pController.is())
1959         return pImpl->m_pController->HandleEvent_Impl( rEvent );
1960     return false;
1961 }
1962 
1963 bool SfxViewShell::HasKeyListeners_Impl() const
1964 {
1965     return (pImpl->m_pController.is())
1966         && pImpl->m_pController->HasKeyListeners_Impl();
1967 }
1968 
1969 bool SfxViewShell::HasMouseClickListeners_Impl() const
1970 {
1971     return (pImpl->m_pController.is())
1972         && pImpl->m_pController->HasMouseClickListeners_Impl();
1973 }
1974 
1975 bool SfxViewShell::Escape()
1976 {
1977     return GetViewFrame()->GetBindings().Execute( SID_TERMINATE_INPLACEACTIVATION );
1978 }
1979 
1980 Reference< view::XRenderable > SfxViewShell::GetRenderable()
1981 {
1982     Reference< view::XRenderable >xRender;
1983     SfxObjectShell* pObj = GetObjectShell();
1984     if( pObj )
1985     {
1986         Reference< frame::XModel > xModel( pObj->GetModel() );
1987         if( xModel.is() )
1988             xRender.set( xModel, UNO_QUERY );
1989     }
1990     return xRender;
1991 }
1992 
1993 void SfxViewShell::notifyWindow(vcl::LOKWindowId nDialogId, const OUString& rAction, const std::vector<vcl::LOKPayloadItem>& rPayload) const
1994 {
1995     SfxLokHelper::notifyWindow(this, nDialogId, rAction, rPayload);
1996 }
1997 
1998 uno::Reference< datatransfer::clipboard::XClipboardNotifier > SfxViewShell::GetClipboardNotifier() const
1999 {
2000     uno::Reference< datatransfer::clipboard::XClipboardNotifier > xClipboardNotifier;
2001     if ( GetViewFrame() )
2002         xClipboardNotifier.set( GetViewFrame()->GetWindow().GetClipboard(), uno::UNO_QUERY );
2003 
2004     return xClipboardNotifier;
2005 }
2006 
2007 void SfxViewShell::AddRemoveClipboardListener( const uno::Reference < datatransfer::clipboard::XClipboardListener >& rClp, bool bAdd )
2008 {
2009     try
2010     {
2011         if ( GetViewFrame() )
2012         {
2013             uno::Reference< datatransfer::clipboard::XClipboard > xClipboard( GetViewFrame()->GetWindow().GetClipboard() );
2014             if( xClipboard.is() )
2015             {
2016                 uno::Reference< datatransfer::clipboard::XClipboardNotifier > xClpbrdNtfr( xClipboard, uno::UNO_QUERY );
2017                 if( xClpbrdNtfr.is() )
2018                 {
2019                     if( bAdd )
2020                         xClpbrdNtfr->addClipboardListener( rClp );
2021                     else
2022                         xClpbrdNtfr->removeClipboardListener( rClp );
2023                 }
2024             }
2025         }
2026     }
2027     catch (const uno::Exception&)
2028     {
2029     }
2030 }
2031 
2032 weld::Window* SfxViewShell::GetFrameWeld() const
2033 {
2034     return pWindow ? pWindow->GetFrameWeld() : nullptr;
2035 }
2036 
2037 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2038