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 <config_features.h> 21 22 #include <osl/file.hxx> 23 #include <osl/thread.hxx> 24 #include <osl/module.hxx> 25 26 #include <rtl/tencinfo.h> 27 #include <sal/log.hxx> 28 29 #include <tools/debug.hxx> 30 #include <tools/time.hxx> 31 #include <tools/stream.hxx> 32 33 #include <unotools/configmgr.hxx> 34 #include <unotools/syslocaleoptions.hxx> 35 36 #include <vcl/dialog.hxx> 37 #include <vcl/lok.hxx> 38 #include <vcl/floatwin.hxx> 39 #include <vcl/settings.hxx> 40 #include <vcl/keycod.hxx> 41 #include <vcl/event.hxx> 42 #include <vcl/vclevent.hxx> 43 #include <vcl/virdev.hxx> 44 #include <vcl/wrkwin.hxx> 45 #include <vcl/svapp.hxx> 46 #include <vcl/cvtgrf.hxx> 47 #include <vcl/toolkit/unowrap.hxx> 48 #include <vcl/timer.hxx> 49 #include <vcl/scheduler.hxx> 50 #if HAVE_FEATURE_OPENGL 51 #include <vcl/opengl/OpenGLWrapper.hxx> 52 #endif 53 54 #include <salinst.hxx> 55 #include <salframe.hxx> 56 #include <salsys.hxx> 57 #include <svdata.hxx> 58 #include <displayconnectiondispatch.hxx> 59 #include <window.h> 60 #include <accmgr.hxx> 61 #include <strings.hrc> 62 #include <strings.hxx> 63 #if OSL_DEBUG_LEVEL > 0 64 #include <schedulerimpl.hxx> 65 #endif 66 67 #include <com/sun/star/uno/Reference.h> 68 #include <com/sun/star/awt/XToolkit.hpp> 69 #include <comphelper/lok.hxx> 70 #include <comphelper/solarmutex.hxx> 71 #include <osl/process.h> 72 73 #include <cassert> 74 #include <utility> 75 #include <thread> 76 77 using namespace ::com::sun::star; 78 using namespace ::com::sun::star::uno; 79 80 namespace { 81 void InitSettings(ImplSVData* pSVData); 82 } 83 84 // keycodes handled internally by VCL 85 static vcl::KeyCode const ReservedKeys[] 86 { 87 vcl::KeyCode(KEY_F1,0) , 88 vcl::KeyCode(KEY_F1,KEY_SHIFT) , 89 vcl::KeyCode(KEY_F1,KEY_MOD1) , 90 vcl::KeyCode(KEY_F2,KEY_SHIFT) , 91 vcl::KeyCode(KEY_F4,KEY_MOD1) , 92 vcl::KeyCode(KEY_F4,KEY_MOD2) , 93 vcl::KeyCode(KEY_F4,KEY_MOD1|KEY_MOD2) , 94 vcl::KeyCode(KEY_F6,0) , 95 vcl::KeyCode(KEY_F6,KEY_MOD1) , 96 vcl::KeyCode(KEY_F6,KEY_SHIFT) , 97 vcl::KeyCode(KEY_F6,KEY_MOD1|KEY_SHIFT) , 98 vcl::KeyCode(KEY_F10,0) 99 #ifdef UNX 100 , 101 vcl::KeyCode(KEY_1,KEY_SHIFT|KEY_MOD1), 102 vcl::KeyCode(KEY_2,KEY_SHIFT|KEY_MOD1), 103 vcl::KeyCode(KEY_3,KEY_SHIFT|KEY_MOD1), 104 vcl::KeyCode(KEY_4,KEY_SHIFT|KEY_MOD1), 105 vcl::KeyCode(KEY_5,KEY_SHIFT|KEY_MOD1), 106 vcl::KeyCode(KEY_6,KEY_SHIFT|KEY_MOD1), 107 vcl::KeyCode(KEY_7,KEY_SHIFT|KEY_MOD1), 108 vcl::KeyCode(KEY_8,KEY_SHIFT|KEY_MOD1), 109 vcl::KeyCode(KEY_9,KEY_SHIFT|KEY_MOD1), 110 vcl::KeyCode(KEY_0,KEY_SHIFT|KEY_MOD1), 111 vcl::KeyCode(KEY_ADD,KEY_SHIFT|KEY_MOD1) 112 #endif 113 }; 114 115 extern "C" { 116 typedef UnoWrapperBase* (*FN_TkCreateUnoWrapper)(); 117 } 118 119 struct ImplPostEventData 120 { 121 VclEventId const mnEvent; 122 VclPtr<vcl::Window> mpWin; 123 ImplSVEvent * mnEventId; 124 KeyEvent maKeyEvent; 125 MouseEvent maMouseEvent; 126 GestureEvent maGestureEvent; 127 128 ImplPostEventData(VclEventId nEvent, vcl::Window* pWin, const KeyEvent& rKeyEvent) 129 : mnEvent(nEvent) 130 , mpWin(pWin) 131 , mnEventId(nullptr) 132 , maKeyEvent(rKeyEvent) 133 {} 134 ImplPostEventData(VclEventId nEvent, vcl::Window* pWin, const MouseEvent& rMouseEvent) 135 : mnEvent(nEvent) 136 , mpWin(pWin) 137 , mnEventId(nullptr) 138 , maMouseEvent(rMouseEvent) 139 {} 140 ImplPostEventData(VclEventId nEvent, vcl::Window* pWin, const GestureEvent& rGestureEvent) 141 : mnEvent(nEvent) 142 , mpWin(pWin) 143 , mnEventId(nullptr) 144 , maGestureEvent(rGestureEvent) 145 {} 146 }; 147 148 Application* GetpApp() 149 { 150 ImplSVData* pSVData = ImplGetSVData(); 151 if ( !pSVData ) 152 return nullptr; 153 return pSVData->mpApp; 154 } 155 156 Application::Application() 157 { 158 // useful for themes at least, perhaps extensions too 159 OUString aVar("LIBO_VERSION"), aValue(LIBO_VERSION_DOTTED); 160 osl_setEnvironment(aVar.pData, aValue.pData); 161 162 ImplGetSVData()->mpApp = this; 163 } 164 165 Application::~Application() 166 { 167 ImplDeInitSVData(); 168 ImplGetSVData()->mpApp = nullptr; 169 } 170 171 int Application::Main() 172 { 173 SAL_WARN("vcl", "Application is a base class and should be overridden."); 174 return EXIT_SUCCESS; 175 } 176 177 bool Application::QueryExit() 178 { 179 WorkWindow* pAppWin = ImplGetSVData()->maWinData.mpAppWin; 180 181 // call the close handler of the application window 182 if ( pAppWin ) 183 return pAppWin->Close(); 184 else 185 return true; 186 } 187 188 void Application::Init() 189 { 190 } 191 192 void Application::InitFinished() 193 { 194 } 195 196 void Application::DeInit() 197 { 198 } 199 200 sal_uInt16 Application::GetCommandLineParamCount() 201 { 202 return static_cast<sal_uInt16>(osl_getCommandArgCount()); 203 } 204 205 OUString Application::GetCommandLineParam( sal_uInt16 nParam ) 206 { 207 OUString aParam; 208 osl_getCommandArg( nParam, &aParam.pData ); 209 return aParam; 210 } 211 212 OUString Application::GetAppFileName() 213 { 214 ImplSVData* pSVData = ImplGetSVData(); 215 SAL_WARN_IF( !pSVData->maAppData.mxAppFileName, "vcl", "AppFileName should be set to something after SVMain!" ); 216 if ( pSVData->maAppData.mxAppFileName ) 217 return *pSVData->maAppData.mxAppFileName; 218 219 /* 220 * provide a fallback for people without initialized vcl here (like setup 221 * in responsefile mode) 222 */ 223 OUString aAppFileName; 224 OUString aExeFileName; 225 osl_getExecutableFile(&aExeFileName.pData); 226 227 // convert path to native file format 228 osl::FileBase::getSystemPathFromFileURL(aExeFileName, aAppFileName); 229 230 return aAppFileName; 231 } 232 233 void Application::Exception( ExceptionCategory nCategory ) 234 { 235 switch ( nCategory ) 236 { 237 // System has precedence (so do nothing) 238 case ExceptionCategory::System: 239 case ExceptionCategory::UserInterface: 240 break; 241 242 #ifdef DBG_UTIL 243 case ExceptionCategory::ResourceNotLoaded: 244 Abort("Resource not loaded"); 245 break; 246 default: 247 Abort("Unknown Error"); 248 break; 249 #else 250 default: 251 Abort(OUString()); 252 break; 253 #endif 254 } 255 } 256 257 void Application::Abort( const OUString& rErrorText ) 258 { 259 //HACK: Dump core iff --norestore command line argument is given (assuming 260 // this process is run by developers who are interested in cores, vs. end 261 // users who are not): 262 bool dumpCore = false; 263 sal_uInt16 n = GetCommandLineParamCount(); 264 for (sal_uInt16 i = 0; i != n; ++i) { 265 if (GetCommandLineParam(i) == "--norestore") { 266 dumpCore = true; 267 break; 268 } 269 } 270 #if OSL_DEBUG_LEVEL > 0 271 dumpCore = true; 272 #endif 273 274 SalAbort( rErrorText, dumpCore ); 275 } 276 277 sal_uLong Application::GetReservedKeyCodeCount() 278 { 279 return SAL_N_ELEMENTS(ReservedKeys); 280 } 281 282 const vcl::KeyCode* Application::GetReservedKeyCode( sal_uLong i ) 283 { 284 if( i >= GetReservedKeyCodeCount() ) 285 return nullptr; 286 else 287 return &ReservedKeys[i]; 288 } 289 290 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplEndAllPopupsMsg, void*, void ) 291 { 292 ImplSVData* pSVData = ImplGetSVData(); 293 while (pSVData->maWinData.mpFirstFloat) 294 pSVData->maWinData.mpFirstFloat->EndPopupMode(FloatWinPopupEndFlags::Cancel); 295 } 296 297 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplEndAllDialogsMsg, void*, void ) 298 { 299 vcl::Window* pAppWindow = Application::GetFirstTopLevelWindow(); 300 while (pAppWindow) 301 { 302 Dialog::EndAllDialogs(pAppWindow); 303 pAppWindow = Application::GetNextTopLevelWindow(pAppWindow); 304 } 305 } 306 307 void Application::EndAllDialogs() 308 { 309 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplEndAllDialogsMsg ) ); 310 } 311 312 void Application::EndAllPopups() 313 { 314 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplEndAllPopupsMsg ) ); 315 } 316 317 318 namespace 319 { 320 VclPtr<vcl::Window> GetEventWindow() 321 { 322 VclPtr<vcl::Window> xWin(Application::GetFirstTopLevelWindow()); 323 while (xWin) 324 { 325 if (xWin->IsVisible()) 326 break; 327 xWin.reset(Application::GetNextTopLevelWindow(xWin)); 328 } 329 return xWin; 330 } 331 332 bool InjectKeyEvent(SvStream& rStream) 333 { 334 VclPtr<vcl::Window> xWin(GetEventWindow()); 335 if (!xWin) 336 return false; 337 338 // skip the first available cycle and insert on the next one when we 339 // are trying the initial event, flagged by a triggered but undeleted 340 // mpEventTestingIdle 341 ImplSVData* pSVData = ImplGetSVData(); 342 if (pSVData->maAppData.mpEventTestingIdle) 343 { 344 delete pSVData->maAppData.mpEventTestingIdle; 345 pSVData->maAppData.mpEventTestingIdle = nullptr; 346 return false; 347 } 348 349 sal_uInt16 nCode, nCharCode; 350 rStream.ReadUInt16(nCode); 351 rStream.ReadUInt16(nCharCode); 352 if (!rStream.good()) 353 return false; 354 355 KeyEvent aVCLKeyEvt(nCharCode, nCode); 356 Application::PostKeyEvent(VclEventId::WindowKeyInput, xWin.get(), &aVCLKeyEvt); 357 Application::PostKeyEvent(VclEventId::WindowKeyUp, xWin.get(), &aVCLKeyEvt); 358 return true; 359 } 360 361 void CloseDialogsAndQuit() 362 { 363 Application::EndAllPopups(); 364 Application::EndAllDialogs(); 365 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplPrepareExitMsg ) ); 366 } 367 } 368 369 IMPL_LINK_NOARG(ImplSVAppData, VclEventTestingHdl, Timer *, void) 370 { 371 if (Application::AnyInput()) 372 { 373 mpEventTestingIdle->Start(); 374 } 375 else 376 { 377 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplVclEventTestingHdl ) ); 378 } 379 } 380 381 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplVclEventTestingHdl, void*, void ) 382 { 383 ImplSVData* pSVData = ImplGetSVData(); 384 SAL_INFO("vcl.eventtesting", "EventTestLimit is " << pSVData->maAppData.mnEventTestLimit); 385 if (pSVData->maAppData.mnEventTestLimit == 0) 386 { 387 delete pSVData->maAppData.mpEventTestInput; 388 SAL_INFO("vcl.eventtesting", "Event Limit reached, exiting" << pSVData->maAppData.mnEventTestLimit); 389 CloseDialogsAndQuit(); 390 } 391 else 392 { 393 if (InjectKeyEvent(*pSVData->maAppData.mpEventTestInput)) 394 --pSVData->maAppData.mnEventTestLimit; 395 if (!pSVData->maAppData.mpEventTestInput->good()) 396 { 397 SAL_INFO("vcl.eventtesting", "Event Input exhausted, exit next cycle"); 398 pSVData->maAppData.mnEventTestLimit = 0; 399 } 400 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplVclEventTestingHdl ) ); 401 } 402 } 403 404 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplPrepareExitMsg, void*, void ) 405 { 406 //now close top level frames 407 (void)GetpApp()->QueryExit(); 408 } 409 410 void Application::Execute() 411 { 412 ImplSVData* pSVData = ImplGetSVData(); 413 pSVData->maAppData.mbInAppExecute = true; 414 pSVData->maAppData.mbAppQuit = false; 415 416 if (Application::IsEventTestingModeEnabled()) 417 { 418 pSVData->maAppData.mnEventTestLimit = 50; 419 pSVData->maAppData.mpEventTestingIdle = new Idle("eventtesting"); 420 pSVData->maAppData.mpEventTestingIdle->SetInvokeHandler(LINK(&(pSVData->maAppData), ImplSVAppData, VclEventTestingHdl)); 421 pSVData->maAppData.mpEventTestingIdle->SetPriority(TaskPriority::HIGH_IDLE); 422 pSVData->maAppData.mpEventTestInput = new SvFileStream("eventtesting", StreamMode::READ); 423 pSVData->maAppData.mpEventTestingIdle->Start(); 424 } 425 426 while ( !pSVData->maAppData.mbAppQuit ) 427 Application::Yield(); 428 429 pSVData->maAppData.mbInAppExecute = false; 430 } 431 432 static bool ImplYield(bool i_bWait, bool i_bAllEvents) 433 { 434 ImplSVData* pSVData = ImplGetSVData(); 435 436 SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait ? "wait" : "no wait") << 437 ": " << (i_bAllEvents ? "all events" : "one event")); 438 439 // there's a data race here on WNT only because ImplYield may be 440 // called without SolarMutex; but the only remaining use of mnDispatchLevel 441 // is in OSX specific code 442 pSVData->maAppData.mnDispatchLevel++; 443 444 // do not wait for events if application was already quit; in that 445 // case only dispatch events already available 446 bool bProcessedEvent = pSVData->mpDefInst->DoYield( 447 i_bWait && !pSVData->maAppData.mbAppQuit, i_bAllEvents ); 448 449 pSVData->maAppData.mnDispatchLevel--; 450 451 DBG_TESTSOLARMUTEX(); // must be locked on return from Yield 452 453 SAL_INFO("vcl.schedule", "Leave ImplYield with return " << bProcessedEvent ); 454 return bProcessedEvent; 455 } 456 457 bool Application::Reschedule( bool i_bAllEvents ) 458 { 459 return ImplYield(false, i_bAllEvents); 460 } 461 462 void Scheduler::ProcessEventsToIdle() 463 { 464 int nSanity = 1; 465 while( Application::Reschedule( true ) ) 466 { 467 if (0 == ++nSanity % 1000) 468 { 469 SAL_WARN("vcl.schedule", "ProcessEventsToIdle: " << nSanity); 470 } 471 } 472 #if OSL_DEBUG_LEVEL > 0 473 // If we yield from a non-main thread we just can guarantee that all idle 474 // events were processed at some point, but our check can't prevent further 475 // processing in the main thread, which may add new events, so skip it. 476 const ImplSVData* pSVData = ImplGetSVData(); 477 if (!pSVData->mpDefInst->IsMainThread()) 478 return; 479 for (int nTaskPriority = 0; nTaskPriority < PRIO_COUNT; ++nTaskPriority) 480 { 481 const ImplSchedulerData* pSchedulerData = pSVData->maSchedCtx.mpFirstSchedulerData[nTaskPriority]; 482 while (pSchedulerData) 483 { 484 if (pSchedulerData->mpTask && !pSchedulerData->mbInScheduler) 485 { 486 Idle *pIdle = dynamic_cast<Idle*>(pSchedulerData->mpTask); 487 if (pIdle && pIdle->IsActive()) 488 { 489 SAL_WARN("vcl.schedule", "Unprocessed Idle: " 490 << pIdle << " " << pIdle->GetDebugName()); 491 } 492 } 493 pSchedulerData = pSchedulerData->mpNext; 494 } 495 } 496 #endif 497 } 498 499 extern "C" { 500 /// used by unit tests that test only via the LOK API 501 SAL_DLLPUBLIC_EXPORT void unit_lok_process_events_to_idle() 502 { 503 const SolarMutexGuard aGuard; 504 Scheduler::ProcessEventsToIdle(); 505 } 506 } 507 508 void Application::Yield() 509 { 510 ImplYield(true, false); 511 } 512 513 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplQuitMsg, void*, void ) 514 { 515 ImplGetSVData()->maAppData.mbAppQuit = true; 516 } 517 518 void Application::Quit() 519 { 520 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplQuitMsg ) ); 521 } 522 523 comphelper::SolarMutex& Application::GetSolarMutex() 524 { 525 ImplSVData* pSVData = ImplGetSVData(); 526 return *(pSVData->mpDefInst->GetYieldMutex()); 527 } 528 529 bool Application::IsMainThread() 530 { 531 return ImplGetSVData()->mnMainThreadId == osl::Thread::getCurrentIdentifier(); 532 } 533 534 sal_uInt32 Application::ReleaseSolarMutex() 535 { 536 ImplSVData* pSVData = ImplGetSVData(); 537 return pSVData->mpDefInst->ReleaseYieldMutexAll(); 538 } 539 540 void Application::AcquireSolarMutex( sal_uInt32 nCount ) 541 { 542 ImplSVData* pSVData = ImplGetSVData(); 543 pSVData->mpDefInst->AcquireYieldMutex( nCount ); 544 } 545 546 bool Application::IsInMain() 547 { 548 ImplSVData* pSVData = ImplGetSVData(); 549 return pSVData && pSVData->maAppData.mbInAppMain; 550 } 551 552 bool Application::IsInExecute() 553 { 554 return ImplGetSVData()->maAppData.mbInAppExecute; 555 } 556 557 bool Application::IsInModalMode() 558 { 559 return (ImplGetSVData()->maAppData.mnModalMode != 0); 560 } 561 562 sal_uInt16 Application::GetDispatchLevel() 563 { 564 return ImplGetSVData()->maAppData.mnDispatchLevel; 565 } 566 567 bool Application::AnyInput( VclInputFlags nType ) 568 { 569 return ImplGetSVData()->mpDefInst->AnyInput( nType ); 570 } 571 572 sal_uInt64 Application::GetLastInputInterval() 573 { 574 return (tools::Time::GetSystemTicks()-ImplGetSVData()->maAppData.mnLastInputTime); 575 } 576 577 bool Application::IsUICaptured() 578 { 579 ImplSVData* pSVData = ImplGetSVData(); 580 581 // If mouse was captured, or if in tracking- or in select-mode of a floatingwindow (e.g. menus 582 // or pulldown toolboxes) another window should be created 583 // D&D active !!! 584 return pSVData->maWinData.mpCaptureWin || pSVData->maWinData.mpTrackWin || 585 pSVData->maWinData.mpFirstFloat || nImplSysDialog; 586 } 587 588 void Application::OverrideSystemSettings( AllSettings& /*rSettings*/ ) 589 { 590 } 591 592 void Application::MergeSystemSettings( AllSettings& rSettings ) 593 { 594 vcl::Window* pWindow = ImplGetSVData()->maWinData.mpFirstFrame; 595 if( ! pWindow ) 596 pWindow = ImplGetDefaultWindow(); 597 if( pWindow ) 598 { 599 ImplSVData* pSVData = ImplGetSVData(); 600 if ( !pSVData->maAppData.mbSettingsInit ) 601 { 602 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings 603 pWindow->ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings ); 604 pSVData->maAppData.mbSettingsInit = true; 605 } 606 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings 607 pWindow->ImplUpdateGlobalSettings( rSettings, false ); 608 } 609 } 610 611 void Application::SetSettings( const AllSettings& rSettings ) 612 { 613 const SolarMutexGuard aGuard; 614 615 ImplSVData* pSVData = ImplGetSVData(); 616 if ( !pSVData->maAppData.mpSettings ) 617 { 618 InitSettings(pSVData); 619 *pSVData->maAppData.mpSettings = rSettings; 620 } 621 else 622 { 623 AllSettings aOldSettings = *pSVData->maAppData.mpSettings; 624 if (aOldSettings.GetUILanguageTag().getLanguageType() != rSettings.GetUILanguageTag().getLanguageType() && 625 pSVData->mbResLocaleSet) 626 { 627 pSVData->mbResLocaleSet = false; 628 } 629 *pSVData->maAppData.mpSettings = rSettings; 630 AllSettingsFlags nChangeFlags = aOldSettings.GetChangeFlags( *pSVData->maAppData.mpSettings ); 631 if ( bool(nChangeFlags) ) 632 { 633 DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, &aOldSettings, nChangeFlags ); 634 635 // notify data change handler 636 ImplCallEventListenersApplicationDataChanged( &aDCEvt); 637 638 // Update all windows 639 vcl::Window* pFirstFrame = pSVData->maWinData.mpFirstFrame; 640 // Reset data that needs to be re-calculated 641 long nOldDPIX = 0; 642 long nOldDPIY = 0; 643 if ( pFirstFrame ) 644 { 645 nOldDPIX = pFirstFrame->GetDPIX(); 646 nOldDPIY = pFirstFrame->GetDPIY(); 647 vcl::Window::ImplInitAppFontData(pFirstFrame); 648 } 649 vcl::Window* pFrame = pFirstFrame; 650 while ( pFrame ) 651 { 652 // call UpdateSettings from ClientWindow in order to prevent updating data twice 653 vcl::Window* pClientWin = pFrame; 654 while ( pClientWin->ImplGetClientWindow() ) 655 pClientWin = pClientWin->ImplGetClientWindow(); 656 pClientWin->UpdateSettings( rSettings, true ); 657 658 vcl::Window* pTempWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap; 659 while ( pTempWin ) 660 { 661 // call UpdateSettings from ClientWindow in order to prevent updating data twice 662 pClientWin = pTempWin; 663 while ( pClientWin->ImplGetClientWindow() ) 664 pClientWin = pClientWin->ImplGetClientWindow(); 665 pClientWin->UpdateSettings( rSettings, true ); 666 pTempWin = pTempWin->mpWindowImpl->mpNextOverlap; 667 } 668 669 pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame; 670 } 671 672 // if DPI resolution for screen output was changed set the new resolution for all 673 // screen compatible VirDev's 674 pFirstFrame = pSVData->maWinData.mpFirstFrame; 675 if ( pFirstFrame ) 676 { 677 if ( (pFirstFrame->GetDPIX() != nOldDPIX) || 678 (pFirstFrame->GetDPIY() != nOldDPIY) ) 679 { 680 VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev; 681 while ( pVirDev ) 682 { 683 if ( pVirDev->mbScreenComp && 684 (pVirDev->GetDPIX() == nOldDPIX) && 685 (pVirDev->GetDPIY() == nOldDPIY) ) 686 { 687 pVirDev->SetDPIX( pFirstFrame->GetDPIX() ); 688 pVirDev->SetDPIY( pFirstFrame->GetDPIY() ); 689 if ( pVirDev->IsMapModeEnabled() ) 690 { 691 MapMode aMapMode = pVirDev->GetMapMode(); 692 pVirDev->SetMapMode(); 693 pVirDev->SetMapMode( aMapMode ); 694 } 695 } 696 697 pVirDev = pVirDev->mpNext; 698 } 699 } 700 } 701 } 702 } 703 } 704 705 const AllSettings& Application::GetSettings() 706 { 707 ImplSVData* pSVData = ImplGetSVData(); 708 if ( !pSVData->maAppData.mpSettings ) 709 { 710 InitSettings(pSVData); 711 } 712 713 return *(pSVData->maAppData.mpSettings); 714 } 715 716 namespace { 717 718 void InitSettings(ImplSVData* pSVData) 719 { 720 assert(!pSVData->maAppData.mpSettings && "initialization should not happen twice!"); 721 722 pSVData->maAppData.mpSettings.reset(new AllSettings()); 723 if (!utl::ConfigManager::IsFuzzing()) 724 { 725 pSVData->maAppData.mpCfgListener = new LocaleConfigurationListener; 726 pSVData->maAppData.mpSettings->GetSysLocale().GetOptions().AddListener( pSVData->maAppData.mpCfgListener ); 727 } 728 } 729 730 } 731 732 void Application::NotifyAllWindows( DataChangedEvent& rDCEvt ) 733 { 734 ImplSVData* pSVData = ImplGetSVData(); 735 vcl::Window* pFrame = pSVData->maWinData.mpFirstFrame; 736 while ( pFrame ) 737 { 738 pFrame->NotifyAllChildren( rDCEvt ); 739 740 vcl::Window* pSysWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap; 741 while ( pSysWin ) 742 { 743 pSysWin->NotifyAllChildren( rDCEvt ); 744 pSysWin = pSysWin->mpWindowImpl->mpNextOverlap; 745 } 746 747 pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame; 748 } 749 } 750 751 void Application::ImplCallEventListenersApplicationDataChanged( void* pData ) 752 { 753 ImplSVData* pSVData = ImplGetSVData(); 754 VclWindowEvent aEvent( nullptr, VclEventId::ApplicationDataChanged, pData ); 755 756 pSVData->maAppData.maEventListeners.Call( aEvent ); 757 } 758 759 void Application::ImplCallEventListeners( VclSimpleEvent& rEvent ) 760 { 761 ImplSVData* pSVData = ImplGetSVData(); 762 pSVData->maAppData.maEventListeners.Call( rEvent ); 763 } 764 765 void Application::AddEventListener( const Link<VclSimpleEvent&,void>& rEventListener ) 766 { 767 ImplSVData* pSVData = ImplGetSVData(); 768 pSVData->maAppData.maEventListeners.addListener( rEventListener ); 769 } 770 771 void Application::RemoveEventListener( const Link<VclSimpleEvent&,void>& rEventListener ) 772 { 773 ImplSVData* pSVData = ImplGetSVData(); 774 pSVData->maAppData.maEventListeners.removeListener( rEventListener ); 775 } 776 777 void Application::AddKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener ) 778 { 779 ImplSVData* pSVData = ImplGetSVData(); 780 pSVData->maAppData.maKeyListeners.push_back( rKeyListener ); 781 } 782 783 void Application::RemoveKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener ) 784 { 785 ImplSVData* pSVData = ImplGetSVData(); 786 auto & rVec = pSVData->maAppData.maKeyListeners; 787 rVec.erase( std::remove(rVec.begin(), rVec.end(), rKeyListener ), rVec.end() ); 788 } 789 790 bool Application::HandleKey( VclEventId nEvent, vcl::Window *pWin, KeyEvent* pKeyEvent ) 791 { 792 // let listeners process the key event 793 VclWindowEvent aEvent( pWin, nEvent, static_cast<void *>(pKeyEvent) ); 794 795 ImplSVData* pSVData = ImplGetSVData(); 796 797 if ( pSVData->maAppData.maKeyListeners.empty() ) 798 return false; 799 800 bool bProcessed = false; 801 // Copy the list, because this can be destroyed when calling a Link... 802 std::vector<Link<VclWindowEvent&,bool>> aCopy( pSVData->maAppData.maKeyListeners ); 803 for ( const Link<VclWindowEvent&,bool>& rLink : aCopy ) 804 { 805 if( rLink.Call( aEvent ) ) 806 { 807 bProcessed = true; 808 break; 809 } 810 } 811 return bProcessed; 812 } 813 814 ImplSVEvent * Application::PostKeyEvent( VclEventId nEvent, vcl::Window *pWin, KeyEvent const * pKeyEvent ) 815 { 816 const SolarMutexGuard aGuard; 817 ImplSVEvent * nEventId = nullptr; 818 819 if( pWin && pKeyEvent ) 820 { 821 std::unique_ptr<ImplPostEventData> pPostEventData(new ImplPostEventData( nEvent, pWin, *pKeyEvent )); 822 823 nEventId = PostUserEvent( 824 LINK( nullptr, Application, PostEventHandler ), 825 pPostEventData.get() ); 826 827 if( nEventId ) 828 { 829 pPostEventData->mnEventId = nEventId; 830 ImplGetSVData()->maAppData.maPostedEventList.emplace_back( pWin, pPostEventData.release() ); 831 } 832 } 833 834 return nEventId; 835 } 836 837 ImplSVEvent* Application::PostGestureEvent(VclEventId nEvent, vcl::Window* pWin, GestureEvent const * pGestureEvent) 838 { 839 const SolarMutexGuard aGuard; 840 ImplSVEvent * nEventId = nullptr; 841 842 if (pWin && pGestureEvent) 843 { 844 Point aTransformedPosition(pGestureEvent->mnX, pGestureEvent->mnY); 845 846 aTransformedPosition.AdjustX(pWin->GetOutOffXPixel()); 847 aTransformedPosition.AdjustY(pWin->GetOutOffYPixel()); 848 849 const GestureEvent aGestureEvent( 850 sal_Int32(aTransformedPosition.X()), 851 sal_Int32(aTransformedPosition.Y()), 852 pGestureEvent->meEventType, 853 pGestureEvent->mnOffset, 854 pGestureEvent->meOrientation 855 ); 856 857 std::unique_ptr<ImplPostEventData> pPostEventData(new ImplPostEventData(nEvent, pWin, aGestureEvent)); 858 859 nEventId = PostUserEvent( 860 LINK( nullptr, Application, PostEventHandler ), 861 pPostEventData.get()); 862 863 if (nEventId) 864 { 865 pPostEventData->mnEventId = nEventId; 866 ImplGetSVData()->maAppData.maPostedEventList.emplace_back(pWin, pPostEventData.release()); 867 } 868 } 869 870 return nEventId; 871 } 872 873 ImplSVEvent* Application::PostMouseEvent( VclEventId nEvent, vcl::Window *pWin, MouseEvent const * pMouseEvent ) 874 { 875 const SolarMutexGuard aGuard; 876 ImplSVEvent * nEventId = nullptr; 877 878 if( pWin && pMouseEvent ) 879 { 880 Point aTransformedPos( pMouseEvent->GetPosPixel() ); 881 882 // LOK uses (0, 0) as the origin of all windows; don't offset. 883 if (!comphelper::LibreOfficeKit::isActive()) 884 { 885 aTransformedPos.AdjustX(pWin->GetOutOffXPixel()); 886 aTransformedPos.AdjustY(pWin->GetOutOffYPixel()); 887 } 888 889 const MouseEvent aTransformedEvent( aTransformedPos, pMouseEvent->GetClicks(), pMouseEvent->GetMode(), 890 pMouseEvent->GetButtons(), pMouseEvent->GetModifier() ); 891 892 std::unique_ptr<ImplPostEventData> pPostEventData(new ImplPostEventData( nEvent, pWin, aTransformedEvent )); 893 894 nEventId = PostUserEvent( 895 LINK( nullptr, Application, PostEventHandler ), 896 pPostEventData.get() ); 897 898 if( nEventId ) 899 { 900 pPostEventData->mnEventId = nEventId; 901 ImplGetSVData()->maAppData.maPostedEventList.emplace_back( pWin, pPostEventData.release() ); 902 } 903 } 904 905 return nEventId; 906 } 907 908 909 IMPL_STATIC_LINK( Application, PostEventHandler, void*, pCallData, void ) 910 { 911 const SolarMutexGuard aGuard; 912 ImplPostEventData* pData = static_cast< ImplPostEventData * >( pCallData ); 913 const void* pEventData; 914 SalEvent nEvent; 915 ImplSVEvent * const nEventId = pData->mnEventId; 916 917 switch( pData->mnEvent ) 918 { 919 case VclEventId::WindowMouseMove: 920 nEvent = SalEvent::ExternalMouseMove; 921 pEventData = &pData->maMouseEvent; 922 break; 923 924 case VclEventId::WindowMouseButtonDown: 925 nEvent = SalEvent::ExternalMouseButtonDown; 926 pEventData = &pData->maMouseEvent; 927 break; 928 929 case VclEventId::WindowMouseButtonUp: 930 nEvent = SalEvent::ExternalMouseButtonUp; 931 pEventData = &pData->maMouseEvent; 932 break; 933 934 case VclEventId::WindowKeyInput: 935 nEvent = SalEvent::ExternalKeyInput; 936 pEventData = &pData->maKeyEvent; 937 break; 938 939 case VclEventId::WindowKeyUp: 940 nEvent = SalEvent::ExternalKeyUp; 941 pEventData = &pData->maKeyEvent; 942 break; 943 944 case VclEventId::WindowGestureEvent: 945 nEvent = SalEvent::ExternalGesture; 946 pEventData = &pData->maGestureEvent; 947 break; 948 949 default: 950 nEvent = SalEvent::NONE; 951 pEventData = nullptr; 952 break; 953 }; 954 955 if( pData->mpWin && pData->mpWin->mpWindowImpl->mpFrameWindow.get() && pEventData ) 956 ImplWindowFrameProc( pData->mpWin->mpWindowImpl->mpFrameWindow.get(), nEvent, pEventData ); 957 958 // remove this event from list of posted events, watch for destruction of internal data 959 auto svdata = ImplGetSVData(); 960 ::std::vector< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() ); 961 962 while( aIter != svdata->maAppData.maPostedEventList.end() ) 963 { 964 if( nEventId == (*aIter).second->mnEventId ) 965 { 966 delete (*aIter).second; 967 aIter = svdata->maAppData.maPostedEventList.erase( aIter ); 968 } 969 else 970 ++aIter; 971 } 972 } 973 974 void Application::RemoveMouseAndKeyEvents( vcl::Window* pWin ) 975 { 976 const SolarMutexGuard aGuard; 977 978 // remove all events for specific window, watch for destruction of internal data 979 auto svdata = ImplGetSVData(); 980 ::std::vector< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() ); 981 982 while( aIter != svdata->maAppData.maPostedEventList.end() ) 983 { 984 if( pWin == (*aIter).first ) 985 { 986 if( (*aIter).second->mnEventId ) 987 RemoveUserEvent( (*aIter).second->mnEventId ); 988 989 delete (*aIter).second; 990 aIter = svdata->maAppData.maPostedEventList.erase( aIter ); 991 } 992 else 993 ++aIter; 994 } 995 } 996 997 ImplSVEvent * Application::PostUserEvent( const Link<void*,void>& rLink, void* pCaller, 998 bool bReferenceLink ) 999 { 1000 vcl::Window* pDefWindow = ImplGetDefaultWindow(); 1001 if ( pDefWindow == nullptr ) 1002 return nullptr; 1003 1004 std::unique_ptr<ImplSVEvent> pSVEvent(new ImplSVEvent); 1005 pSVEvent->mpData = pCaller; 1006 pSVEvent->maLink = rLink; 1007 pSVEvent->mpWindow = nullptr; 1008 pSVEvent->mbCall = true; 1009 if (bReferenceLink) 1010 { 1011 SolarMutexGuard aGuard; 1012 // Double check that this is indeed a vcl::Window instance. 1013 assert(dynamic_cast<vcl::Window *>( 1014 static_cast<OutputDevice *>(rLink.GetInstance())) == 1015 static_cast<vcl::Window *>(rLink.GetInstance())); 1016 pSVEvent->mpInstanceRef = static_cast<vcl::Window *>(rLink.GetInstance()); 1017 } 1018 1019 auto pTmpEvent = pSVEvent.get(); 1020 if (!pDefWindow->ImplGetFrame()->PostEvent( std::move(pSVEvent) )) 1021 return nullptr; 1022 return pTmpEvent; 1023 } 1024 1025 void Application::RemoveUserEvent( ImplSVEvent * nUserEvent ) 1026 { 1027 if(nUserEvent) 1028 { 1029 SAL_WARN_IF( nUserEvent->mpWindow, "vcl", 1030 "Application::RemoveUserEvent(): Event is send to a window" ); 1031 SAL_WARN_IF( !nUserEvent->mbCall, "vcl", 1032 "Application::RemoveUserEvent(): Event is already removed" ); 1033 1034 nUserEvent->mpWindow.clear(); 1035 nUserEvent->mpInstanceRef.clear(); 1036 nUserEvent->mbCall = false; 1037 } 1038 } 1039 1040 void Application::LockFontUpdates(bool bLock) 1041 { 1042 OutputDevice::LockFontUpdates(bLock); 1043 } 1044 1045 WorkWindow* Application::GetAppWindow() 1046 { 1047 return ImplGetSVData()->maWinData.mpAppWin; 1048 } 1049 1050 vcl::Window* Application::GetFocusWindow() 1051 { 1052 return ImplGetSVData()->maWinData.mpFocusWin; 1053 } 1054 1055 OutputDevice* Application::GetDefaultDevice() 1056 { 1057 return ImplGetDefaultWindow(); 1058 } 1059 1060 vcl::Window* Application::GetFirstTopLevelWindow() 1061 { 1062 ImplSVData* pSVData = ImplGetSVData(); 1063 return pSVData->maWinData.mpFirstFrame; 1064 } 1065 1066 vcl::Window* Application::GetNextTopLevelWindow( vcl::Window const * pWindow ) 1067 { 1068 return pWindow->mpWindowImpl->mpFrameData->mpNextFrame; 1069 } 1070 1071 long Application::GetTopWindowCount() 1072 { 1073 long nRet = 0; 1074 ImplSVData* pSVData = ImplGetSVData(); 1075 vcl::Window *pWin = pSVData ? pSVData->maWinData.mpFirstFrame.get() : nullptr; 1076 while( pWin ) 1077 { 1078 if( pWin->ImplGetWindow()->IsTopWindow() ) 1079 nRet++; 1080 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame; 1081 } 1082 return nRet; 1083 } 1084 1085 vcl::Window* Application::GetTopWindow( long nIndex ) 1086 { 1087 long nIdx = 0; 1088 ImplSVData* pSVData = ImplGetSVData(); 1089 vcl::Window *pWin = pSVData ? pSVData->maWinData.mpFirstFrame.get() : nullptr; 1090 while( pWin ) 1091 { 1092 if( pWin->ImplGetWindow()->IsTopWindow() ) 1093 { 1094 if( nIdx == nIndex ) 1095 return pWin->ImplGetWindow(); 1096 else 1097 nIdx++; 1098 } 1099 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame; 1100 } 1101 return nullptr; 1102 } 1103 1104 vcl::Window* Application::GetActiveTopWindow() 1105 { 1106 vcl::Window *pWin = ImplGetSVData()->maWinData.mpFocusWin; 1107 while( pWin ) 1108 { 1109 if( pWin->IsTopWindow() ) 1110 return pWin; 1111 pWin = pWin->mpWindowImpl->mpParent; 1112 } 1113 return nullptr; 1114 } 1115 1116 void Application::SetAppName( const OUString& rUniqueName ) 1117 { 1118 ImplSVData* pSVData = ImplGetSVData(); 1119 pSVData->maAppData.mxAppName = rUniqueName; 1120 } 1121 1122 OUString Application::GetAppName() 1123 { 1124 ImplSVData* pSVData = ImplGetSVData(); 1125 if ( pSVData->maAppData.mxAppName ) 1126 return *(pSVData->maAppData.mxAppName); 1127 else 1128 return OUString(); 1129 } 1130 1131 OUString Application::GetHWOSConfInfo() 1132 { 1133 ImplSVData* pSVData = ImplGetSVData(); 1134 OUStringBuffer aDetails; 1135 1136 aDetails.append( VclResId(SV_APP_CPUTHREADS) ); 1137 aDetails.append( static_cast<sal_Int32>(std::thread::hardware_concurrency()) ); 1138 aDetails.append( "; " ); 1139 1140 OUString aVersion; 1141 if ( pSVData && pSVData->mpDefInst ) 1142 aVersion = pSVData->mpDefInst->getOSVersion(); 1143 else 1144 aVersion = "-"; 1145 1146 aDetails.append( VclResId(SV_APP_OSVERSION) ); 1147 aDetails.append( aVersion ); 1148 aDetails.append( "; " ); 1149 1150 aDetails.append( VclResId(SV_APP_UIRENDER) ); 1151 #if HAVE_FEATURE_OPENGL 1152 if ( OpenGLWrapper::isVCLOpenGLEnabled() ) 1153 aDetails.append( VclResId(SV_APP_GL) ); 1154 else 1155 #endif 1156 aDetails.append( VclResId(SV_APP_DEFAULT) ); 1157 aDetails.append( "; " ); 1158 1159 #if (defined LINUX || defined _WIN32 || defined MACOSX) 1160 aDetails.append( SV_APP_VCLBACKEND ); 1161 aDetails.append( GetToolkitName() ); 1162 aDetails.append( "; " ); 1163 #endif 1164 1165 return aDetails.makeStringAndClear(); 1166 } 1167 1168 void Application::SetDisplayName( const OUString& rName ) 1169 { 1170 ImplSVData* pSVData = ImplGetSVData(); 1171 pSVData->maAppData.mxDisplayName = rName; 1172 } 1173 1174 OUString Application::GetDisplayName() 1175 { 1176 ImplSVData* pSVData = ImplGetSVData(); 1177 if ( pSVData->maAppData.mxDisplayName ) 1178 return *(pSVData->maAppData.mxDisplayName); 1179 else if ( pSVData->maWinData.mpAppWin ) 1180 return pSVData->maWinData.mpAppWin->GetText(); 1181 else 1182 return OUString(); 1183 } 1184 1185 unsigned int Application::GetScreenCount() 1186 { 1187 SalSystem* pSys = ImplGetSalSystem(); 1188 return pSys ? pSys->GetDisplayScreenCount() : 0; 1189 } 1190 1191 bool Application::IsUnifiedDisplay() 1192 { 1193 SalSystem* pSys = ImplGetSalSystem(); 1194 return pSys == nullptr || pSys->IsUnifiedDisplay(); 1195 } 1196 1197 unsigned int Application::GetDisplayBuiltInScreen() 1198 { 1199 SalSystem* pSys = ImplGetSalSystem(); 1200 return pSys ? pSys->GetDisplayBuiltInScreen() : 0; 1201 } 1202 1203 unsigned int Application::GetDisplayExternalScreen() 1204 { 1205 // This is really unpleasant, in theory we could have multiple 1206 // external displays etc. 1207 int nExternal(0); 1208 switch (GetDisplayBuiltInScreen()) 1209 { 1210 case 0: 1211 nExternal = 1; 1212 break; 1213 case 1: 1214 nExternal = 0; 1215 break; 1216 default: 1217 // When the built-in display is neither 0 nor 1 1218 // then place the full-screen presentation on the 1219 // first available screen. 1220 nExternal = 0; 1221 break; 1222 } 1223 return nExternal; 1224 } 1225 1226 tools::Rectangle Application::GetScreenPosSizePixel( unsigned int nScreen ) 1227 { 1228 SalSystem* pSys = ImplGetSalSystem(); 1229 return pSys ? pSys->GetDisplayScreenPosSizePixel( nScreen ) : tools::Rectangle(); 1230 } 1231 1232 namespace { 1233 unsigned long calcDistSquare( const Point& i_rPoint, const tools::Rectangle& i_rRect ) 1234 { 1235 const Point aRectCenter( (i_rRect.Left() + i_rRect.Right())/2, 1236 (i_rRect.Top() + i_rRect.Bottom())/ 2 ); 1237 const long nDX = aRectCenter.X() - i_rPoint.X(); 1238 const long nDY = aRectCenter.Y() - i_rPoint.Y(); 1239 return nDX*nDX + nDY*nDY; 1240 } 1241 } 1242 1243 unsigned int Application::GetBestScreen( const tools::Rectangle& i_rRect ) 1244 { 1245 if( !IsUnifiedDisplay() ) 1246 return GetDisplayBuiltInScreen(); 1247 1248 const unsigned int nScreens = GetScreenCount(); 1249 unsigned int nBestMatchScreen = 0; 1250 unsigned long nOverlap = 0; 1251 for( unsigned int i = 0; i < nScreens; i++ ) 1252 { 1253 const tools::Rectangle aCurScreenRect( GetScreenPosSizePixel( i ) ); 1254 // if a screen contains the rectangle completely it is obviously the best screen 1255 if( aCurScreenRect.IsInside( i_rRect ) ) 1256 return i; 1257 // next the screen which contains most of the area of the rect is the best 1258 tools::Rectangle aIntersection( aCurScreenRect.GetIntersection( i_rRect ) ); 1259 if( ! aIntersection.IsEmpty() ) 1260 { 1261 const unsigned long nCurOverlap( aIntersection.GetWidth() * aIntersection.GetHeight() ); 1262 if( nCurOverlap > nOverlap ) 1263 { 1264 nOverlap = nCurOverlap; 1265 nBestMatchScreen = i; 1266 } 1267 } 1268 } 1269 if( nOverlap > 0 ) 1270 return nBestMatchScreen; 1271 1272 // finally the screen which center is nearest to the rect is the best 1273 const Point aCenter( (i_rRect.Left() + i_rRect.Right())/2, 1274 (i_rRect.Top() + i_rRect.Bottom())/2 ); 1275 unsigned long nDist = ULONG_MAX; 1276 for( unsigned int i = 0; i < nScreens; i++ ) 1277 { 1278 const tools::Rectangle aCurScreenRect( GetScreenPosSizePixel( i ) ); 1279 const unsigned long nCurDist( calcDistSquare( aCenter, aCurScreenRect ) ); 1280 if( nCurDist < nDist ) 1281 { 1282 nBestMatchScreen = i; 1283 nDist = nCurDist; 1284 } 1285 } 1286 return nBestMatchScreen; 1287 } 1288 1289 bool Application::InsertAccel( Accelerator* pAccel ) 1290 { 1291 ImplSVData* pSVData = ImplGetSVData(); 1292 1293 if ( !pSVData->maAppData.mpAccelMgr ) 1294 pSVData->maAppData.mpAccelMgr = new ImplAccelManager(); 1295 return pSVData->maAppData.mpAccelMgr->InsertAccel( pAccel ); 1296 } 1297 1298 void Application::RemoveAccel( Accelerator const * pAccel ) 1299 { 1300 ImplSVData* pSVData = ImplGetSVData(); 1301 1302 if ( pSVData->maAppData.mpAccelMgr ) 1303 pSVData->maAppData.mpAccelMgr->RemoveAccel( pAccel ); 1304 } 1305 1306 void Application::SetHelp( Help* pHelp ) 1307 { 1308 ImplGetSVData()->maAppData.mpHelp = pHelp; 1309 } 1310 1311 void Application::UpdateMainThread() 1312 { 1313 ImplSVData* pSVData = ImplGetSVData(); 1314 if (pSVData && pSVData->mpDefInst) 1315 pSVData->mpDefInst->updateMainThread(); 1316 } 1317 1318 Help* Application::GetHelp() 1319 { 1320 return ImplGetSVData()->maAppData.mpHelp; 1321 } 1322 1323 OUString Application::GetToolkitName() 1324 { 1325 ImplSVData* pSVData = ImplGetSVData(); 1326 if ( pSVData->maAppData.mxToolkitName ) 1327 return *(pSVData->maAppData.mxToolkitName); 1328 else 1329 return OUString(); 1330 } 1331 1332 vcl::Window* Application::GetDefDialogParent() 1333 { 1334 ImplSVData* pSVData = ImplGetSVData(); 1335 // find some useful dialog parent 1336 1337 // always use the topmost parent of the candidate 1338 // window to avoid using dialogs or floaters 1339 // as DefDialogParent 1340 1341 // current focus frame 1342 vcl::Window *pWin = pSVData->maWinData.mpFocusWin; 1343 if (pWin && !pWin->IsMenuFloatingWindow()) 1344 { 1345 while (pWin->mpWindowImpl && pWin->mpWindowImpl->mpParent) 1346 pWin = pWin->mpWindowImpl->mpParent; 1347 1348 // check for corrupted window hierarchy, #122232#, may be we now crash somewhere else 1349 if (!pWin->mpWindowImpl) 1350 { 1351 OSL_FAIL( "Window hierarchy corrupted!" ); 1352 pSVData->maWinData.mpFocusWin = nullptr; // avoid further access 1353 return nullptr; 1354 } 1355 1356 if ((pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0) 1357 { 1358 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow(); 1359 } 1360 } 1361 1362 // last active application frame 1363 pWin = pSVData->maWinData.mpActiveApplicationFrame; 1364 if (pWin) 1365 { 1366 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow(); 1367 } 1368 1369 // first visible top window (may be totally wrong...) 1370 pWin = pSVData->maWinData.mpFirstFrame; 1371 while (pWin) 1372 { 1373 if( pWin->ImplGetWindow()->IsTopWindow() && 1374 pWin->mpWindowImpl->mbReallyVisible && 1375 (pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0 1376 ) 1377 { 1378 while( pWin->mpWindowImpl->mpParent ) 1379 pWin = pWin->mpWindowImpl->mpParent; 1380 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow(); 1381 } 1382 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame; 1383 } 1384 1385 // use the desktop 1386 return nullptr; 1387 } 1388 1389 DialogCancelMode Application::GetDialogCancelMode() 1390 { 1391 return ImplGetSVData()->maAppData.meDialogCancel; 1392 } 1393 1394 void Application::SetDialogCancelMode( DialogCancelMode mode ) 1395 { 1396 ImplGetSVData()->maAppData.meDialogCancel = mode; 1397 } 1398 1399 bool Application::IsDialogCancelEnabled() 1400 { 1401 return ImplGetSVData()->maAppData.meDialogCancel != DialogCancelMode::Off; 1402 } 1403 1404 void Application::SetSystemWindowMode( SystemWindowFlags nMode ) 1405 { 1406 ImplGetSVData()->maAppData.mnSysWinMode = nMode; 1407 } 1408 1409 SystemWindowFlags Application::GetSystemWindowMode() 1410 { 1411 return ImplGetSVData()->maAppData.mnSysWinMode; 1412 } 1413 1414 css::uno::Reference< css::awt::XToolkit > Application::GetVCLToolkit() 1415 { 1416 css::uno::Reference< css::awt::XToolkit > xT; 1417 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper(); 1418 if ( pWrapper ) 1419 xT = pWrapper->GetVCLToolkit(); 1420 return xT; 1421 } 1422 1423 #ifdef DISABLE_DYNLOADING 1424 1425 extern "C" { UnoWrapperBase* CreateUnoWrapper(); } 1426 1427 #else 1428 1429 extern "C" { static void thisModule() {} } 1430 1431 #endif 1432 1433 UnoWrapperBase* UnoWrapperBase::GetUnoWrapper( bool bCreateIfNotExist ) 1434 { 1435 ImplSVData* pSVData = ImplGetSVData(); 1436 static bool bAlreadyTriedToCreate = false; 1437 if ( !pSVData->mpUnoWrapper && bCreateIfNotExist && !bAlreadyTriedToCreate ) 1438 { 1439 #ifndef DISABLE_DYNLOADING 1440 osl::Module aTkLib; 1441 aTkLib.loadRelative(&thisModule, TK_DLL_NAME); 1442 if (aTkLib.is()) 1443 { 1444 FN_TkCreateUnoWrapper fnCreateWrapper = reinterpret_cast<FN_TkCreateUnoWrapper>(aTkLib.getFunctionSymbol("CreateUnoWrapper")); 1445 if ( fnCreateWrapper ) 1446 { 1447 pSVData->mpUnoWrapper = fnCreateWrapper(); 1448 } 1449 aTkLib.release(); 1450 } 1451 SAL_WARN_IF( !pSVData->mpUnoWrapper, "vcl", "UnoWrapper could not be created!" ); 1452 #else 1453 pSVData->mpUnoWrapper = CreateUnoWrapper(); 1454 #endif 1455 bAlreadyTriedToCreate = true; 1456 } 1457 return pSVData->mpUnoWrapper; 1458 } 1459 1460 void UnoWrapperBase::SetUnoWrapper( UnoWrapperBase* pWrapper ) 1461 { 1462 ImplSVData* pSVData = ImplGetSVData(); 1463 SAL_WARN_IF( pSVData->mpUnoWrapper, "vcl", "SetUnoWrapper: Wrapper already exists" ); 1464 pSVData->mpUnoWrapper = pWrapper; 1465 } 1466 1467 css::uno::Reference< css::awt::XDisplayConnection > Application::GetDisplayConnection() 1468 { 1469 ImplSVData* pSVData = ImplGetSVData(); 1470 1471 if( !pSVData->mxDisplayConnection.is() ) 1472 { 1473 pSVData->mxDisplayConnection.set( new vcl::DisplayConnectionDispatch ); 1474 pSVData->mxDisplayConnection->start(); 1475 } 1476 1477 return pSVData->mxDisplayConnection.get(); 1478 } 1479 1480 void Application::SetFilterHdl( const Link<ConvertData&,bool>& rLink ) 1481 { 1482 ImplGetSVData()->maGDIData.mpGrfConverter->SetFilterHdl( rLink ); 1483 } 1484 1485 const LocaleDataWrapper& Application::GetAppLocaleDataWrapper() 1486 { 1487 return GetSettings().GetLocaleDataWrapper(); 1488 } 1489 1490 void Application::EnableHeadlessMode( bool dialogsAreFatal ) 1491 { 1492 DialogCancelMode eNewMode = dialogsAreFatal ? DialogCancelMode::Fatal : DialogCancelMode::Silent; 1493 DialogCancelMode eOldMode = GetDialogCancelMode(); 1494 assert(eOldMode == DialogCancelMode::Off || GetDialogCancelMode() == eNewMode); 1495 if (eOldMode != eNewMode) 1496 SetDialogCancelMode( eNewMode ); 1497 } 1498 1499 bool Application::IsHeadlessModeEnabled() 1500 { 1501 return IsDialogCancelEnabled() || comphelper::LibreOfficeKit::isActive(); 1502 } 1503 1504 void Application::EnableBitmapRendering() 1505 { 1506 ImplGetSVData()->maAppData.mbRenderToBitmaps = true; 1507 } 1508 1509 bool Application::IsBitmapRendering() 1510 { 1511 return ImplGetSVData()->maAppData.mbRenderToBitmaps; 1512 } 1513 1514 void Application::EnableConsoleOnly() 1515 { 1516 EnableHeadlessMode(true); 1517 EnableBitmapRendering(); 1518 } 1519 1520 static bool bEventTestingMode = false; 1521 1522 bool Application::IsEventTestingModeEnabled() 1523 { 1524 return bEventTestingMode; 1525 } 1526 1527 void Application::EnableEventTestingMode() 1528 { 1529 bEventTestingMode = true; 1530 } 1531 1532 static bool bSafeMode = false; 1533 1534 bool Application::IsSafeModeEnabled() 1535 { 1536 return bSafeMode; 1537 } 1538 1539 void Application::EnableSafeMode() 1540 { 1541 bSafeMode = true; 1542 } 1543 1544 void Application::ShowNativeErrorBox(const OUString& sTitle , 1545 const OUString& sMessage) 1546 { 1547 int btn = ImplGetSalSystem()->ShowNativeMessageBox( 1548 sTitle, 1549 sMessage); 1550 if (btn != SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK) { 1551 SAL_WARN( "vcl", "ShowNativeMessageBox returned " << btn); 1552 } 1553 } 1554 1555 const OUString& Application::GetDesktopEnvironment() 1556 { 1557 if (IsHeadlessModeEnabled()) 1558 { 1559 static const OUString aNone("none"); 1560 return aNone; 1561 } 1562 else 1563 return SalGetDesktopEnvironment(); 1564 } 1565 1566 void Application::AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService) 1567 { 1568 ImplSVData* pSVData = ImplGetSVData(); 1569 pSVData->mpDefInst->AddToRecentDocumentList(rFileUrl, rMimeType, rDocumentService); 1570 } 1571 1572 bool InitAccessBridge() 1573 { 1574 // Disable MSAA bridge on UNIX 1575 #if defined UNX 1576 return true; 1577 #else 1578 bool bRet = ImplInitAccessBridge(); 1579 1580 if( !bRet ) 1581 { 1582 // disable accessibility if the user chooses to continue 1583 AllSettings aSettings = Application::GetSettings(); 1584 MiscSettings aMisc = aSettings.GetMiscSettings(); 1585 aMisc.SetEnableATToolSupport( false ); 1586 aSettings.SetMiscSettings( aMisc ); 1587 Application::SetSettings( aSettings ); 1588 } 1589 return bRet; 1590 #endif // !UNX 1591 } 1592 1593 // MT: AppEvent was in oldsv.cxx, but is still needed... 1594 void Application::AppEvent( const ApplicationEvent& /*rAppEvent*/ ) 1595 { 1596 } 1597 1598 bool Application::hasNativeFileSelection() 1599 { 1600 ImplSVData* pSVData = ImplGetSVData(); 1601 return pSVData->mpDefInst->hasNativeFileSelection(); 1602 } 1603 1604 Reference< ui::dialogs::XFilePicker2 > 1605 Application::createFilePicker( const Reference< uno::XComponentContext >& xSM ) 1606 { 1607 ImplSVData* pSVData = ImplGetSVData(); 1608 return pSVData->mpDefInst->createFilePicker( xSM ); 1609 } 1610 1611 Reference< ui::dialogs::XFolderPicker2 > 1612 Application::createFolderPicker( const Reference< uno::XComponentContext >& xSM ) 1613 { 1614 ImplSVData* pSVData = ImplGetSVData(); 1615 return pSVData->mpDefInst->createFolderPicker( xSM ); 1616 } 1617 1618 void Application::setDeInitHook(Link<LinkParamNone*,void> const & hook) { 1619 ImplSVData * pSVData = ImplGetSVData(); 1620 assert(!pSVData->maDeInitHook.IsSet()); 1621 pSVData->maDeInitHook = hook; 1622 // Fake this for VCLXToolkit ctor instantiated from 1623 // postprocess/CppunitTest_services.mk: 1624 pSVData->maAppData.mbInAppMain = true; 1625 } 1626 1627 namespace vcl { namespace lok { 1628 1629 void registerPollCallbacks( 1630 LibreOfficeKitPollCallback pPollCallback, 1631 LibreOfficeKitWakeCallback pWakeCallback, 1632 void *pData) { 1633 1634 ImplSVData * pSVData = ImplGetSVData(); 1635 if (pSVData) 1636 { 1637 pSVData->mpPollCallback = pPollCallback; 1638 pSVData->mpWakeCallback = pWakeCallback; 1639 pSVData->mpPollClosure = pData; 1640 } 1641 } 1642 1643 void unregisterPollCallbacks() 1644 { 1645 ImplSVData * pSVData = ImplGetSVData(); 1646 if (pSVData) 1647 { 1648 // Just set mpPollClosure to null as that is what calling this means, that the callback data 1649 // points to an object that no longer exists. In particular, don't set 1650 // pSVData->mpPollCallback to nullptr as that is used to detect whether Unipoll is in use in 1651 // isUnipoll(). 1652 pSVData->mpPollClosure = nullptr; 1653 } 1654 } 1655 1656 bool isUnipoll() 1657 { 1658 ImplSVData * pSVData = ImplGetSVData(); 1659 return pSVData && pSVData->mpPollCallback != nullptr; 1660 } 1661 1662 } } // namespace lok, namespace vcl 1663 1664 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1665
