/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/** One instance of a PresenterScreenListener is registered per Impress document and waits for the full screen slide show to start and to end.
*/ class PresenterScreenListener
: private ::cppu::BaseMutex, public PresenterScreenListenerInterfaceBase
{ public:
PresenterScreenListener (
css::uno::Reference<css::uno::XComponentContext> xContext,
css::uno::Reference<css::frame::XModel2> xModel);
PresenterScreenListener(const PresenterScreenListener&) = delete;
PresenterScreenListener& operator=(const PresenterScreenListener&) = delete;
Reference< XServiceInfo > xInfo( xModel, UNO_QUERY ); if( xInfo.is() && xInfo->supportsService(u"com.sun.star.presentation.PresentationDocument"_ustr) )
{ // Create a new listener that waits for the full screen presentation // to start and to end. It takes care of its own lifetime.
::rtl::Reference<PresenterScreenListener> pListener ( new PresenterScreenListener(mxComponentContext, xModel));
pListener->Initialize();
}
if (xShape.is())
{ // when presenter is used and shape changes, check // and evtl. trigger update of 'NextSlide' view
mpPresenterScreen->CheckNextSlideUpdate(xShape);
}
}
}
}
// find first controller that is not the current controller (the one with the slideshow auto tmpController = mxModel->getCurrentController();
Reference< container::XEnumeration > xEnum( mxModel->getControllers() ); if( xEnum.is() )
{ while( xEnum->hasMoreElements() )
{
Reference< frame::XController > xC( xEnum->nextElement(), UNO_QUERY ); if( xC.is() && (xC.get() != tmpController.get()) )
{
mxController = dynamic_cast<::sd::DrawController*>(xC.get());
assert(bool(mxController) == bool(xC) && "only support instances of type DrawController"); break;
}
}
} // Get the XController from the first argument.
Reference<XComponentContext> xContext(mxContextWeak);
Reference<drawing::framework::XResourceId> xMainPaneId(
GetMainPaneId(xPresentation, xContext)); // An empty reference means that the presenter screen can // not or must not be displayed. if ( ! xMainPaneId.is()) return;
if (xCC.is() && xContext.is())
{ // Store the current configuration so that we can restore it when // the presenter view is deactivated.
mxSavedConfiguration = xCC->getRequestedConfiguration();
xCC->lock();
try
{ // At the moment the presenter controller is displayed in its // own full screen window that is controlled by the same // configuration controller as the Impress document from // which the presentation was started. Therefore the main // pane is activated additionally to the already existing // panes and does not replace them.
xCC->requestResourceActivation(
xMainPaneId,
ResourceActivationMode_ADD);
SetupConfiguration(xContext, xMainPaneId);
mpPresenterController = new PresenterController( this,
xContext,
mxController,
xSlideShowController,
mpPaneContainer,
xMainPaneId);
// Create pane and view factories and integrate them into the // drawing framework.
SetupPaneFactory(xContext);
SetupViewFactory(xContext);
// Get the existing presenter console screen, we want to switch the // presentation to use that instead.
sal_Int32 nNewScreen = GetPresenterScreenNumber (xPresentation); if (nNewScreen < 0) return;
// Adapt that display number to be the 'default' setting of 0 if it matches
sal_Int32 nExternalDisplay = Application::GetDisplayExternalScreen();
if (nNewScreen == nExternalDisplay)
nNewScreen = 0; // screen zero is best == the primary display else
nNewScreen++; // otherwise we store screens offset by one.
// Set the new presentation display
Reference<beans::XPropertySet> xProperties (xPresentation, UNO_QUERY_THROW);
xProperties->setPropertyValue(u"Display"_ustr, Any(nNewScreen));
} catch (const uno::Exception &) {
}
}
void PresenterScreen::CheckNextSlideUpdate(const Reference<drawing::XShape>& rxShape)
{ if (nullptr == mpPresenterController) return;
// forward to PresenterController if used
mpPresenterController->CheckNextSlideUpdate(rxShape);
}
/** * Return the real VCL screen number to show the presenter console * on or -1 to not show anything.
*/
sal_Int32 PresenterScreen::GetPresenterScreenNumber ( const Reference<presentation::XPresentation2>& rxPresentation) const
{
sal_Int32 nScreenNumber (0); try
{ if ( ! rxPresentation.is()) return -1;
// Determine the screen on which the full screen presentation is being // displayed.
sal_Int32 nDisplayNumber (-1); if ( ! (rxPresentation->getPropertyValue(u"Display"_ustr) >>= nDisplayNumber)) return -1; if (nDisplayNumber == -1)
{ // The special value -1 indicates that the slide show // spans all available displays. That leaves no room for // the presenter screen. return -1;
}
SAL_INFO("sdext.presenter", "Display number is " << nDisplayNumber);
if (nDisplayNumber > 0)
{
nScreenNumber = nDisplayNumber - 1;
} elseif (nDisplayNumber == 0)
{ // A display number value of 0 indicates the primary screen. // Find out which screen number that is.
nScreenNumber = Application::GetDisplayExternalScreen();
}
// We still have to determine the number of screens to decide // whether the presenter screen may be shown at all.
sal_Int32 nScreenCount = Application::GetScreenCount();
if (nScreenCount < 2 || nDisplayNumber > nScreenCount)
{ // There is either only one screen or the full screen // presentation spans all available screens. The presenter // screen is shown only when a special flag in the configuration // is set or when the presenter screen will be shown as // non-full screen window
Reference<XComponentContext> xContext (mxContextWeak);
PresenterConfigurationAccess aConfiguration (
xContext,
u"/org.openoffice.Office.PresenterScreen/"_ustr,
PresenterConfigurationAccess::READ_ONLY); bool bStartAlways (false); bool bPresenterScreenFullScreen = isPresenterScreenFullScreen(xContext); if (aConfiguration.GetConfigurationNode(
u"Presenter/StartAlways"_ustr) >>= bStartAlways)
{ if (bStartAlways || !bPresenterScreenFullScreen) return GetPresenterScreenFromScreen(nScreenNumber);
} return -1;
}
} catch (const beans::UnknownPropertyException&)
{
OSL_ASSERT(false); // For some reason we can not access the screen number. Use // the default instead.
}
SAL_INFO("sdext.presenter", "Get presenter screen for screen " << nScreenNumber); return GetPresenterScreenFromScreen(nScreenNumber);
}
sal_Int32 PresenterScreen::GetPresenterScreenFromScreen( sal_Int32 nPresentationScreen )
{ // Setup the resource id of the full screen background pane so that // it is displayed on another screen than the presentation.
sal_Int32 nPresenterScreenNumber (1); switch (nPresentationScreen)
{ case 0:
nPresenterScreenNumber = 1; break;
case 1:
nPresenterScreenNumber = 0; break;
default:
SAL_INFO("sdext.presenter", "Warning unexpected, out of bound screen " "mapped to 0" << nPresentationScreen); // When the full screen presentation is displayed on a screen // other than 0 or 1 then place the presenter on the first // available screen.
nPresenterScreenNumber = 0; break;
} return nPresenterScreenNumber;
}
Reference<drawing::framework::XResourceId> PresenterScreen::GetMainPaneId ( const Reference<presentation::XPresentation2>& rxPresentation, const Reference<XComponentContext>& xContext) const
{ // A negative value means that the presentation spans all available // displays. That leaves no room for the presenter. const sal_Int32 nScreen(GetPresenterScreenNumber(rxPresentation)); if (nScreen < 0) return nullptr;
auto fullScreenStr = isPresenterScreenFullScreen(xContext)
? u"true"_ustr
: u"false"_ustr;
void PresenterScreen::RequestShutdownPresenterScreen()
{ // IASS: only cleanup when we are initialized if (!mbIsInitialized) return;
// Restore the configuration that was active before the presenter screen // has been activated. Now, that the presenter screen is displayed in // its own top level window this probably not necessary, but one never knows.
rtl::Reference<::sd::framework::ConfigurationController> xCC (mxConfigurationControllerWeak); if (xCC.is() && mxSavedConfiguration.is())
{
xCC->restoreConfiguration(mxSavedConfiguration);
mxSavedConfiguration = nullptr;
}
if (xCC.is())
{ // The actual restoration of the configuration takes place // asynchronously. The view and pane factories can only by disposed // after that. Therefore, set up a listener and wait for the // restoration.
rtl::Reference<PresenterScreen> xSelf(this);
PresenterFrameworkObserver::RunOnUpdateEnd(
xCC,
[xSelf=std::move(xSelf)](bool){ return xSelf->ShutdownPresenterScreen(); });
xCC->update();
}
// IASS: reset to non-initialized
mbIsInitialized = false;
}
// Read the parent layout first, if one is referenced.
OUString sParentLayout;
PresenterConfigurationAccess::GetConfigurationNode(
xLayoutNode,
u"ParentLayout"_ustr) >>= sParentLayout; if (!sParentLayout.isEmpty())
{ // Prevent infinite recursion. if (rsLayoutName != sParentLayout)
ProcessLayout(rConfiguration, sParentLayout, rxContext, rxAnchorId);
}
// Process the actual layout list.
Reference<container::XNameAccess> xList (
PresenterConfigurationAccess::GetConfigurationNode(
xLayoutNode,
u"Layout"_ustr),
UNO_QUERY_THROW);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.