Coverage Report

Created: 2025-11-16 09:57

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