Update git submodules
[LibreOffice.git] / sd / source / ui / slideshow / showwin.cxx
blobf0dcd4857a170c371278b302415b4c90aab9c15a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
34 #include <helpids.h>
35 #include <strings.hrc>
37 #include <sal/log.hxx>
38 #include <utility>
39 #include <vcl/settings.hxx>
40 #include <vcl/virdev.hxx>
41 #include <tools/duration.hxx>
43 using namespace ::com::sun::star;
45 namespace sd {
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)
60 , mnFirstMouseMove(0)
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.
67 EnableRTL (false);
69 MapMode aMap(GetMapMode());
70 aMap.SetMapUnit(MapUnit::Map100thMM);
71 SetMapMode(aMap);
73 // set HelpId
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!
83 GetParent()->Show();
84 AddEventListener( LINK( this, ShowWindow, EventHdl ) );
87 ShowWindow::~ShowWindow()
89 disposeOnce();
92 void ShowWindow::dispose()
94 maPauseTimer.Stop();
95 maMouseTimer.Stop();
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;
104 if (bFakeKeyPress)
105 return;
107 bool bReturn = false;
109 if( SHOWWINDOWMODE_PREVIEW == meShowWindowMode )
111 TerminateShow();
112 bReturn = true;
114 else if( SHOWWINDOWMODE_END == meShowWindowMode )
116 const int nKeyCode = rKEvt.GetKeyCode().GetCode();
117 switch( nKeyCode )
119 case KEY_PAGEUP:
120 case KEY_LEFT:
121 case KEY_UP:
122 case KEY_P:
123 case KEY_HOME:
124 case KEY_END:
125 case awt::Key::CONTEXTMENU:
126 // these keys will be handled by the slide show even
127 // while in end mode
128 break;
129 default:
130 TerminateShow();
131 bReturn = true;
134 else if( SHOWWINDOWMODE_BLANK == meShowWindowMode )
136 RestartShow();
137 bReturn = true;
139 else if( SHOWWINDOWMODE_PAUSE == meShowWindowMode )
141 const int nKeyCode = rKEvt.GetKeyCode().GetCode();
142 switch( nKeyCode )
144 case KEY_ESCAPE:
145 TerminateShow();
146 bReturn = true;
147 break;
148 case KEY_PAGEUP:
149 case KEY_RIGHT:
150 case KEY_UP:
151 case KEY_P:
152 case KEY_HOME:
153 case KEY_END:
154 case awt::Key::CONTEXTMENU:
155 // these keys will be handled by the slide show even
156 // while in end mode
157 break;
158 default:
159 RestartShow();
160 bReturn = true;
161 break;
165 if( !bReturn )
167 if( mxController.is() )
168 bReturn = mxController->keyInput(rKEvt);
170 if( !bReturn )
172 if( mpViewShell )
174 mpViewShell->KeyInput(rKEvt,this);
176 else
178 Window::KeyInput(rKEvt);
183 if( mpViewShell )
184 mpViewShell->SetActiveWindow( this );
187 void ShowWindow::MouseButtonDown(const MouseEvent& /*rMEvt*/)
189 if( SHOWWINDOWMODE_PREVIEW == meShowWindowMode )
191 TerminateShow();
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 )
212 ShowPointer( true );
213 mnFirstMouseMove = 0;
214 mbMouseCursorHidden = false;
215 maMouseTimer.SetTimeout( HIDE_MOUSE_TIMEOUT );
216 maMouseTimer.Start();
219 else
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();
229 else
231 // current mousemove restarts the idle timer to hide the mouse
232 maMouseTimer.Start();
236 if( mpViewShell )
237 mpViewShell->SetActiveWindow( this );
240 void ShowWindow::MouseButtonUp(const MouseEvent& rMEvt)
242 if( SHOWWINDOWMODE_PREVIEW == meShowWindowMode )
244 TerminateShow();
246 else if( (SHOWWINDOWMODE_END == meShowWindowMode) && !rMEvt.IsRight() )
248 TerminateShow();
250 else if( (( SHOWWINDOWMODE_BLANK == meShowWindowMode ) || ( SHOWWINDOWMODE_PAUSE == meShowWindowMode ))
251 && !rMEvt.IsRight() )
253 RestartShow();
255 else
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);
278 else
280 GetOutDev()->DrawWallpaper( rRect, maShowBackground );
282 if( SHOWWINDOWMODE_END == meShowWindowMode )
284 DrawEndScene();
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()
299 Window::LoseFocus();
301 if( SHOWWINDOWMODE_PREVIEW == meShowWindowMode)
302 TerminateShow();
305 void ShowWindow::SetEndMode()
307 if( !(( SHOWWINDOWMODE_NORMAL == meShowWindowMode ) && mpViewShell && mpViewShell->GetView()) )
308 return;
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;
321 Invalidate();
324 bool ShowWindow::SetPauseMode( sal_Int32 nTimeout, Graphic const * pLogo )
326 rtl::Reference< SlideShow > xSlideShow;
328 if( mpViewShell )
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;
350 if( pLogo )
351 maLogo = *pLogo;
353 Invalidate();
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;
378 Invalidate();
381 return( SHOWWINDOWMODE_BLANK == meShowWindowMode );
384 void ShowWindow::SetPreviewMode()
386 meShowWindowMode = SHOWWINDOWMODE_PREVIEW;
389 void ShowWindow::TerminateShow()
391 maLogo.Clear();
392 maPauseTimer.Stop();
393 maMouseTimer.Stop();
394 GetOutDev()->Erase();
395 maShowBackground = Wallpaper( COL_BLACK );
396 meShowWindowMode = SHOWWINDOWMODE_NORMAL;
397 mnPauseTimeout = SLIDE_NO_TIMEOUT;
399 if( mpViewShell )
401 // show navigator?
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;
424 maLogo.Clear();
425 maPauseTimer.Stop();
426 GetOutDev()->Erase();
427 maShowBackground = Wallpaper( COL_BLACK );
428 meShowWindowMode = SHOWWINDOWMODE_NORMAL;
429 mnPauseTimeout = SLIDE_NO_TIMEOUT;
431 if( mpViewShell )
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);
442 Invalidate();
444 else
446 xSlideShow->jumpToPageIndex( nPageIndexToRestart );
451 mnRestartPageIndex = PAGE_NO_END;
453 // show navigator?
454 if( mbShowNavigatorAfterSpecialMode )
456 if (mpViewShell)
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 ) );
470 bool bDrawn = false;
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 ) )
482 Size aGrfSize;
484 if (maLogo.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel)
485 aGrfSize = PixelToLogic( maLogo.GetPrefSize() );
486 else
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));
494 else
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 );
521 bDrawn = true;
525 if( !bDrawn )
527 SetFont( aFont );
528 GetOutDev()->DrawText( Point( aOutOrg.X() + aOffset.Width(), aOutOrg.Y() + aOffset.Height() ), aText );
529 SetFont( aOldFont );
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() );
546 SetFont( aFont );
547 GetOutDev()->DrawText( Point( aOutOrg.X() + aTextSize.Height(), aOutOrg.Y() + aTextSize.Height() ), aText );
548 SetFont( aOldFont );
551 IMPL_LINK( ShowWindow, PauseTimeoutHdl, Timer*, pTimer, void )
553 if( !( --mnPauseTimeout ) )
554 RestartShow();
555 else
557 DrawPauseScene( true );
558 pTimer->Start();
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;
570 else
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();
596 while (nChild)
598 --nChild;
599 GetChild(nChild)->Show( false );
603 void ShowWindow::AddWindowToPaintView()
605 if( mpViewShell->GetView() )
606 mpViewShell->GetView()->AddDeviceToPaintView( *GetOutDev(), nullptr );
608 sal_uInt16 nChild = GetChildCount();
609 while (nChild)
611 --nChild;
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);
621 if (xAcc)
623 return xAcc;
625 if (mpViewShell != nullptr)
627 xAcc = mpViewShell->CreateAccessibleDocumentView (this);
628 SetAccessible(xAcc);
629 return xAcc;
631 else
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: */