LibreOffice Module sfx2 (master) 1
backingcomp.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "backingwindow.hxx"
21
22#include <com/sun/star/frame/XDispatchProvider.hpp>
23#include <com/sun/star/beans/XPropertySet.hpp>
24#include <com/sun/star/awt/KeyEvent.hpp>
25#include <com/sun/star/frame/XLayoutManager.hpp>
26#include <com/sun/star/lang/XServiceInfo.hpp>
27#include <com/sun/star/lang/XInitialization.hpp>
28#include <com/sun/star/awt/XWindow.hpp>
29#include <com/sun/star/awt/XKeyListener.hpp>
30#include <com/sun/star/uno/XComponentContext.hpp>
31#include <com/sun/star/frame/XFrame.hpp>
32#include <com/sun/star/frame/XDispatch.hpp>
33#include <com/sun/star/lang/XEventListener.hpp>
34#include <com/sun/star/lang/XComponent.hpp>
35#include <com/sun/star/lang/XTypeProvider.hpp>
36
40#include <cppuhelper/weak.hxx>
42#include <vcl/wrkwin.hxx>
43#include <vcl/svapp.hxx>
44#include <vcl/syswin.hxx>
45
47
48namespace {
49
61class BackingComp : public css::lang::XTypeProvider
62 , public css::lang::XServiceInfo
63 , public css::lang::XInitialization
64 , public css::frame::XController // => XComponent
65 , public css::awt::XKeyListener // => XEventListener
66 , public css::frame::XDispatchProvider
67 , public css::frame::XDispatch
68 , public ::cppu::OWeakObject
69{
70private:
72 css::uno::Reference< css::awt::XWindow > m_xWindow;
73
75 css::uno::Reference< css::frame::XFrame > m_xFrame;
76
77 Size m_aInitialWindowMinSize;
78
79public:
80
81 explicit BackingComp();
82
83 // XInterface
84 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
85 virtual void SAL_CALL acquire ( ) noexcept override;
86 virtual void SAL_CALL release ( ) noexcept override;
87
88 // XTypeProvide
89 virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes () override;
90 virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
91
92 // XServiceInfo
93 virtual OUString SAL_CALL getImplementationName ( ) override;
94 virtual sal_Bool SAL_CALL supportsService ( const OUString& sServiceName ) override;
95 virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
96
97 // XInitialization
98 virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& lArgs ) override;
99
100 // XController
101 virtual void SAL_CALL attachFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) override;
102 virtual sal_Bool SAL_CALL attachModel( const css::uno::Reference< css::frame::XModel >& xModel ) override;
103 virtual sal_Bool SAL_CALL suspend( sal_Bool bSuspend ) override;
104 virtual css::uno::Any SAL_CALL getViewData() override;
105 virtual void SAL_CALL restoreViewData( const css::uno::Any& aData ) override;
106 virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel() override;
107 virtual css::uno::Reference< css::frame::XFrame > SAL_CALL getFrame() override;
108
109 // XKeyListener
110 virtual void SAL_CALL keyPressed ( const css::awt::KeyEvent& aEvent ) override;
111 virtual void SAL_CALL keyReleased( const css::awt::KeyEvent& aEvent ) override;
112
113 // XEventListener
114 virtual void SAL_CALL disposing( const css::lang::EventObject& aEvent ) override;
115
116 // XComponent
117 virtual void SAL_CALL dispose ( ) override;
118 virtual void SAL_CALL addEventListener ( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
119 virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
120
121 // XDispatchProvider
122 virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( const css::util::URL& aURL, const OUString& sTargetFrameName , sal_Int32 nSearchFlags ) override;
123 virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptions ) override;
124
125 // XDispatch
126 virtual void SAL_CALL dispatch( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) override;
127 virtual void SAL_CALL addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xListener, const css::util::URL& aURL ) override;
128 virtual void SAL_CALL removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xListener, const css::util::URL& aURL ) override;
129};
130
131BackingComp::BackingComp()
132{
133}
134
150css::uno::Any SAL_CALL BackingComp::queryInterface( /*IN*/ const css::uno::Type& aType )
151{
152 // first look for own supported interfaces
153 css::uno::Any aResult = ::cppu::queryInterface(
154 aType,
155 static_cast< css::lang::XTypeProvider* >(this),
156 static_cast< css::lang::XServiceInfo* >(this),
157 static_cast< css::lang::XInitialization* >(this),
158 static_cast< css::frame::XController* >(this),
159 static_cast< css::lang::XComponent* >(this),
160 static_cast< css::lang::XEventListener* >(this),
161 static_cast< css::awt::XKeyListener* >(static_cast< css::lang::XEventListener* >(this)),
162 static_cast< css::frame::XDispatchProvider* >(this),
163 static_cast< css::frame::XDispatch* >(this) );
164
165 // then look for supported window interfaces
166 // Note: They exist only, if this instance was initialized
167 // with a valid window reference. It's aggregation on demand ...
168 if (!aResult.hasValue())
169 {
170 /* SAFE { */
171 SolarMutexGuard aGuard;
172 if (m_xWindow.is())
173 aResult = m_xWindow->queryInterface(aType);
174 /* } SAFE */
175 }
176
177 // look for XWeak and XInterface
178 if (!aResult.hasValue())
179 aResult = OWeakObject::queryInterface(aType);
180
181 return aResult;
182}
183
184
188void SAL_CALL BackingComp::acquire()
189 noexcept
190{
191 OWeakObject::acquire();
192}
193
194
198void SAL_CALL BackingComp::release()
199 noexcept
200{
201 OWeakObject::release();
202}
203
204
216css::uno::Sequence< css::uno::Type > SAL_CALL BackingComp::getTypes()
217{
218 static cppu::OTypeCollection aTypeCollection = [this]() {
219 SolarMutexGuard aGuard;
220 css::uno::Reference<css::lang::XTypeProvider> xProvider(m_xWindow, css::uno::UNO_QUERY);
221
222 css::uno::Sequence<css::uno::Type> lWindowTypes;
223 if (xProvider.is())
224 lWindowTypes = xProvider->getTypes();
225
234 }();
235
236 return aTypeCollection.getTypes();
237}
238
239
249css::uno::Sequence< sal_Int8 > SAL_CALL BackingComp::getImplementationId()
250{
251 return css::uno::Sequence<sal_Int8>();
252}
253
254OUString SAL_CALL BackingComp::getImplementationName()
255{
256 return "com.sun.star.comp.sfx2.BackingComp";
257}
258
259sal_Bool SAL_CALL BackingComp::supportsService( /*IN*/ const OUString& sServiceName )
260{
261 return cppu::supportsService(this, sServiceName);
262}
263
264css::uno::Sequence< OUString > SAL_CALL BackingComp::getSupportedServiceNames()
265{
266 return { "com.sun.star.frame.StartModule", "com.sun.star.frame.ProtocolHandler" };
267}
268
269
323void SAL_CALL BackingComp::attachFrame( /*IN*/ const css::uno::Reference< css::frame::XFrame >& xFrame )
324{
325 /* SAFE */
326 SolarMutexGuard aGuard;
327
328 // check some required states
329 if (m_xFrame.is())
330 throw css::uno::RuntimeException(
331 "already attached",
332 getXWeak());
333
334 if (!xFrame.is())
335 throw css::uno::RuntimeException(
336 "invalid frame reference",
337 getXWeak());
338
339 if (!m_xWindow.is())
340 return; // disposed
341
342 // safe the frame reference
344
345 // initialize the component and its parent window
346 css::uno::Reference< css::awt::XWindow > xParentWindow = xFrame->getContainerWindow();
347 VclPtr< WorkWindow > pParent = static_cast<WorkWindow*>(VCLUnoHelper::GetWindow(xParentWindow));
349
350 // disable full screen mode of the frame!
351 if (pParent && pParent->IsFullScreenMode())
352 {
353 pParent->ShowFullScreenMode(false);
354 pParent->SetMenuBarMode(MenuBarMode::Normal);
355 }
356
357 // create the menu bar for the backing component
358 css::uno::Reference< css::beans::XPropertySet > xPropSet(m_xFrame, css::uno::UNO_QUERY_THROW);
359 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
360 xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
361 if (xLayoutManager.is())
362 {
363 xLayoutManager->lock();
364 xLayoutManager->createElement("private:resource/menubar/menubar");
365 xLayoutManager->unlock();
366 }
367
368 if (pWindow)
369 {
370 // set help ID for our canvas
371 pWindow->SetHelpId("FWK_HID_BACKINGWINDOW");
372 }
373
374 // inform BackingWindow about frame
375 BackingWindow* pBack = dynamic_cast<BackingWindow*>(pWindow.get());
376 if( pBack )
377 pBack->setOwningFrame( m_xFrame );
378
379 // Set a minimum size for Start Center
380 if( !pParent || !pBack )
381 return;
382
383 tools::Long nMenuHeight = 0;
384 vcl::Window* pMenu = pParent->GetWindow(GetWindowType::Next);
385 if( pMenu )
386 nMenuHeight = pMenu->GetSizePixel().Height();
387
388 m_aInitialWindowMinSize = pParent->GetMinOutputSizePixel();
389 if (!m_aInitialWindowMinSize.Width())
390 m_aInitialWindowMinSize.AdjustWidth(1);
391 if (!m_aInitialWindowMinSize.Height())
392 m_aInitialWindowMinSize.AdjustHeight(1);
393
394 pParent->SetMinOutputSizePixel(
395 Size(
396 pBack->get_width_request(),
397 pBack->get_height_request() + nMenuHeight));
398
399 /* } SAFE */
400}
401
402
411sal_Bool SAL_CALL BackingComp::attachModel( /*IN*/ const css::uno::Reference< css::frame::XModel >& )
412{
413 return false;
414}
415
416
425css::uno::Reference< css::frame::XModel > SAL_CALL BackingComp::getModel()
426{
427 return css::uno::Reference< css::frame::XModel >();
428}
429
430
436css::uno::Any SAL_CALL BackingComp::getViewData()
437{
438 return css::uno::Any();
439}
440
441
448void SAL_CALL BackingComp::restoreViewData( /*IN*/ const css::uno::Any& )
449{
450}
451
452
461css::uno::Reference< css::frame::XFrame > SAL_CALL BackingComp::getFrame()
462{
463 /* SAFE { */
464 SolarMutexGuard aGuard;
465 return m_xFrame;
466 /* } SAFE */
467}
468
469
483sal_Bool SAL_CALL BackingComp::suspend( /*IN*/ sal_Bool )
484{
485 /* FIXME ... implemented by using default :-( */
486 return true;
487}
488
489
505void SAL_CALL BackingComp::disposing( /*IN*/ const css::lang::EventObject& aEvent )
506{
507 // Attention: don't free m_pAccExec here! see comments inside dtor and
508 // keyPressed() for further details.
509
510 /* SAFE { */
511 SolarMutexGuard aGuard;
512
513 if (!aEvent.Source.is() || aEvent.Source!=m_xWindow || !m_xWindow.is())
514 throw css::uno::RuntimeException(
515 "unexpected source or called twice",
516 getXWeak());
517
518 m_xWindow.clear();
519
520 /* } SAFE */
521}
522
523
532void SAL_CALL BackingComp::dispose()
533{
534 /* SAFE { */
535 SolarMutexGuard aGuard;
536
537 if (m_xFrame.is())
538 {
539 css::uno::Reference< css::awt::XWindow > xParentWindow = m_xFrame->getContainerWindow();
540 VclPtr< WorkWindow > pParent = static_cast<WorkWindow*>(VCLUnoHelper::GetWindow(xParentWindow));
541 if (pParent)
542 {
543 pParent->SetMinOutputSizePixel(m_aInitialWindowMinSize);
544 // hide NotebookBar
545 sfx2::SfxNotebookBar::CloseMethod(static_cast<SystemWindow*>(pParent));
546 }
547 }
548
549 // stop listening at the window
550 if (m_xWindow.is())
551 {
552 m_xWindow->removeEventListener(this);
553 m_xWindow->removeKeyListener(this);
554 m_xWindow.clear();
555 }
556
557 // forget all other used references
558 m_xFrame.clear();
559
560 /* } SAFE */
561}
562
563
574void SAL_CALL BackingComp::addEventListener( /*IN*/ const css::uno::Reference< css::lang::XEventListener >& )
575{
576 throw css::uno::RuntimeException(
577 "not supported",
578 getXWeak());
579}
580
581
590void SAL_CALL BackingComp::removeEventListener( /*IN*/ const css::uno::Reference< css::lang::XEventListener >& )
591{
592}
593
594
613void SAL_CALL BackingComp::initialize( /*IN*/ const css::uno::Sequence< css::uno::Any >& lArgs )
614{
615 /* SAFE { */
616 SolarMutexGuard aGuard;
617
618 if (m_xWindow.is())
619 throw css::uno::Exception(
620 "already initialized",
621 getXWeak());
622
623 css::uno::Reference< css::awt::XWindow > xParentWindow;
624 if (
625 (lArgs.getLength()!=1 ) ||
626 (!(lArgs[0] >>= xParentWindow)) ||
627 (!xParentWindow.is() )
628 )
629 {
630 throw css::uno::Exception(
631 "wrong or corrupt argument list",
632 getXWeak());
633 }
634
635 // create the component window
636 VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(xParentWindow);
638 m_xWindow = VCLUnoHelper::GetInterface(pWindow);
639
640 if (!m_xWindow.is())
641 throw css::uno::RuntimeException(
642 "couldn't create component window",
643 getXWeak());
644
645 // start listening for window disposing
646 // It's set at our owner frame as component window later too. So it will may be disposed there ...
647 m_xWindow->addEventListener(static_cast< css::lang::XEventListener* >(this));
648
649 m_xWindow->setVisible(true);
650
651 /* } SAFE */
652}
653
654
655void SAL_CALL BackingComp::keyPressed( /*IN*/ const css::awt::KeyEvent& )
656{
657}
658
659
660void SAL_CALL BackingComp::keyReleased( /*IN*/ const css::awt::KeyEvent& )
661{
662 /* Attention
663 Please use keyPressed() instead of this method. Otherwise it would be possible, that
664 - a key input may be first switch to the backing mode
665 - and this component register itself as key listener too
666 - and it's first event will be a keyReleased() for the already well known event, which switched to the backing mode!
667 So it will be handled twice! document => backing mode => exit app...
668 */
669}
670
671// XDispatchProvider
672css::uno::Reference< css::frame::XDispatch > SAL_CALL BackingComp::queryDispatch( const css::util::URL& aURL, const OUString& /*sTargetFrameName*/, sal_Int32 /*nSearchFlags*/ )
673{
674 css::uno::Reference< css::frame::XDispatch > xDispatch;
675 if ( aURL.Protocol == "vnd.org.libreoffice.recentdocs:" )
676 xDispatch = this;
677
678 return xDispatch;
679}
680
681css::uno::Sequence < css::uno::Reference< css::frame::XDispatch > > SAL_CALL BackingComp::queryDispatches( const css::uno::Sequence < css::frame::DispatchDescriptor >& seqDescripts )
682{
683 sal_Int32 nCount = seqDescripts.getLength();
684 css::uno::Sequence < css::uno::Reference < XDispatch > > lDispatcher( nCount );
685
686 std::transform(seqDescripts.begin(), seqDescripts.end(), lDispatcher.getArray(),
687 [this](const css::frame::DispatchDescriptor& rDesc) -> css::uno::Reference<XDispatch> {
688 return queryDispatch(rDesc.FeatureURL, rDesc.FrameName, rDesc.SearchFlags); });
689
690 return lDispatcher;
691}
692
693// XDispatch
694void SAL_CALL BackingComp::dispatch( const css::util::URL& aURL, const css::uno::Sequence < css::beans::PropertyValue >& /*lArgs*/ )
695{
696 // vnd.org.libreoffice.recentdocs:ClearRecentFileList - clear recent files
697 if ( aURL.Path != "ClearRecentFileList" )
698 return;
699
700 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(m_xWindow);
701 BackingWindow* pBack = dynamic_cast<BackingWindow*>(pWindow.get());
702 if( !pBack )
703 return;
704
705 pBack->clearRecentFileList();
706
707 // Recalculate minimum width
708 css::uno::Reference< css::awt::XWindow > xParentWindow = m_xFrame->getContainerWindow();
709 VclPtr< WorkWindow > pParent = static_cast<WorkWindow*>(VCLUnoHelper::GetWindow(xParentWindow));
710 if( pParent )
711 {
712 pParent->SetMinOutputSizePixel( Size(
713 pBack->get_width_request(),
714 pParent->GetMinOutputSizePixel().Height()) );
715 }
716}
717
718void SAL_CALL BackingComp::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xControl*/, const css::util::URL& /*aURL*/ )
719{
720}
721
722void SAL_CALL BackingComp::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xControl*/, const css::util::URL& /*aURL*/ )
723{
724}
725
726}
727
728extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
730 css::uno::XComponentContext *,
731 css::uno::Sequence<css::uno::Any> const &)
732{
733 return cppu::acquire(new BackingComp);
734}
735
736/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::lang::XComponent > m_xFrame
AnyEventRef aEvent
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_sfx2_BackingComp_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
void clearRecentFileList()
void setOwningFrame(const css::uno::Reference< css::frame::XFrame > &xFrame)
constexpr tools::Long Height() const
tools::Long AdjustHeight(tools::Long n)
tools::Long AdjustWidth(tools::Long n)
constexpr tools::Long Width() const
static css::uno::Reference< css::awt::XWindow > GetInterface(vcl::Window *pWindow)
static vcl::Window * GetWindow(const css::uno::Reference< css::awt::XWindow > &rxWindow)
reference_type * get() const
static VclPtr< reference_type > Create(Arg &&... arg)
css::uno::Sequence< css::uno::Type > SAL_CALL getTypes()
virtual void SAL_CALL acquire() SAL_NOEXCEPT SAL_OVERRIDE
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType) SAL_OVERRIDE
static void CloseMethod(SfxBindings &rBindings)
sal_Int32 get_height_request() const
virtual Size GetSizePixel() const
sal_Int32 get_width_request() const
int nCount
Reference< XDispatch > xDispatch
URL aURL
DdeData aData
Definition: lnkbase2.cxx:82
Type
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
long Long
Reference< XFrame > xFrame
unsigned char sal_Bool
signed char sal_Int8