Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/slideshow/slideshowimpl.cxx
Line
Count
Source
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 <sal/config.h>
21
22
#include <algorithm>
23
24
#include <config_features.h>
25
26
#include <com/sun/star/frame/theAutoRecovery.hpp>
27
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
28
#include <com/sun/star/document/XEventsSupplier.hpp>
29
#include <com/sun/star/drawing/XMasterPageTarget.hpp>
30
#include <com/sun/star/beans/PropertyValue.hpp>
31
#include <com/sun/star/beans/XPropertySetInfo.hpp>
32
#include <com/sun/star/beans/XPropertySet.hpp>
33
#include <com/sun/star/awt/SystemPointer.hpp>
34
#include <com/sun/star/util/URLTransformer.hpp>
35
#include <com/sun/star/util/XURLTransformer.hpp>
36
#include <com/sun/star/frame/XDispatch.hpp>
37
#include <com/sun/star/frame/XLayoutManager.hpp>
38
#include <com/sun/star/presentation/SlideShow.hpp>
39
#include <com/sun/star/media/XPlayer.hpp>
40
#include <officecfg/Office/Impress.hxx>
41
#include <officecfg/Office/Recovery.hxx>
42
#include <svl/stritem.hxx>
43
#include <svl/urihelper.hxx>
44
#include <basic/sbstar.hxx>
45
46
#include <toolkit/helper/vclunohelper.hxx>
47
#include <comphelper/diagnose_ex.hxx>
48
#include <comphelper/sequence.hxx>
49
50
#include <sfx2/infobar.hxx>
51
#include <sfx2/dispatch.hxx>
52
#include <sfx2/docfile.hxx>
53
#include <sfx2/app.hxx>
54
#include <sfx2/viewfrm.hxx>
55
#include <svx/svdoole2.hxx>
56
#include <svx/f3dchild.hxx>
57
#include <svx/imapdlg.hxx>
58
#include <svx/fontwork.hxx>
59
#include <svx/SvxColorChildWindow.hxx>
60
#include <svx/bmpmask.hxx>
61
#include <svx/srchdlg.hxx>
62
#include <svx/hyperdlg.hxx>
63
#include <svx/svxids.hrc>
64
#include <svx/unoapi.hxx>
65
#include <AnimationChildWindow.hxx>
66
#include <notifydocumentevent.hxx>
67
#include "slideshowimpl.hxx"
68
#include "slideshowviewimpl.hxx"
69
#include "PaneHider.hxx"
70
71
#include <bitmaps.hlst>
72
#include <strings.hrc>
73
#include <sdresid.hxx>
74
#include <utility>
75
#include <vcl/ColorDialog.hxx>
76
#include <vcl/canvastools.hxx>
77
#include <vcl/commandevent.hxx>
78
#include <vcl/weld/Builder.hxx>
79
#include <vcl/weld/Menu.hxx>
80
#include <vcl/weld/Window.hxx>
81
#include <vcl/weld/weldutils.hxx>
82
83
#include <vcl/settings.hxx>
84
#include <vcl/svapp.hxx>
85
#include <vcl/vclevent.hxx>
86
#include <vcl/help.hxx>
87
#include <comphelper/processfactory.hxx>
88
#include <comphelper/propertyvalue.hxx>
89
#include <rtl/ref.hxx>
90
#include <o3tl/safeint.hxx>
91
#include <o3tl/string_view.hxx>
92
#include <avmedia/mediawindow.hxx>
93
#include <DrawDocShell.hxx>
94
#include <ViewShellBase.hxx>
95
#include <PresentationViewShell.hxx>
96
#include <RemoteServer.hxx>
97
#include <customshowlist.hxx>
98
#include <unopage.hxx>
99
#include <sdpage.hxx>
100
#include <sdmod.hxx>
101
#include <app.hrc>
102
#include <cusshow.hxx>
103
#include <optsitem.hxx>
104
#include <unomodel.hxx>
105
106
0
#define CM_SLIDES       21
107
108
using ::com::sun::star::animations::XAnimationNode;
109
using ::com::sun::star::animations::XAnimationListener;
110
using ::com::sun::star::awt::XWindow;
111
using namespace ::com::sun::star;
112
using namespace ::com::sun::star::lang;
113
using namespace ::com::sun::star::uno;
114
using namespace ::com::sun::star::drawing;
115
using namespace ::com::sun::star::container;
116
using namespace ::com::sun::star::presentation;
117
using namespace ::com::sun::star::beans;
118
119
namespace sd
120
{
121
/** Slots, which will be disabled in the slide show and are managed by Sfx.
122
    Have to be sorted in the order of the SIDs */
123
sal_uInt16 const pAllowed[] =
124
{
125
    SID_OPENDOC                             , //     5501   ///< that internally jumps work
126
    SID_JUMPTOMARK                          , //     5598
127
    SID_OPENHYPERLINK                       , //     6676
128
    SID_PRESENTATION_END                     //    27218
129
};
130
131
class AnimationSlideController
132
{
133
public:
134
    enum Mode { ALL, FROM, CUSTOM, PREVIEW };
135
136
public:
137
    AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode );
138
139
0
    void setStartSlideNumber( sal_Int32 nSlideNumber ) { mnStartSlideNumber = nSlideNumber; }
140
    sal_Int32 getStartSlideIndex() const;
141
142
    sal_Int32 getCurrentSlideNumber() const;
143
    sal_Int32 getCurrentSlideIndex() const;
144
145
0
    sal_Int32 getSlideIndexCount() const { return maSlideNumbers.size(); }
146
0
    sal_Int32 getSlideNumberCount() const { return mnSlideCount; }
147
148
    sal_Int32 getSlideNumber( sal_Int32 nSlideIndex ) const;
149
150
    void insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible = true );
151
    void setPreviewNode( const Reference< XAnimationNode >& xPreviewNode );
152
153
    bool jumpToSlideIndex( sal_Int32 nNewSlideIndex );
154
    bool jumpToSlideNumber( sal_Int32 nNewSlideIndex );
155
156
    bool nextSlide();
157
    bool previousSlide();
158
159
    void displayCurrentSlide( const Reference< XSlideShow >& xShow,
160
                              const Reference< XDrawPagesSupplier>& xDrawPages,
161
                              const bool bSkipAllMainSequenceEffects );
162
163
    sal_Int32 getNextSlideIndex() const;
164
    sal_Int32 getPreviousSlideIndex() const;
165
166
    bool isVisibleSlideNumber( sal_Int32 nSlideNumber ) const;
167
168
    Reference< XDrawPage > getSlideByNumber( sal_Int32 nSlideNumber ) const;
169
170
    sal_Int32 getNextSlideNumber() const;
171
172
0
    bool hasSlides() const { return !maSlideNumbers.empty(); }
173
174
    // for InteractiveSlideShow we need to temporarily change the program
175
    // and mode, so allow save/restore that settings
176
    void pushForPreview();
177
    void popFromPreview();
178
private:
179
    bool getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode );
180
    sal_Int32 findSlideIndex( sal_Int32 nSlideNumber ) const;
181
182
0
    bool isValidIndex( sal_Int32 nIndex ) const { return (nIndex >= 0) && (o3tl::make_unsigned(nIndex) < maSlideNumbers.size()); }
183
0
    bool isValidSlideNumber( sal_Int32 nSlideNumber ) const { return (nSlideNumber >= 0) && (nSlideNumber < mnSlideCount); }
184
185
private:
186
    Mode meMode;
187
    sal_Int32 mnStartSlideNumber;
188
    std::vector< sal_Int32 > maSlideNumbers;
189
    std::vector< bool > maSlideVisible;
190
    std::vector< bool > maSlideVisited;
191
    Reference< XAnimationNode > mxPreviewNode;
192
    sal_Int32 mnSlideCount;
193
    sal_Int32 mnCurrentSlideIndex;
194
    sal_Int32 mnHiddenSlideNumber;
195
    Reference< XIndexAccess > mxSlides;
196
197
    // IASS data for push/pop
198
    std::vector< sal_Int32 > maSlideNumbers2;
199
    std::vector< bool > maSlideVisible2;
200
    std::vector< bool > maSlideVisited2;
201
    Reference< XAnimationNode > mxPreviewNode2;
202
    Mode meMode2;
203
};
204
205
void AnimationSlideController::pushForPreview()
206
0
{
207
0
    maSlideNumbers2 = maSlideNumbers;
208
0
    maSlideVisible2 = maSlideVisible;
209
0
    maSlideVisited2 = maSlideVisited;
210
0
    maSlideNumbers.clear();
211
0
    maSlideVisible.clear();
212
0
    maSlideVisited.clear();
213
0
    mxPreviewNode2 = mxPreviewNode;
214
0
    meMode2 = meMode;
215
0
    meMode = AnimationSlideController::PREVIEW;
216
0
}
217
218
void AnimationSlideController::popFromPreview()
219
0
{
220
0
    maSlideNumbers = maSlideNumbers2;
221
0
    maSlideVisible = maSlideVisible2;
222
0
    maSlideVisited = maSlideVisited2;
223
0
    maSlideNumbers2.clear();
224
0
    maSlideVisible2.clear();
225
0
    maSlideVisited2.clear();
226
0
    mxPreviewNode = mxPreviewNode2;
227
0
    meMode = meMode2;
228
0
}
229
230
Reference< XDrawPage > AnimationSlideController::getSlideByNumber( sal_Int32 nSlideNumber ) const
231
0
{
232
0
    Reference< XDrawPage > xSlide;
233
0
    if( mxSlides.is() && (nSlideNumber >= 0) && (nSlideNumber < mxSlides->getCount()) )
234
0
        mxSlides->getByIndex( nSlideNumber ) >>= xSlide;
235
0
    return xSlide;
236
0
}
237
238
bool AnimationSlideController::isVisibleSlideNumber( sal_Int32 nSlideNumber ) const
239
0
{
240
0
    sal_Int32 nIndex = findSlideIndex( nSlideNumber );
241
242
0
    if( nIndex != -1 )
243
0
        return maSlideVisible[ nIndex ];
244
0
    else
245
0
        return false;
246
0
}
247
248
void AnimationSlideController::setPreviewNode( const Reference< XAnimationNode >& xPreviewNode )
249
0
{
250
0
    mxPreviewNode = xPreviewNode;
251
0
}
252
253
AnimationSlideController::AnimationSlideController( Reference< XIndexAccess > const & xSlides, Mode eMode  )
254
0
:   meMode( eMode )
255
0
,   mnStartSlideNumber(-1)
256
0
,   mnSlideCount( 0 )
257
0
,   mnCurrentSlideIndex(0)
258
0
,   mnHiddenSlideNumber( -1 )
259
0
,   mxSlides( xSlides )
260
0
,   meMode2( eMode )
261
0
{
262
0
    if( mxSlides.is() )
263
0
        mnSlideCount = xSlides->getCount();
264
0
}
265
266
sal_Int32 AnimationSlideController::getStartSlideIndex() const
267
0
{
268
0
    if( mnStartSlideNumber >= 0 )
269
0
    {
270
0
        sal_Int32 nIndex;
271
0
        const sal_Int32 nCount = maSlideNumbers.size();
272
273
0
        for( nIndex = 0; nIndex < nCount; nIndex++ )
274
0
        {
275
0
            if( maSlideNumbers[nIndex] == mnStartSlideNumber )
276
0
                return nIndex;
277
0
        }
278
0
    }
279
280
0
    return 0;
281
0
}
282
283
sal_Int32 AnimationSlideController::getCurrentSlideNumber() const
284
0
{
285
0
    if( mnHiddenSlideNumber != -1 )
286
0
        return mnHiddenSlideNumber;
287
0
    else if( !maSlideNumbers.empty() )
288
0
        return maSlideNumbers[mnCurrentSlideIndex];
289
0
    else
290
0
        return 0;
291
0
}
292
293
sal_Int32 AnimationSlideController::getCurrentSlideIndex() const
294
0
{
295
0
    if( mnHiddenSlideNumber != -1 )
296
0
        return -1;
297
0
    else
298
0
        return mnCurrentSlideIndex;
299
0
}
300
301
bool AnimationSlideController::jumpToSlideIndex( sal_Int32 nNewSlideIndex )
302
0
{
303
0
    if( isValidIndex( nNewSlideIndex ) )
304
0
    {
305
0
        mnCurrentSlideIndex = nNewSlideIndex;
306
0
        mnHiddenSlideNumber = -1;
307
0
        maSlideVisited[mnCurrentSlideIndex] = true;
308
0
        return true;
309
0
    }
310
0
    else
311
0
    {
312
0
        return false;
313
0
    }
314
0
}
315
316
bool AnimationSlideController::jumpToSlideNumber( sal_Int32 nNewSlideNumber )
317
0
{
318
0
    sal_Int32 nIndex = findSlideIndex( nNewSlideNumber );
319
0
    if( isValidIndex( nIndex ) )
320
0
    {
321
0
        return jumpToSlideIndex( nIndex );
322
0
    }
323
0
    else if( (nNewSlideNumber >= 0) && (nNewSlideNumber < mnSlideCount) )
324
0
    {
325
        // jump to a hidden slide
326
0
        mnHiddenSlideNumber = nNewSlideNumber;
327
0
        return true;
328
0
    }
329
0
    else
330
0
    {
331
0
        return false;
332
0
    }
333
0
}
334
335
sal_Int32 AnimationSlideController::getSlideNumber( sal_Int32 nSlideIndex ) const
336
0
{
337
0
    if( isValidIndex( nSlideIndex ) )
338
0
        return maSlideNumbers[nSlideIndex];
339
0
    else
340
0
        return -1;
341
0
}
342
343
void AnimationSlideController::insertSlideNumber( sal_Int32 nSlideNumber, bool bVisible /* = true */ )
344
0
{
345
0
    DBG_ASSERT( isValidSlideNumber( nSlideNumber ), "sd::AnimationSlideController::insertSlideNumber(), illegal index" );
346
0
    if( isValidSlideNumber( nSlideNumber ) )
347
0
    {
348
0
        maSlideNumbers.push_back( nSlideNumber );
349
0
        maSlideVisible.push_back( bVisible );
350
0
        maSlideVisited.push_back( false );
351
0
    }
352
0
}
353
354
bool AnimationSlideController::getSlideAPI( sal_Int32 nSlideNumber, Reference< XDrawPage >& xSlide, Reference< XAnimationNode >& xAnimNode )
355
0
{
356
0
    if( isValidSlideNumber( nSlideNumber ) ) try
357
0
    {
358
0
        xSlide.set( mxSlides->getByIndex(nSlideNumber), UNO_QUERY_THROW );
359
360
0
        if( meMode == PREVIEW )
361
0
        {
362
0
            xAnimNode = mxPreviewNode;
363
0
        }
364
0
        else
365
0
        {
366
0
            Reference< animations::XAnimationNodeSupplier > xAnimNodeSupplier( xSlide, UNO_QUERY_THROW );
367
0
            xAnimNode = xAnimNodeSupplier->getAnimationNode();
368
0
        }
369
370
0
        return true;
371
0
    }
372
0
    catch( Exception& )
373
0
    {
374
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::AnimationSlideController::getSlideAPI()" );
375
0
    }
376
377
0
    return false;
378
0
}
379
380
sal_Int32 AnimationSlideController::findSlideIndex( sal_Int32 nSlideNumber ) const
381
0
{
382
0
    sal_Int32 nIndex;
383
0
    const sal_Int32 nCount = maSlideNumbers.size();
384
385
0
    for( nIndex = 0; nIndex < nCount; nIndex++ )
386
0
    {
387
0
        if( maSlideNumbers[nIndex] == nSlideNumber )
388
0
            return nIndex;
389
0
    }
390
391
0
    return -1;
392
0
}
393
394
sal_Int32 AnimationSlideController::getNextSlideIndex() const
395
0
{
396
0
    switch( meMode )
397
0
    {
398
0
    case ALL:
399
0
        {
400
0
            sal_Int32 nNewSlideIndex = mnCurrentSlideIndex + 1;
401
0
            if( isValidIndex( nNewSlideIndex ) )
402
0
            {
403
                // if the current slide is not excluded, make sure the
404
                // next slide is also not excluded.
405
                // if the current slide is excluded, we want to go
406
                // to the next slide, even if this is also excluded.
407
0
                if( maSlideVisible[mnCurrentSlideIndex] )
408
0
                {
409
0
                    while( isValidIndex( nNewSlideIndex ) )
410
0
                    {
411
0
                        if( maSlideVisible[nNewSlideIndex] )
412
0
                            break;
413
414
0
                        nNewSlideIndex++;
415
0
                    }
416
0
                }
417
0
            }
418
0
            return isValidIndex( nNewSlideIndex ) ? nNewSlideIndex : -1;
419
0
        }
420
421
0
    case FROM:
422
0
    case CUSTOM:
423
0
        return mnHiddenSlideNumber == -1 ? mnCurrentSlideIndex + 1 : mnCurrentSlideIndex;
424
425
0
    default:
426
0
    case PREVIEW:
427
0
        return -1;
428
429
0
    }
430
0
}
431
432
sal_Int32 AnimationSlideController::getNextSlideNumber() const
433
0
{
434
0
    sal_Int32 nNextSlideIndex = getNextSlideIndex();
435
0
    if( isValidIndex( nNextSlideIndex ) )
436
0
    {
437
0
        return maSlideNumbers[nNextSlideIndex];
438
0
    }
439
0
    else
440
0
    {
441
0
        return -1;
442
0
    }
443
0
}
444
445
bool AnimationSlideController::nextSlide()
446
0
{
447
0
    return jumpToSlideIndex( getNextSlideIndex() );
448
0
}
449
450
sal_Int32 AnimationSlideController::getPreviousSlideIndex() const
451
0
{
452
0
    sal_Int32 nNewSlideIndex = mnCurrentSlideIndex - 1;
453
454
0
    switch( meMode )
455
0
    {
456
0
        case ALL:
457
0
        {
458
            // make sure the previous slide is visible
459
            // or was already visited
460
0
            while( isValidIndex( nNewSlideIndex ) )
461
0
            {
462
0
                if( maSlideVisible[nNewSlideIndex] || maSlideVisited[nNewSlideIndex] )
463
0
                    break;
464
465
0
                nNewSlideIndex--;
466
0
            }
467
468
0
            break;
469
0
        }
470
471
0
        case PREVIEW:
472
0
            return -1;
473
474
0
        default:
475
0
            break;
476
0
    }
477
478
0
    return nNewSlideIndex;
479
0
}
480
481
bool AnimationSlideController::previousSlide()
482
0
{
483
0
    return jumpToSlideIndex( getPreviousSlideIndex() );
484
0
}
485
486
void AnimationSlideController::displayCurrentSlide( const Reference< XSlideShow >& xShow,
487
                                                    const Reference< XDrawPagesSupplier>& xDrawPages,
488
                                                    const bool bSkipAllMainSequenceEffects )
489
0
{
490
0
    const sal_Int32 nCurrentSlideNumber = getCurrentSlideNumber();
491
492
0
    if( !(xShow.is() && (nCurrentSlideNumber != -1 )) )
493
0
        return;
494
495
0
    Reference< XDrawPage > xSlide;
496
0
    Reference< XAnimationNode > xAnimNode;
497
0
    ::std::vector<PropertyValue> aProperties;
498
499
0
    const sal_Int32 nNextSlideNumber = getNextSlideNumber();
500
0
    if( getSlideAPI( nNextSlideNumber, xSlide, xAnimNode )  )
501
0
    {
502
0
        Sequence< Any > aValue{ Any(xSlide), Any(xAnimNode) };
503
0
        aProperties.emplace_back( "Prefetch" ,
504
0
                -1,
505
0
                Any(aValue),
506
0
                PropertyState_DIRECT_VALUE);
507
0
    }
508
0
    if (bSkipAllMainSequenceEffects)
509
0
    {
510
        // Add one property that prevents the slide transition from being
511
        // shown (to speed up the transition to the previous slide) and
512
        // one to show all main sequence effects so that the user can
513
        // continue to undo effects.
514
0
        aProperties.emplace_back( "SkipAllMainSequenceEffects",
515
0
                -1,
516
0
                Any(true),
517
0
                PropertyState_DIRECT_VALUE);
518
0
        aProperties.emplace_back("SkipSlideTransition",
519
0
                -1,
520
0
                Any(true),
521
0
                PropertyState_DIRECT_VALUE);
522
0
    }
523
524
0
    if( getSlideAPI( nCurrentSlideNumber, xSlide, xAnimNode ) )
525
0
        xShow->displaySlide( xSlide, xDrawPages, xAnimNode, comphelper::containerToSequence(aProperties) );
526
0
}
527
528
constexpr OUString gsOnClick( u"OnClick"_ustr );
529
constexpr OUString gsBookmark( u"Bookmark"_ustr );
530
constexpr OUString gsVerb( u"Verb"_ustr );
531
532
SlideshowImpl::SlideshowImpl( const Reference< XPresentation2 >& xPresentation, ViewShell* pViewSh, ::sd::View* pView, SdDrawDocument* pDoc, vcl::Window* pParentWindow )
533
0
: mxShow()
534
0
, mxView()
535
0
, mxModel(pDoc->getUnoModel())
536
0
, maUpdateTimer("SlideShowImpl maUpdateTimer")
537
0
, maInputFreezeTimer("SlideShowImpl maInputFreezeTimer")
538
0
, maDeactivateTimer("SlideShowImpl maDeactivateTimer")
539
0
, mpView(pView)
540
0
, mpViewShell(pViewSh)
541
0
, mpDocSh(pDoc->GetDocSh())
542
0
, mpDoc(pDoc)
543
0
, mpParentWindow(pParentWindow)
544
0
, mpShowWindow(nullptr)
545
0
, mpSlideController()
546
0
, mnRestoreSlide(0)
547
0
, maPopupMousePos()
548
0
, maPresSize( -1, -1 )
549
0
, meAnimationMode(ANIMATIONMODE_SHOW)
550
0
, maCharBuffer()
551
0
, mpOldActiveWindow(nullptr)
552
0
, maStarBASICGlobalErrorHdl()
553
0
, mnChildMask( 0 )
554
0
, mbDisposed(false)
555
0
, mbAutoSaveWasOn(false)
556
0
, mbRehearseTimings(false)
557
0
, mbIsPaused(false)
558
0
, mbWasPaused(false)
559
0
, mbInputFreeze(false)
560
0
, mbActive(false)
561
0
, maPresSettings( pDoc->getPresentationSettings() )
562
0
, mnUserPaintColor( 0x80ff0000L )
563
0
, mbUsePen(false)
564
0
, mdUserPaintStrokeWidth ( 150.0 )
565
0
, maShapeEventMap()
566
0
, mxPreviewDrawPage()
567
0
, mxPreviewAnimationNode()
568
0
, mxPlayer()
569
0
, mpPaneHider()
570
0
, mnEndShowEvent(nullptr)
571
0
, mnContextMenuEvent(nullptr)
572
0
, mnEventObjectChange(nullptr)
573
0
, mnEventObjectInserted(nullptr)
574
0
, mnEventObjectRemoved(nullptr)
575
0
, mnEventPageOrderChange(nullptr)
576
0
, mxPresentation( xPresentation )
577
0
, mxListenerProxy()
578
0
, mxShow2()
579
0
, mxView2()
580
, meAnimationMode2()
581
0
, mbInterActiveSetup(false)
582
0
, maPresSettings2()
583
0
, mxPreviewDrawPage2()
584
0
, mxPreviewAnimationNode2()
585
0
, mnSlideIndex(0)
586
0
{
587
0
    if( mpViewShell )
588
0
        mpOldActiveWindow = mpViewShell->GetActiveWindow();
589
590
0
    maUpdateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, updateHdl));
591
    // Priority must not be too high or we'll starve input handling etc.
592
0
    maUpdateTimer.SetPriority(TaskPriority::REPAINT);
593
594
0
    maDeactivateTimer.SetInvokeHandler(LINK(this, SlideshowImpl, deactivateHdl));
595
0
    maDeactivateTimer.SetTimeout( 20 );
596
597
0
    maInputFreezeTimer.SetInvokeHandler( LINK( this, SlideshowImpl, ReadyForNextInputHdl ) );
598
0
    maInputFreezeTimer.SetTimeout( 20 );
599
600
        // no autosave during show
601
0
    if (officecfg::Office::Recovery::AutoSave::Enabled::get())
602
0
        mbAutoSaveWasOn = true;
603
604
0
    Application::AddEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
605
606
0
    mbUsePen = maPresSettings.mbMouseAsPen;
607
608
0
    SdOptions* pOptions = SdModule::get()->GetSdOptions(DocumentType::Impress);
609
0
    if( pOptions )
610
0
    {
611
0
        mnUserPaintColor = pOptions->GetPresentationPenColor();
612
0
        mdUserPaintStrokeWidth = pOptions->GetPresentationPenWidth();
613
0
    }
614
615
    // to be able to react on various changes in the DrawModel, this class
616
    // is now derived from SfxListener and registers itself at the DrawModel
617
0
    if (nullptr != mpDoc)
618
0
        StartListening(*mpDoc);
619
0
}
Unexecuted instantiation: sd::SlideshowImpl::SlideshowImpl(com::sun::star::uno::Reference<com::sun::star::presentation::XPresentation2> const&, sd::ViewShell*, sd::View*, SdDrawDocument*, vcl::Window*)
Unexecuted instantiation: sd::SlideshowImpl::SlideshowImpl(com::sun::star::uno::Reference<com::sun::star::presentation::XPresentation2> const&, sd::ViewShell*, sd::View*, SdDrawDocument*, vcl::Window*)
620
621
SlideshowImpl::~SlideshowImpl()
622
0
{
623
    // stop listening to DrawModel (see above)
624
0
    if (nullptr != mpDoc)
625
0
        EndListening(*mpDoc);
626
627
0
    SdModule* pModule = SdModule::get();
628
    //rhbz#806663 SlideshowImpl can outlive SdModule
629
0
    SdOptions* pOptions = pModule ?
630
0
        pModule->GetSdOptions(DocumentType::Impress) : nullptr;
631
0
    if( pOptions )
632
0
    {
633
0
        pOptions->SetPresentationPenColor(mnUserPaintColor);
634
0
        pOptions->SetPresentationPenWidth(mdUserPaintStrokeWidth);
635
0
    }
636
637
0
    Application::RemoveEventListener( LINK( this, SlideshowImpl, EventListenerHdl ) );
638
639
0
    maDeactivateTimer.Stop();
640
641
0
    if( !mbDisposed )
642
0
    {
643
0
        OSL_FAIL("SlideshowImpl::~SlideshowImpl(), component was not disposed!");
644
0
        std::unique_lock g(m_aMutex);
645
0
        disposing(g);
646
0
    }
647
0
}
648
649
void SlideshowImpl::disposing(std::unique_lock<std::mutex>&)
650
0
{
651
#ifdef ENABLE_SDREMOTE
652
    RemoteServer::presentationStopped();
653
#endif
654
    // IASS: This is the central methodology to 'steer' the
655
    // PresenterConsole - in this case, to shut it down
656
0
    if( mxShow.is() && mpDoc )
657
0
        NotifyDocumentEvent(
658
0
            *mpDoc,
659
0
            u"OnEndPresentation"_ustr );
660
661
0
    if( mbAutoSaveWasOn )
662
0
        setAutoSaveState( true );
663
664
0
    if( mnEndShowEvent )
665
0
        Application::RemoveUserEvent( mnEndShowEvent );
666
0
    if( mnContextMenuEvent )
667
0
        Application::RemoveUserEvent( mnContextMenuEvent );
668
0
    if( mnEventObjectChange )
669
0
        Application::RemoveUserEvent( mnEventObjectChange );
670
0
    if( mnEventObjectInserted )
671
0
        Application::RemoveUserEvent( mnEventObjectInserted );
672
0
    if( mnEventObjectRemoved )
673
0
        Application::RemoveUserEvent( mnEventObjectRemoved );
674
0
    if( mnEventPageOrderChange )
675
0
        Application::RemoveUserEvent( mnEventPageOrderChange );
676
677
0
    maInputFreezeTimer.Stop();
678
679
0
    SolarMutexGuard aSolarGuard;
680
681
0
    if( !mxShow.is() )
682
0
        return;
683
684
0
    if( mxPresentation.is() )
685
0
        mxPresentation->end();
686
687
0
    maUpdateTimer.Stop();
688
689
0
    removeShapeEvents();
690
691
0
    if( mxListenerProxy.is() )
692
0
        mxListenerProxy->removeAsSlideShowListener();
693
694
0
    try
695
0
    {
696
0
        if( mxView.is() )
697
0
            mxShow->removeView( mxView );
698
699
0
        Reference< XComponent > xComponent( mxShow, UNO_QUERY );
700
0
        if( xComponent.is() )
701
0
            xComponent->dispose();
702
703
0
        if( mxView.is() )
704
0
            mxView->dispose();
705
0
    }
706
0
    catch( Exception& )
707
0
    {
708
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stop()" );
709
0
    }
710
711
0
    mxShow.clear();
712
0
    mxView.clear();
713
0
    mxListenerProxy.clear();
714
0
    mpSlideController.reset();
715
716
    // take DrawView from presentation window, but give the old window back
717
0
    if( mpShowWindow && mpView )
718
0
        mpView->DeleteDeviceFromPaintView( *mpShowWindow->GetOutDev() );
719
720
0
    if( mpView )
721
0
        mpView->SetAnimationPause( false );
722
723
0
    if( mpViewShell )
724
0
    {
725
0
        mpViewShell->SetActiveWindow(mpOldActiveWindow);
726
0
        if (mpShowWindow)
727
0
            mpShowWindow->SetViewShell( nullptr );
728
0
    }
729
730
0
    if( mpView )
731
0
        mpView->InvalidateAllWin();
732
733
0
    if( maPresSettings.mbFullScreen )
734
0
    {
735
#if HAVE_FEATURE_SCRIPTING
736
        // restore StarBASICErrorHdl
737
        StarBASIC::SetGlobalErrorHdl(maStarBASICGlobalErrorHdl);
738
        maStarBASICGlobalErrorHdl = Link<StarBASIC*,bool>();
739
#endif
740
0
    }
741
0
    else
742
0
    {
743
0
        if( mpShowWindow )
744
0
            mpShowWindow->Hide();
745
0
    }
746
747
0
    if( meAnimationMode == ANIMATIONMODE_SHOW )
748
0
    {
749
0
        mpDocSh->SetSlotFilter();
750
0
        mpDocSh->ApplySlotFilter();
751
752
0
        Help::EnableContextHelp();
753
0
        Help::EnableExtHelp();
754
755
0
        showChildWindows();
756
0
        mnChildMask = 0;
757
0
    }
758
759
    // show current window again
760
0
    if( mpViewShell && dynamic_cast< PresentationViewShell *>( mpViewShell ) ==  nullptr)
761
0
    {
762
0
        if( meAnimationMode == ANIMATIONMODE_SHOW )
763
0
        {
764
0
            mpViewShell->GetViewShellBase().ShowUIControls (true);
765
0
            mpPaneHider.reset();
766
0
        }
767
0
        else if( meAnimationMode == ANIMATIONMODE_PREVIEW )
768
0
        {
769
0
            mpViewShell->ShowUIControls(true);
770
0
        }
771
0
    }
772
773
0
    if( mpShowWindow )
774
0
        mpShowWindow->Hide();
775
0
    mpShowWindow.disposeAndClear();
776
777
0
    if ( mpViewShell )
778
0
    {
779
0
        if( meAnimationMode == ANIMATIONMODE_SHOW )
780
0
        {
781
0
            ::sd::Window* pActWin = mpViewShell->GetActiveWindow();
782
783
0
            if (pActWin)
784
0
            {
785
0
                Size aVisSizePixel = pActWin->GetOutputSizePixel();
786
0
                ::tools::Rectangle aVisAreaWin = pActWin->PixelToLogic( ::tools::Rectangle( Point(0,0), aVisSizePixel) );
787
0
                mpViewShell->VisAreaChanged(aVisAreaWin);
788
0
                if (mpView)
789
0
                    mpView->VisAreaChanged(pActWin->GetOutDev());
790
0
                pActWin->GrabFocus();
791
0
            }
792
0
        }
793
794
        // restart the custom show dialog if he started us
795
0
        if( mpViewShell->IsStartShowWithDialog() && getDispatcher() )
796
0
        {
797
0
            mpViewShell->SetStartShowWithDialog( false );
798
0
            getDispatcher()->Execute( SID_CUSTOMSHOW_DLG, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
799
0
        }
800
801
0
        mpViewShell->GetViewShellBase().UpdateBorder(true);
802
0
    }
803
804
0
    if( mpShowWindow )
805
0
    {
806
0
        mpShowWindow.disposeAndClear();
807
0
    }
808
809
0
    setActiveXToolbarsVisible( true );
810
811
0
    mbDisposed = true;
812
0
}
813
814
bool SlideshowImpl::isInteractiveSetup() const
815
0
{
816
0
    return mbInterActiveSetup;
817
0
}
818
819
void SlideshowImpl::startInteractivePreview( const Reference< XDrawPage >& xDrawPage, const Reference< XAnimationNode >& xAnimationNode )
820
0
{
821
    // set flag that we are in IASS mode
822
0
    mbInterActiveSetup = true;
823
824
    // save stuff that will be replaced temporarily
825
0
    mxShow2 = mxShow;
826
0
    mxView2 = mxView;
827
0
    mxPreviewDrawPage2 = mxPreviewDrawPage;
828
0
    mxPreviewAnimationNode2 = mxPreviewAnimationNode;
829
0
    meAnimationMode2 = meAnimationMode;
830
0
    maPresSettings2 = maPresSettings;
831
832
    // remember slide shown before preview
833
0
    mnSlideIndex = getCurrentSlideIndex();
834
835
    // set DrawPage/AnimationNode
836
0
    mxPreviewDrawPage = xDrawPage;
837
0
    mxPreviewAnimationNode = xAnimationNode;
838
0
    meAnimationMode = ANIMATIONMODE_PREVIEW;
839
840
    // set PresSettings for preview
841
0
    maPresSettings.mbAll = false;
842
0
    maPresSettings.mbEndless = false;
843
0
    maPresSettings.mbCustomShow = false;
844
0
    maPresSettings.mbManual = false;
845
0
    maPresSettings.mbMouseVisible = false;
846
0
    maPresSettings.mbMouseAsPen = false;
847
0
    maPresSettings.mbLockedPages = false;
848
0
    maPresSettings.mbAlwaysOnTop = false;
849
0
    maPresSettings.mbFullScreen = false;
850
0
    maPresSettings.mbAnimationAllowed = true;
851
0
    maPresSettings.mnPauseTimeout = 0;
852
0
    maPresSettings.mbShowPauseLogo = false;
853
854
    // create a new temporary AnimationSlideController
855
0
    mpSlideController->pushForPreview();
856
    // Reference< XDrawPagesSupplier > xDrawPages( mpDoc->getUnoModel(), UNO_QUERY_THROW );
857
    // Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
858
    // mpSlideController = std::make_shared<AnimationSlideController>( xSlides, AnimationSlideController::PREVIEW );
859
0
    sal_Int32 nSlideNumber = 0;
860
0
    Reference< XPropertySet > xSet( xDrawPage, UNO_QUERY_THROW );
861
0
    xSet->getPropertyValue( u"Number"_ustr ) >>= nSlideNumber;
862
0
    mpSlideController->insertSlideNumber( nSlideNumber-1 );
863
0
    mpSlideController->setPreviewNode( xAnimationNode );
864
865
    // prepare properties
866
0
    sal_Int32 nPropertyCount = 1;
867
0
    if( xAnimationNode.is() )
868
0
        nPropertyCount++;
869
0
    Sequence< beans::PropertyValue > aProperties(nPropertyCount);
870
0
    auto pProperties = aProperties.getArray();
871
0
    pProperties[0].Name = "AutomaticAdvancement";
872
0
    pProperties[0].Value <<= 1.0; // one second timeout
873
874
0
    if( xAnimationNode.is() )
875
0
    {
876
0
        pProperties[1].Name = "NoSlideTransitions";
877
0
        pProperties[1].Value <<= true;
878
0
    }
879
880
    // start preview
881
0
    startShowImpl( aProperties );
882
0
}
883
884
void SlideshowImpl::endInteractivePreview()
885
0
{
886
0
    if (!mbInterActiveSetup)
887
        // not in use, nothing to do
888
0
        return;
889
890
    // cleanup Show/View
891
0
    try
892
0
    {
893
0
        if( mxView.is() )
894
0
            mxShow->removeView( mxView );
895
896
0
        Reference< XComponent > xComponent( mxShow, UNO_QUERY );
897
0
        if( xComponent.is() )
898
0
            xComponent->dispose();
899
900
0
        if( mxView.is() )
901
0
            mxView->dispose();
902
0
    }
903
0
    catch( Exception& )
904
0
    {
905
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stop()" );
906
0
    }
907
0
    mxShow.clear();
908
0
    mxView.clear();
909
0
    mxView = mxView2;
910
0
    mxShow = mxShow2;
911
912
    // restore SlideController
913
0
    mpSlideController->popFromPreview();
914
915
    // restore other settings and cleanup temporary incarnations
916
0
    maPresSettings = maPresSettings2;
917
0
    meAnimationMode = meAnimationMode2;
918
0
    mxPreviewAnimationNode = mxPreviewAnimationNode2;
919
0
    mxPreviewAnimationNode2.clear();
920
0
    mxPreviewDrawPage = mxPreviewDrawPage2;
921
0
    mxPreviewDrawPage2.clear();
922
923
    // go back to slide shown before preview
924
0
    gotoSlideIndex(mnSlideIndex);
925
926
    // reset IASS mode flag
927
0
    mbInterActiveSetup = false;
928
0
}
929
930
bool SlideshowImpl::startPreview(
931
        const Reference< XDrawPage >& xDrawPage,
932
        const Reference< XAnimationNode >& xAnimationNode,
933
        vcl::Window * pParent )
934
0
{
935
0
    bool bRet = false;
936
937
0
    try
938
0
    {
939
0
        const Reference<lang::XServiceInfo> xServiceInfo( xDrawPage, UNO_QUERY );
940
0
        if (xServiceInfo.is()) {
941
0
            const Sequence<OUString> supportedServices(
942
0
                xServiceInfo->getSupportedServiceNames() );
943
0
            if (comphelper::findValue(supportedServices, "com.sun.star.drawing.MasterPage") != -1) {
944
0
                OSL_FAIL("sd::SlideshowImpl::startPreview() "
945
0
                          "not allowed on master page!");
946
0
                return false;
947
0
            }
948
0
        }
949
950
0
        mxPreviewDrawPage = xDrawPage;
951
0
        mxPreviewAnimationNode = xAnimationNode;
952
0
        meAnimationMode = ANIMATIONMODE_PREVIEW;
953
954
0
        maPresSettings.mbAll = false;
955
0
        maPresSettings.mbEndless = false;
956
0
        maPresSettings.mbCustomShow = false;
957
0
        maPresSettings.mbManual = false;
958
0
        maPresSettings.mbMouseVisible = false;
959
0
        maPresSettings.mbMouseAsPen = false;
960
0
        maPresSettings.mbLockedPages = false;
961
0
        maPresSettings.mbAlwaysOnTop = false;
962
0
        maPresSettings.mbFullScreen = false;
963
0
        maPresSettings.mbAnimationAllowed = true;
964
0
        maPresSettings.mnPauseTimeout = 0;
965
0
        maPresSettings.mbShowPauseLogo = false;
966
967
0
        rtl::Reference< SdXImpressDocument > xDrawPages( mpDoc->getUnoModel() );
968
0
        Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
969
0
        mpSlideController = std::make_unique<AnimationSlideController>( xSlides, AnimationSlideController::PREVIEW );
970
971
0
        sal_Int32 nSlideNumber = 0;
972
0
        Reference< XPropertySet > xSet( mxPreviewDrawPage, UNO_QUERY_THROW );
973
0
        xSet->getPropertyValue( u"Number"_ustr ) >>= nSlideNumber;
974
0
        mpSlideController->insertSlideNumber( nSlideNumber-1 );
975
0
        mpSlideController->setPreviewNode( xAnimationNode );
976
977
0
        mpShowWindow = VclPtr<ShowWindow>::Create( this, ((pParent == nullptr) && mpViewShell) ?  mpParentWindow.get() : pParent );
978
0
        if( mpViewShell )
979
0
        {
980
0
            mpViewShell->SetActiveWindow( mpShowWindow );
981
0
            mpShowWindow->SetViewShell (mpViewShell);
982
0
            mpViewShell->ShowUIControls (false);
983
0
        }
984
985
0
        if( mpView )
986
0
        {
987
0
            mpView->AddDeviceToPaintView( *mpShowWindow->GetOutDev() );
988
0
            mpView->SetAnimationPause( true );
989
0
        }
990
991
        // call resize handler
992
0
        if( pParent )
993
0
        {
994
0
            maPresSize = pParent->GetSizePixel();
995
0
        }
996
0
        else if( mpViewShell )
997
0
        {
998
0
            ::tools::Rectangle aContentRect (mpViewShell->GetViewShellBase().getClientRectangle());
999
0
            if (AllSettings::GetLayoutRTL())
1000
0
            {
1001
0
                aContentRect.SetLeft( aContentRect.Right() );
1002
0
                aContentRect.AdjustRight(aContentRect.Right() );
1003
0
            }
1004
0
            maPresSize = aContentRect.GetSize();
1005
0
            mpShowWindow->SetPosPixel( aContentRect.TopLeft() );
1006
0
        }
1007
0
        else
1008
0
        {
1009
0
            OSL_FAIL("sd::SlideshowImpl::startPreview(), I need either a parent window or a viewshell!");
1010
0
        }
1011
0
        resize( maPresSize );
1012
1013
0
        sal_Int32 nPropertyCount = 1;
1014
0
        if( mxPreviewAnimationNode.is() )
1015
0
            nPropertyCount++;
1016
1017
0
        Sequence< beans::PropertyValue > aProperties(nPropertyCount);
1018
0
        auto pProperties = aProperties.getArray();
1019
0
        pProperties[0].Name = "AutomaticAdvancement";
1020
0
        pProperties[0].Value <<= 1.0; // one second timeout
1021
1022
0
        if( mxPreviewAnimationNode.is() )
1023
0
        {
1024
0
            pProperties[1].Name = "NoSlideTransitions";
1025
0
            pProperties[1].Value <<= true;
1026
0
        }
1027
1028
0
        bRet = startShowImpl( aProperties );
1029
1030
0
        if( mpShowWindow != nullptr && meAnimationMode == ANIMATIONMODE_PREVIEW )
1031
0
            mpShowWindow->SetPreviewMode();
1032
1033
0
    }
1034
0
    catch( Exception& )
1035
0
    {
1036
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startPreview()" );
1037
0
        bRet = false;
1038
0
    }
1039
1040
0
    return bRet;
1041
0
}
1042
1043
bool SlideshowImpl::startShow( PresentationSettingsEx const * pPresSettings )
1044
0
{
1045
0
    const rtl::Reference<SlideshowImpl> xKeepAlive(this);
1046
1047
0
    DBG_ASSERT( !mxShow.is(), "sd::SlideshowImpl::startShow(), called twice!" );
1048
0
    if( mxShow.is() )
1049
0
        return true;
1050
0
    DBG_ASSERT( mpParentWindow!=nullptr, "sd::SlideshowImpl::startShow() called without parent window" );
1051
0
    if (mpParentWindow == nullptr)
1052
0
        return false;
1053
1054
    // Autoplay (pps/ppsx)
1055
0
    if (mpViewShell->GetDoc()->GetStartWithPresentation())
1056
0
    {
1057
0
        mpViewShell->GetDoc()->SetExitAfterPresenting(true);
1058
0
    }
1059
1060
0
    bool bRet = false;
1061
1062
0
    try
1063
0
    {
1064
0
        if( pPresSettings )
1065
0
        {
1066
0
            maPresSettings = *pPresSettings;
1067
0
            mbRehearseTimings = pPresSettings->mbRehearseTimings;
1068
0
        }
1069
1070
0
        OUString  aPresSlide( maPresSettings.maPresPage );
1071
0
        SdPage* pStartPage = mpViewShell->GetActualPage();
1072
0
        bool    bStartWithActualSlide =  pStartPage;
1073
1074
        // times should be measured?
1075
0
        if( mbRehearseTimings )
1076
0
        {
1077
0
            maPresSettings.mbEndless = false;
1078
0
            maPresSettings.mbManual = true;
1079
0
            maPresSettings.mbMouseVisible = true;
1080
0
            maPresSettings.mbMouseAsPen = false;
1081
0
            maPresSettings.mnPauseTimeout = 0;
1082
0
            maPresSettings.mbShowPauseLogo = false;
1083
0
        }
1084
1085
0
        if( pStartPage )
1086
0
        {
1087
0
            if( pStartPage->GetPageKind() == PageKind::Notes )
1088
0
            {
1089
                // we are in notes page mode, so get
1090
                // the corresponding draw page
1091
0
                const sal_uInt16 nNotePgNum = pStartPage->GetPageNum();
1092
0
                assert(nNotePgNum >= 2);
1093
0
                const sal_uInt16 nPgNum = ( nNotePgNum - 2 ) >> 1;
1094
0
                pStartPage = mpDoc->GetSdPage( nPgNum, PageKind::Standard );
1095
0
            }
1096
0
        }
1097
1098
0
        if( bStartWithActualSlide )
1099
0
        {
1100
0
            if ( aPresSlide.isEmpty())
1101
0
            {
1102
                // no preset slide yet, so pick current on one
1103
0
                aPresSlide = pStartPage->GetName();
1104
                // if the starting slide is hidden, we can't set slide controller to ALL mode
1105
0
                maPresSettings.mbAll = !pStartPage->IsExcluded();
1106
0
            }
1107
1108
0
            if( meAnimationMode != ANIMATIONMODE_SHOW )
1109
0
            {
1110
0
                if( pStartPage->GetPageKind() == PageKind::Standard )
1111
0
                {
1112
0
                    maPresSettings.mbAll = false;
1113
0
                }
1114
0
            }
1115
0
        }
1116
1117
        // build page list
1118
0
        createSlideList( maPresSettings.mbAll, aPresSlide );
1119
1120
        // remember Slide number from where the show was started
1121
0
        if( pStartPage )
1122
0
            mnRestoreSlide = ( pStartPage->GetPageNum() - 1 ) / 2;
1123
1124
0
        if( mpSlideController->hasSlides() )
1125
0
        {
1126
            // hide child windows
1127
0
            hideChildWindows();
1128
1129
0
            mpShowWindow = VclPtr<ShowWindow>::Create( this, mpParentWindow );
1130
0
            mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
1131
0
            mpViewShell->SetActiveWindow( mpShowWindow );
1132
0
            mpShowWindow->SetViewShell (mpViewShell);
1133
0
            mpViewShell->GetViewShellBase().ShowUIControls (false);
1134
            // Hide the side panes for in-place presentations.
1135
0
            if ( ! maPresSettings.mbFullScreen)
1136
0
                mpPaneHider.reset(new PaneHider(*mpViewShell,this));
1137
1138
            // these Slots are forbidden in other views for this document
1139
0
            if( mpDocSh && pPresSettings && !pPresSettings->mbInteractive) // IASS
1140
0
            {
1141
0
                mpDocSh->SetSlotFilter( true, pAllowed );
1142
0
                mpDocSh->ApplySlotFilter();
1143
0
            }
1144
1145
0
            Help::DisableContextHelp();
1146
0
            Help::DisableExtHelp();
1147
1148
0
            if( maPresSettings.mbFullScreen )
1149
0
            {
1150
#if HAVE_FEATURE_SCRIPTING
1151
                // disable basic ide error handling
1152
                maStarBASICGlobalErrorHdl = StarBASIC::GetGlobalErrorHdl();
1153
                StarBASIC::SetGlobalErrorHdl( Link<StarBASIC*,bool>() );
1154
#endif
1155
0
            }
1156
1157
            // call resize handler
1158
0
            maPresSize = mpParentWindow->GetSizePixel();
1159
0
            if (!maPresSettings.mbFullScreen)
1160
0
            {
1161
0
                const ::tools::Rectangle& aClientRect = mpViewShell->GetViewShellBase().getClientRectangle();
1162
0
                maPresSize = aClientRect.GetSize();
1163
0
                mpShowWindow->SetPosPixel( aClientRect.TopLeft() );
1164
0
                resize( maPresSize );
1165
0
            }
1166
1167
            // #i41824#
1168
            // Note: In FullScreen Mode the OS (window manager) sends a resize to
1169
            // the WorkWindow once it actually resized it to full size.  The
1170
            // WorkWindow propagates the resize to the DrawViewShell which calls
1171
            // resize() at the SlideShow (this).  Calling resize here results in a
1172
            // temporary display of a black window in the window's default size
1173
1174
0
            if( mpView )
1175
0
            {
1176
0
                mpView->AddDeviceToPaintView( *mpShowWindow->GetOutDev() );
1177
0
                mpView->SetAnimationPause( true );
1178
0
            }
1179
1180
0
            SfxBindings* pBindings = getBindings();
1181
0
            if( pBindings )
1182
0
            {
1183
0
                pBindings->Invalidate( SID_PRESENTATION );
1184
0
                pBindings->Invalidate( SID_REHEARSE_TIMINGS );
1185
0
            }
1186
1187
            // Defer the sd::ShowWindow's GrabFocus to SlideShow::activate. so that the accessible event can be fired correctly.
1188
            //mpShowWindow->GrabFocus();
1189
1190
0
            std::vector<beans::PropertyValue> aProperties;
1191
0
            aProperties.reserve( 4 );
1192
1193
0
            aProperties.emplace_back( "AdvanceOnClick" ,
1194
0
                    -1, Any( !maPresSettings.mbLockedPages ),
1195
0
                    beans::PropertyState_DIRECT_VALUE );
1196
1197
0
            aProperties.emplace_back( "ImageAnimationsAllowed" ,
1198
0
                    -1, Any( maPresSettings.mbAnimationAllowed ),
1199
0
                    beans::PropertyState_DIRECT_VALUE );
1200
1201
0
            const bool bZOrderEnabled(
1202
0
                SdModule::get()->GetSdOptions( mpDoc->GetDocumentType() )->IsSlideshowRespectZOrder() );
1203
0
            aProperties.emplace_back( "DisableAnimationZOrder" ,
1204
0
                    -1, Any( !bZOrderEnabled ),
1205
0
                    beans::PropertyState_DIRECT_VALUE );
1206
1207
0
            aProperties.emplace_back( "ForceManualAdvance" ,
1208
0
                    -1, Any( maPresSettings.mbManual ),
1209
0
                    beans::PropertyState_DIRECT_VALUE );
1210
1211
0
            if( mbUsePen )
1212
0
            {
1213
0
                aProperties.emplace_back( "UserPaintColor" ,
1214
                        // User paint color is black by default.
1215
0
                        -1, Any( mnUserPaintColor ),
1216
0
                        beans::PropertyState_DIRECT_VALUE );
1217
1218
0
                aProperties.emplace_back( "UserPaintStrokeWidth" ,
1219
                        // User paint color is black by default.
1220
0
                        -1, Any( mdUserPaintStrokeWidth ),
1221
0
                        beans::PropertyState_DIRECT_VALUE );
1222
0
            }
1223
1224
0
            if (mbRehearseTimings) {
1225
0
                aProperties.emplace_back( "RehearseTimings" ,
1226
0
                        -1, Any(true), beans::PropertyState_DIRECT_VALUE );
1227
0
            }
1228
1229
0
            bRet = startShowImpl( Sequence<beans::PropertyValue>(
1230
0
                                      aProperties.data(), aProperties.size() ) );
1231
1232
0
        }
1233
1234
0
        setActiveXToolbarsVisible( false );
1235
0
    }
1236
0
    catch (const Exception&)
1237
0
    {
1238
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShow()" );
1239
0
        bRet = false;
1240
0
    }
1241
1242
0
    return bRet;
1243
0
}
1244
1245
bool SlideshowImpl::startShowImpl( const Sequence< beans::PropertyValue >& aProperties )
1246
0
{
1247
0
    try
1248
0
    {
1249
0
        mxShow.set( createSlideShow(), UNO_SET_THROW );
1250
1251
0
        mxView = new SlideShowView(
1252
0
                                             *mpShowWindow,
1253
0
                                             mpDoc,
1254
0
                                             meAnimationMode,
1255
0
                                             this,
1256
0
                                             maPresSettings.mbFullScreen);
1257
1258
        // try add wait symbol to properties:
1259
0
        const Reference<rendering::XSpriteCanvas> xSpriteCanvas(
1260
0
            mxView->getCanvas() );
1261
0
        if (xSpriteCanvas.is())
1262
0
        {
1263
0
            Bitmap waitSymbolBitmap(BMP_WAIT_ICON);
1264
0
            const Reference<rendering::XBitmap> xBitmap(
1265
0
                vcl::unotools::xBitmapFromBitmap( waitSymbolBitmap ) );
1266
0
            if (xBitmap.is())
1267
0
            {
1268
0
                mxShow->setProperty(
1269
0
                    beans::PropertyValue( u"WaitSymbolBitmap"_ustr ,
1270
0
                        -1,
1271
0
                        Any( xBitmap ),
1272
0
                        beans::PropertyState_DIRECT_VALUE ) );
1273
0
            }
1274
1275
0
            Bitmap pointerSymbolBitmap(BMP_POINTER_ICON);
1276
0
            const Reference<rendering::XBitmap> xPointerBitmap(
1277
0
                vcl::unotools::xBitmapFromBitmap( pointerSymbolBitmap ) );
1278
0
            if (xPointerBitmap.is())
1279
0
            {
1280
0
                mxShow->setProperty(
1281
0
                    beans::PropertyValue( u"PointerSymbolBitmap"_ustr ,
1282
0
                        -1,
1283
0
                        Any( xPointerBitmap ),
1284
0
                        beans::PropertyState_DIRECT_VALUE ) );
1285
0
            }
1286
0
            if (officecfg::Office::Impress::Misc::Start::ShowNavigationPanel::get())
1287
0
            {
1288
0
                NavbarButtonSize btnScale = static_cast<NavbarButtonSize>(officecfg::Office::Impress::Layout::Display::NavigationBtnScale::get());
1289
0
                OUString prevSlidePath = u""_ustr;
1290
0
                OUString nextSlidePath = u""_ustr;
1291
0
                OUString menuPath = u""_ustr;
1292
0
                switch (btnScale)
1293
0
                {
1294
0
                    case NavbarButtonSize::Large:
1295
0
                    {
1296
0
                        prevSlidePath = BMP_PREV_SLIDE_LARGE;
1297
0
                        nextSlidePath = BMP_NEXT_SLIDE_LARGE;
1298
0
                        menuPath = BMP_MENU_SLIDE_LARGE;
1299
0
                        break;
1300
0
                    }
1301
0
                    case NavbarButtonSize::XLarge:
1302
0
                    {
1303
0
                        prevSlidePath = BMP_PREV_SLIDE_EXTRALARGE;
1304
0
                        nextSlidePath = BMP_NEXT_SLIDE_EXTRALARGE;
1305
0
                        menuPath = BMP_MENU_SLIDE_EXTRALARGE;
1306
0
                        break;
1307
0
                    }
1308
0
                    case NavbarButtonSize::Auto:
1309
0
                    {
1310
0
                        mxShow->setProperty(beans::PropertyValue("NavigationBarAutoscale", -1,
1311
0
                                Any(true),
1312
0
                                PropertyState_DIRECT_VALUE));
1313
0
                    }
1314
0
                    [[fallthrough]]; // Preset default buttons size
1315
0
                    case NavbarButtonSize::Small:
1316
0
                    default:
1317
0
                    {
1318
0
                        prevSlidePath = BMP_PREV_SLIDE_SMALL;
1319
0
                        nextSlidePath = BMP_NEXT_SLIDE_SMALL;
1320
0
                        menuPath = BMP_MENU_SLIDE_SMALL;
1321
0
                        break;
1322
0
                    }
1323
0
                }
1324
0
                Bitmap prevSlideBm(prevSlidePath);
1325
0
                const Reference<rendering::XBitmap> xPrevSBitmap(
1326
0
                    vcl::unotools::xBitmapFromBitmap(prevSlideBm));
1327
0
                if (xPrevSBitmap.is())
1328
0
                {
1329
0
                    mxShow->setProperty(beans::PropertyValue(u"NavigationSlidePrev"_ustr, -1,
1330
0
                                                             Any(xPrevSBitmap),
1331
0
                                                             beans::PropertyState_DIRECT_VALUE));
1332
0
                }
1333
0
                Bitmap menuSlideBm(menuPath);
1334
0
                const Reference<rendering::XBitmap> xMenuSBitmap(
1335
0
                    vcl::unotools::xBitmapFromBitmap(menuSlideBm));
1336
0
                if (xMenuSBitmap.is())
1337
0
                {
1338
0
                    mxShow->setProperty(beans::PropertyValue(u"NavigationSlideMenu"_ustr, -1,
1339
0
                                                             Any(xMenuSBitmap),
1340
0
                                                             beans::PropertyState_DIRECT_VALUE));
1341
0
                }
1342
0
                Bitmap nextSlideBm(nextSlidePath);
1343
0
                const Reference<rendering::XBitmap> xNextSBitmap(
1344
0
                    vcl::unotools::xBitmapFromBitmap(nextSlideBm));
1345
0
                if (xNextSBitmap.is())
1346
0
                {
1347
0
                    mxShow->setProperty(beans::PropertyValue(u"NavigationSlideNext"_ustr, -1,
1348
0
                                                             Any(xNextSBitmap),
1349
0
                                                             beans::PropertyState_DIRECT_VALUE));
1350
0
                }
1351
0
            }
1352
0
        }
1353
1354
0
        for( const auto& rProp : aProperties )
1355
0
            mxShow->setProperty( rProp );
1356
1357
0
        mxShow->addView( mxView );
1358
1359
0
        mxListenerProxy.set( new SlideShowListenerProxy( this, mxShow ) );
1360
0
        mxListenerProxy->addAsSlideShowListener();
1361
1362
        // IASS: Do only startup the PresenterConsole if this is not
1363
        // the SlideShow Preview mode (else would be double)
1364
0
        if (!mbInterActiveSetup)
1365
0
        {
1366
            // IASS: This is the central methodology to 'steer' the
1367
            // PresenterConsole - in this case, to start it up and make
1368
            // it visible (if activated)
1369
0
            NotifyDocumentEvent(
1370
0
                *mpDoc,
1371
0
                u"OnStartPresentation"_ustr);
1372
0
        }
1373
1374
0
        displaySlideIndex( mpSlideController->getStartSlideIndex() );
1375
1376
0
        return true;
1377
0
    }
1378
0
    catch( Exception& )
1379
0
    {
1380
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::startShowImpl()" );
1381
0
        return false;
1382
0
    }
1383
0
}
1384
1385
/** called only by the slideshow view when the first paint event occurs.
1386
    This actually starts the slideshow. */
1387
void SlideshowImpl::onFirstPaint()
1388
0
{
1389
0
    if( mpShowWindow )
1390
0
    {
1391
        /*
1392
        mpShowWindow->SetBackground( Wallpaper( COL_BLACK ) );
1393
        mpShowWindow->Erase();
1394
        mpShowWindow->SetBackground();
1395
        */
1396
0
    }
1397
1398
0
    SolarMutexGuard aSolarGuard;
1399
0
    maUpdateTimer.SetTimeout( sal_uLong(100) );
1400
0
    maUpdateTimer.Start();
1401
0
}
1402
1403
void SlideshowImpl::paint()
1404
0
{
1405
0
    if( mxView.is() ) try
1406
0
    {
1407
0
        awt::PaintEvent aEvt;
1408
        // aEvt.UpdateRect = TODO
1409
0
        mxView->paint( aEvt );
1410
0
    }
1411
0
    catch( Exception& )
1412
0
    {
1413
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::paint()" );
1414
0
    }
1415
0
}
1416
1417
void SAL_CALL SlideshowImpl::addSlideShowListener( const Reference< XSlideShowListener >& xListener )
1418
0
{
1419
0
    if( mxListenerProxy.is() )
1420
0
        mxListenerProxy->addSlideShowListener( xListener );
1421
0
}
1422
1423
void SAL_CALL SlideshowImpl::removeSlideShowListener( const Reference< XSlideShowListener >& xListener )
1424
0
{
1425
0
    if( mxListenerProxy.is() )
1426
0
        mxListenerProxy->removeSlideShowListener( xListener );
1427
0
}
1428
1429
void SlideshowImpl::slideEnded(const bool bReverse)
1430
0
{
1431
0
    if (bReverse)
1432
0
        gotoPreviousSlide(true);
1433
0
    else
1434
0
        gotoNextSlide();
1435
0
}
1436
1437
bool SlideshowImpl::swipe(const CommandGestureSwipeData &rSwipeData)
1438
0
{
1439
0
    if (mbUsePen || mnContextMenuEvent)
1440
0
        return false;
1441
0
    double nVelocityX = rSwipeData.getVelocityX();
1442
    // tdf#108475 make it swipe only if some reasonable movement was involved
1443
0
    if (fabs(nVelocityX) < 50)
1444
0
        return false;
1445
0
    if (nVelocityX > 0)
1446
0
    {
1447
0
        gotoPreviousSlide();
1448
0
    }
1449
0
    else
1450
0
    {
1451
0
        gotoNextEffect();
1452
0
    }
1453
    //a swipe is followed by a mouse up, tell the view to ignore that mouse up as we've reacted
1454
    //to the swipe instead
1455
0
    mxView->ignoreNextMouseReleased();
1456
0
    return true;
1457
0
}
1458
1459
bool SlideshowImpl::longpress(const CommandGestureLongPressData &rLongPressData)
1460
0
{
1461
0
    if (mnContextMenuEvent)
1462
0
        return false;
1463
1464
0
    maPopupMousePos = Point(rLongPressData.getX(), rLongPressData.getY());
1465
0
    mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
1466
1467
0
    return true;
1468
0
}
1469
1470
void SlideshowImpl::removeShapeEvents()
1471
0
{
1472
0
    if( !(mxShow.is() && mxListenerProxy.is()) )
1473
0
        return;
1474
1475
0
    try
1476
0
    {
1477
0
        for( const auto& rEntry : maShapeEventMap )
1478
0
        {
1479
0
            mxListenerProxy->removeShapeEventListener( rEntry.first );
1480
0
            mxShow->setShapeCursor( rEntry.first, awt::SystemPointer::ARROW );
1481
0
        }
1482
1483
0
        maShapeEventMap.clear();
1484
0
    }
1485
0
    catch( Exception& )
1486
0
    {
1487
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::removeShapeEvents()" );
1488
0
    }
1489
0
}
1490
1491
void SlideshowImpl::registerShapeEvents(sal_Int32 nSlideNumber)
1492
0
{
1493
0
    if( nSlideNumber < 0 )
1494
0
        return;
1495
1496
0
    try
1497
0
    {
1498
0
        Reference< XIndexAccess > xPages( mxModel->getDrawPages(), UNO_QUERY_THROW );
1499
1500
0
        Reference< XShapes > xDrawPage;
1501
0
        xPages->getByIndex(nSlideNumber) >>= xDrawPage;
1502
1503
0
        if( xDrawPage.is() )
1504
0
        {
1505
0
            Reference< XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
1506
0
            if( xMasterPageTarget.is() )
1507
0
            {
1508
0
                Reference< XShapes > xMasterPage = xMasterPageTarget->getMasterPage();
1509
0
                if( xMasterPage.is() )
1510
0
                    registerShapeEvents( xMasterPage );
1511
0
            }
1512
0
            registerShapeEvents( xDrawPage );
1513
0
        }
1514
0
    }
1515
0
    catch( Exception& )
1516
0
    {
1517
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" );
1518
0
    }
1519
0
}
1520
1521
void SlideshowImpl::registerShapeEvents( Reference< XShapes > const & xShapes )
1522
0
{
1523
0
    try
1524
0
    {
1525
0
        const sal_Int32 nShapeCount = xShapes->getCount();
1526
0
        sal_Int32 nShape;
1527
0
        for( nShape = 0; nShape < nShapeCount; nShape++ )
1528
0
        {
1529
0
            Reference< XShape > xShape;
1530
0
            xShapes->getByIndex( nShape ) >>= xShape;
1531
1532
0
            if( xShape.is() && xShape->getShapeType() == "com.sun.star.drawing.GroupShape" )
1533
0
            {
1534
0
                Reference< XShapes > xSubShapes( xShape, UNO_QUERY );
1535
0
                if( xSubShapes.is() )
1536
0
                    registerShapeEvents( xSubShapes );
1537
0
            }
1538
1539
0
            Reference< XPropertySet > xSet( xShape, UNO_QUERY );
1540
0
            if( !xSet.is() )
1541
0
                continue;
1542
1543
0
            Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1544
0
            if( !xSetInfo.is() || !xSetInfo->hasPropertyByName( gsOnClick ) )
1545
0
                continue;
1546
1547
0
            WrappedShapeEventImpl aEvent;
1548
0
            xSet->getPropertyValue( gsOnClick ) >>= aEvent.meClickAction;
1549
1550
0
            switch( aEvent.meClickAction )
1551
0
            {
1552
0
            case ClickAction_PREVPAGE:
1553
0
            case ClickAction_NEXTPAGE:
1554
0
            case ClickAction_FIRSTPAGE:
1555
0
            case ClickAction_LASTPAGE:
1556
0
            case ClickAction_STOPPRESENTATION:
1557
0
                break;
1558
0
            case ClickAction_BOOKMARK:
1559
0
                if( xSetInfo->hasPropertyByName( gsBookmark ) )
1560
0
                    xSet->getPropertyValue( gsBookmark ) >>= aEvent.maStrBookmark;
1561
0
                if( getSlideNumberForBookmark( aEvent.maStrBookmark ) == -1 )
1562
0
                    continue;
1563
0
                break;
1564
0
            case ClickAction_DOCUMENT:
1565
0
            case ClickAction_SOUND:
1566
0
            case ClickAction_PROGRAM:
1567
0
            case ClickAction_MACRO:
1568
0
                if( xSetInfo->hasPropertyByName( gsBookmark ) )
1569
0
                    xSet->getPropertyValue( gsBookmark ) >>= aEvent.maStrBookmark;
1570
0
                break;
1571
0
            case ClickAction_VERB:
1572
0
                if( xSetInfo->hasPropertyByName( gsVerb ) )
1573
0
                    xSet->getPropertyValue( gsVerb ) >>= aEvent.mnVerb;
1574
0
                break;
1575
0
            default:
1576
0
                continue; // skip all others
1577
0
            }
1578
1579
0
            maShapeEventMap[ xShape ] = std::move(aEvent);
1580
1581
0
            if( mxListenerProxy.is() )
1582
0
                mxListenerProxy->addShapeEventListener( xShape );
1583
0
            mxShow->setShapeCursor( xShape, awt::SystemPointer::REFHAND );
1584
0
        }
1585
0
    }
1586
0
    catch( Exception& )
1587
0
    {
1588
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::registerShapeEvents()" );
1589
0
    }
1590
0
}
1591
1592
void SlideshowImpl::displayCurrentSlide (const bool bSkipAllMainSequenceEffects)
1593
0
{
1594
0
    stopSound();
1595
0
    removeShapeEvents();
1596
1597
0
    if( mpSlideController && mxShow.is() )
1598
0
    {
1599
0
        rtl::Reference< SdXImpressDocument > xDrawPages( mpDoc->getUnoModel() );
1600
0
        mpSlideController->displayCurrentSlide( mxShow, xDrawPages, bSkipAllMainSequenceEffects );
1601
0
        registerShapeEvents(mpSlideController->getCurrentSlideNumber());
1602
0
        update();
1603
1604
0
    }
1605
    // send out page change event and notify to update all acc info for current page
1606
0
    if (mpViewShell)
1607
0
    {
1608
0
        sal_Int32 currentPageIndex = getCurrentSlideIndex();
1609
0
        mpViewShell->fireSwitchCurrentPage(currentPageIndex);
1610
0
        mpViewShell->NotifyAccUpdate();
1611
0
    }
1612
0
}
1613
1614
void SlideshowImpl::endPresentation()
1615
0
{
1616
0
    if( maPresSettings.mbMouseAsPen)
1617
0
    {
1618
0
        rtl::Reference< SdXImpressDocument > xDocFactory(mpDoc->getUnoModel() );
1619
0
        if( xDocFactory.is() )
1620
0
            mxShow->registerUserPaintPolygons(xDocFactory);
1621
0
    }
1622
1623
0
    if( !mnEndShowEvent )
1624
0
        mnEndShowEvent = Application::PostUserEvent( LINK(this, SlideshowImpl, endPresentationHdl) );
1625
0
}
1626
1627
IMPL_LINK_NOARG(SlideshowImpl, endPresentationHdl, void*, void)
1628
0
{
1629
0
    mnEndShowEvent = nullptr;
1630
1631
0
    stopSound();
1632
1633
0
    if( mxPresentation.is() )
1634
0
        mxPresentation->end();
1635
0
}
1636
1637
void SAL_CALL SlideshowImpl::pause()
1638
0
{
1639
0
    SolarMutexGuard aSolarGuard;
1640
1641
0
    if( mbIsPaused )
1642
0
        return;
1643
1644
0
    try
1645
0
    {
1646
0
        mbIsPaused = true;
1647
0
        if( mxShow.is() )
1648
0
        {
1649
0
            mxShow->pause(true);
1650
1651
0
            if( mxListenerProxy.is() )
1652
0
                mxListenerProxy->paused();
1653
0
        }
1654
0
    }
1655
0
    catch( Exception& )
1656
0
    {
1657
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::pause()" );
1658
0
    }
1659
0
}
1660
1661
void SAL_CALL SlideshowImpl::resume()
1662
0
{
1663
0
    SolarMutexGuard aSolarGuard;
1664
1665
0
    if( mbIsPaused ) try
1666
0
    {
1667
0
        if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK || mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
1668
0
        {
1669
0
            mpShowWindow->RestartShow();
1670
0
        }
1671
0
        else
1672
0
        {
1673
0
            mbIsPaused = false;
1674
0
            if( mxShow.is() )
1675
0
            {
1676
0
                mxShow->pause(false);
1677
0
                update();
1678
1679
0
                if( mxListenerProxy.is() )
1680
0
                    mxListenerProxy->resumed();
1681
0
            }
1682
0
        }
1683
0
    }
1684
0
    catch( Exception& )
1685
0
    {
1686
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resume()" );
1687
0
    }
1688
#ifdef ENABLE_SDREMOTE
1689
    RemoteServer::presentationStarted( this );
1690
#endif
1691
0
}
1692
1693
sal_Bool SAL_CALL SlideshowImpl::isPaused()
1694
0
{
1695
0
    SolarMutexGuard aSolarGuard;
1696
0
    return mbIsPaused;
1697
0
}
1698
1699
void SAL_CALL SlideshowImpl::blankScreen( sal_Int32 nColor )
1700
0
{
1701
0
    SolarMutexGuard aSolarGuard;
1702
1703
0
    if( mpShowWindow && mpSlideController )
1704
0
    {
1705
0
        if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), Color(ColorTransparency, nColor) ) )
1706
0
        {
1707
0
            pause();
1708
0
        }
1709
0
    }
1710
0
}
1711
1712
// XShapeEventListener
1713
1714
void SlideshowImpl::click( const Reference< XShape >& xShape )
1715
0
{
1716
0
    SolarMutexGuard aSolarGuard;
1717
1718
0
    auto it = maShapeEventMap.find(xShape);
1719
0
    if (it == maShapeEventMap.end())
1720
0
        return;
1721
0
    WrappedShapeEventImpl* pEvent = &it->second;
1722
1723
0
    switch( pEvent->meClickAction )
1724
0
    {
1725
0
    case ClickAction_PREVPAGE:          gotoPreviousSlide();        break;
1726
0
    case ClickAction_NEXTPAGE:          gotoNextSlide();            break;
1727
0
    case ClickAction_FIRSTPAGE:         gotoFirstSlide();           break;
1728
0
    case ClickAction_LASTPAGE:          gotoLastSlide();            break;
1729
0
    case ClickAction_STOPPRESENTATION:  endPresentation();          break;
1730
0
    case ClickAction_BOOKMARK:
1731
0
    {
1732
0
        gotoBookmark( pEvent->maStrBookmark );
1733
0
    }
1734
0
    break;
1735
0
    case ClickAction_SOUND:
1736
0
    {
1737
0
#if HAVE_FEATURE_AVMEDIA
1738
0
        try
1739
0
        {
1740
0
            mxPlayer.set(avmedia::MediaWindow::createPlayer(pEvent->maStrBookmark, u""_ustr/*TODO?*/), uno::UNO_SET_THROW );
1741
0
            mxPlayer->start();
1742
0
        }
1743
0
        catch( uno::Exception& )
1744
0
        {
1745
0
            TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::click()" );
1746
0
        }
1747
0
#endif
1748
0
    }
1749
0
    break;
1750
1751
0
    case ClickAction_DOCUMENT:
1752
0
    {
1753
0
        OUString aBookmark( pEvent->maStrBookmark );
1754
1755
0
        sal_Int32 nPos = aBookmark.indexOf( '#' );
1756
0
        if( nPos >= 0 )
1757
0
        {
1758
0
            OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1759
0
            OUString aName( aBookmark.copy( nPos+1 ) );
1760
0
            aURL += getUiNameFromPageApiNameImpl( aName );
1761
0
            aBookmark = aURL;
1762
0
        }
1763
1764
0
        mpDocSh->OpenBookmark( aBookmark );
1765
0
    }
1766
0
    break;
1767
1768
0
    case ClickAction_PROGRAM:
1769
0
    {
1770
0
        INetURLObject aURL(
1771
0
            ::URIHelper::SmartRel2Abs(
1772
0
                INetURLObject(mpDocSh->GetMedium()->GetBaseURL()),
1773
0
                pEvent->maStrBookmark, ::URIHelper::GetMaybeFileHdl(), true,
1774
0
                false, INetURLObject::EncodeMechanism::WasEncoded,
1775
0
                INetURLObject::DecodeMechanism::Unambiguous ) );
1776
1777
0
        if( INetProtocol::File == aURL.GetProtocol() )
1778
0
        {
1779
0
            SfxStringItem aUrl( SID_FILE_NAME, aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
1780
0
            SfxBoolItem aBrowsing( SID_BROWSE, true );
1781
1782
0
            if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
1783
0
            {
1784
0
                SfxUnoFrameItem aDocFrame(SID_FILLFRAME, pViewFrm->GetFrame().GetFrameInterface());
1785
0
                pViewFrm->GetDispatcher()->ExecuteList( SID_OPENDOC,
1786
0
                    SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
1787
0
                    { &aUrl, &aBrowsing }, { &aDocFrame } );
1788
0
            }
1789
0
        }
1790
0
    }
1791
0
    break;
1792
1793
#if HAVE_FEATURE_SCRIPTING
1794
    case presentation::ClickAction_MACRO:
1795
    {
1796
        const OUString aMacro( pEvent->maStrBookmark );
1797
1798
        if ( SfxApplication::IsXScriptURL( aMacro ) )
1799
        {
1800
            Any aRet;
1801
            Sequence< sal_Int16 > aOutArgsIndex;
1802
            Sequence< Any > aOutArgs;
1803
            Sequence< Any >* pInArgs = new Sequence< Any >(0);
1804
            mpDocSh->CallXScript( aMacro, *pInArgs, aRet, aOutArgsIndex, aOutArgs);
1805
        }
1806
        else
1807
        {
1808
            // aMacro has the following syntax:
1809
            // "Macroname.Modulname.Libname.Documentname" or
1810
            // "Macroname.Modulname.Libname.Applicationname"
1811
            sal_Int32 nIdx{ 0 };
1812
            const std::u16string_view aMacroName = o3tl::getToken(aMacro, 0, '.', nIdx);
1813
            const std::u16string_view aModulName = o3tl::getToken(aMacro, 0, '.', nIdx);
1814
1815
            // todo: is the limitation still given that only
1816
            // Modulname+Macroname can be used here?
1817
            OUString aExecMacro = OUString::Concat(aModulName) + "." + aMacroName;
1818
            mpDocSh->GetBasic()->Call(aExecMacro);
1819
        }
1820
    }
1821
    break;
1822
#endif
1823
1824
0
    case ClickAction_VERB:
1825
0
    {
1826
        // todo, better do it async?
1827
0
        SdrObject* pObj = SdrObject::getSdrObjectFromXShape(xShape);
1828
0
        SdrOle2Obj* pOleObject = dynamic_cast< SdrOle2Obj* >(pObj);
1829
0
        if (pOleObject && mpViewShell )
1830
0
            mpViewShell->ActivateObject(pOleObject, pEvent->mnVerb);
1831
0
    }
1832
0
    break;
1833
0
    default:
1834
0
        break;
1835
0
    }
1836
0
}
1837
1838
sal_Int32 SlideshowImpl::getSlideNumberForBookmark( const OUString& rStrBookmark )
1839
0
{
1840
0
    bool bIsMasterPage;
1841
0
    OUString aBookmark = getUiNameFromPageApiNameImpl( rStrBookmark );
1842
0
    sal_uInt16 nPgNum = mpDoc->GetPageByName( aBookmark, bIsMasterPage );
1843
1844
0
    if( nPgNum == SDRPAGE_NOTFOUND )
1845
0
    {
1846
        // Is the bookmark an object?
1847
0
        SdrObject* pObj = mpDoc->GetObj( aBookmark );
1848
1849
0
        if( pObj )
1850
0
        {
1851
0
            nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
1852
0
            bIsMasterPage = pObj->getSdrPageFromSdrObject()->IsMasterPage();
1853
0
        }
1854
0
    }
1855
1856
0
    if( (nPgNum == SDRPAGE_NOTFOUND) || bIsMasterPage || static_cast<SdPage*>(mpDoc->GetPage(nPgNum))->GetPageKind() != PageKind::Standard )
1857
0
        return -1;
1858
1859
0
    return ( nPgNum - 1) >> 1;
1860
0
}
1861
1862
void SlideshowImpl::contextMenuShow(const css::awt::Point& point)
1863
0
{
1864
0
    maPopupMousePos = { point.X, point.Y };
1865
0
    mnContextMenuEvent = Application::PostUserEvent(LINK(this, SlideshowImpl, ContextMenuHdl));
1866
0
}
1867
1868
void SlideshowImpl::hyperLinkClicked( OUString const& aHyperLink )
1869
0
{
1870
0
    OUString aBookmark( aHyperLink );
1871
1872
0
    sal_Int32 nPos = aBookmark.indexOf( '#' );
1873
0
    if( nPos >= 0 )
1874
0
    {
1875
0
        OUString aURL( aBookmark.copy( 0, nPos+1 ) );
1876
0
        OUString aName( aBookmark.copy( nPos+1 ) );
1877
0
        aURL += getUiNameFromPageApiNameImpl( aName );
1878
0
        aBookmark = aURL;
1879
0
    }
1880
1881
0
    mpDocSh->OpenBookmark( aBookmark );
1882
0
}
1883
1884
void SlideshowImpl::displaySlideNumber( sal_Int32 nSlideNumber )
1885
0
{
1886
0
    if( mpSlideController )
1887
0
    {
1888
0
        if( mpSlideController->jumpToSlideNumber( nSlideNumber ) )
1889
0
        {
1890
0
            displayCurrentSlide();
1891
0
        }
1892
0
    }
1893
0
}
1894
1895
/** nSlideIndex == -1 displays current slide again */
1896
void SlideshowImpl::displaySlideIndex( sal_Int32 nSlideIndex )
1897
0
{
1898
0
    if( mpSlideController )
1899
0
    {
1900
0
        if( (nSlideIndex == -1) || mpSlideController->jumpToSlideIndex( nSlideIndex ) )
1901
0
        {
1902
0
            displayCurrentSlide();
1903
0
        }
1904
0
    }
1905
0
}
1906
1907
void SlideshowImpl::jumpToBookmark( const OUString& sBookmark )
1908
0
{
1909
0
    sal_Int32 nSlideNumber = getSlideNumberForBookmark( sBookmark );
1910
0
    if( nSlideNumber != -1 )
1911
0
        displaySlideNumber( nSlideNumber );
1912
0
}
1913
1914
sal_Int32 SlideshowImpl::getCurrentSlideNumber() const
1915
0
{
1916
0
    return mpSlideController ? mpSlideController->getCurrentSlideNumber() : -1;
1917
0
}
1918
1919
sal_Bool SAL_CALL SlideshowImpl::isEndless()
1920
0
{
1921
0
    SolarMutexGuard aSolarGuard;
1922
0
    return maPresSettings.mbEndless;
1923
0
}
1924
1925
void SlideshowImpl::update()
1926
0
{
1927
0
    startUpdateTimer();
1928
0
}
1929
1930
void SlideshowImpl::startUpdateTimer()
1931
0
{
1932
0
    SolarMutexGuard aSolarGuard;
1933
0
    maUpdateTimer.SetTimeout( 0 );
1934
0
    maUpdateTimer.Start();
1935
0
}
1936
1937
/** this timer is called 20ms after a new slide was displayed.
1938
    This is used to unfreeze user input that was disabled after
1939
    slide change to skip input that was buffered during slide
1940
    transition preparation */
1941
IMPL_LINK_NOARG(SlideshowImpl, ReadyForNextInputHdl, Timer *, void)
1942
0
{
1943
0
    mbInputFreeze = false;
1944
0
}
1945
1946
/** if I catch someone someday who calls this method by hand
1947
    and not by using the timer, I will personally punish this
1948
    person seriously, even if this person is me.
1949
*/
1950
IMPL_LINK_NOARG(SlideshowImpl, updateHdl, Timer *, void)
1951
0
{
1952
0
    updateSlideShow();
1953
0
}
1954
1955
void SlideshowImpl::updateSlideShow()
1956
0
{
1957
    // prevent me from deletion when recursing (App::EnableYieldMode does)
1958
0
    const rtl::Reference<SlideshowImpl> xKeepAlive(this);
1959
1960
0
    Reference< XSlideShow > xShow( mxShow );
1961
0
    if ( ! xShow.is())
1962
0
        return;
1963
1964
0
    try
1965
0
    {
1966
0
        double fUpdate = 0.0;
1967
0
        if( !xShow->update(fUpdate) )
1968
0
            fUpdate = -1.0;
1969
1970
0
        if (mxShow.is() && (fUpdate >= 0.0))
1971
0
        {
1972
0
            if (::basegfx::fTools::equalZero(fUpdate))
1973
0
            {
1974
                // Make sure idle tasks don't starve when we don't have to wait.
1975
                // Don't process any events generated after invoking the function.
1976
0
                Application::Reschedule(/*bHandleAllCurrentEvents=*/true);
1977
0
            }
1978
0
            else
1979
0
            {
1980
                // Avoid busy loop when the previous call to update()
1981
                // returns a small positive number but not 0 (which is
1982
                // handled above).  Also, make sure that calls to update()
1983
                // have a minimum frequency.
1984
                // => Allow up to 60 frames per second.  Call at least once
1985
                // every 4 seconds.
1986
0
                const static sal_Int32 nMaximumFrameCount (60);
1987
0
                const static double nMinimumTimeout (1.0 / nMaximumFrameCount);
1988
0
                const static double nMaximumTimeout (4.0);
1989
0
                fUpdate = std::clamp(fUpdate, nMinimumTimeout, nMaximumTimeout);
1990
1991
                // Make sure that the maximum frame count has not been set
1992
                // too high (only then conversion to milliseconds and long
1993
                // integer may lead to zero value.)
1994
0
                OSL_ASSERT(static_cast<sal_uLong>(fUpdate * 1000.0) > 0);
1995
0
            }
1996
1997
            // Use our high resolution timers for the asynchronous callback.
1998
0
            maUpdateTimer.SetTimeout(static_cast<sal_uLong>(fUpdate * 1000.0));
1999
0
            maUpdateTimer.Start();
2000
0
        }
2001
0
    }
2002
0
    catch( Exception& )
2003
0
    {
2004
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::updateSlideShow()" );
2005
0
    }
2006
0
}
2007
2008
bool SlideshowImpl::keyInput(const KeyEvent& rKEvt)
2009
0
{
2010
0
    if( !mxShow.is() || mbInputFreeze )
2011
0
        return false;
2012
2013
0
    bool bRet = true;
2014
2015
0
    try
2016
0
    {
2017
0
        const int nKeyCode = rKEvt.GetKeyCode().GetCode();
2018
0
        switch( nKeyCode )
2019
0
        {
2020
0
            case awt::Key::CONTEXTMENU:
2021
0
                if( !mnContextMenuEvent )
2022
0
                {
2023
0
                    if( mpShowWindow )
2024
0
                        maPopupMousePos = mpShowWindow->GetPointerState().maPos;
2025
0
                    mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
2026
0
                }
2027
0
                break;
2028
2029
            // cancel show
2030
0
            case KEY_ESCAPE:
2031
0
            case KEY_SUBTRACT:
2032
                // in case the user cancels the presentation, switch to current slide
2033
                // in edit mode
2034
0
                if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2035
0
                {
2036
0
                    if( mpSlideController->getCurrentSlideNumber() != -1 )
2037
0
                        mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2038
0
                }
2039
0
                endPresentation();
2040
0
                break;
2041
2042
            // advance show
2043
0
            case KEY_PAGEDOWN:
2044
0
                if(rKEvt.GetKeyCode().IsMod2())
2045
0
                {
2046
0
                    gotoNextSlide();
2047
0
                    break;
2048
0
                }
2049
0
                [[fallthrough]];
2050
0
            case KEY_SPACE:
2051
0
            case KEY_RIGHT:
2052
0
            case KEY_DOWN:
2053
0
            case KEY_XF86FORWARD:
2054
0
                gotoNextEffect();
2055
0
                break;
2056
2057
0
            case KEY_RETURN:
2058
0
            {
2059
0
                if( !maCharBuffer.isEmpty() )
2060
0
                {
2061
0
                    if( mpSlideController )
2062
0
                    {
2063
0
                        if( mpSlideController->jumpToSlideNumber( maCharBuffer.toInt32() - 1 ) )
2064
0
                            displayCurrentSlide();
2065
0
                    }
2066
0
                    maCharBuffer.clear();
2067
0
                }
2068
0
                else
2069
0
                {
2070
0
                    gotoNextEffect();
2071
0
                }
2072
0
            }
2073
0
            break;
2074
2075
            // numeric: add to buffer
2076
0
            case KEY_0:
2077
0
            case KEY_1:
2078
0
            case KEY_2:
2079
0
            case KEY_3:
2080
0
            case KEY_4:
2081
0
            case KEY_5:
2082
0
            case KEY_6:
2083
0
            case KEY_7:
2084
0
            case KEY_8:
2085
0
            case KEY_9:
2086
0
                maCharBuffer += OUStringChar( rKEvt.GetCharCode() );
2087
0
                break;
2088
2089
0
            case KEY_PAGEUP:
2090
0
                if(rKEvt.GetKeyCode().IsMod2())
2091
0
                {
2092
0
                    gotoPreviousSlide();
2093
0
                    break;
2094
0
                }
2095
0
                [[fallthrough]];
2096
0
            case KEY_LEFT:
2097
0
            case KEY_UP:
2098
0
            case KEY_BACKSPACE:
2099
0
            case KEY_XF86BACK:
2100
0
                gotoPreviousEffect();
2101
0
                break;
2102
2103
0
            case KEY_P:
2104
0
                setUsePen( !mbUsePen );
2105
0
                break;
2106
2107
            // tdf#149351 Ctrl+A disables pointer as pen mode
2108
0
            case KEY_A:
2109
0
                if(rKEvt.GetKeyCode().IsMod1())
2110
0
                {
2111
0
                    setUsePen( false );
2112
0
                    break;
2113
0
                }
2114
0
            break;
2115
2116
0
            case KEY_E:
2117
0
                setEraseAllInk( true );
2118
0
                updateSlideShow();
2119
0
                break;
2120
2121
0
            case KEY_HOME:
2122
0
                gotoFirstSlide();
2123
0
                break;
2124
2125
0
            case KEY_END:
2126
0
                gotoLastSlide();
2127
0
                break;
2128
2129
0
            case KEY_B:
2130
0
            case KEY_W:
2131
0
            case KEY_POINT:
2132
0
            case KEY_COMMA:
2133
0
            {
2134
0
                blankScreen( ((nKeyCode == KEY_W ) || (nKeyCode == KEY_COMMA)) ? 0x00ffffff : 0x00000000 );
2135
0
            }
2136
0
            break;
2137
2138
0
            default:
2139
0
                bRet = false;
2140
0
            break;
2141
0
        }
2142
0
    }
2143
0
    catch( Exception& )
2144
0
    {
2145
0
        bRet = false;
2146
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::keyInput()" );
2147
0
    }
2148
2149
0
    return bRet;
2150
0
}
2151
2152
IMPL_LINK( SlideshowImpl, EventListenerHdl, VclSimpleEvent&, rSimpleEvent, void )
2153
0
{
2154
0
    if( !mxShow.is() || mbInputFreeze )
2155
0
        return;
2156
2157
0
    if( !((rSimpleEvent.GetId() == VclEventId::WindowCommand) && static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData()) )
2158
0
        return;
2159
2160
0
    const CommandEvent& rEvent = *static_cast<const CommandEvent*>(static_cast<VclWindowEvent*>(&rSimpleEvent)->GetData());
2161
2162
0
    if( rEvent.GetCommand() != CommandEventId::Media )
2163
0
        return;
2164
2165
0
    CommandMediaData* pMediaData = rEvent.GetMediaData();
2166
0
    pMediaData->SetPassThroughToOS(false);
2167
0
    switch (pMediaData->GetMediaId())
2168
0
    {
2169
#if defined( MACOSX )
2170
    case MediaCommand::Menu:
2171
        if( !mnContextMenuEvent )
2172
        {
2173
            if( mpShowWindow )
2174
                maPopupMousePos = mpShowWindow->GetPointerState().maPos;
2175
            mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
2176
        }
2177
        break;
2178
    case MediaCommand::VolumeDown:
2179
        gotoPreviousSlide();
2180
        break;
2181
    case MediaCommand::VolumeUp:
2182
        gotoNextEffect();
2183
        break;
2184
#endif
2185
0
    case MediaCommand::NextTrack:
2186
0
        gotoNextEffect();
2187
0
        break;
2188
0
    case MediaCommand::Pause:
2189
0
        if( !mbIsPaused )
2190
0
            blankScreen(0);
2191
0
        break;
2192
0
    case MediaCommand::Play:
2193
0
        if( mbIsPaused )
2194
0
            resume();
2195
0
        break;
2196
2197
0
    case MediaCommand::PlayPause:
2198
0
        if( mbIsPaused )
2199
0
            resume();
2200
0
        else
2201
0
            blankScreen(0);
2202
0
        break;
2203
0
    case MediaCommand::PreviousTrack:
2204
0
        gotoPreviousSlide();
2205
0
        break;
2206
0
    case MediaCommand::NextTrackHold:
2207
0
        gotoLastSlide();
2208
0
        break;
2209
2210
0
    case MediaCommand::Rewind:
2211
0
        gotoFirstSlide();
2212
0
        break;
2213
0
    case MediaCommand::Stop:
2214
        // in case the user cancels the presentation, switch to current slide
2215
        // in edit mode
2216
0
        if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2217
0
        {
2218
0
            if( mpSlideController->getCurrentSlideNumber() != -1 )
2219
0
                mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2220
0
        }
2221
0
        endPresentation();
2222
0
        break;
2223
0
    default:
2224
0
        pMediaData->SetPassThroughToOS(true);
2225
0
        break;
2226
0
    }
2227
0
}
2228
2229
void SlideshowImpl::mouseButtonUp(const MouseEvent& rMEvt)
2230
0
{
2231
0
    if( rMEvt.IsRight() && !mnContextMenuEvent )
2232
0
    {
2233
0
        maPopupMousePos = rMEvt.GetPosPixel();
2234
0
        mnContextMenuEvent = Application::PostUserEvent( LINK( this, SlideshowImpl, ContextMenuHdl ) );
2235
0
    }
2236
0
}
2237
2238
IMPL_LINK_NOARG(SlideshowImpl, ContextMenuHdl, void*, void)
2239
0
{
2240
0
    mnContextMenuEvent = nullptr;
2241
2242
0
    if (mpSlideController == nullptr)
2243
0
        return;
2244
2245
0
    mbWasPaused = mbIsPaused;
2246
0
    if( !mbWasPaused )
2247
0
        pause();
2248
2249
0
    std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, u"modules/simpress/ui/slidecontextmenu.ui"_ustr));
2250
0
    std::unique_ptr<weld::Menu> xMenu(xBuilder->weld_menu(u"menu"_ustr));
2251
0
    OUString sNextImage(BMP_MENU_NEXT), sPrevImage(BMP_MENU_PREV);
2252
0
    xMenu->insert(0, u"next"_ustr, SdResId(RID_SVXSTR_MENU_NEXT), &sNextImage, nullptr, nullptr, TRISTATE_INDET);
2253
0
    xMenu->insert(1, u"prev"_ustr, SdResId(RID_SVXSTR_MENU_PREV), &sPrevImage, nullptr, nullptr, TRISTATE_INDET);
2254
2255
    // Adding button to display if in Pen  mode
2256
0
    xMenu->set_active(u"pen"_ustr, mbUsePen);
2257
2258
0
    const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2259
0
    xMenu->set_visible(u"next"_ustr, mpSlideController->getNextSlideIndex() != -1);
2260
0
    xMenu->set_visible(u"prev"_ustr, (mpSlideController->getPreviousSlideIndex() != -1 ) || (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK));
2261
0
    xMenu->set_visible(u"edit"_ustr, mpViewShell->GetDoc()->GetStartWithPresentation() != 0);
2262
2263
0
    std::unique_ptr<weld::Menu> xPageMenu(xBuilder->weld_menu(u"gotomenu"_ustr));
2264
0
    OUString sFirstImage(BMP_MENU_FIRST), sLastImage(BMP_MENU_LAST);
2265
0
    xPageMenu->insert(0, u"first"_ustr, SdResId(RID_SVXSTR_MENU_FIRST), &sFirstImage, nullptr, nullptr, TRISTATE_INDET);
2266
0
    xPageMenu->insert(1, u"last"_ustr, SdResId(RID_SVXSTR_MENU_LAST), &sLastImage, nullptr, nullptr, TRISTATE_INDET);
2267
2268
    // populate slide goto list
2269
0
    const sal_Int32 nPageNumberCount = mpSlideController->getSlideNumberCount();
2270
0
    if( nPageNumberCount <= 1 )
2271
0
    {
2272
0
        xMenu->set_visible(u"goto"_ustr, false);
2273
0
    }
2274
0
    else
2275
0
    {
2276
0
        sal_Int32 nCurrentSlideNumber = mpSlideController->getCurrentSlideNumber();
2277
0
        if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2278
0
            nCurrentSlideNumber = -1;
2279
2280
0
        xPageMenu->set_visible(u"first"_ustr, mpSlideController->getSlideNumber(0) != nCurrentSlideNumber);
2281
0
        xPageMenu->set_visible(u"last"_ustr, mpSlideController->getSlideNumber(mpSlideController->getSlideIndexCount() - 1) != nCurrentSlideNumber);
2282
2283
0
        sal_Int32 nPageNumber;
2284
2285
0
        for( nPageNumber = 0; nPageNumber < nPageNumberCount; nPageNumber++ )
2286
0
        {
2287
0
            if( mpSlideController->isVisibleSlideNumber( nPageNumber ) )
2288
0
            {
2289
0
                SdPage* pPage = mpDoc->GetSdPage(static_cast<sal_uInt16>(nPageNumber), PageKind::Standard);
2290
0
                if (pPage)
2291
0
                {
2292
0
                    OUString sId(OUString::number(CM_SLIDES + nPageNumber));
2293
0
                    xPageMenu->append_check(sId, pPage->GetName());
2294
0
                    if (nPageNumber == nCurrentSlideNumber)
2295
0
                        xPageMenu->set_active(sId, true);
2296
0
                }
2297
0
            }
2298
0
        }
2299
0
    }
2300
2301
0
    std::unique_ptr<weld::Menu> xBlankMenu(xBuilder->weld_menu(u"screenmenu"_ustr));
2302
2303
0
    if (mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK)
2304
0
    {
2305
0
        xBlankMenu->set_active((mpShowWindow->GetBlankColor() == COL_WHITE) ? "white" : "black", true);
2306
0
    }
2307
2308
0
    std::unique_ptr<weld::Menu> xWidthMenu(xBuilder->weld_menu(u"widthmenu"_ustr));
2309
2310
    // populate color width list
2311
0
    sal_Int32 nIterator;
2312
0
    double nWidth;
2313
2314
0
    nWidth = 4.0;
2315
0
    for( nIterator = 1; nIterator < 6; nIterator++)
2316
0
    {
2317
0
        switch(nIterator)
2318
0
        {
2319
0
            case 1:
2320
0
                nWidth = 4.0;
2321
0
                break;
2322
0
            case 2:
2323
0
                nWidth = 100.0;
2324
0
                break;
2325
0
            case 3:
2326
0
                nWidth = 150.0;
2327
0
                break;
2328
0
            case 4:
2329
0
                nWidth = 200.0;
2330
0
                break;
2331
0
            case 5:
2332
0
                nWidth = 400.0;
2333
0
                break;
2334
0
            default:
2335
0
                break;
2336
0
        }
2337
2338
0
        if (nWidth == mdUserPaintStrokeWidth)
2339
0
            xWidthMenu->set_active(OUString::number(nWidth), true);
2340
0
    }
2341
2342
0
    ::tools::Rectangle aRect(maPopupMousePos, Size(1,1));
2343
0
    weld::Window* pParent = weld::GetPopupParent(*mpShowWindow, aRect);
2344
0
    ContextMenuSelectHdl(xMenu->popup_at_rect(pParent, aRect));
2345
2346
0
    if( mxView.is() )
2347
0
        mxView->ignoreNextMouseReleased();
2348
2349
0
    if( !mbWasPaused )
2350
0
        resume();
2351
0
}
2352
2353
void SlideshowImpl::ContextMenuSelectHdl(std::u16string_view rMenuId)
2354
0
{
2355
0
    if (rMenuId == u"prev")
2356
0
    {
2357
0
        gotoPreviousSlide();
2358
0
        mbWasPaused = false;
2359
0
    }
2360
0
    else if(rMenuId == u"next")
2361
0
    {
2362
0
        gotoNextSlide();
2363
0
        mbWasPaused = false;
2364
0
    }
2365
0
    else if (rMenuId == u"first")
2366
0
    {
2367
0
        gotoFirstSlide();
2368
0
        mbWasPaused = false;
2369
0
    }
2370
0
    else if (rMenuId == u"last")
2371
0
    {
2372
0
        gotoLastSlide();
2373
0
        mbWasPaused = false;
2374
0
    }
2375
0
    else if (rMenuId == u"black" || rMenuId == u"white")
2376
0
    {
2377
0
        const Color aBlankColor(rMenuId == u"white" ? COL_WHITE : COL_BLACK);
2378
0
        if( mbWasPaused )
2379
0
        {
2380
0
            if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_BLANK )
2381
0
            {
2382
0
                if( mpShowWindow->GetBlankColor() == aBlankColor )
2383
0
                {
2384
0
                    mbWasPaused = false;
2385
0
                    mpShowWindow->RestartShow();
2386
0
                    return;
2387
0
                }
2388
0
            }
2389
0
            mpShowWindow->RestartShow();
2390
0
        }
2391
0
        if( mpShowWindow->SetBlankMode( mpSlideController->getCurrentSlideIndex(), aBlankColor ) )
2392
0
        {
2393
0
            pause();
2394
0
            mbWasPaused = true;
2395
0
        }
2396
0
    }
2397
0
    else if (rMenuId == u"color")
2398
0
    {
2399
        //Open a color picker based on SvColorDialog
2400
0
        ::Color aColor( ColorTransparency, mnUserPaintColor );
2401
0
        ColorDialog aColorDlg(mpShowWindow->GetFrameWeld());
2402
0
        aColorDlg.SetColor( aColor );
2403
2404
0
        if (aColorDlg.Execute())
2405
0
        {
2406
0
            aColor = aColorDlg.GetColor();
2407
0
            setPenColor(sal_Int32(aColor));
2408
0
        }
2409
0
        mbWasPaused = false;
2410
0
    }
2411
0
    else if (rMenuId == u"4")
2412
0
    {
2413
0
        setPenWidth(4.0);
2414
0
        mbWasPaused = false;
2415
0
    }
2416
0
    else if (rMenuId == u"100")
2417
0
    {
2418
0
        setPenWidth(100.0);
2419
0
        mbWasPaused = false;
2420
0
    }
2421
0
    else if (rMenuId == u"150")
2422
0
    {
2423
0
        setPenWidth(150.0);
2424
0
        mbWasPaused = false;
2425
0
    }
2426
0
    else if (rMenuId == u"200")
2427
0
    {
2428
0
        setPenWidth(200.0);
2429
0
        mbWasPaused = false;
2430
0
    }
2431
0
    else if (rMenuId == u"400")
2432
0
    {
2433
0
        setPenWidth(400.0);
2434
0
        mbWasPaused = false;
2435
0
    }
2436
0
    else if (rMenuId == u"erase")
2437
0
    {
2438
0
        setEraseAllInk(true);
2439
0
        mbWasPaused = false;
2440
0
    }
2441
0
    else if (rMenuId == u"pen")
2442
0
    {
2443
0
        setUsePen(!mbUsePen);
2444
0
        mbWasPaused = false;
2445
0
    }
2446
0
    else if (rMenuId == u"edit")
2447
0
    {
2448
        // When in autoplay mode (pps/ppsx), offer editing of the presentation
2449
        // Turn autostart off, else Impress will close when exiting the Presentation
2450
0
        mpViewShell->GetDoc()->SetExitAfterPresenting(false);
2451
0
        if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2452
0
        {
2453
0
            if( mpSlideController->getCurrentSlideNumber() != -1 )
2454
0
            {
2455
0
                mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2456
0
            }
2457
0
        }
2458
0
        endPresentation();
2459
0
    }
2460
0
    else if (rMenuId == u"end")
2461
0
    {
2462
        // in case the user cancels the presentation, switch to current slide
2463
        // in edit mode
2464
0
        if( mpSlideController && (ANIMATIONMODE_SHOW == meAnimationMode) )
2465
0
        {
2466
0
            if( mpSlideController->getCurrentSlideNumber() != -1 )
2467
0
            {
2468
0
                mnRestoreSlide = mpSlideController->getCurrentSlideNumber();
2469
0
            }
2470
0
        }
2471
0
        endPresentation();
2472
0
    }
2473
0
    else if (!rMenuId.empty())
2474
0
    {
2475
0
        sal_Int32 nPageNumber = o3tl::toInt32(rMenuId) - CM_SLIDES;
2476
0
        const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
2477
0
        if( (eMode == SHOWWINDOWMODE_END) || (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
2478
0
        {
2479
0
            mpShowWindow->RestartShow( nPageNumber );
2480
0
        }
2481
0
        else if( nPageNumber != mpSlideController->getCurrentSlideNumber() )
2482
0
        {
2483
0
            displaySlideNumber( nPageNumber );
2484
0
        }
2485
0
        mbWasPaused = false;
2486
0
    }
2487
0
}
2488
2489
Reference< XSlideShow > SlideshowImpl::createSlideShow()
2490
0
{
2491
0
    Reference< XSlideShow > xShow;
2492
2493
0
    try
2494
0
    {
2495
0
        const Reference< uno::XComponentContext >& xContext =
2496
0
            ::comphelper::getProcessComponentContext();
2497
2498
0
        xShow.set( presentation::SlideShow::create(xContext), UNO_SET_THROW );
2499
0
    }
2500
0
    catch( uno::Exception& )
2501
0
    {
2502
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::createSlideShow()" );
2503
0
    }
2504
2505
0
    return xShow;
2506
0
}
2507
2508
void SlideshowImpl::createSlideList( bool bAll, std::u16string_view rPresSlide )
2509
0
{
2510
0
    const sal_uInt16 nSlideCount = mpDoc->GetSdPageCount( PageKind::Standard );
2511
2512
0
    if( !nSlideCount )
2513
0
        return;
2514
2515
0
    SdCustomShow*   pCustomShow;
2516
2517
0
    if( mpDoc->GetCustomShowList() && maPresSettings.mbCustomShow )
2518
0
        pCustomShow = mpDoc->GetCustomShowList()->GetCurObject();
2519
0
    else
2520
0
        pCustomShow = nullptr;
2521
2522
    // create animation slide controller
2523
0
    AnimationSlideController::Mode eMode =
2524
0
        ( pCustomShow && !pCustomShow->PagesVector().empty() ) ? AnimationSlideController::CUSTOM :
2525
0
            (bAll ? AnimationSlideController::ALL : AnimationSlideController::FROM);
2526
2527
0
    rtl::Reference< SdXImpressDocument > xDrawPages( mpDoc->getUnoModel() );
2528
0
    Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
2529
0
    mpSlideController = std::make_unique<AnimationSlideController>( xSlides, eMode );
2530
2531
0
    if( eMode != AnimationSlideController::CUSTOM )
2532
0
    {
2533
0
        sal_Int32 nFirstVisibleSlide = 0;
2534
2535
        // normal presentation
2536
0
        if( !rPresSlide.empty() )
2537
0
        {
2538
0
            sal_Int32 nSlide;
2539
0
            bool bTakeNextAvailable = false;
2540
2541
0
            for( nSlide = 0, nFirstVisibleSlide = -1;
2542
0
                ( nSlide < nSlideCount ) && ( -1 == nFirstVisibleSlide ); nSlide++ )
2543
0
            {
2544
0
                SdPage* pTestSlide = mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard );
2545
2546
0
                if( pTestSlide->GetName() == rPresSlide )
2547
0
                {
2548
0
                    if( pTestSlide->IsExcluded() )
2549
0
                        bTakeNextAvailable = true;
2550
0
                    else
2551
0
                        nFirstVisibleSlide = nSlide;
2552
0
                }
2553
0
                else if( bTakeNextAvailable && !pTestSlide->IsExcluded() )
2554
0
                    nFirstVisibleSlide = nSlide;
2555
0
            }
2556
2557
0
            if( -1 == nFirstVisibleSlide )
2558
0
                nFirstVisibleSlide = 0;
2559
0
        }
2560
2561
0
        for( sal_Int32 i = 0; i < nSlideCount; i++ )
2562
0
        {
2563
0
            bool bVisible = ! mpDoc->GetSdPage( static_cast<sal_uInt16>(i), PageKind::Standard )->IsExcluded();
2564
0
            if( bVisible || (eMode == AnimationSlideController::ALL) )
2565
0
                mpSlideController->insertSlideNumber( i, bVisible );
2566
0
        }
2567
2568
0
        mpSlideController->setStartSlideNumber( nFirstVisibleSlide );
2569
0
    }
2570
0
    else
2571
0
    {
2572
0
        if( meAnimationMode != ANIMATIONMODE_SHOW && !rPresSlide.empty() )
2573
0
        {
2574
0
            sal_Int32 nSlide;
2575
0
            for( nSlide = 0; nSlide < nSlideCount; nSlide++ )
2576
0
                if( rPresSlide == mpDoc->GetSdPage( static_cast<sal_uInt16>(nSlide), PageKind::Standard )->GetName() )
2577
0
                    break;
2578
2579
0
            if( nSlide < nSlideCount )
2580
0
                mpSlideController->insertSlideNumber( static_cast<sal_uInt16>(nSlide) );
2581
0
        }
2582
2583
0
        for( const auto& rpPage : pCustomShow->PagesVector() )
2584
0
        {
2585
0
            const sal_uInt16 nSdSlide = ( rpPage->GetPageNum() - 1 ) / 2;
2586
2587
0
            if( ! mpDoc->GetSdPage( nSdSlide, PageKind::Standard )->IsExcluded())
2588
0
                mpSlideController->insertSlideNumber( nSdSlide );
2589
0
        }
2590
0
    }
2591
0
}
2592
2593
typedef sal_uInt16 (*FncGetChildWindowId)();
2594
2595
const FncGetChildWindowId aShowChildren[] =
2596
{
2597
    &AnimationChildWindow::GetChildWindowId,
2598
    &Svx3DChildWindow::GetChildWindowId,
2599
    &SvxFontWorkChildWindow::GetChildWindowId,
2600
    &SvxColorChildWindow::GetChildWindowId,
2601
    &SvxSearchDialogWrapper::GetChildWindowId,
2602
    &SvxBmpMaskChildWindow::GetChildWindowId,
2603
    &SvxIMapDlgChildWindow::GetChildWindowId,
2604
    &SvxHlinkDlgWrapper::GetChildWindowId,
2605
    &SfxInfoBarContainerChild::GetChildWindowId
2606
};
2607
2608
void SlideshowImpl::hideChildWindows()
2609
0
{
2610
0
    mnChildMask = 0;
2611
2612
0
    if( ANIMATIONMODE_SHOW != meAnimationMode )
2613
0
        return;
2614
2615
0
    SfxViewFrame* pViewFrame = getViewFrame();
2616
2617
0
    if( !pViewFrame )
2618
0
        return;
2619
2620
0
    for( sal_uLong i = 0; i < SAL_N_ELEMENTS( aShowChildren ); i++ )
2621
0
    {
2622
0
        const sal_uInt16 nId = ( *aShowChildren[ i ] )();
2623
2624
0
        if( pViewFrame->GetChildWindow( nId ) )
2625
0
        {
2626
0
            pViewFrame->SetChildWindow( nId, false );
2627
0
            mnChildMask |= ::tools::ULong(1) << i;
2628
0
        }
2629
0
    }
2630
0
}
2631
2632
void SlideshowImpl::showChildWindows()
2633
0
{
2634
0
    if( ANIMATIONMODE_SHOW == meAnimationMode )
2635
0
    {
2636
0
        SfxViewFrame* pViewFrame = getViewFrame();
2637
0
        if( pViewFrame )
2638
0
        {
2639
0
            for( sal_uLong i = 0; i < SAL_N_ELEMENTS(aShowChildren); i++ )
2640
0
            {
2641
0
                if( mnChildMask & ( ::tools::ULong(1) << i ) )
2642
0
                    pViewFrame->SetChildWindow( ( *aShowChildren[ i ] )(), true );
2643
0
            }
2644
0
        }
2645
0
    }
2646
0
}
2647
2648
SfxViewFrame* SlideshowImpl::getViewFrame() const
2649
0
{
2650
0
    return mpViewShell ? mpViewShell->GetViewFrame() : nullptr;
2651
0
}
2652
2653
SfxDispatcher* SlideshowImpl::getDispatcher() const
2654
0
{
2655
0
    return (mpViewShell && mpViewShell->GetViewFrame()) ? mpViewShell->GetViewFrame()->GetDispatcher() : nullptr;
2656
0
}
2657
2658
SfxBindings* SlideshowImpl::getBindings() const
2659
0
{
2660
0
    return (mpViewShell && mpViewShell->GetViewFrame()) ? &mpViewShell->GetViewFrame()->GetBindings() : nullptr;
2661
0
}
2662
2663
void SlideshowImpl::resize( const Size& rSize )
2664
0
{
2665
0
    maPresSize = rSize;
2666
2667
0
    if(mpShowWindow)
2668
0
    {
2669
0
        mpShowWindow->SetSizePixel( maPresSize );
2670
0
        mpShowWindow->Show();
2671
0
    }
2672
2673
0
    if( mxView.is() ) try
2674
0
    {
2675
0
        awt::WindowEvent aEvt;
2676
0
        mxView->windowResized(aEvt);
2677
0
    }
2678
0
    catch( Exception& )
2679
0
    {
2680
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::resize()" );
2681
0
    }
2682
0
}
2683
2684
void SlideshowImpl::setActiveXToolbarsVisible( bool bVisible )
2685
0
{
2686
    // in case of ActiveX control the toolbars should not be visible if slide show runs in window mode
2687
    // actually it runs always in window mode in case of ActiveX control
2688
0
    if ( !(!maPresSettings.mbFullScreen && mpDocSh && mpDocSh->GetMedium()) )
2689
0
        return;
2690
2691
0
    const SfxBoolItem* pItem = mpDocSh->GetMedium()->GetItemSet().GetItem(SID_VIEWONLY, false);
2692
0
    if ( !(pItem && pItem->GetValue()) )
2693
0
        return;
2694
2695
    // this is a plugin/activex mode, no toolbars should be visible during slide show
2696
    // after the end of slide show they should be visible again
2697
0
    SfxViewFrame* pViewFrame = getViewFrame();
2698
0
    if( !pViewFrame )
2699
0
        return;
2700
2701
0
    try
2702
0
    {
2703
0
        Reference< frame::XLayoutManager > xLayoutManager;
2704
0
        Reference< beans::XPropertySet > xFrameProps( pViewFrame->GetFrame().GetFrameInterface(), UNO_QUERY_THROW );
2705
0
        if ( ( xFrameProps->getPropertyValue( u"LayoutManager"_ustr )
2706
0
                    >>= xLayoutManager )
2707
0
          && xLayoutManager.is() )
2708
0
        {
2709
0
            xLayoutManager->setVisible( bVisible );
2710
0
        }
2711
0
    }
2712
0
    catch( uno::Exception& )
2713
0
    {}
2714
0
}
2715
2716
void SAL_CALL SlideshowImpl::activate()
2717
0
{
2718
0
    SolarMutexGuard aSolarGuard;
2719
2720
0
    maDeactivateTimer.Stop();
2721
2722
0
    if( mbActive || !mxShow.is() )
2723
0
        return;
2724
2725
0
    mbActive = true;
2726
2727
0
    if( ANIMATIONMODE_SHOW == meAnimationMode )
2728
0
    {
2729
0
        if( mbAutoSaveWasOn )
2730
0
            setAutoSaveState( false );
2731
2732
0
        if( mpShowWindow )
2733
0
        {
2734
0
            SfxViewFrame* pViewFrame = getViewFrame();
2735
0
            SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : nullptr;
2736
2737
0
            hideChildWindows();
2738
2739
0
            if( pDispatcher )
2740
0
            {
2741
                // filter all forbidden slots
2742
0
                pDispatcher->SetSlotFilter( SfxSlotFilterState::ENABLED, pAllowed );
2743
0
            }
2744
2745
0
            if( getBindings() )
2746
0
                getBindings()->InvalidateAll(true);
2747
2748
0
            mpShowWindow->GrabFocus();
2749
0
        }
2750
0
    }
2751
2752
0
    resume();
2753
0
}
2754
2755
void SAL_CALL SlideshowImpl::deactivate()
2756
0
{
2757
0
    SolarMutexGuard aSolarGuard;
2758
2759
0
    if( mbActive && mxShow.is() )
2760
0
    {
2761
0
        maDeactivateTimer.Start();
2762
0
    }
2763
0
}
2764
2765
IMPL_LINK_NOARG(SlideshowImpl, deactivateHdl, Timer *, void)
2766
0
{
2767
0
    if( !(mbActive && mxShow.is()) )
2768
0
        return;
2769
2770
0
    mbActive = false;
2771
2772
0
    pause();
2773
2774
0
    if( ANIMATIONMODE_SHOW == meAnimationMode )
2775
0
    {
2776
0
        if( mbAutoSaveWasOn )
2777
0
            setAutoSaveState( true );
2778
2779
0
        if( mpShowWindow )
2780
0
        {
2781
0
            showChildWindows();
2782
0
        }
2783
0
    }
2784
0
}
2785
2786
sal_Bool SAL_CALL SlideshowImpl::isActive()
2787
0
{
2788
0
    SolarMutexGuard aSolarGuard;
2789
0
    return mbActive;
2790
0
}
2791
2792
void SlideshowImpl::setAutoSaveState( bool bOn)
2793
0
{
2794
0
    try
2795
0
    {
2796
0
        const uno::Reference<uno::XComponentContext>& xContext( ::comphelper::getProcessComponentContext() );
2797
2798
0
        uno::Reference< util::XURLTransformer > xParser(util::URLTransformer::create(xContext));
2799
0
        util::URL aURL;
2800
0
        aURL.Complete = "vnd.sun.star.autorecovery:/setAutoSaveState";
2801
0
        xParser->parseStrict(aURL);
2802
2803
0
        Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue(u"AutoSaveState"_ustr, bOn) };
2804
2805
0
        uno::Reference< frame::XDispatch > xAutoSave = frame::theAutoRecovery::get(xContext);
2806
0
        xAutoSave->dispatch(aURL, aArgs);
2807
0
    }
2808
0
    catch( Exception& )
2809
0
    {
2810
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::setAutoSaveState()");
2811
0
    }
2812
0
}
2813
2814
Reference< XDrawPage > SAL_CALL SlideshowImpl::getCurrentSlide()
2815
0
{
2816
0
    SolarMutexGuard aSolarGuard;
2817
2818
0
    Reference< XDrawPage > xSlide;
2819
0
    if( mxShow.is() && mpSlideController )
2820
0
    {
2821
0
        sal_Int32 nSlide = getCurrentSlideNumber();
2822
0
        if( (nSlide >= 0) && (nSlide < mpSlideController->getSlideNumberCount() ) )
2823
0
            xSlide = mpSlideController->getSlideByNumber( nSlide );
2824
0
    }
2825
2826
0
    return xSlide;
2827
0
}
2828
2829
sal_Int32 SAL_CALL SlideshowImpl::getNextSlideIndex()
2830
0
{
2831
0
    SolarMutexGuard aSolarGuard;
2832
2833
0
    if( mxShow.is() )
2834
0
    {
2835
0
        return mpSlideController->getNextSlideIndex();
2836
0
    }
2837
0
    else
2838
0
    {
2839
0
        return -1;
2840
0
    }
2841
0
}
2842
2843
sal_Int32 SAL_CALL SlideshowImpl::getCurrentSlideIndex()
2844
0
{
2845
0
    return mpSlideController ? mpSlideController->getCurrentSlideIndex() : -1;
2846
0
}
2847
2848
// css::presentation::XSlideShowController:
2849
2850
::sal_Int32 SAL_CALL SlideshowImpl::getSlideCount()
2851
0
{
2852
0
    return mpSlideController ? mpSlideController->getSlideIndexCount() : 0;
2853
0
}
2854
2855
Reference< XDrawPage > SAL_CALL SlideshowImpl::getSlideByIndex(::sal_Int32 Index)
2856
0
{
2857
0
    if ((mpSlideController == nullptr) || (Index < 0)
2858
0
        || (Index >= mpSlideController->getSlideIndexCount()))
2859
0
        throw IndexOutOfBoundsException();
2860
2861
0
    return mpSlideController->getSlideByNumber( mpSlideController->getSlideNumber( Index ) );
2862
0
}
2863
2864
sal_Bool SAL_CALL SlideshowImpl::getAlwaysOnTop()
2865
0
{
2866
0
    SolarMutexGuard aSolarGuard;
2867
0
    return maPresSettings.mbAlwaysOnTop;
2868
0
}
2869
2870
void SAL_CALL SlideshowImpl::setAlwaysOnTop( sal_Bool bAlways )
2871
0
{
2872
0
    SolarMutexGuard aSolarGuard;
2873
0
    if( maPresSettings.mbAlwaysOnTop != bool(bAlways) )
2874
0
    {
2875
0
        maPresSettings.mbAlwaysOnTop = bAlways;
2876
        // todo, can this be changed while running?
2877
0
    }
2878
0
}
2879
2880
sal_Bool SAL_CALL SlideshowImpl::isFullScreen()
2881
0
{
2882
0
    SolarMutexGuard aSolarGuard;
2883
0
    return maPresSettings.mbFullScreen;
2884
0
}
2885
2886
sal_Bool SAL_CALL SlideshowImpl::getMouseVisible()
2887
0
{
2888
0
    SolarMutexGuard aSolarGuard;
2889
0
    return maPresSettings.mbMouseVisible;
2890
0
}
2891
2892
void SAL_CALL SlideshowImpl::setMouseVisible( sal_Bool bVisible )
2893
0
{
2894
0
    SolarMutexGuard aSolarGuard;
2895
0
    if( maPresSettings.mbMouseVisible != bool(bVisible) )
2896
0
    {
2897
0
        maPresSettings.mbMouseVisible = bVisible;
2898
0
        if( mpShowWindow )
2899
0
            mpShowWindow->SetMouseAutoHide( !maPresSettings.mbMouseVisible );
2900
0
    }
2901
0
}
2902
2903
sal_Bool SAL_CALL SlideshowImpl::getUsePen()
2904
0
{
2905
0
    SolarMutexGuard aSolarGuard;
2906
0
    return mbUsePen;
2907
0
}
2908
2909
void SAL_CALL SlideshowImpl::setUsePen( sal_Bool bMouseAsPen )
2910
0
{
2911
0
    SolarMutexGuard aSolarGuard;
2912
0
    mbUsePen = bMouseAsPen;
2913
0
    if( !mxShow.is() )
2914
0
        return;
2915
2916
0
    try
2917
0
    {
2918
        // For Pencolor;
2919
0
        beans::PropertyValue aPenProp;
2920
0
        aPenProp.Name = "UserPaintColor";
2921
0
        if( mbUsePen )
2922
0
            aPenProp.Value <<= mnUserPaintColor;
2923
0
        mxShow->setProperty( aPenProp );
2924
2925
        //for StrokeWidth :
2926
0
        if( mbUsePen )
2927
0
        {
2928
0
            beans::PropertyValue aPenPropWidth;
2929
0
            aPenPropWidth.Name = "UserPaintStrokeWidth";
2930
0
            aPenPropWidth.Value <<= mdUserPaintStrokeWidth;
2931
0
            mxShow->setProperty( aPenPropWidth );
2932
2933
            // for Pen Mode
2934
0
            beans::PropertyValue aPenPropSwitchPenMode;
2935
0
            aPenPropSwitchPenMode.Name = "SwitchPenMode";
2936
0
            aPenPropSwitchPenMode.Value <<= true;
2937
0
            mxShow->setProperty( aPenPropSwitchPenMode );
2938
0
        }
2939
0
    }
2940
0
    catch( Exception& )
2941
0
    {
2942
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::setUsePen()" );
2943
0
    }
2944
0
}
2945
2946
double SAL_CALL SlideshowImpl::getPenWidth()
2947
0
{
2948
0
    SolarMutexGuard aSolarGuard;
2949
0
    return mdUserPaintStrokeWidth;
2950
0
}
2951
2952
void SAL_CALL SlideshowImpl::setPenWidth( double dStrokeWidth )
2953
0
{
2954
0
    SolarMutexGuard aSolarGuard;
2955
0
    mdUserPaintStrokeWidth = dStrokeWidth;
2956
0
    setUsePen( true ); // enable pen mode, update color and width
2957
0
}
2958
2959
sal_Int32 SAL_CALL SlideshowImpl::getPenColor()
2960
0
{
2961
0
    SolarMutexGuard aSolarGuard;
2962
0
    return mnUserPaintColor;
2963
0
}
2964
2965
void SAL_CALL SlideshowImpl::setPenColor( sal_Int32 nColor )
2966
0
{
2967
0
    SolarMutexGuard aSolarGuard;
2968
0
    mnUserPaintColor = nColor;
2969
0
    setUsePen( true ); // enable pen mode, update color
2970
0
}
2971
2972
void SAL_CALL SlideshowImpl::setEraseAllInk(sal_Bool bEraseAllInk)
2973
0
{
2974
0
    if( !bEraseAllInk )
2975
0
        return;
2976
2977
0
    SolarMutexGuard aSolarGuard;
2978
0
    if( !mxShow.is() )
2979
0
        return;
2980
2981
0
    try
2982
0
    {
2983
0
        beans::PropertyValue aPenPropEraseAllInk;
2984
0
        aPenPropEraseAllInk.Name = "EraseAllInk";
2985
0
        aPenPropEraseAllInk.Value <<= bEraseAllInk;
2986
0
        mxShow->setProperty( aPenPropEraseAllInk );
2987
0
    }
2988
0
    catch( Exception& )
2989
0
    {
2990
0
        TOOLS_WARN_EXCEPTION( "sd.slideshow", "sd::SlideshowImpl::setEraseAllInk()" );
2991
0
    }
2992
0
}
2993
2994
// XSlideShowController Methods
2995
sal_Bool SAL_CALL SlideshowImpl::isRunning(  )
2996
0
{
2997
0
    SolarMutexGuard aSolarGuard;
2998
0
    return mxShow.is();
2999
0
}
3000
3001
void SAL_CALL SlideshowImpl::gotoNextEffect(  )
3002
0
{
3003
0
    SolarMutexGuard aSolarGuard;
3004
3005
0
    if( !(mxShow.is() && mpSlideController && mpShowWindow) )
3006
0
        return;
3007
3008
0
    if( mbIsPaused && mpShowWindow->GetShowWindowMode() != SHOWWINDOWMODE_END )
3009
0
        resume();
3010
3011
0
    const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
3012
0
    if( eMode == SHOWWINDOWMODE_END )
3013
0
    {
3014
0
        endPresentation();
3015
0
    }
3016
0
    else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
3017
0
    {
3018
0
        mpShowWindow->RestartShow();
3019
0
    }
3020
0
    else
3021
0
    {
3022
0
        mxShow->nextEffect();
3023
0
        update();
3024
0
    }
3025
0
}
3026
3027
void SAL_CALL SlideshowImpl::gotoPreviousEffect(  )
3028
0
{
3029
0
    SolarMutexGuard aSolarGuard;
3030
3031
0
    if( !(mxShow.is() && mpSlideController && mpShowWindow) )
3032
0
        return;
3033
3034
0
    const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
3035
0
    if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) || mbIsPaused )
3036
0
    {
3037
0
        resume();
3038
0
    }
3039
0
    else
3040
0
    {
3041
0
        mxShow->previousEffect();
3042
0
        update();
3043
0
    }
3044
0
}
3045
3046
void SAL_CALL SlideshowImpl::gotoFirstSlide(  )
3047
0
{
3048
0
    SolarMutexGuard aSolarGuard;
3049
3050
0
    if( !(mpShowWindow && mpSlideController) )
3051
0
        return;
3052
3053
0
    if( mbIsPaused )
3054
0
        resume();
3055
3056
0
    if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
3057
0
    {
3058
0
        if( mpSlideController->getSlideIndexCount() )
3059
0
            mpShowWindow->RestartShow( 0);
3060
0
    }
3061
0
    else
3062
0
    {
3063
0
        displaySlideIndex( 0 );
3064
0
    }
3065
0
}
3066
3067
void SAL_CALL SlideshowImpl::gotoNextSlide(  )
3068
0
{
3069
0
    SolarMutexGuard aSolarGuard;
3070
3071
0
    if( mbIsPaused )
3072
0
        resume();
3073
3074
0
    const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
3075
0
    if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
3076
0
    {
3077
0
        mpShowWindow->RestartShow();
3078
0
    }
3079
0
    else
3080
0
    {
3081
        // if this is a show, ignore user inputs and
3082
        // start 20ms timer to reenable inputs to filter
3083
        // buffered inputs during slide transition
3084
0
        if( meAnimationMode == ANIMATIONMODE_SHOW )
3085
0
        {
3086
0
            mbInputFreeze = true;
3087
0
            maInputFreezeTimer.Start();
3088
0
        }
3089
3090
0
        if( mpSlideController )
3091
0
        {
3092
0
            if( mpSlideController->nextSlide() )
3093
0
            {
3094
0
                displayCurrentSlide();
3095
0
            }
3096
0
            else
3097
0
            {
3098
0
                stopSound();
3099
3100
0
                if( meAnimationMode == ANIMATIONMODE_PREVIEW )
3101
0
                {
3102
0
                    endPresentation();
3103
0
                }
3104
0
                else if( maPresSettings.mbEndless )
3105
0
                {
3106
0
                    if( maPresSettings.mnPauseTimeout )
3107
0
                    {
3108
0
                        if( mpShowWindow )
3109
0
                        {
3110
0
                            if ( maPresSettings.mbShowPauseLogo )
3111
0
                            {
3112
0
                                Graphic aGraphic(SfxApplication::GetApplicationLogo(360));
3113
0
                                mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout, &aGraphic );
3114
0
                            }
3115
0
                            else
3116
0
                                mpShowWindow->SetPauseMode( maPresSettings.mnPauseTimeout );
3117
0
                        }
3118
0
                    }
3119
0
                    else
3120
0
                    {
3121
0
                        displaySlideIndex( 0 );
3122
0
                    }
3123
0
                }
3124
0
                else
3125
0
                {
3126
0
                    if( mpShowWindow )
3127
0
                    {
3128
0
                        mpShowWindow->SetEndMode();
3129
0
                        if (!mpViewShell->GetDoc()->GetStartWithPresentation())
3130
0
                            pause();
3131
0
                    }
3132
0
                }
3133
0
            }
3134
0
        }
3135
0
    }
3136
0
}
3137
3138
void SAL_CALL SlideshowImpl::gotoPreviousSlide(  )
3139
0
{
3140
0
    gotoPreviousSlide(false);
3141
0
}
3142
3143
void SlideshowImpl::gotoPreviousSlide (const bool bSkipAllMainSequenceEffects)
3144
0
{
3145
0
    SolarMutexGuard aSolarGuard;
3146
3147
0
    if( !(mxShow.is() && mpSlideController) )
3148
0
        return;
3149
3150
0
    try
3151
0
    {
3152
0
        if( mbIsPaused )
3153
0
            resume();
3154
3155
0
        const ShowWindowMode eMode = mpShowWindow->GetShowWindowMode();
3156
0
        if( eMode == SHOWWINDOWMODE_END )
3157
0
        {
3158
0
            mpShowWindow->RestartShow( mpSlideController->getCurrentSlideIndex() );
3159
0
        }
3160
0
        else if( (eMode == SHOWWINDOWMODE_PAUSE) || (eMode == SHOWWINDOWMODE_BLANK) )
3161
0
        {
3162
0
            mpShowWindow->RestartShow();
3163
0
        }
3164
0
        else
3165
0
        {
3166
0
            if( mpSlideController->previousSlide())
3167
0
                displayCurrentSlide(bSkipAllMainSequenceEffects);
3168
0
            else if (bSkipAllMainSequenceEffects)
3169
0
            {
3170
                // We could not go to the previous slide (probably because
3171
                // the current slide is already the first one).  We still
3172
                // have to call displayCurrentSlide because the calling
3173
                // slideshow can not determine whether there is a previous
3174
                // slide or not and has already prepared for a slide change.
3175
                // This slide change has to be completed now, even when
3176
                // changing to the same slide.
3177
                // Note that in this special case we do NOT pass
3178
                // bSkipAllMainSequenceEffects because we display the same
3179
                // slide as before and do not want to show all its effects.
3180
0
                displayCurrentSlide();
3181
0
            }
3182
0
        }
3183
0
    }
3184
0
    catch( Exception& )
3185
0
    {
3186
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::gotoPreviousSlide()" );
3187
0
    }
3188
0
}
3189
3190
void SAL_CALL SlideshowImpl::gotoLastSlide()
3191
0
{
3192
0
    SolarMutexGuard aSolarGuard;
3193
3194
0
    if( !mpSlideController )
3195
0
        return;
3196
3197
0
    if( mbIsPaused )
3198
0
        resume();
3199
3200
0
    const sal_Int32 nLastSlideIndex = mpSlideController->getSlideIndexCount() - 1;
3201
0
    if( nLastSlideIndex >= 0 )
3202
0
    {
3203
0
        if( mpShowWindow->GetShowWindowMode() == SHOWWINDOWMODE_END )
3204
0
        {
3205
0
            mpShowWindow->RestartShow( nLastSlideIndex );
3206
0
        }
3207
0
        else
3208
0
        {
3209
0
            displaySlideIndex( nLastSlideIndex );
3210
0
        }
3211
0
    }
3212
0
}
3213
3214
void SAL_CALL SlideshowImpl::gotoBookmark( const OUString& rBookmark )
3215
0
{
3216
0
    SolarMutexGuard aSolarGuard;
3217
3218
0
    if( mbIsPaused )
3219
0
        resume();
3220
3221
0
    sal_Int32 nSlideNumber = getSlideNumberForBookmark( rBookmark );
3222
0
    if( nSlideNumber != -1 )
3223
0
        displaySlideNumber( nSlideNumber );
3224
0
}
3225
3226
void SAL_CALL SlideshowImpl::gotoSlide( const Reference< XDrawPage >& xSlide )
3227
0
{
3228
0
    SolarMutexGuard aSolarGuard;
3229
3230
0
    if( !(mpSlideController && xSlide.is()) )
3231
0
        return;
3232
3233
0
    if( mbIsPaused )
3234
0
        resume();
3235
3236
0
    const sal_Int32 nSlideCount = mpSlideController->getSlideNumberCount();
3237
0
    for( sal_Int32 nSlide = 0; nSlide < nSlideCount; nSlide++ )
3238
0
    {
3239
0
        if( mpSlideController->getSlideByNumber( nSlide ) == xSlide )
3240
0
        {
3241
0
            displaySlideNumber( nSlide );
3242
0
        }
3243
0
    }
3244
0
}
3245
3246
void SAL_CALL SlideshowImpl::gotoSlideIndex( sal_Int32 nIndex )
3247
0
{
3248
0
    SolarMutexGuard aSolarGuard;
3249
3250
0
    if( mbIsPaused )
3251
0
        resume();
3252
3253
0
    displaySlideIndex( nIndex );
3254
0
}
3255
3256
void SAL_CALL SlideshowImpl::stopSound(  )
3257
0
{
3258
0
    SolarMutexGuard aSolarGuard;
3259
3260
0
    try
3261
0
    {
3262
0
        if( mxPlayer.is() )
3263
0
        {
3264
0
            mxPlayer->stop();
3265
0
            mxPlayer.clear();
3266
0
        }
3267
0
    }
3268
0
    catch( Exception& )
3269
0
    {
3270
0
        TOOLS_WARN_EXCEPTION( "sd", "sd::SlideshowImpl::stopSound()" );
3271
0
    }
3272
0
}
3273
3274
// XIndexAccess
3275
3276
::sal_Int32 SAL_CALL SlideshowImpl::getCount(  )
3277
0
{
3278
0
    return getSlideCount();
3279
0
}
3280
3281
css::uno::Any SAL_CALL SlideshowImpl::getByIndex( ::sal_Int32 Index )
3282
0
{
3283
0
    return Any( getSlideByIndex( Index ) );
3284
0
}
3285
3286
css::uno::Type SAL_CALL SlideshowImpl::getElementType(  )
3287
0
{
3288
0
    return cppu::UnoType<XDrawPage>::get();
3289
0
}
3290
3291
sal_Bool SAL_CALL SlideshowImpl::hasElements(  )
3292
0
{
3293
0
    return getSlideCount() != 0;
3294
0
}
3295
3296
namespace
3297
{
3298
    class AsyncUpdateSlideshow_Impl
3299
    {
3300
    public:
3301
        struct AsyncUpdateSlideshowData
3302
        {
3303
            SlideshowImpl* pSlideshowImpl;
3304
            uno::Reference< css::drawing::XDrawPage > XCurrentSlide;
3305
            SdrHintKind eHintKind;
3306
        };
3307
3308
        static ImplSVEvent* AsyncUpdateSlideshow(
3309
            SlideshowImpl* pSlideshowImpl,
3310
            const uno::Reference< css::drawing::XDrawPage >& rXCurrentSlide,
3311
            SdrHintKind eHintKind)
3312
0
        {
3313
0
            AsyncUpdateSlideshowData* pNew(new AsyncUpdateSlideshowData);
3314
0
            pNew->pSlideshowImpl = pSlideshowImpl;
3315
0
            pNew->XCurrentSlide = rXCurrentSlide;
3316
0
            pNew->eHintKind = eHintKind;
3317
0
            return Application::PostUserEvent(LINK(nullptr, AsyncUpdateSlideshow_Impl, Update), pNew);
3318
            // coverity[leaked_storage] - pDisruptor takes care of its own destruction at idle time
3319
0
        }
3320
3321
        DECL_STATIC_LINK(AsyncUpdateSlideshow_Impl, Update, void*, void);
3322
    };
3323
3324
    IMPL_STATIC_LINK(AsyncUpdateSlideshow_Impl, Update, void*, pData, void)
3325
0
    {
3326
0
        AsyncUpdateSlideshowData* pSlideData(static_cast<AsyncUpdateSlideshowData*>(pData));
3327
0
        pSlideData->pSlideshowImpl->AsyncNotifyEvent(pSlideData->XCurrentSlide, pSlideData->eHintKind);
3328
0
        delete pSlideData;
3329
0
    }
3330
}
3331
3332
void SlideshowImpl::AsyncNotifyEvent(
3333
    const uno::Reference< css::drawing::XDrawPage >& rXCurrentSlide,
3334
    const SdrHintKind eHintKind)
3335
0
{
3336
0
    switch (eHintKind)
3337
0
    {
3338
0
        case SdrHintKind::ObjectInserted:
3339
0
        {
3340
0
            mnEventObjectInserted = nullptr;
3341
3342
            // refresh single slide
3343
0
            gotoSlide(rXCurrentSlide);
3344
0
            break;
3345
0
        }
3346
0
        case SdrHintKind::ObjectRemoved:
3347
0
        {
3348
0
            mnEventObjectRemoved = nullptr;
3349
3350
            // refresh single slide
3351
0
            gotoSlide(rXCurrentSlide);
3352
0
            break;
3353
0
        }
3354
0
        case SdrHintKind::ObjectChange:
3355
0
        {
3356
0
            mnEventObjectChange = nullptr;
3357
3358
            // refresh single slide
3359
0
            gotoSlide(rXCurrentSlide);
3360
0
            break;
3361
0
        }
3362
0
        case SdrHintKind::PageOrderChange:
3363
0
        {
3364
0
            mnEventPageOrderChange = nullptr;
3365
3366
            // order of pages (object pages or master pages) changed (Insert/Remove/ChangePos)
3367
            // rXCurrentSlide is the current slide before the change.
3368
0
            rtl::Reference< SdXImpressDocument > xDrawPages( mpDoc->getUnoModel() );
3369
0
            Reference< XIndexAccess > xSlides( xDrawPages->getDrawPages(), UNO_QUERY_THROW );
3370
0
            const sal_Int32 nNewSlideCount(xSlides.is() ? xSlides->getCount() : 0);
3371
3372
0
            if (nNewSlideCount != mpSlideController->getSlideNumberCount())
3373
0
            {
3374
                // need to reinitialize AnimationSlideController
3375
0
                OUString aPresSlide( maPresSettings.maPresPage );
3376
0
                createSlideList( maPresSettings.mbAll, aPresSlide );
3377
0
            }
3378
3379
            // Check if current slide before change is still valid (maybe removed)
3380
0
            const sal_Int32 nSlideCount(mpSlideController->getSlideNumberCount());
3381
0
            bool bSlideStillValid(false);
3382
3383
0
            for (sal_Int32 nSlide(0); !bSlideStillValid && nSlide < nSlideCount; nSlide++)
3384
0
            {
3385
0
                if (rXCurrentSlide == mpSlideController->getSlideByNumber(nSlide))
3386
0
                {
3387
0
                    bSlideStillValid = true;
3388
0
                }
3389
0
            }
3390
3391
0
            if(bSlideStillValid)
3392
0
            {
3393
                // stay on that slide
3394
0
                gotoSlide(rXCurrentSlide);
3395
0
            }
3396
0
            else
3397
0
            {
3398
                // not possible to stay on that slide, go to 1st slide (kinda restart)
3399
0
                gotoFirstSlide();
3400
0
            }
3401
0
            break;
3402
0
        }
3403
0
        default:
3404
0
            break;
3405
0
    }
3406
0
}
3407
3408
bool SlideshowImpl::isCurrentSlideInvolved(const SdrHint& rHint)
3409
0
{
3410
    // get current slide
3411
0
    uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3412
0
    if (!XCurrentSlide.is())
3413
0
        return false;
3414
3415
0
    SdrPage* pCurrentSlide(GetSdrPageFromXDrawPage(XCurrentSlide));
3416
0
    if (nullptr == pCurrentSlide)
3417
0
        return false;
3418
3419
0
    const SdrPage* pHintPage(rHint.GetPage());
3420
0
    if (nullptr == pHintPage)
3421
0
        return false;
3422
3423
0
    if (pHintPage->IsMasterPage())
3424
0
    {
3425
0
        if (pCurrentSlide->TRG_HasMasterPage())
3426
0
        {
3427
            // current slide uses MasterPage on which the change happened
3428
0
            return pHintPage == &pCurrentSlide->TRG_GetMasterPage();
3429
0
        }
3430
0
    }
3431
3432
    // object on current slide was changed
3433
0
    return pHintPage == pCurrentSlide;
3434
0
}
3435
3436
void SlideshowImpl::sendHintSlideChanged(const SdrPage* pChangedPage) const
3437
0
{
3438
0
    if (nullptr == pChangedPage)
3439
0
        return;
3440
3441
0
    if (!mxShow.is())
3442
0
        return;
3443
3444
0
    mxShow->setProperty(
3445
0
        beans::PropertyValue( u"HintSlideChanged"_ustr ,
3446
0
            -1,
3447
0
            Any( GetXDrawPageForSdrPage(const_cast<SdrPage*>(pChangedPage)) ),
3448
0
            beans::PropertyState_DIRECT_VALUE ) );
3449
0
}
3450
3451
void SlideshowImpl::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
3452
0
{
3453
0
    if (SfxHintId::ThisIsAnSdrHint != rHint.GetId())
3454
        // nothing to do for non-SdrHints
3455
0
        return;
3456
3457
0
    if (nullptr == mpDoc)
3458
        // better do nothing when no DrawModel (should not happen)
3459
0
        return;
3460
3461
    // tdf#158664 I am surprised, but the 'this' instance keeps incarnated
3462
    // when the slideshow was running once, so need to check for
3463
    // SlideShow instance/running to be safe.
3464
    // NOTE: isRunning() checks mxShow.is(), that is what we want
3465
0
    if (!isRunning())
3466
        // no SlideShow instance or not running, nothing to do
3467
0
        return;
3468
3469
0
    const SdrHint& rSdrHint(static_cast<const SdrHint&>(rHint));
3470
0
    const SdrHintKind eHintKind(rSdrHint.GetKind());
3471
3472
0
    switch (eHintKind)
3473
0
    {
3474
0
        case SdrHintKind::ObjectInserted:
3475
0
        {
3476
0
            if (nullptr != mnEventObjectInserted)
3477
                // avoid multiple events
3478
0
                return;
3479
3480
            // tdf#160669 IASS: inform about ALL changed slides due to prefetch
3481
0
            sendHintSlideChanged(rSdrHint.GetPage());
3482
3483
0
            if (!isCurrentSlideInvolved(rSdrHint))
3484
                // nothing to do when current slide is not involved
3485
0
                return;
3486
3487
            // Refresh current slide
3488
0
            uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3489
0
            mnEventObjectInserted = AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
3490
0
            break;
3491
0
        }
3492
0
        case SdrHintKind::ObjectRemoved:
3493
0
        {
3494
0
            if (nullptr != mnEventObjectRemoved)
3495
                // avoid multiple events
3496
0
                return;
3497
3498
            // tdf#160669 IASS: inform about ALL changed slides due to prefetch
3499
0
            sendHintSlideChanged(rSdrHint.GetPage());
3500
3501
0
            if (!isCurrentSlideInvolved(rSdrHint))
3502
                // nothing to do when current slide is not involved
3503
0
                return;
3504
3505
            // Refresh current slide
3506
0
            uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3507
0
            mnEventObjectRemoved = AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
3508
0
            break;
3509
0
        }
3510
0
        case SdrHintKind::ObjectChange:
3511
0
        {
3512
0
            if (nullptr != mnEventObjectChange)
3513
                // avoid multiple events
3514
0
                return;
3515
3516
            // tdf#160669 IASS: inform about ALL changed slides due to prefetch
3517
0
            sendHintSlideChanged(rSdrHint.GetPage());
3518
3519
0
            if (!isCurrentSlideInvolved(rSdrHint))
3520
                // nothing to do when current slide is not involved
3521
0
                return;
3522
3523
            // Refresh current slide. Need to do that asynchronous, else e.g.
3524
            // text edit changes EditEngine/Outliner are not progressed far
3525
            // enough (ObjectChanged broadcast which we are in here seems
3526
            // too early for some cases)
3527
0
            uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3528
0
            mnEventObjectChange = AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
3529
0
            break;
3530
0
        }
3531
0
        case SdrHintKind::PageOrderChange:
3532
0
        {
3533
            // Unfortunately we get multiple events, e.g. when drag/drop position change in
3534
            // slide sorter on left side of EditView. This includes some with page number +1,
3535
            // then again -1 (it's a position change). Problem is that in-between already
3536
            // a re-schedule seems to happen, so indeed AsyncNotifyEvent will change to +1/-1
3537
            // already. Since we get even more, at least try to take the last one. I found no
3538
            // good solution yet for this.
3539
0
            if (nullptr != mnEventPageOrderChange)
3540
0
                Application::RemoveUserEvent( mnEventPageOrderChange );
3541
3542
            // tdf#160669 IASS: inform about ALL changed slides due to prefetch
3543
0
            sendHintSlideChanged(rSdrHint.GetPage());
3544
3545
            // order of pages (object pages or master pages) changed (Insert/Remove/ChangePos)
3546
0
            uno::Reference< css::drawing::XDrawPage > XCurrentSlide(getCurrentSlide());
3547
0
            mnEventPageOrderChange = AsyncUpdateSlideshow_Impl::AsyncUpdateSlideshow(this, XCurrentSlide, eHintKind);
3548
0
            break;
3549
0
        }
3550
0
        case SdrHintKind::ModelCleared:
3551
0
        {
3552
            // immediately end presentation
3553
0
            endPresentation();
3554
0
            break;
3555
0
        }
3556
0
        default:
3557
0
            break;
3558
0
    }
3559
0
}
3560
3561
Reference< XSlideShow > SAL_CALL SlideshowImpl::getSlideShow()
3562
0
{
3563
0
    return mxShow;
3564
0
}
3565
3566
PresentationSettingsEx::PresentationSettingsEx( const PresentationSettingsEx& r )
3567
0
: PresentationSettings( r )
3568
0
, mbRehearseTimings(r.mbRehearseTimings)
3569
0
, mbPreview(r.mbPreview)
3570
0
, mpParentWindow( nullptr )
3571
0
{
3572
0
}
3573
3574
PresentationSettingsEx::PresentationSettingsEx( PresentationSettings const & r )
3575
0
: PresentationSettings( r )
3576
0
, mbRehearseTimings(false)
3577
0
, mbPreview(false)
3578
0
, mpParentWindow(nullptr)
3579
0
{
3580
0
}
3581
3582
void PresentationSettingsEx::SetArguments( const Sequence< PropertyValue >& rArguments )
3583
0
{
3584
0
    for( const PropertyValue& rValue : rArguments )
3585
0
    {
3586
0
        SetPropertyValue( rValue.Name, rValue.Value );
3587
0
    }
3588
0
}
3589
3590
void PresentationSettingsEx::SetPropertyValue( std::u16string_view rProperty, const Any& rValue )
3591
0
{
3592
0
    if ( rProperty == u"RehearseTimings" )
3593
0
    {
3594
0
        if( rValue >>= mbRehearseTimings )
3595
0
            return;
3596
0
    }
3597
0
    else if ( rProperty == u"Preview" )
3598
0
    {
3599
0
        if( rValue >>= mbPreview )
3600
0
            return;
3601
0
    }
3602
0
    else if ( rProperty == u"AnimationNode" )
3603
0
    {
3604
0
        if( rValue >>= mxAnimationNode )
3605
0
            return;
3606
0
    }
3607
0
    else if ( rProperty == u"ParentWindow" )
3608
0
    {
3609
0
        Reference< XWindow > xWindow;
3610
0
        if( rValue >>= xWindow )
3611
0
        {
3612
0
            mpParentWindow = xWindow.is() ? VCLUnoHelper::GetWindow( xWindow )
3613
0
                                          : nullptr;
3614
0
            return;
3615
0
        }
3616
0
    }
3617
0
    else if ( rProperty == u"AllowAnimations" )
3618
0
    {
3619
0
        if( rValue >>= mbAnimationAllowed )
3620
0
            return;
3621
0
    }
3622
0
    else if ( rProperty == u"FirstPage" )
3623
0
    {
3624
0
        OUString aPresPage;
3625
0
        if( rValue >>= aPresPage )
3626
0
        {
3627
0
            maPresPage = getUiNameFromPageApiNameImpl(aPresPage);
3628
0
            mbCustomShow = false;
3629
0
            mbAll = false;
3630
0
            return;
3631
0
        }
3632
0
        else
3633
0
        {
3634
0
            if( rValue >>= mxStartPage )
3635
0
                return;
3636
0
        }
3637
0
    }
3638
0
    else if ( rProperty == u"IsAlwaysOnTop" )
3639
0
    {
3640
0
        if( rValue >>= mbAlwaysOnTop )
3641
0
            return;
3642
0
    }
3643
0
    else if ( rProperty == u"IsAutomatic" )
3644
0
    {
3645
0
        if( rValue >>= mbManual )
3646
0
            return;
3647
0
    }
3648
0
    else if ( rProperty == u"IsEndless" )
3649
0
    {
3650
0
        if( rValue >>= mbEndless )
3651
0
            return;
3652
0
    }
3653
0
    else if ( rProperty == u"IsFullScreen" )
3654
0
    {
3655
0
        if( rValue >>= mbFullScreen )
3656
0
            return;
3657
0
    }
3658
0
    else if ( rProperty == u"IsMouseVisible" )
3659
0
    {
3660
0
        if( rValue >>= mbMouseVisible )
3661
0
            return;
3662
0
    }
3663
0
    else if ( rProperty == u"Pause" )
3664
0
    {
3665
0
        sal_Int32 nPause = -1;
3666
0
        if( (rValue >>= nPause) && (nPause >= 0) )
3667
0
        {
3668
0
            mnPauseTimeout = nPause;
3669
0
            return;
3670
0
        }
3671
0
    }
3672
0
    else if ( rProperty == u"UsePen" )
3673
0
    {
3674
0
        if( rValue >>= mbMouseAsPen )
3675
0
            return;
3676
0
    }
3677
0
    throw IllegalArgumentException();
3678
0
}
3679
3680
// XAnimationListener
3681
3682
SlideShowListenerProxy::SlideShowListenerProxy( rtl::Reference< SlideshowImpl > xController, css::uno::Reference< css::presentation::XSlideShow > xSlideShow )
3683
0
: mxController(std::move( xController ))
3684
0
, mxSlideShow(std::move( xSlideShow ))
3685
0
{
3686
0
}
3687
3688
SlideShowListenerProxy::~SlideShowListenerProxy()
3689
0
{
3690
0
}
3691
3692
void SlideShowListenerProxy::addAsSlideShowListener()
3693
0
{
3694
0
    if( mxSlideShow.is() )
3695
0
    {
3696
0
        Reference< XSlideShowListener > xSlideShowListener( this );
3697
0
        mxSlideShow->addSlideShowListener( xSlideShowListener );
3698
0
    }
3699
0
}
3700
3701
void SlideShowListenerProxy::removeAsSlideShowListener()
3702
0
{
3703
0
    if( mxSlideShow.is() )
3704
0
    {
3705
0
        Reference< XSlideShowListener > xSlideShowListener( this );
3706
0
        mxSlideShow->removeSlideShowListener( xSlideShowListener );
3707
0
    }
3708
0
}
3709
3710
void SlideShowListenerProxy::addShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3711
0
{
3712
0
    if( mxSlideShow.is() )
3713
0
    {
3714
0
        Reference< XShapeEventListener > xListener( this );
3715
0
        mxSlideShow->addShapeEventListener( xListener, xShape );
3716
0
    }
3717
0
}
3718
3719
void SlideShowListenerProxy::removeShapeEventListener( const css::uno::Reference< css::drawing::XShape >& xShape )
3720
0
{
3721
0
    if( mxSlideShow.is() )
3722
0
    {
3723
0
        Reference< XShapeEventListener > xListener( this );
3724
0
        mxSlideShow->removeShapeEventListener( xListener, xShape );
3725
0
    }
3726
0
}
3727
3728
void SlideShowListenerProxy::addSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3729
0
{
3730
0
    std::unique_lock g(m_aMutex);
3731
0
    maListeners.addInterface(g, xListener);
3732
0
}
3733
3734
void SlideShowListenerProxy::removeSlideShowListener( const css::uno::Reference< css::presentation::XSlideShowListener >& xListener )
3735
0
{
3736
0
    std::unique_lock g(m_aMutex);
3737
0
    maListeners.removeInterface(g, xListener);
3738
0
}
3739
3740
void SAL_CALL SlideShowListenerProxy::beginEvent( const Reference< XAnimationNode >& xNode )
3741
0
{
3742
0
    std::unique_lock aGuard( m_aMutex );
3743
3744
0
    if( maListeners.getLength(aGuard) >= 0 )
3745
0
    {
3746
0
        maListeners.forEach(aGuard,
3747
0
            [&] (Reference<XAnimationListener> const& xListener) {
3748
0
                return xListener->beginEvent(xNode);
3749
0
            } );
3750
0
    }
3751
0
}
3752
3753
void SAL_CALL SlideShowListenerProxy::endEvent( const Reference< XAnimationNode >& xNode )
3754
0
{
3755
0
    std::unique_lock aGuard( m_aMutex );
3756
3757
0
    if( maListeners.getLength(aGuard) >= 0 )
3758
0
    {
3759
0
        maListeners.forEach(aGuard,
3760
0
            [&] (Reference<XAnimationListener> const& xListener) {
3761
0
                return xListener->endEvent(xNode);
3762
0
            } );
3763
0
    }
3764
0
}
3765
3766
void SAL_CALL SlideShowListenerProxy::repeat( const Reference< XAnimationNode >& xNode, ::sal_Int32 nRepeat )
3767
0
{
3768
0
    std::unique_lock aGuard( m_aMutex );
3769
3770
0
    if( maListeners.getLength(aGuard) >= 0 )
3771
0
    {
3772
0
        maListeners.forEach(aGuard,
3773
0
            [&] (Reference<XAnimationListener> const& xListener) {
3774
0
                return xListener->repeat(xNode, nRepeat);
3775
0
            } );
3776
0
    }
3777
0
}
3778
3779
// css::presentation::XSlideShowListener:
3780
3781
void SAL_CALL SlideShowListenerProxy::paused(  )
3782
0
{
3783
0
    std::unique_lock aGuard( m_aMutex );
3784
3785
0
    maListeners.forEach(aGuard,
3786
0
        [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3787
0
        {
3788
0
            xListener->paused();
3789
0
        });
3790
0
}
3791
3792
void SAL_CALL SlideShowListenerProxy::resumed(  )
3793
0
{
3794
0
    std::unique_lock aGuard( m_aMutex );
3795
3796
0
    maListeners.forEach(aGuard,
3797
0
        [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3798
0
        {
3799
0
            xListener->resumed();
3800
0
        });
3801
0
}
3802
3803
void SAL_CALL SlideShowListenerProxy::slideTransitionStarted( )
3804
0
{
3805
0
    std::unique_lock aGuard( m_aMutex );
3806
3807
0
    maListeners.forEach(aGuard,
3808
0
        [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3809
0
        {
3810
0
            xListener->slideTransitionStarted();
3811
0
        });
3812
0
}
3813
3814
void SAL_CALL SlideShowListenerProxy::slideTransitionEnded( )
3815
0
{
3816
0
    std::unique_lock aGuard( m_aMutex );
3817
3818
0
    maListeners.forEach(aGuard,
3819
0
        [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3820
0
        {
3821
0
            xListener->slideTransitionEnded ();
3822
0
        });
3823
0
}
3824
3825
void SAL_CALL SlideShowListenerProxy::slideAnimationsEnded(  )
3826
0
{
3827
0
    std::unique_lock aGuard( m_aMutex );
3828
3829
0
    maListeners.forEach(aGuard,
3830
0
        [](uno::Reference<presentation::XSlideShowListener> const& xListener)
3831
0
        {
3832
0
            xListener->slideAnimationsEnded ();
3833
0
        });
3834
0
}
3835
3836
void SlideShowListenerProxy::slideEnded(sal_Bool bReverse)
3837
0
{
3838
0
    {
3839
0
        std::unique_lock aGuard( m_aMutex );
3840
3841
0
        if( maListeners.getLength(aGuard) >= 0 )
3842
0
        {
3843
0
            maListeners.forEach(aGuard,
3844
0
                [&] (Reference<XSlideShowListener> const& xListener) {
3845
0
                    return xListener->slideEnded(bReverse);
3846
0
                } );
3847
0
        }
3848
0
    }
3849
3850
0
    {
3851
0
        SolarMutexGuard aSolarGuard;
3852
0
        if( mxController.is() )
3853
0
            mxController->slideEnded(bReverse);
3854
0
    }
3855
0
}
3856
3857
void SlideShowListenerProxy::hyperLinkClicked( OUString const& aHyperLink )
3858
0
{
3859
0
    {
3860
0
        std::unique_lock aGuard( m_aMutex );
3861
3862
0
        if( maListeners.getLength(aGuard) >= 0 )
3863
0
        {
3864
0
            maListeners.forEach(aGuard,
3865
0
                [&] (Reference<XSlideShowListener> const& xListener) {
3866
0
                    return xListener->hyperLinkClicked(aHyperLink);
3867
0
                } );
3868
0
        }
3869
0
    }
3870
3871
0
    {
3872
0
        SolarMutexGuard aSolarGuard;
3873
0
        if( mxController.is() )
3874
0
            mxController->hyperLinkClicked(aHyperLink);
3875
0
    }
3876
0
}
3877
3878
// XEventListener
3879
3880
void SAL_CALL SlideShowListenerProxy::disposing( const css::lang::EventObject& aDisposeEvent )
3881
0
{
3882
0
    std::unique_lock g(m_aMutex);
3883
0
    maListeners.disposeAndClear( g, aDisposeEvent );
3884
0
    mxController.clear();
3885
0
    mxSlideShow.clear();
3886
0
}
3887
3888
// XShapeEventListener
3889
3890
void SAL_CALL SlideShowListenerProxy::click( const Reference< XShape >& xShape, const css::awt::MouseEvent& /*aOriginalEvent*/ )
3891
0
{
3892
0
    SolarMutexGuard aSolarGuard;
3893
0
    if( mxController.is() )
3894
0
        mxController->click(xShape );
3895
0
}
3896
3897
void SAL_CALL SlideShowListenerProxy::contextMenuShow(const css::awt::Point& point)
3898
0
{
3899
0
    SolarMutexGuard aSolarGuard;
3900
0
    if (mxController.is())
3901
0
        mxController->contextMenuShow(point);
3902
0
}
3903
3904
} // namespace ::sd
3905
3906
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */