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 <helpids.h>
23 
24 #include <com/sun/star/beans/NamedValue.hpp>
25 #include <com/sun/star/util/XURLTransformer.hpp>
26 #include <com/sun/star/frame/XDispatchProvider.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/awt/Toolkit.hpp>
29 #include <com/sun/star/awt/XDataTransferProviderAccess.hpp>
30 #include <com/sun/star/awt/KeyEvent.hpp>
31 #include <com/sun/star/awt/KeyModifier.hpp>
32 #include <com/sun/star/frame/XLayoutManager.hpp>
33 #include <com/sun/star/util/URLTransformer.hpp>
34 #include <com/sun/star/lang/XServiceInfo.hpp>
35 #include <com/sun/star/lang/XInitialization.hpp>
36 #include <com/sun/star/awt/XWindow.hpp>
37 #include <com/sun/star/awt/XKeyListener.hpp>
38 #include <com/sun/star/uno/XComponentContext.hpp>
39 #include <com/sun/star/frame/XFrame.hpp>
40 #include <com/sun/star/frame/XDispatch.hpp>
41 #include <com/sun/star/lang/XEventListener.hpp>
42 #include <com/sun/star/lang/XComponent.hpp>
43 #include <com/sun/star/lang/XTypeProvider.hpp>
44 
45 #include <cppuhelper/supportsservice.hxx>
46 #include <cppuhelper/queryinterface.hxx>
47 #include <cppuhelper/typeprovider.hxx>
48 #include <cppuhelper/weak.hxx>
49 #include <toolkit/helper/vclunohelper.hxx>
50 #include <vcl/keycod.hxx>
51 #include <vcl/wrkwin.hxx>
52 #include <vcl/svapp.hxx>
53 #include <vcl/syswin.hxx>
54 #include <rtl/ref.hxx>
55 #include <rtl/ustrbuf.hxx>
56 
57 #include <svl/solar.hrc>
58 #include <svl/urihelper.hxx>
59 #include <osl/file.hxx>
60 #include <unotools/configmgr.hxx>
61 
62 #include <unotools/bootstrap.hxx>
63 
64 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
65 
66 namespace {
67 
68 /**
69     implements the backing component.
70 
71     This component is a special one, which doesn't provide a controller
72     nor a model. It supports the following features:
73         - Drag & Drop
74         - Key Accelerators
75         - Simple Menu
76         - Progress Bar
77         - Background
78  */
79 class BackingComp : public  css::lang::XTypeProvider
80                   , public  css::lang::XServiceInfo
81                   , public  css::lang::XInitialization
82                   , public  css::frame::XController  // => XComponent
83                   , public  css::awt::XKeyListener // => XEventListener
84                   , public css::frame::XDispatchProvider
85                   , public css::frame::XDispatch
86                   , public  ::cppu::OWeakObject
87 {
88 private:
89     /** reference to the component window. */
90     css::uno::Reference< css::awt::XWindow > m_xWindow;
91 
92     /** the owner frame of this component. */
93     css::uno::Reference< css::frame::XFrame > m_xFrame;
94 
95     Size m_aInitialWindowMinSize;
96 
97 public:
98 
99     explicit BackingComp();
100 
101     // XInterface
102     virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
103     virtual void          SAL_CALL acquire       (                             ) throw(                          ) override;
104     virtual void          SAL_CALL release       (                             ) throw(                          ) override;
105 
106     // XTypeProvide
107     virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes           () override;
108     virtual css::uno::Sequence< sal_Int8 >       SAL_CALL getImplementationId() override;
109 
110     // XServiceInfo
111     virtual OUString                       SAL_CALL getImplementationName   (                                     ) override;
112     virtual sal_Bool                              SAL_CALL supportsService         ( const OUString& sServiceName ) override;
113     virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames(                                     ) override;
114 
115     // XInitialization
116     virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& lArgs ) override;
117 
118     // XController
119     virtual void SAL_CALL attachFrame( const css::uno::Reference< css::frame::XFrame >& xFrame ) override;
120     virtual sal_Bool SAL_CALL attachModel( const css::uno::Reference< css::frame::XModel >& xModel ) override;
121     virtual sal_Bool SAL_CALL suspend( sal_Bool bSuspend ) override;
122     virtual css::uno::Any SAL_CALL getViewData() override;
123     virtual void SAL_CALL restoreViewData( const css::uno::Any& aData ) override;
124     virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel() override;
125     virtual css::uno::Reference< css::frame::XFrame > SAL_CALL getFrame() override;
126 
127     // XKeyListener
128     virtual void SAL_CALL keyPressed ( const css::awt::KeyEvent& aEvent ) override;
129     virtual void SAL_CALL keyReleased( const css::awt::KeyEvent& aEvent ) override;
130 
131     // XEventListener
132     virtual void SAL_CALL disposing( const css::lang::EventObject& aEvent ) override;
133 
134     // XComponent
135     virtual void SAL_CALL dispose            (                                                                   ) override;
136     virtual void SAL_CALL addEventListener   ( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
137     virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
138 
139     // XDispatchProvider
140     virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch( const css::util::URL& aURL, const OUString& sTargetFrameName , sal_Int32 nSearchFlags ) override;
141     virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptions    ) override;
142 
143     // XDispatch
144     virtual void SAL_CALL dispatch( const css::util::URL& aURL, const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) override;
145     virtual void SAL_CALL addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xListener, const css::util::URL& aURL ) override;
146     virtual void SAL_CALL removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& xListener, const css::util::URL& aURL ) override;
147 };
148 
BackingComp()149 BackingComp::BackingComp()
150 {
151 }
152 
153 /** return information about supported interfaces.
154 
155     Some interfaces are supported by his class directly, but some other ones are
156     used by aggregation. An instance of this class must provide some window interfaces.
157     But it must represent a VCL window behind such interfaces too! So we use an internal
158     saved window member to ask it for its interfaces and return it. But we must be aware then,
159     that it can be destroyed from outside too ...
160 
161     @param  aType
162                 describe the required interface type
163 
164     @return An Any holding the instance, which provides the queried interface.
165             Note: There exist two possible results ... this instance itself and her window member!
166  */
167 
queryInterface(const css::uno::Type & aType)168 css::uno::Any SAL_CALL BackingComp::queryInterface( /*IN*/ const css::uno::Type& aType )
169 {
170     // first look for own supported interfaces
171     css::uno::Any aResult = ::cppu::queryInterface(
172                 aType,
173                 static_cast< css::lang::XTypeProvider* >(this),
174                 static_cast< css::lang::XServiceInfo* >(this),
175                 static_cast< css::lang::XInitialization* >(this),
176                 static_cast< css::frame::XController* >(this),
177                 static_cast< css::lang::XComponent* >(this),
178                 static_cast< css::lang::XEventListener* >(this),
179                 static_cast< css::awt::XKeyListener* >(static_cast< css::lang::XEventListener* >(this)),
180                 static_cast< css::frame::XDispatchProvider* >(this),
181                 static_cast< css::frame::XDispatch* >(this) );
182 
183     // then look for supported window interfaces
184     // Note: They exist only, if this instance was initialized
185     // with a valid window reference. It's aggregation on demand ...
186     if (!aResult.hasValue())
187     {
188         /* SAFE { */
189         SolarMutexGuard aGuard;
190         if (m_xWindow.is())
191             aResult = m_xWindow->queryInterface(aType);
192         /* } SAFE */
193     }
194 
195     // look for XWeak and XInterface
196     if (!aResult.hasValue())
197         aResult = OWeakObject::queryInterface(aType);
198 
199     return aResult;
200 }
201 
202 
203 /** increase ref count of this instance.
204  */
205 
acquire()206 void SAL_CALL BackingComp::acquire()
207     throw()
208 {
209     OWeakObject::acquire();
210 }
211 
212 
213 /** decrease ref count of this instance.
214  */
215 
release()216 void SAL_CALL BackingComp::release()
217     throw()
218 {
219     OWeakObject::release();
220 }
221 
222 
223 /** return collection about all supported interfaces.
224 
225     Optimize this method !
226     We initialize a static variable only one time.
227     And we don't must use a mutex at every call!
228     For the first call; pTypeCollection is NULL -
229     for the second call pTypeCollection is different from NULL!
230 
231     @return A list of all supported interface types.
232 */
233 
getTypes()234 css::uno::Sequence< css::uno::Type > SAL_CALL BackingComp::getTypes()
235 {
236     static cppu::OTypeCollection aTypeCollection = [this]() {
237         SolarMutexGuard aGuard;
238         css::uno::Reference<css::lang::XTypeProvider> xProvider(m_xWindow, css::uno::UNO_QUERY);
239 
240         css::uno::Sequence<css::uno::Type> lWindowTypes;
241         if (xProvider.is())
242             lWindowTypes = xProvider->getTypes();
243 
244         return cppu::OTypeCollection(
245             cppu::UnoType<css::lang::XInitialization>::get(),
246             cppu::UnoType<css::lang::XTypeProvider>::get(),
247             cppu::UnoType<css::lang::XServiceInfo>::get(),
248             cppu::UnoType<css::frame::XController>::get(),
249             cppu::UnoType<css::lang::XComponent>::get(),
250             cppu::UnoType<css::frame::XDispatchProvider>::get(),
251             cppu::UnoType<css::frame::XDispatch>::get(), lWindowTypes);
252     }();
253 
254     return aTypeCollection.getTypes();
255 }
256 
257 
258 /** create one unique Id for all instances of this class.
259 
260     Optimize this method
261     We initialize a static variable only one time. And we don't must use a mutex at every call!
262     For the first call; pID is NULL - for the second call pID is different from NULL!
263 
264     @return A byte array, which represent the unique id.
265 */
266 
getImplementationId()267 css::uno::Sequence< sal_Int8 > SAL_CALL BackingComp::getImplementationId()
268 {
269     return css::uno::Sequence<sal_Int8>();
270 }
271 
getImplementationName()272 OUString SAL_CALL BackingComp::getImplementationName()
273 {
274     return "com.sun.star.comp.sfx2.BackingComp";
275 }
276 
supportsService(const OUString & sServiceName)277 sal_Bool SAL_CALL BackingComp::supportsService( /*IN*/ const OUString& sServiceName )
278 {
279     return cppu::supportsService(this, sServiceName);
280 }
281 
getSupportedServiceNames()282 css::uno::Sequence< OUString > SAL_CALL BackingComp::getSupportedServiceNames()
283 {
284     return { "com.sun.star.frame.StartModule", "com.sun.star.frame.ProtocolHandler" };
285 }
286 
287 
288 /**
289     attach this component to a target frame.
290 
291     We have to use the container window of this frame as parent window of our own component window.
292     But it's not allowed to work with it really. May another component used it too.
293     Currently we need it only to create our child component window and support it's
294     interfaces inside our queryInterface() method. The user of us must have e.g. the
295     XWindow interface of it to be able to call setComponent(xWindow,xController) at the
296     frame!
297 
298     May he will do the following things:
299 
300     <listing>
301         XController xBackingComp = (XController)UnoRuntime.queryInterface(
302             XController.class,
303             xSMGR.createInstance(SERVICENAME_STARTMODULE));
304 
305         // at this time XWindow isn't present at this instance!
306         XWindow xBackingComp = (XWindow)UnoRuntime.queryInterface(
307             XWindow.class,
308             xBackingComp);
309 
310         // attach controller to the frame
311         // We will use its container window, to create
312         // the component window. From now we offer the window interfaces!
313         xBackingComp.attachFrame(xFrame);
314 
315         XWindow xBackingComp = (XWindow)UnoRuntime.queryInterface(
316             XWindow.class,
317             xBackingComp);
318 
319         // Our user can set us at the frame as new component
320         xFrame.setComponent(xBackingWin, xBackingComp);
321 
322         // But that had no effect to our view state.
323         // We must be started to create our UI elements like e.g. menu, title, background ...
324         XInitialization xBackingInit = (XInitialization)UnoRuntime.queryInterface(
325             XInitialization.class,
326             xBackingComp);
327 
328         xBackingInit.initialize(lArgs);
329     </listing>
330 
331     @param  xFrame
332                 reference to our new target frame
333 
334     @throw  css::uno::RuntimeException
335                 if the given frame reference is wrong or component window couldn't be created
336                 successfully.
337                 We throw it too, if we already attached to a frame. Because we don't support
338                 reparenting of our component window on demand!
339 */
340 
attachFrame(const css::uno::Reference<css::frame::XFrame> & xFrame)341 void SAL_CALL BackingComp::attachFrame( /*IN*/ const css::uno::Reference< css::frame::XFrame >& xFrame )
342 {
343     /* SAFE */
344     SolarMutexGuard aGuard;
345 
346     // check some required states
347     if (m_xFrame.is())
348         throw css::uno::RuntimeException(
349                 "already attached",
350                 static_cast< ::cppu::OWeakObject* >(this));
351 
352     if (!xFrame.is())
353         throw css::uno::RuntimeException(
354                 "invalid frame reference",
355                 static_cast< ::cppu::OWeakObject* >(this));
356 
357     if (!m_xWindow.is())
358         return; // disposed
359 
360     // safe the frame reference
361     m_xFrame = xFrame;
362 
363     // initialize the component and its parent window
364     css::uno::Reference< css::awt::XWindow > xParentWindow = xFrame->getContainerWindow();
365     VclPtr< WorkWindow > pParent = static_cast<WorkWindow*>(VCLUnoHelper::GetWindow(xParentWindow).get());
366     VclPtr< vcl::Window > pWindow = VCLUnoHelper::GetWindow(m_xWindow);
367 
368     // disable full screen mode of the frame!
369     if (pParent && pParent->IsFullScreenMode())
370     {
371         pParent->ShowFullScreenMode(false);
372         pParent->SetMenuBarMode(MenuBarMode::Normal);
373     }
374 
375     // create the menu bar for the backing component
376     css::uno::Reference< css::beans::XPropertySet > xPropSet(m_xFrame, css::uno::UNO_QUERY_THROW);
377     css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
378     xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
379     if (xLayoutManager.is())
380     {
381         xLayoutManager->lock();
382         xLayoutManager->createElement("private:resource/menubar/menubar");
383         xLayoutManager->unlock();
384     }
385 
386     if (pWindow)
387     {
388         // set help ID for our canvas
389         pWindow->SetHelpId("FWK_HID_BACKINGWINDOW");
390     }
391 
392     // inform BackingWindow about frame
393     BackingWindow* pBack = dynamic_cast<BackingWindow*>(pWindow.get());
394     if( pBack )
395         pBack->setOwningFrame( m_xFrame );
396 
397     // set NotebookBar
398     SystemWindow* pSysWindow = pParent;
399     if (pSysWindow)
400     {
401         //sfx2::SfxNotebookBar::StateMethod(pSysWindow, m_xFrame, "sfx/ui/notebookbar.ui");
402     }
403 
404     // Set a minimum size for Start Center
405     if( !pParent || !pBack )
406         return;
407 
408     long nMenuHeight = 0;
409     vcl::Window* pMenu = pParent->GetWindow(GetWindowType::Next);
410     if( pMenu )
411         nMenuHeight = pMenu->GetSizePixel().Height();
412 
413     m_aInitialWindowMinSize = pParent->GetMinOutputSizePixel();
414     if (!m_aInitialWindowMinSize.Width())
415         m_aInitialWindowMinSize.AdjustWidth(1);
416     if (!m_aInitialWindowMinSize.Height())
417         m_aInitialWindowMinSize.AdjustHeight(1);
418 
419     pParent->SetMinOutputSizePixel(
420         Size(
421             pBack->get_width_request(),
422             pBack->get_height_request() + nMenuHeight));
423 
424     /* } SAFE */
425 }
426 
427 
428 /** not supported.
429 
430     This component does not know any model. It will be represented by a window and
431     its controller only.
432 
433     return  <FALSE/> every time.
434  */
435 
attachModel(const css::uno::Reference<css::frame::XModel> &)436 sal_Bool SAL_CALL BackingComp::attachModel( /*IN*/ const css::uno::Reference< css::frame::XModel >& )
437 {
438     return false;
439 }
440 
441 
442 /** not supported.
443 
444     This component does not know any model. It will be represented by a window and
445     its controller only.
446 
447     return  An empty reference every time.
448  */
449 
getModel()450 css::uno::Reference< css::frame::XModel > SAL_CALL BackingComp::getModel()
451 {
452     return css::uno::Reference< css::frame::XModel >();
453 }
454 
455 
456 /** not supported.
457 
458     return  An empty value.
459  */
460 
getViewData()461 css::uno::Any SAL_CALL BackingComp::getViewData()
462 {
463     return css::uno::Any();
464 }
465 
466 
467 /** not supported.
468 
469     @param  aData
470                 not used.
471  */
472 
restoreViewData(const css::uno::Any &)473 void SAL_CALL BackingComp::restoreViewData( /*IN*/ const css::uno::Any& )
474 {
475 }
476 
477 
478 /** returns the attached frame for this component.
479 
480     @see    attachFrame()
481 
482     @return The internally saved frame reference.
483             Can be null, if attachFrame() was not called before.
484  */
485 
getFrame()486 css::uno::Reference< css::frame::XFrame > SAL_CALL BackingComp::getFrame()
487 {
488     /* SAFE { */
489     SolarMutexGuard aGuard;
490     return m_xFrame;
491     /* } SAFE */
492 }
493 
494 
495 /** ask controller for its current working state.
496 
497     If someone wishes to close this component, it must suspend the controller before.
498     That will be a chance for it to disagree with that AND show any UI for a possible
499     UI user.
500 
501     @param  bSuspend
502                 If it's set to sal_True this controller should be suspended.
503                 sal_False will resuspend it.
504 
505     @return sal_True if the request could be finished successfully; sal_False otherwise.
506  */
507 
suspend(sal_Bool)508 sal_Bool SAL_CALL BackingComp::suspend( /*IN*/ sal_Bool )
509 {
510     /* FIXME ... implemented by using default :-( */
511     return true;
512 }
513 
514 
515 /** callback from our window member.
516 
517     Our internal saved window wish to die. It will be disposed from outside (may be the frame)
518     and inform us. We must release its reference only here. Of course we check the given reference
519     here and reject callback from unknown sources.
520 
521     Note: deregistration as listener isn't necessary here. The broadcaster do it automatically.
522 
523     @param  aEvent
524                 describe the broadcaster of this callback
525 
526     @throw css::uno::RuntimeException
527                 if the broadcaster doesn't represent the expected window reference.
528 */
529 
disposing(const css::lang::EventObject & aEvent)530 void SAL_CALL BackingComp::disposing( /*IN*/ const css::lang::EventObject& aEvent )
531 {
532     // Attention: don't free m_pAccExec here! see comments inside dtor and
533     // keyPressed() for further details.
534 
535     /* SAFE { */
536     SolarMutexGuard aGuard;
537 
538     if (!aEvent.Source.is() || aEvent.Source!=m_xWindow || !m_xWindow.is())
539         throw css::uno::RuntimeException(
540                 "unexpected source or called twice",
541                 static_cast< ::cppu::OWeakObject* >(this));
542 
543     m_xWindow.clear();
544 
545     /* } SAFE */
546 }
547 
548 
549 /** kill this instance.
550 
551     It can be called from our owner frame only. But there is no possibility to check the caller.
552     We have to release all our internal used resources and die. From this point we can throw
553     DisposedExceptions for every further interface request... but current implementation doesn't do so...
554 
555 */
556 
dispose()557 void SAL_CALL BackingComp::dispose()
558 {
559     /* SAFE { */
560     SolarMutexGuard aGuard;
561 
562     if (m_xFrame.is())
563     {
564         css::uno::Reference< css::awt::XWindow > xParentWindow = m_xFrame->getContainerWindow();
565         VclPtr< WorkWindow > pParent = static_cast<WorkWindow*>(VCLUnoHelper::GetWindow(xParentWindow).get());
566         if (pParent)
567         {
568             pParent->SetMinOutputSizePixel(m_aInitialWindowMinSize);
569             // hide NotebookBar
570             sfx2::SfxNotebookBar::CloseMethod(static_cast<SystemWindow*>(pParent));
571         }
572     }
573 
574     // stop listening at the window
575     if (m_xWindow.is())
576     {
577         m_xWindow->removeEventListener(this);
578         m_xWindow->removeKeyListener(this);
579         m_xWindow.clear();
580     }
581 
582     // forget all other used references
583     m_xFrame.clear();
584 
585     /* } SAFE */
586 }
587 
588 
589 /** not supported.
590 
591     @param  xListener
592                 not used.
593 
594     @throw  css::uno::RuntimeException
595                 because the listener expect to be holded alive by this container.
596                 We must inform it about this unsupported feature.
597  */
598 
addEventListener(const css::uno::Reference<css::lang::XEventListener> &)599 void SAL_CALL BackingComp::addEventListener( /*IN*/ const css::uno::Reference< css::lang::XEventListener >& )
600 {
601     throw css::uno::RuntimeException(
602             "not supported",
603             static_cast< ::cppu::OWeakObject* >(this));
604 }
605 
606 
607 /** not supported.
608 
609     Because registration is not supported too, we must do nothing here. Nobody can call this method really.
610 
611     @param  xListener
612                 not used.
613  */
614 
removeEventListener(const css::uno::Reference<css::lang::XEventListener> &)615 void SAL_CALL BackingComp::removeEventListener( /*IN*/ const css::uno::Reference< css::lang::XEventListener >& )
616 {
617 }
618 
619 
620 /**
621     force initialization for this component.
622 
623     Inside attachFrame() we created our component window. But it was not allowed there, to
624     initialize it. E.g. the menu must be set at the container window of the frame, which
625     is our parent window. But may at that time another component used it.
626     That's why our creator has to inform us, when it's time to initialize us really.
627     Currently only calling of this method must be done. But further implementations
628     can use special in parameter to configure this initialization...
629 
630     @param  lArgs
631                 currently not used
632 
633     @throw  css::uno::RuntimeException
634                 if some resources are missing
635                 Means if may be attachedFrame() wasn't called before.
636  */
637 
initialize(const css::uno::Sequence<css::uno::Any> & lArgs)638 void SAL_CALL BackingComp::initialize( /*IN*/ const css::uno::Sequence< css::uno::Any >& lArgs )
639 {
640     /* SAFE { */
641     SolarMutexGuard aGuard;
642 
643     if (m_xWindow.is())
644         throw css::uno::Exception(
645                 "already initialized",
646                 static_cast< ::cppu::OWeakObject* >(this));
647 
648     css::uno::Reference< css::awt::XWindow > xParentWindow;
649     if (
650         (lArgs.getLength()!=1         ) ||
651         (!(lArgs[0] >>= xParentWindow)) ||
652         (!xParentWindow.is()          )
653        )
654     {
655         throw css::uno::Exception(
656                 "wrong or corrupt argument list",
657                 static_cast< ::cppu::OWeakObject* >(this));
658     }
659 
660     // create the component window
661     VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow(xParentWindow);
662     VclPtr<vcl::Window> pWindow = VclPtr<BackingWindow>::Create(pParent);
663     m_xWindow = VCLUnoHelper::GetInterface(pWindow);
664 
665     if (!m_xWindow.is())
666         throw css::uno::RuntimeException(
667                 "couldn't create component window",
668                 static_cast< ::cppu::OWeakObject* >(this));
669 
670     // start listening for window disposing
671     // It's set at our owner frame as component window later too. So it will may be disposed there ...
672     m_xWindow->addEventListener(static_cast< css::lang::XEventListener* >(this));
673 
674     m_xWindow->setVisible(true);
675 
676     /* } SAFE */
677 }
678 
679 
keyPressed(const css::awt::KeyEvent &)680 void SAL_CALL BackingComp::keyPressed( /*IN*/ const css::awt::KeyEvent&  )
681 {
682 }
683 
684 
keyReleased(const css::awt::KeyEvent &)685 void SAL_CALL BackingComp::keyReleased( /*IN*/ const css::awt::KeyEvent& )
686 {
687     /* Attention
688         Please use keyPressed() instead of this method. Otherwise it would be possible, that
689         - a key input may be first switch to the backing mode
690         - and this component register itself as key listener too
691         - and it's first event will be a keyRealeased() for the already well known event, which switched to the backing mode!
692         So it will be handled twice! document => backing mode => exit app ...
693      */
694 }
695 
696 // XDispatchProvider
queryDispatch(const css::util::URL & aURL,const OUString &,sal_Int32)697 css::uno::Reference< css::frame::XDispatch > SAL_CALL BackingComp::queryDispatch( const css::util::URL& aURL, const OUString& /*sTargetFrameName*/, sal_Int32 /*nSearchFlags*/ )
698 {
699     css::uno::Reference< css::frame::XDispatch > xDispatch;
700     if ( aURL.Protocol == "vnd.org.libreoffice.recentdocs:" )
701         xDispatch = this;
702 
703     return xDispatch;
704 }
705 
queryDispatches(const css::uno::Sequence<css::frame::DispatchDescriptor> & seqDescripts)706 css::uno::Sequence < css::uno::Reference< css::frame::XDispatch > > SAL_CALL BackingComp::queryDispatches( const css::uno::Sequence < css::frame::DispatchDescriptor >& seqDescripts )
707 {
708     sal_Int32 nCount = seqDescripts.getLength();
709     css::uno::Sequence < css::uno::Reference < XDispatch > > lDispatcher( nCount );
710 
711     std::transform(seqDescripts.begin(), seqDescripts.end(), lDispatcher.begin(),
712         [this](const css::frame::DispatchDescriptor& rDesc) -> css::uno::Reference<XDispatch> {
713             return queryDispatch(rDesc.FeatureURL, rDesc.FrameName, rDesc.SearchFlags); });
714 
715     return lDispatcher;
716 }
717 
718 // XDispatch
dispatch(const css::util::URL & aURL,const css::uno::Sequence<css::beans::PropertyValue> &)719 void SAL_CALL BackingComp::dispatch( const css::util::URL& aURL, const css::uno::Sequence < css::beans::PropertyValue >& /*lArgs*/ )
720 {
721     // vnd.org.libreoffice.recentdocs:ClearRecentFileList  - clear recent files
722     if ( aURL.Path != "ClearRecentFileList" )
723         return;
724 
725     VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(m_xWindow);
726     BackingWindow* pBack = dynamic_cast<BackingWindow*>(pWindow.get());
727     if( !pBack )
728         return;
729 
730     pBack->clearRecentFileList();
731 
732     // Recalculate minimum width
733     css::uno::Reference< css::awt::XWindow > xParentWindow = m_xFrame->getContainerWindow();
734     VclPtr< WorkWindow > pParent = static_cast<WorkWindow*>(VCLUnoHelper::GetWindow(xParentWindow).get());
735     if( pParent )
736     {
737         pParent->SetMinOutputSizePixel( Size(
738                 pBack->get_width_request(),
739                 pParent->GetMinOutputSizePixel().Height()) );
740     }
741 }
742 
addStatusListener(const css::uno::Reference<css::frame::XStatusListener> &,const css::util::URL &)743 void SAL_CALL BackingComp::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xControl*/, const css::util::URL& /*aURL*/ )
744 {
745 }
746 
removeStatusListener(const css::uno::Reference<css::frame::XStatusListener> &,const css::util::URL &)747 void SAL_CALL BackingComp::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xControl*/, const css::util::URL& /*aURL*/ )
748 {
749 }
750 
751 }
752 
753 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_sfx2_BackingComp_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)754 com_sun_star_comp_sfx2_BackingComp_get_implementation(
755     css::uno::XComponentContext *,
756     css::uno::Sequence<css::uno::Any> const &)
757 {
758     return cppu::acquire(new BackingComp);
759 }
760 
761 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
762