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 <com/sun/star/awt/Key.hpp> 21 22 #include "showwindow.hxx" 23 #include "slideshowimpl.hxx" 24 25 #include <unotools/localedatawrapper.hxx> 26 #include <unotools/syslocale.hxx> 27 #include <sfx2/viewfrm.hxx> 28 #include <sfx2/sfxsids.hrc> 29 30 31 #include <slideshow.hxx> 32 #include <ViewShell.hxx> 33 #include <sdresid.hxx> 34 #include <helpids.h> 35 #include <strings.hrc> 36 37 #include <sal/log.hxx> 38 #include <vcl/settings.hxx> 39 #include <vcl/virdev.hxx> 40 41 using namespace ::com::sun::star; 42 43 namespace sd { 44 45 static const sal_uInt64 HIDE_MOUSE_TIMEOUT = 10000; 46 static const sal_uInt64 SHOW_MOUSE_TIMEOUT = 1000; 47 48 ShowWindow::ShowWindow( const ::rtl::Reference< SlideshowImpl >& xController, vcl::Window* pParent ) 49 : ::sd::Window( pParent ) 50 , mnPauseTimeout( SLIDE_NO_TIMEOUT ) 51 , mnRestartPageIndex( PAGE_NO_END ) 52 , meShowWindowMode(SHOWWINDOWMODE_NORMAL) 53 , mbShowNavigatorAfterSpecialMode( false ) 54 , mbMouseAutoHide(true) 55 , mbMouseCursorHidden(false) 56 , mnFirstMouseMove(0) 57 , mxController( xController ) 58 { 59 SetOutDevViewType( OutDevViewType::SlideShow ); 60 61 // Do never mirror the preview window. This explicitly includes right 62 // to left writing environments. 63 EnableRTL (false); 64 65 MapMode aMap(GetMapMode()); 66 aMap.SetMapUnit(MapUnit::Map100thMM); 67 SetMapMode(aMap); 68 69 // set HelpId 70 SetHelpId( HID_SD_WIN_PRESENTATION ); 71 72 maPauseTimer.SetInvokeHandler( LINK( this, ShowWindow, PauseTimeoutHdl ) ); 73 maPauseTimer.SetTimeout( 1000 ); 74 maMouseTimer.SetInvokeHandler( LINK( this, ShowWindow, MouseTimeoutHdl ) ); 75 maMouseTimer.SetTimeout( HIDE_MOUSE_TIMEOUT ); 76 77 maShowBackground = Wallpaper( COL_BLACK ); 78 SetBackground(); // avoids that VCL paints any background! 79 GetParent()->Show(); 80 AddEventListener( LINK( this, ShowWindow, EventHdl ) ); 81 } 82 83 ShowWindow::~ShowWindow() 84 { 85 disposeOnce(); 86 } 87 88 void ShowWindow::dispose() 89 { 90 maPauseTimer.Stop(); 91 maMouseTimer.Stop(); 92 ::sd::Window::dispose(); 93 } 94 95 void ShowWindow::KeyInput(const KeyEvent& rKEvt) 96 { 97 bool bReturn = false; 98 99 if( SHOWWINDOWMODE_PREVIEW == meShowWindowMode ) 100 { 101 TerminateShow(); 102 bReturn = true; 103 } 104 else if( SHOWWINDOWMODE_END == meShowWindowMode ) 105 { 106 const int nKeyCode = rKEvt.GetKeyCode().GetCode(); 107 switch( nKeyCode ) 108 { 109 case KEY_PAGEUP: 110 case KEY_LEFT: 111 case KEY_UP: 112 case KEY_P: 113 case KEY_HOME: 114 case KEY_END: 115 case awt::Key::CONTEXTMENU: 116 // these keys will be handled by the slide show even 117 // while in end mode 118 break; 119 default: 120 TerminateShow(); 121 bReturn = true; 122 } 123 } 124 else if( SHOWWINDOWMODE_BLANK == meShowWindowMode ) 125 { 126 RestartShow(); 127 bReturn = true; 128 } 129 else if( SHOWWINDOWMODE_PAUSE == meShowWindowMode ) 130 { 131 const int nKeyCode = rKEvt.GetKeyCode().GetCode(); 132 switch( nKeyCode ) 133 { 134 case KEY_ESCAPE: 135 TerminateShow(); 136 bReturn = true; 137 break; 138 case KEY_PAGEUP: 139 case KEY_RIGHT: 140 case KEY_UP: 141 case KEY_P: 142 case KEY_HOME: 143 case KEY_END: 144 case awt::Key::CONTEXTMENU: 145 // these keys will be handled by the slide show even 146 // while in end mode 147 break; 148 default: 149 RestartShow(); 150 bReturn = true; 151 break; 152 } 153 } 154 155 if( !bReturn ) 156 { 157 if( mxController.is() ) 158 bReturn = mxController->keyInput(rKEvt); 159 160 if( !bReturn ) 161 { 162 if( mpViewShell ) 163 { 164 mpViewShell->KeyInput(rKEvt,this); 165 } 166 else 167 { 168 Window::KeyInput(rKEvt); 169 } 170 } 171 } 172 173 if( mpViewShell ) 174 mpViewShell->SetActiveWindow( this ); 175 } 176 177 void ShowWindow::MouseButtonDown(const MouseEvent& /*rMEvt*/) 178 { 179 if( SHOWWINDOWMODE_PREVIEW == meShowWindowMode ) 180 { 181 TerminateShow(); 182 } 183 else if( mpViewShell ) 184 { 185 mpViewShell->SetActiveWindow( this ); 186 } 187 } 188 189 void ShowWindow::MouseMove(const MouseEvent& /*rMEvt*/) 190 { 191 if( mbMouseAutoHide ) 192 { 193 if( mbMouseCursorHidden ) 194 { 195 if( mnFirstMouseMove ) 196 { 197 // if this is not the first mouse move while hidden, see if 198 // enough time has pasted to show mouse pointer again 199 sal_uInt64 nTime = ::tools::Time::GetSystemTicks(); 200 if( (nTime - mnFirstMouseMove) >= SHOW_MOUSE_TIMEOUT ) 201 { 202 ShowPointer( true ); 203 mnFirstMouseMove = 0; 204 mbMouseCursorHidden = false; 205 maMouseTimer.SetTimeout( HIDE_MOUSE_TIMEOUT ); 206 maMouseTimer.Start(); 207 } 208 } 209 else 210 { 211 // if this is the first mouse move, note current 212 // time and start idle timer to cancel show mouse pointer 213 // again if not enough mouse movement is measured 214 mnFirstMouseMove = ::tools::Time::GetSystemTicks(); 215 maMouseTimer.SetTimeout( 2*SHOW_MOUSE_TIMEOUT ); 216 maMouseTimer.Start(); 217 } 218 } 219 else 220 { 221 // current mousemove restarts the idle timer to hide the mouse 222 maMouseTimer.Start(); 223 } 224 } 225 226 if( mpViewShell ) 227 mpViewShell->SetActiveWindow( this ); 228 } 229 230 void ShowWindow::MouseButtonUp(const MouseEvent& rMEvt) 231 { 232 if( SHOWWINDOWMODE_PREVIEW == meShowWindowMode ) 233 { 234 TerminateShow(); 235 } 236 else if( (SHOWWINDOWMODE_END == meShowWindowMode) && !rMEvt.IsRight() ) 237 { 238 TerminateShow(); 239 } 240 else if( (( SHOWWINDOWMODE_BLANK == meShowWindowMode ) || ( SHOWWINDOWMODE_PAUSE == meShowWindowMode )) 241 && !rMEvt.IsRight() ) 242 { 243 RestartShow(); 244 } 245 else 246 { 247 if( mxController.is() ) 248 mxController->mouseButtonUp( rMEvt ); 249 } 250 } 251 252 /** 253 * if FuSlideShow is still available, forward it 254 */ 255 void ShowWindow::Paint(vcl::RenderContext& /*rRenderContext*/, const ::tools::Rectangle& rRect) 256 { 257 if( (meShowWindowMode == SHOWWINDOWMODE_NORMAL) || (meShowWindowMode == SHOWWINDOWMODE_PREVIEW) ) 258 { 259 if( mxController.is() ) 260 { 261 mxController->paint(); 262 } 263 else if(mpViewShell ) 264 { 265 mpViewShell->Paint(rRect, this); 266 } 267 } 268 else 269 { 270 DrawWallpaper( rRect, maShowBackground ); 271 272 if( SHOWWINDOWMODE_END == meShowWindowMode ) 273 { 274 DrawEndScene(); 275 } 276 else if( SHOWWINDOWMODE_PAUSE == meShowWindowMode ) 277 { 278 DrawPauseScene( false ); 279 } 280 else if( SHOWWINDOWMODE_BLANK == meShowWindowMode ) 281 { 282 // just blank through background color => nothing to be done here 283 } 284 } 285 } 286 287 void ShowWindow::LoseFocus() 288 { 289 Window::LoseFocus(); 290 291 if( SHOWWINDOWMODE_PREVIEW == meShowWindowMode) 292 TerminateShow(); 293 } 294 295 void ShowWindow::SetEndMode() 296 { 297 if( !(( SHOWWINDOWMODE_NORMAL == meShowWindowMode ) && mpViewShell && mpViewShell->GetView()) ) 298 return; 299 300 DeleteWindowFromPaintView(); 301 meShowWindowMode = SHOWWINDOWMODE_END; 302 maShowBackground = Wallpaper( COL_BLACK ); 303 304 // hide navigator if it is visible 305 if( mpViewShell->GetViewFrame()->GetChildWindow( SID_NAVIGATOR ) ) 306 { 307 mpViewShell->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR, false ); 308 mbShowNavigatorAfterSpecialMode = true; 309 } 310 311 Invalidate(); 312 } 313 314 bool ShowWindow::SetPauseMode( sal_Int32 nTimeout, Graphic const * pLogo ) 315 { 316 rtl::Reference< SlideShow > xSlideShow; 317 318 if( mpViewShell ) 319 xSlideShow = SlideShow::GetSlideShow( mpViewShell->GetViewShellBase() ); 320 321 if( xSlideShow.is() && !nTimeout ) 322 { 323 xSlideShow->jumpToPageIndex( 0 ); 324 } 325 else if( ( SHOWWINDOWMODE_NORMAL == meShowWindowMode ) && mpViewShell && mpViewShell->GetView() ) 326 { 327 DeleteWindowFromPaintView(); 328 mnPauseTimeout = nTimeout; 329 mnRestartPageIndex = 0; 330 meShowWindowMode = SHOWWINDOWMODE_PAUSE; 331 maShowBackground = Wallpaper( COL_BLACK ); 332 333 // hide navigator if it is visible 334 if( mpViewShell->GetViewFrame()->GetChildWindow( SID_NAVIGATOR ) ) 335 { 336 mpViewShell->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR, false ); 337 mbShowNavigatorAfterSpecialMode = true; 338 } 339 340 if( pLogo ) 341 maLogo = *pLogo; 342 343 Invalidate(); 344 345 if( SLIDE_NO_TIMEOUT != mnPauseTimeout ) 346 maPauseTimer.Start(); 347 } 348 349 return( SHOWWINDOWMODE_PAUSE == meShowWindowMode ); 350 } 351 352 bool ShowWindow::SetBlankMode( sal_Int32 nPageIndexToRestart, const Color& rBlankColor ) 353 { 354 if( ( SHOWWINDOWMODE_NORMAL == meShowWindowMode ) && mpViewShell && mpViewShell->GetView() ) 355 { 356 DeleteWindowFromPaintView(); 357 mnRestartPageIndex = nPageIndexToRestart; 358 meShowWindowMode = SHOWWINDOWMODE_BLANK; 359 maShowBackground = Wallpaper( rBlankColor ); 360 361 // hide navigator if it is visible 362 if( mpViewShell->GetViewFrame()->GetChildWindow( SID_NAVIGATOR ) ) 363 { 364 mpViewShell->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR, false ); 365 mbShowNavigatorAfterSpecialMode = true; 366 } 367 368 Invalidate(); 369 } 370 371 return( SHOWWINDOWMODE_BLANK == meShowWindowMode ); 372 } 373 374 void ShowWindow::SetPreviewMode() 375 { 376 meShowWindowMode = SHOWWINDOWMODE_PREVIEW; 377 } 378 379 void ShowWindow::TerminateShow() 380 { 381 maLogo.Clear(); 382 maPauseTimer.Stop(); 383 maMouseTimer.Stop(); 384 Erase(); 385 maShowBackground = Wallpaper( COL_BLACK ); 386 meShowWindowMode = SHOWWINDOWMODE_NORMAL; 387 mnPauseTimeout = SLIDE_NO_TIMEOUT; 388 389 if( mpViewShell ) 390 { 391 // show navigator? 392 if( mbShowNavigatorAfterSpecialMode ) 393 { 394 mpViewShell->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR ); 395 mbShowNavigatorAfterSpecialMode = false; 396 } 397 } 398 399 if( mxController.is() ) 400 mxController->endPresentation(); 401 402 mnRestartPageIndex = PAGE_NO_END; 403 } 404 405 void ShowWindow::RestartShow() 406 { 407 RestartShow( mnRestartPageIndex ); 408 } 409 410 void ShowWindow::RestartShow( sal_Int32 nPageIndexToRestart ) 411 412 { 413 ShowWindowMode eOldShowWindowMode = meShowWindowMode; 414 415 maLogo.Clear(); 416 maPauseTimer.Stop(); 417 Erase(); 418 maShowBackground = Wallpaper( COL_BLACK ); 419 meShowWindowMode = SHOWWINDOWMODE_NORMAL; 420 mnPauseTimeout = SLIDE_NO_TIMEOUT; 421 422 if( mpViewShell ) 423 { 424 rtl::Reference< SlideShow > xSlideShow( SlideShow::GetSlideShow( mpViewShell->GetViewShellBase() ) ); 425 426 if( xSlideShow.is() ) 427 { 428 AddWindowToPaintView(); 429 430 if( SHOWWINDOWMODE_BLANK == eOldShowWindowMode ) 431 { 432 xSlideShow->pause(false); 433 Invalidate(); 434 } 435 else 436 { 437 xSlideShow->jumpToPageIndex( nPageIndexToRestart ); 438 } 439 } 440 } 441 442 mnRestartPageIndex = PAGE_NO_END; 443 444 // show navigator? 445 if( mbShowNavigatorAfterSpecialMode ) 446 { 447 if (mpViewShell) 448 mpViewShell->GetViewFrame()->ShowChildWindow( SID_NAVIGATOR ); 449 mbShowNavigatorAfterSpecialMode = false; 450 } 451 } 452 453 void ShowWindow::DrawPauseScene( bool bTimeoutOnly ) 454 { 455 const MapMode& rMap = GetMapMode(); 456 const Point aOutOrg( PixelToLogic( Point() ) ); 457 const Size aOutSize( GetOutputSize() ); 458 const Size aTextSize(LogicToLogic(Size(0, 14), MapMode(MapUnit::MapPoint), rMap)); 459 const Size aOffset(LogicToLogic(Size(1000, 1000), MapMode(MapUnit::Map100thMM), rMap)); 460 OUString aText( SdResId( STR_PRES_PAUSE ) ); 461 bool bDrawn = false; 462 463 vcl::Font aFont( GetSettings().GetStyleSettings().GetMenuFont() ); 464 const vcl::Font aOldFont( GetFont() ); 465 466 aFont.SetFontSize( aTextSize ); 467 aFont.SetColor( COL_WHITE ); 468 aFont.SetCharSet( aOldFont.GetCharSet() ); 469 aFont.SetLanguage( aOldFont.GetLanguage() ); 470 471 if( !bTimeoutOnly && ( maLogo.GetType() != GraphicType::NONE ) ) 472 { 473 Size aGrfSize; 474 475 if (maLogo.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel) 476 aGrfSize = PixelToLogic( maLogo.GetPrefSize() ); 477 else 478 aGrfSize = LogicToLogic( maLogo.GetPrefSize(), maLogo.GetPrefMapMode(), rMap ); 479 480 const Point aGrfPos( std::max( aOutOrg.X() + aOutSize.Width() - aGrfSize.Width() - aOffset.Width(), aOutOrg.X() ), 481 std::max( aOutOrg.Y() + aOutSize.Height() - aGrfSize.Height() - aOffset.Height(), aOutOrg.Y() ) ); 482 483 if( maLogo.IsAnimated() ) 484 maLogo.StartAnimation( this, aGrfPos, aGrfSize, reinterpret_cast<sal_IntPtr>(this) ); 485 else 486 maLogo.Draw( this, aGrfPos, aGrfSize ); 487 } 488 489 if( SLIDE_NO_TIMEOUT != mnPauseTimeout ) 490 { 491 MapMode aVMap( rMap ); 492 ScopedVclPtrInstance< VirtualDevice > pVDev( *this ); 493 494 aVMap.SetOrigin( Point() ); 495 pVDev->SetMapMode( aVMap ); 496 pVDev->SetBackground( Wallpaper( COL_BLACK ) ); 497 498 // set font first, to determine real output height 499 pVDev->SetFont( aFont ); 500 501 const Size aVDevSize( aOutSize.Width(), pVDev->GetTextHeight() ); 502 503 if( pVDev->SetOutputSize( aVDevSize ) ) 504 { 505 // Note: if performance gets an issue here, we can use NumberFormatter directly 506 SvtSysLocale aSysLocale; 507 const LocaleDataWrapper& aLocaleData = aSysLocale.GetLocaleData(); 508 509 aText += " ( " + aLocaleData.getDuration( ::tools::Time( 0, 0, mnPauseTimeout ) ) + " )"; 510 pVDev->DrawText( Point( aOffset.Width(), 0 ), aText ); 511 DrawOutDev( Point( aOutOrg.X(), aOffset.Height() ), aVDevSize, Point(), aVDevSize, *pVDev ); 512 bDrawn = true; 513 } 514 } 515 516 if( !bDrawn ) 517 { 518 SetFont( aFont ); 519 DrawText( Point( aOutOrg.X() + aOffset.Width(), aOutOrg.Y() + aOffset.Height() ), aText ); 520 SetFont( aOldFont ); 521 } 522 } 523 524 void ShowWindow::DrawEndScene() 525 { 526 const vcl::Font aOldFont( GetFont() ); 527 vcl::Font aFont( GetSettings().GetStyleSettings().GetMenuFont() ); 528 529 const Point aOutOrg( PixelToLogic( Point() ) ); 530 const Size aTextSize(LogicToLogic(Size(0, 14), MapMode(MapUnit::MapPoint), GetMapMode())); 531 const OUString aText( SdResId( STR_PRES_SOFTEND ) ); 532 533 aFont.SetFontSize( aTextSize ); 534 aFont.SetColor( COL_WHITE ); 535 aFont.SetCharSet( aOldFont.GetCharSet() ); 536 aFont.SetLanguage( aOldFont.GetLanguage() ); 537 SetFont( aFont ); 538 DrawText( Point( aOutOrg.X() + aTextSize.Height(), aOutOrg.Y() + aTextSize.Height() ), aText ); 539 SetFont( aOldFont ); 540 } 541 542 IMPL_LINK( ShowWindow, PauseTimeoutHdl, Timer*, pTimer, void ) 543 { 544 if( !( --mnPauseTimeout ) ) 545 RestartShow(); 546 else 547 { 548 DrawPauseScene( true ); 549 pTimer->Start(); 550 } 551 } 552 553 IMPL_LINK_NOARG(ShowWindow, MouseTimeoutHdl, Timer *, void) 554 { 555 if( mbMouseCursorHidden ) 556 { 557 // not enough mouse movements since first recording so 558 // cancel show mouse pointer for now 559 mnFirstMouseMove = 0; 560 } 561 else 562 { 563 // mouse has been idle too long, hide pointer 564 ShowPointer( false ); 565 mbMouseCursorHidden = true; 566 } 567 } 568 569 IMPL_LINK( ShowWindow, EventHdl, VclWindowEvent&, rEvent, void ) 570 { 571 if( mbMouseAutoHide ) 572 { 573 if (rEvent.GetId() == VclEventId::WindowShow) 574 { 575 maMouseTimer.SetTimeout( HIDE_MOUSE_TIMEOUT ); 576 maMouseTimer.Start(); 577 } 578 } 579 } 580 581 void ShowWindow::DeleteWindowFromPaintView() 582 { 583 if( mpViewShell->GetView() ) 584 mpViewShell->GetView()->DeleteWindowFromPaintView( this ); 585 586 sal_uInt16 nChild = GetChildCount(); 587 while( nChild-- ) 588 GetChild( nChild )->Show( false ); 589 } 590 591 void ShowWindow::AddWindowToPaintView() 592 { 593 if( mpViewShell->GetView() ) 594 mpViewShell->GetView()->AddWindowToPaintView( this, nullptr ); 595 596 sal_uInt16 nChild = GetChildCount(); 597 while( nChild-- ) 598 GetChild( nChild )->Show(); 599 } 600 601 // Override the sd::Window's CreateAccessible to create a different accessible object 602 css::uno::Reference<css::accessibility::XAccessible> 603 ShowWindow::CreateAccessible() 604 { 605 css::uno::Reference< css::accessibility::XAccessible > xAcc = GetAccessible(false); 606 if (xAcc.get()) 607 { 608 return xAcc; 609 } 610 if (mpViewShell != nullptr) 611 { 612 xAcc = mpViewShell->CreateAccessibleDocumentView (this); 613 SetAccessible(xAcc); 614 return xAcc; 615 } 616 else 617 { 618 SAL_WARN("sd", "::sd::Window::CreateAccessible: no view shell"); 619 return vcl::Window::CreateAccessible (); 620 } 621 } 622 } // end of namespace sd 623 624 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 625
