1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/awt/Key.hpp>
22 #include "showwindow.hxx"
23 #include "slideshowimpl.hxx"
25 #include <unotools/localedatawrapper.hxx>
26 #include <unotools/syslocale.hxx>
27 #include <sfx2/viewfrm.hxx>
28 #include <sfx2/sfxsids.hrc>
31 #include <slideshow.hxx>
32 #include <ViewShell.hxx>
33 #include <sdresid.hxx>
35 #include <strings.hrc>
37 #include <sal/log.hxx>
39 #include <vcl/settings.hxx>
40 #include <vcl/virdev.hxx>
41 #include <tools/duration.hxx>
43 using namespace ::com::sun::star
;
47 const sal_uInt64 HIDE_MOUSE_TIMEOUT
= 10000;
48 const sal_uInt64 SHOW_MOUSE_TIMEOUT
= 1000;
50 ShowWindow::ShowWindow( ::rtl::Reference
< SlideshowImpl
> xController
, vcl::Window
* pParent
)
51 : ::sd::Window( pParent
)
52 , maPauseTimer("sd ShowWindow maPauseTimer")
53 , maMouseTimer("sd ShowWindow maMouseTimer")
54 , mnPauseTimeout( SLIDE_NO_TIMEOUT
)
55 , mnRestartPageIndex( PAGE_NO_END
)
56 , meShowWindowMode(SHOWWINDOWMODE_NORMAL
)
57 , mbShowNavigatorAfterSpecialMode( false )
58 , mbMouseAutoHide(true)
59 , mbMouseCursorHidden(false)
61 , mxController(std::move( xController
))
63 GetOutDev()->SetOutDevViewType( OutDevViewType::SlideShow
);
65 // Do never mirror the preview window. This explicitly includes right
66 // to left writing environments.
69 MapMode
aMap(GetMapMode());
70 aMap
.SetMapUnit(MapUnit::Map100thMM
);
74 SetHelpId( HID_SD_WIN_PRESENTATION
);
76 maPauseTimer
.SetInvokeHandler( LINK( this, ShowWindow
, PauseTimeoutHdl
) );
77 maPauseTimer
.SetTimeout( 1000 );
78 maMouseTimer
.SetInvokeHandler( LINK( this, ShowWindow
, MouseTimeoutHdl
) );
79 maMouseTimer
.SetTimeout( HIDE_MOUSE_TIMEOUT
);
81 maShowBackground
= Wallpaper( COL_BLACK
);
82 SetBackground(); // avoids that VCL paints any background!
84 AddEventListener( LINK( this, ShowWindow
, EventHdl
) );
87 ShowWindow::~ShowWindow()
92 void ShowWindow::dispose()
96 ::sd::Window::dispose();
99 void ShowWindow::KeyInput(const KeyEvent
& rKEvt
)
101 // Ignore workaround of https://gitlab.gnome.org/GNOME/gtk/issues/1785
102 // See calls to GtkSalFrame::makeFakeKeyPress (Fixed in GTK 3.24)
103 bool bFakeKeyPress
= rKEvt
.GetKeyCode().GetFullCode() == 0;
107 bool bReturn
= false;
109 if( SHOWWINDOWMODE_PREVIEW
== meShowWindowMode
)
114 else if( SHOWWINDOWMODE_END
== meShowWindowMode
)
116 const int nKeyCode
= rKEvt
.GetKeyCode().GetCode();
125 case awt::Key::CONTEXTMENU
:
126 // these keys will be handled by the slide show even
134 else if( SHOWWINDOWMODE_BLANK
== meShowWindowMode
)
139 else if( SHOWWINDOWMODE_PAUSE
== meShowWindowMode
)
141 const int nKeyCode
= rKEvt
.GetKeyCode().GetCode();
154 case awt::Key::CONTEXTMENU
:
155 // these keys will be handled by the slide show even
167 if( mxController
.is() )
168 bReturn
= mxController
->keyInput(rKEvt
);
174 mpViewShell
->KeyInput(rKEvt
,this);
178 Window::KeyInput(rKEvt
);
184 mpViewShell
->SetActiveWindow( this );
187 void ShowWindow::MouseButtonDown(const MouseEvent
& /*rMEvt*/)
189 if( SHOWWINDOWMODE_PREVIEW
== meShowWindowMode
)
193 else if( mpViewShell
)
195 mpViewShell
->SetActiveWindow( this );
199 void ShowWindow::MouseMove(const MouseEvent
& /*rMEvt*/)
201 if( mbMouseAutoHide
)
203 if( mbMouseCursorHidden
)
205 if( mnFirstMouseMove
)
207 // if this is not the first mouse move while hidden, see if
208 // enough time has pasted to show mouse pointer again
209 sal_uInt64 nTime
= ::tools::Time::GetSystemTicks();
210 if( (nTime
- mnFirstMouseMove
) >= SHOW_MOUSE_TIMEOUT
)
213 mnFirstMouseMove
= 0;
214 mbMouseCursorHidden
= false;
215 maMouseTimer
.SetTimeout( HIDE_MOUSE_TIMEOUT
);
216 maMouseTimer
.Start();
221 // if this is the first mouse move, note current
222 // time and start idle timer to cancel show mouse pointer
223 // again if not enough mouse movement is measured
224 mnFirstMouseMove
= ::tools::Time::GetSystemTicks();
225 maMouseTimer
.SetTimeout( 2*SHOW_MOUSE_TIMEOUT
);
226 maMouseTimer
.Start();
231 // current mousemove restarts the idle timer to hide the mouse
232 maMouseTimer
.Start();
237 mpViewShell
->SetActiveWindow( this );
240 void ShowWindow::MouseButtonUp(const MouseEvent
& rMEvt
)
242 if( SHOWWINDOWMODE_PREVIEW
== meShowWindowMode
)
246 else if( (SHOWWINDOWMODE_END
== meShowWindowMode
) && !rMEvt
.IsRight() )
250 else if( (( SHOWWINDOWMODE_BLANK
== meShowWindowMode
) || ( SHOWWINDOWMODE_PAUSE
== meShowWindowMode
))
251 && !rMEvt
.IsRight() )
257 if( mxController
.is() )
258 mxController
->mouseButtonUp( rMEvt
);
263 * if FuSlideShow is still available, forward it
265 void ShowWindow::Paint(vcl::RenderContext
& /*rRenderContext*/, const ::tools::Rectangle
& rRect
)
267 if( (meShowWindowMode
== SHOWWINDOWMODE_NORMAL
) || (meShowWindowMode
== SHOWWINDOWMODE_PREVIEW
) )
269 if( mxController
.is() )
271 mxController
->paint();
273 else if(mpViewShell
)
275 mpViewShell
->Paint(rRect
, this);
280 GetOutDev()->DrawWallpaper( rRect
, maShowBackground
);
282 if( SHOWWINDOWMODE_END
== meShowWindowMode
)
286 else if( SHOWWINDOWMODE_PAUSE
== meShowWindowMode
)
288 DrawPauseScene( false );
290 else if( SHOWWINDOWMODE_BLANK
== meShowWindowMode
)
292 // just blank through background color => nothing to be done here
297 void ShowWindow::LoseFocus()
301 if( SHOWWINDOWMODE_PREVIEW
== meShowWindowMode
)
305 void ShowWindow::SetEndMode()
307 if( !(( SHOWWINDOWMODE_NORMAL
== meShowWindowMode
) && mpViewShell
&& mpViewShell
->GetView()) )
310 DeleteWindowFromPaintView();
311 meShowWindowMode
= SHOWWINDOWMODE_END
;
312 maShowBackground
= Wallpaper( COL_BLACK
);
314 // hide navigator if it is visible
315 if( mpViewShell
->GetViewFrame()->GetChildWindow( SID_NAVIGATOR
) )
317 mpViewShell
->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR
, false );
318 mbShowNavigatorAfterSpecialMode
= true;
324 bool ShowWindow::SetPauseMode( sal_Int32 nTimeout
, Graphic
const * pLogo
)
326 rtl::Reference
< SlideShow
> xSlideShow
;
329 xSlideShow
= SlideShow::GetSlideShow( mpViewShell
->GetViewShellBase() );
331 if( xSlideShow
.is() && !nTimeout
)
333 xSlideShow
->jumpToPageIndex( 0 );
335 else if( ( SHOWWINDOWMODE_NORMAL
== meShowWindowMode
) && mpViewShell
&& mpViewShell
->GetView() )
337 DeleteWindowFromPaintView();
338 mnPauseTimeout
= nTimeout
;
339 mnRestartPageIndex
= 0;
340 meShowWindowMode
= SHOWWINDOWMODE_PAUSE
;
341 maShowBackground
= Wallpaper( COL_BLACK
);
343 // hide navigator if it is visible
344 if( mpViewShell
->GetViewFrame()->GetChildWindow( SID_NAVIGATOR
) )
346 mpViewShell
->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR
, false );
347 mbShowNavigatorAfterSpecialMode
= true;
355 if( SLIDE_NO_TIMEOUT
!= mnPauseTimeout
)
356 maPauseTimer
.Start();
359 return( SHOWWINDOWMODE_PAUSE
== meShowWindowMode
);
362 bool ShowWindow::SetBlankMode( sal_Int32 nPageIndexToRestart
, const Color
& rBlankColor
)
364 if( ( SHOWWINDOWMODE_NORMAL
== meShowWindowMode
) && mpViewShell
&& mpViewShell
->GetView() )
366 DeleteWindowFromPaintView();
367 mnRestartPageIndex
= nPageIndexToRestart
;
368 meShowWindowMode
= SHOWWINDOWMODE_BLANK
;
369 maShowBackground
= Wallpaper( rBlankColor
);
371 // hide navigator if it is visible
372 if( mpViewShell
->GetViewFrame()->GetChildWindow( SID_NAVIGATOR
) )
374 mpViewShell
->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR
, false );
375 mbShowNavigatorAfterSpecialMode
= true;
381 return( SHOWWINDOWMODE_BLANK
== meShowWindowMode
);
384 void ShowWindow::SetPreviewMode()
386 meShowWindowMode
= SHOWWINDOWMODE_PREVIEW
;
389 void ShowWindow::TerminateShow()
394 GetOutDev()->Erase();
395 maShowBackground
= Wallpaper( COL_BLACK
);
396 meShowWindowMode
= SHOWWINDOWMODE_NORMAL
;
397 mnPauseTimeout
= SLIDE_NO_TIMEOUT
;
402 if( mbShowNavigatorAfterSpecialMode
)
404 mpViewShell
->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR
);
405 mbShowNavigatorAfterSpecialMode
= false;
409 if( mxController
.is() )
410 mxController
->endPresentation();
412 mnRestartPageIndex
= PAGE_NO_END
;
415 void ShowWindow::RestartShow()
417 RestartShow( mnRestartPageIndex
);
420 void ShowWindow::RestartShow( sal_Int32 nPageIndexToRestart
)
422 ShowWindowMode eOldShowWindowMode
= meShowWindowMode
;
426 GetOutDev()->Erase();
427 maShowBackground
= Wallpaper( COL_BLACK
);
428 meShowWindowMode
= SHOWWINDOWMODE_NORMAL
;
429 mnPauseTimeout
= SLIDE_NO_TIMEOUT
;
433 rtl::Reference
< SlideShow
> xSlideShow( SlideShow::GetSlideShow( mpViewShell
->GetViewShellBase() ) );
435 if( xSlideShow
.is() )
437 AddWindowToPaintView();
439 if( SHOWWINDOWMODE_BLANK
== eOldShowWindowMode
|| SHOWWINDOWMODE_END
== eOldShowWindowMode
)
441 xSlideShow
->pause(false);
446 xSlideShow
->jumpToPageIndex( nPageIndexToRestart
);
451 mnRestartPageIndex
= PAGE_NO_END
;
454 if( mbShowNavigatorAfterSpecialMode
)
457 mpViewShell
->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR
);
458 mbShowNavigatorAfterSpecialMode
= false;
462 void ShowWindow::DrawPauseScene( bool bTimeoutOnly
)
464 const MapMode
& rMap
= GetMapMode();
465 const Point
aOutOrg( PixelToLogic( Point() ) );
466 const Size
aOutSize( GetOutDev()->GetOutputSize() );
467 const Size
aTextSize(OutputDevice::LogicToLogic(Size(0, 14), MapMode(MapUnit::MapPoint
), rMap
));
468 const Size
aOffset(OutputDevice::LogicToLogic(Size(1000, 1000), MapMode(MapUnit::Map100thMM
), rMap
));
469 OUString
aText( SdResId( STR_PRES_PAUSE
) );
472 vcl::Font
aFont( GetSettings().GetStyleSettings().GetMenuFont() );
473 const vcl::Font
aOldFont( GetFont() );
475 aFont
.SetFontSize( aTextSize
);
476 aFont
.SetColor( COL_WHITE
);
477 aFont
.SetCharSet( aOldFont
.GetCharSet() );
478 aFont
.SetLanguage( aOldFont
.GetLanguage() );
480 if( !bTimeoutOnly
&& ( maLogo
.GetType() != GraphicType::NONE
) )
484 if (maLogo
.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel
)
485 aGrfSize
= PixelToLogic( maLogo
.GetPrefSize() );
487 aGrfSize
= OutputDevice::LogicToLogic( maLogo
.GetPrefSize(), maLogo
.GetPrefMapMode(), rMap
);
489 const Point
aGrfPos( std::max( aOutOrg
.X() + aOutSize
.Width() - aGrfSize
.Width() - aOffset
.Width(), aOutOrg
.X() ),
490 std::max( aOutOrg
.Y() + aOutSize
.Height() - aGrfSize
.Height() - aOffset
.Height(), aOutOrg
.Y() ) );
492 if( maLogo
.IsAnimated() )
493 maLogo
.StartAnimation(*GetOutDev(), aGrfPos
, aGrfSize
, reinterpret_cast<sal_IntPtr
>(this));
495 maLogo
.Draw(*GetOutDev(), aGrfPos
, aGrfSize
);
498 if( SLIDE_NO_TIMEOUT
!= mnPauseTimeout
)
500 MapMode
aVMap( rMap
);
501 ScopedVclPtrInstance
< VirtualDevice
> pVDev( *GetOutDev() );
503 aVMap
.SetOrigin( Point() );
504 pVDev
->SetMapMode( aVMap
);
505 pVDev
->SetBackground( Wallpaper( COL_BLACK
) );
507 // set font first, to determine real output height
508 pVDev
->SetFont( aFont
);
510 const Size
aVDevSize( aOutSize
.Width(), pVDev
->GetTextHeight() );
512 if( pVDev
->SetOutputSize( aVDevSize
) )
514 // Note: if performance gets an issue here, we can use NumberFormatter directly
515 SvtSysLocale aSysLocale
;
516 const LocaleDataWrapper
& aLocaleData
= aSysLocale
.GetLocaleData();
518 aText
+= " ( " + aLocaleData
.getDuration( ::tools::Duration( 0, 0, 0, mnPauseTimeout
, 0 )) + " )";
519 pVDev
->DrawText( Point( aOffset
.Width(), 0 ), aText
);
520 GetOutDev()->DrawOutDev( Point( aOutOrg
.X(), aOffset
.Height() ), aVDevSize
, Point(), aVDevSize
, *pVDev
);
528 GetOutDev()->DrawText( Point( aOutOrg
.X() + aOffset
.Width(), aOutOrg
.Y() + aOffset
.Height() ), aText
);
533 void ShowWindow::DrawEndScene()
535 const vcl::Font
aOldFont( GetFont() );
536 vcl::Font
aFont( GetSettings().GetStyleSettings().GetMenuFont() );
538 const Point
aOutOrg( PixelToLogic( Point() ) );
539 const Size
aTextSize(OutputDevice::LogicToLogic(Size(0, 14), MapMode(MapUnit::MapPoint
), GetMapMode()));
540 const OUString
aText( SdResId( STR_PRES_SOFTEND
) );
542 aFont
.SetFontSize( aTextSize
);
543 aFont
.SetColor( COL_WHITE
);
544 aFont
.SetCharSet( aOldFont
.GetCharSet() );
545 aFont
.SetLanguage( aOldFont
.GetLanguage() );
547 GetOutDev()->DrawText( Point( aOutOrg
.X() + aTextSize
.Height(), aOutOrg
.Y() + aTextSize
.Height() ), aText
);
551 IMPL_LINK( ShowWindow
, PauseTimeoutHdl
, Timer
*, pTimer
, void )
553 if( !( --mnPauseTimeout
) )
557 DrawPauseScene( true );
562 IMPL_LINK_NOARG(ShowWindow
, MouseTimeoutHdl
, Timer
*, void)
564 if( mbMouseCursorHidden
)
566 // not enough mouse movements since first recording so
567 // cancel show mouse pointer for now
568 mnFirstMouseMove
= 0;
572 // mouse has been idle too long, hide pointer
573 ShowPointer( false );
574 mbMouseCursorHidden
= true;
578 IMPL_LINK( ShowWindow
, EventHdl
, VclWindowEvent
&, rEvent
, void )
580 if( mbMouseAutoHide
)
582 if (rEvent
.GetId() == VclEventId::WindowShow
)
584 maMouseTimer
.SetTimeout( HIDE_MOUSE_TIMEOUT
);
585 maMouseTimer
.Start();
590 void ShowWindow::DeleteWindowFromPaintView()
592 if( mpViewShell
->GetView() )
593 mpViewShell
->GetView()->DeleteDeviceFromPaintView( *GetOutDev() );
595 sal_uInt16 nChild
= GetChildCount();
599 GetChild(nChild
)->Show( false );
603 void ShowWindow::AddWindowToPaintView()
605 if( mpViewShell
->GetView() )
606 mpViewShell
->GetView()->AddDeviceToPaintView( *GetOutDev(), nullptr );
608 sal_uInt16 nChild
= GetChildCount();
612 GetChild(nChild
)->Show();
616 // Override the sd::Window's CreateAccessible to create a different accessible object
617 css::uno::Reference
<css::accessibility::XAccessible
>
618 ShowWindow::CreateAccessible()
620 css::uno::Reference
< css::accessibility::XAccessible
> xAcc
= GetAccessible(false);
625 if (mpViewShell
!= nullptr)
627 xAcc
= mpViewShell
->CreateAccessibleDocumentView (this);
633 SAL_WARN("sd", "::sd::Window::CreateAccessible: no view shell");
634 return vcl::Window::CreateAccessible ();
637 } // end of namespace sd
639 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */