bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / app / svapp.cxx
blobc4c3be9699e3c5bcb5a56ecbca3d21526bee3089
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 <config_features.h>
22 #include <osl/file.hxx>
23 #include <osl/thread.hxx>
24 #include <osl/module.hxx>
26 #include <sal/log.hxx>
28 #include <tools/debug.hxx>
29 #include <tools/time.hxx>
30 #include <tools/stream.hxx>
32 #include <unotools/configmgr.hxx>
33 #include <unotools/syslocaleoptions.hxx>
35 #include <vcl/dialog.hxx>
36 #include <vcl/lok.hxx>
37 #include <vcl/floatwin.hxx>
38 #include <vcl/settings.hxx>
39 #include <vcl/keycod.hxx>
40 #include <vcl/event.hxx>
41 #include <vcl/vclevent.hxx>
42 #include <vcl/virdev.hxx>
43 #include <vcl/wrkwin.hxx>
44 #include <vcl/svapp.hxx>
45 #include <vcl/cvtgrf.hxx>
46 #include <vcl/toolkit/unowrap.hxx>
47 #include <vcl/timer.hxx>
48 #include <vcl/scheduler.hxx>
49 #if HAVE_FEATURE_OPENGL
50 #include <vcl/opengl/OpenGLWrapper.hxx>
51 #endif
53 #include <salinst.hxx>
54 #include <salframe.hxx>
55 #include <salsys.hxx>
56 #include <svdata.hxx>
57 #include <displayconnectiondispatch.hxx>
58 #include <window.h>
59 #include <accmgr.hxx>
60 #include <strings.hrc>
61 #include <strings.hxx>
62 #if OSL_DEBUG_LEVEL > 0
63 #include <schedulerimpl.hxx>
64 #endif
66 #include <com/sun/star/uno/Reference.h>
67 #include <com/sun/star/awt/XToolkit.hpp>
68 #include <comphelper/lok.hxx>
69 #include <comphelper/solarmutex.hxx>
70 #include <osl/process.h>
72 #include <cassert>
73 #include <utility>
74 #include <thread>
76 using namespace ::com::sun::star;
77 using namespace ::com::sun::star::uno;
79 namespace {
80 void InitSettings(ImplSVData* pSVData);
83 // keycodes handled internally by VCL
84 static vcl::KeyCode const ReservedKeys[]
86 vcl::KeyCode(KEY_F1,0) ,
87 vcl::KeyCode(KEY_F1,KEY_SHIFT) ,
88 vcl::KeyCode(KEY_F1,KEY_MOD1) ,
89 vcl::KeyCode(KEY_F2,KEY_SHIFT) ,
90 vcl::KeyCode(KEY_F4,KEY_MOD1) ,
91 vcl::KeyCode(KEY_F4,KEY_MOD2) ,
92 vcl::KeyCode(KEY_F4,KEY_MOD1|KEY_MOD2) ,
93 vcl::KeyCode(KEY_F6,0) ,
94 vcl::KeyCode(KEY_F6,KEY_MOD1) ,
95 vcl::KeyCode(KEY_F6,KEY_SHIFT) ,
96 vcl::KeyCode(KEY_F6,KEY_MOD1|KEY_SHIFT) ,
97 vcl::KeyCode(KEY_F10,0)
98 #ifdef UNX
100 vcl::KeyCode(KEY_1,KEY_SHIFT|KEY_MOD1),
101 vcl::KeyCode(KEY_2,KEY_SHIFT|KEY_MOD1),
102 vcl::KeyCode(KEY_3,KEY_SHIFT|KEY_MOD1),
103 vcl::KeyCode(KEY_4,KEY_SHIFT|KEY_MOD1),
104 vcl::KeyCode(KEY_5,KEY_SHIFT|KEY_MOD1),
105 vcl::KeyCode(KEY_6,KEY_SHIFT|KEY_MOD1),
106 vcl::KeyCode(KEY_7,KEY_SHIFT|KEY_MOD1),
107 vcl::KeyCode(KEY_8,KEY_SHIFT|KEY_MOD1),
108 vcl::KeyCode(KEY_9,KEY_SHIFT|KEY_MOD1),
109 vcl::KeyCode(KEY_0,KEY_SHIFT|KEY_MOD1),
110 vcl::KeyCode(KEY_ADD,KEY_SHIFT|KEY_MOD1)
111 #endif
114 extern "C" {
115 typedef UnoWrapperBase* (*FN_TkCreateUnoWrapper)();
118 struct ImplPostEventData
120 VclEventId const mnEvent;
121 VclPtr<vcl::Window> mpWin;
122 ImplSVEvent * mnEventId;
123 KeyEvent maKeyEvent;
124 MouseEvent maMouseEvent;
125 GestureEvent maGestureEvent;
127 ImplPostEventData(VclEventId nEvent, vcl::Window* pWin, const KeyEvent& rKeyEvent)
128 : mnEvent(nEvent)
129 , mpWin(pWin)
130 , mnEventId(nullptr)
131 , maKeyEvent(rKeyEvent)
133 ImplPostEventData(VclEventId nEvent, vcl::Window* pWin, const MouseEvent& rMouseEvent)
134 : mnEvent(nEvent)
135 , mpWin(pWin)
136 , mnEventId(nullptr)
137 , maMouseEvent(rMouseEvent)
139 ImplPostEventData(VclEventId nEvent, vcl::Window* pWin, const GestureEvent& rGestureEvent)
140 : mnEvent(nEvent)
141 , mpWin(pWin)
142 , mnEventId(nullptr)
143 , maGestureEvent(rGestureEvent)
147 Application* GetpApp()
149 ImplSVData* pSVData = ImplGetSVData();
150 if ( !pSVData )
151 return nullptr;
152 return pSVData->mpApp;
155 Application::Application()
157 // useful for themes at least, perhaps extensions too
158 OUString aVar("LIBO_VERSION"), aValue(LIBO_VERSION_DOTTED);
159 osl_setEnvironment(aVar.pData, aValue.pData);
161 ImplGetSVData()->mpApp = this;
164 Application::~Application()
166 ImplDeInitSVData();
167 ImplGetSVData()->mpApp = nullptr;
170 int Application::Main()
172 SAL_WARN("vcl", "Application is a base class and should be overridden.");
173 return EXIT_SUCCESS;
176 bool Application::QueryExit()
178 WorkWindow* pAppWin = ImplGetSVData()->maWinData.mpAppWin;
180 // call the close handler of the application window
181 if ( pAppWin )
182 return pAppWin->Close();
183 else
184 return true;
187 void Application::Init()
191 void Application::InitFinished()
195 void Application::DeInit()
199 sal_uInt16 Application::GetCommandLineParamCount()
201 return static_cast<sal_uInt16>(osl_getCommandArgCount());
204 OUString Application::GetCommandLineParam( sal_uInt16 nParam )
206 OUString aParam;
207 osl_getCommandArg( nParam, &aParam.pData );
208 return aParam;
211 OUString Application::GetAppFileName()
213 ImplSVData* pSVData = ImplGetSVData();
214 SAL_WARN_IF( !pSVData->maAppData.mxAppFileName, "vcl", "AppFileName should be set to something after SVMain!" );
215 if ( pSVData->maAppData.mxAppFileName )
216 return *pSVData->maAppData.mxAppFileName;
219 * provide a fallback for people without initialized vcl here (like setup
220 * in responsefile mode)
222 OUString aAppFileName;
223 OUString aExeFileName;
224 osl_getExecutableFile(&aExeFileName.pData);
226 // convert path to native file format
227 osl::FileBase::getSystemPathFromFileURL(aExeFileName, aAppFileName);
229 return aAppFileName;
232 void Application::Exception( ExceptionCategory nCategory )
234 switch ( nCategory )
236 // System has precedence (so do nothing)
237 case ExceptionCategory::System:
238 case ExceptionCategory::UserInterface:
239 break;
241 #ifdef DBG_UTIL
242 case ExceptionCategory::ResourceNotLoaded:
243 Abort("Resource not loaded");
244 break;
245 default:
246 Abort("Unknown Error");
247 break;
248 #else
249 default:
250 Abort(OUString());
251 break;
252 #endif
256 void Application::Abort( const OUString& rErrorText )
258 //HACK: Dump core iff --norestore command line argument is given (assuming
259 // this process is run by developers who are interested in cores, vs. end
260 // users who are not):
261 bool dumpCore = false;
262 sal_uInt16 n = GetCommandLineParamCount();
263 for (sal_uInt16 i = 0; i != n; ++i) {
264 if (GetCommandLineParam(i) == "--norestore") {
265 dumpCore = true;
266 break;
269 #if OSL_DEBUG_LEVEL > 0
270 dumpCore = true;
271 #endif
273 SalAbort( rErrorText, dumpCore );
276 sal_uLong Application::GetReservedKeyCodeCount()
278 return SAL_N_ELEMENTS(ReservedKeys);
281 const vcl::KeyCode* Application::GetReservedKeyCode( sal_uLong i )
283 if( i >= GetReservedKeyCodeCount() )
284 return nullptr;
285 else
286 return &ReservedKeys[i];
289 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplEndAllPopupsMsg, void*, void )
291 ImplSVData* pSVData = ImplGetSVData();
292 while (pSVData->maWinData.mpFirstFloat)
293 pSVData->maWinData.mpFirstFloat->EndPopupMode(FloatWinPopupEndFlags::Cancel);
296 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplEndAllDialogsMsg, void*, void )
298 vcl::Window* pAppWindow = Application::GetFirstTopLevelWindow();
299 while (pAppWindow)
301 Dialog::EndAllDialogs(pAppWindow);
302 pAppWindow = Application::GetNextTopLevelWindow(pAppWindow);
306 void Application::EndAllDialogs()
308 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplEndAllDialogsMsg ) );
311 void Application::EndAllPopups()
313 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplEndAllPopupsMsg ) );
317 namespace
319 VclPtr<vcl::Window> GetEventWindow()
321 VclPtr<vcl::Window> xWin(Application::GetFirstTopLevelWindow());
322 while (xWin)
324 if (xWin->IsVisible())
325 break;
326 xWin.reset(Application::GetNextTopLevelWindow(xWin));
328 return xWin;
331 bool InjectKeyEvent(SvStream& rStream)
333 VclPtr<vcl::Window> xWin(GetEventWindow());
334 if (!xWin)
335 return false;
337 // skip the first available cycle and insert on the next one when we
338 // are trying the initial event, flagged by a triggered but undeleted
339 // mpEventTestingIdle
340 ImplSVData* pSVData = ImplGetSVData();
341 if (pSVData->maAppData.mpEventTestingIdle)
343 delete pSVData->maAppData.mpEventTestingIdle;
344 pSVData->maAppData.mpEventTestingIdle = nullptr;
345 return false;
348 sal_uInt16 nCode, nCharCode;
349 rStream.ReadUInt16(nCode);
350 rStream.ReadUInt16(nCharCode);
351 if (!rStream.good())
352 return false;
354 KeyEvent aVCLKeyEvt(nCharCode, nCode);
355 Application::PostKeyEvent(VclEventId::WindowKeyInput, xWin.get(), &aVCLKeyEvt);
356 Application::PostKeyEvent(VclEventId::WindowKeyUp, xWin.get(), &aVCLKeyEvt);
357 return true;
360 void CloseDialogsAndQuit()
362 Application::EndAllPopups();
363 Application::EndAllDialogs();
364 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplPrepareExitMsg ) );
368 IMPL_LINK_NOARG(ImplSVAppData, VclEventTestingHdl, Timer *, void)
370 if (Application::AnyInput())
372 mpEventTestingIdle->Start();
374 else
376 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplVclEventTestingHdl ) );
380 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplVclEventTestingHdl, void*, void )
382 ImplSVData* pSVData = ImplGetSVData();
383 SAL_INFO("vcl.eventtesting", "EventTestLimit is " << pSVData->maAppData.mnEventTestLimit);
384 if (pSVData->maAppData.mnEventTestLimit == 0)
386 delete pSVData->maAppData.mpEventTestInput;
387 SAL_INFO("vcl.eventtesting", "Event Limit reached, exiting" << pSVData->maAppData.mnEventTestLimit);
388 CloseDialogsAndQuit();
390 else
392 if (InjectKeyEvent(*pSVData->maAppData.mpEventTestInput))
393 --pSVData->maAppData.mnEventTestLimit;
394 if (!pSVData->maAppData.mpEventTestInput->good())
396 SAL_INFO("vcl.eventtesting", "Event Input exhausted, exit next cycle");
397 pSVData->maAppData.mnEventTestLimit = 0;
399 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplVclEventTestingHdl ) );
403 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplPrepareExitMsg, void*, void )
405 //now close top level frames
406 (void)GetpApp()->QueryExit();
409 void Application::Execute()
411 ImplSVData* pSVData = ImplGetSVData();
412 pSVData->maAppData.mbInAppExecute = true;
413 pSVData->maAppData.mbAppQuit = false;
415 if (Application::IsEventTestingModeEnabled())
417 pSVData->maAppData.mnEventTestLimit = 50;
418 pSVData->maAppData.mpEventTestingIdle = new Idle("eventtesting");
419 pSVData->maAppData.mpEventTestingIdle->SetInvokeHandler(LINK(&(pSVData->maAppData), ImplSVAppData, VclEventTestingHdl));
420 pSVData->maAppData.mpEventTestingIdle->SetPriority(TaskPriority::HIGH_IDLE);
421 pSVData->maAppData.mpEventTestInput = new SvFileStream("eventtesting", StreamMode::READ);
422 pSVData->maAppData.mpEventTestingIdle->Start();
425 while ( !pSVData->maAppData.mbAppQuit )
426 Application::Yield();
428 pSVData->maAppData.mbInAppExecute = false;
431 static bool ImplYield(bool i_bWait, bool i_bAllEvents)
433 ImplSVData* pSVData = ImplGetSVData();
435 SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait ? "wait" : "no wait") <<
436 ": " << (i_bAllEvents ? "all events" : "one event"));
438 // there's a data race here on WNT only because ImplYield may be
439 // called without SolarMutex; but the only remaining use of mnDispatchLevel
440 // is in OSX specific code
441 pSVData->maAppData.mnDispatchLevel++;
443 // do not wait for events if application was already quit; in that
444 // case only dispatch events already available
445 bool bProcessedEvent = pSVData->mpDefInst->DoYield(
446 i_bWait && !pSVData->maAppData.mbAppQuit, i_bAllEvents );
448 pSVData->maAppData.mnDispatchLevel--;
450 DBG_TESTSOLARMUTEX(); // must be locked on return from Yield
452 SAL_INFO("vcl.schedule", "Leave ImplYield with return " << bProcessedEvent );
453 return bProcessedEvent;
456 bool Application::Reschedule( bool i_bAllEvents )
458 return ImplYield(false, i_bAllEvents);
461 void Scheduler::ProcessEventsToIdle()
463 int nSanity = 1;
464 while( Application::Reschedule( true ) )
466 if (0 == ++nSanity % 1000)
468 SAL_WARN("vcl.schedule", "ProcessEventsToIdle: " << nSanity);
471 #if OSL_DEBUG_LEVEL > 0
472 // If we yield from a non-main thread we just can guarantee that all idle
473 // events were processed at some point, but our check can't prevent further
474 // processing in the main thread, which may add new events, so skip it.
475 const ImplSVData* pSVData = ImplGetSVData();
476 if (!pSVData->mpDefInst->IsMainThread())
477 return;
478 for (int nTaskPriority = 0; nTaskPriority < PRIO_COUNT; ++nTaskPriority)
480 const ImplSchedulerData* pSchedulerData = pSVData->maSchedCtx.mpFirstSchedulerData[nTaskPriority];
481 while (pSchedulerData)
483 if (pSchedulerData->mpTask && !pSchedulerData->mbInScheduler)
485 Idle *pIdle = dynamic_cast<Idle*>(pSchedulerData->mpTask);
486 if (pIdle && pIdle->IsActive())
488 SAL_WARN("vcl.schedule", "Unprocessed Idle: "
489 << pIdle << " " << pIdle->GetDebugName());
492 pSchedulerData = pSchedulerData->mpNext;
495 #endif
498 extern "C" {
499 /// used by unit tests that test only via the LOK API
500 SAL_DLLPUBLIC_EXPORT void unit_lok_process_events_to_idle()
502 const SolarMutexGuard aGuard;
503 Scheduler::ProcessEventsToIdle();
507 void Application::Yield()
509 ImplYield(true, false);
512 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplQuitMsg, void*, void )
514 ImplGetSVData()->maAppData.mbAppQuit = true;
517 void Application::Quit()
519 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplQuitMsg ) );
522 comphelper::SolarMutex& Application::GetSolarMutex()
524 ImplSVData* pSVData = ImplGetSVData();
525 return *(pSVData->mpDefInst->GetYieldMutex());
528 bool Application::IsMainThread()
530 return ImplGetSVData()->mnMainThreadId == osl::Thread::getCurrentIdentifier();
533 sal_uInt32 Application::ReleaseSolarMutex()
535 ImplSVData* pSVData = ImplGetSVData();
536 return pSVData->mpDefInst->ReleaseYieldMutexAll();
539 void Application::AcquireSolarMutex( sal_uInt32 nCount )
541 ImplSVData* pSVData = ImplGetSVData();
542 pSVData->mpDefInst->AcquireYieldMutex( nCount );
545 bool Application::IsInMain()
547 ImplSVData* pSVData = ImplGetSVData();
548 return pSVData && pSVData->maAppData.mbInAppMain;
551 bool Application::IsInExecute()
553 return ImplGetSVData()->maAppData.mbInAppExecute;
556 bool Application::IsInModalMode()
558 return (ImplGetSVData()->maAppData.mnModalMode != 0);
561 sal_uInt16 Application::GetDispatchLevel()
563 return ImplGetSVData()->maAppData.mnDispatchLevel;
566 bool Application::AnyInput( VclInputFlags nType )
568 return ImplGetSVData()->mpDefInst->AnyInput( nType );
571 sal_uInt64 Application::GetLastInputInterval()
573 return (tools::Time::GetSystemTicks()-ImplGetSVData()->maAppData.mnLastInputTime);
576 bool Application::IsUICaptured()
578 ImplSVData* pSVData = ImplGetSVData();
580 // If mouse was captured, or if in tracking- or in select-mode of a floatingwindow (e.g. menus
581 // or pulldown toolboxes) another window should be created
582 // D&D active !!!
583 return pSVData->maWinData.mpCaptureWin || pSVData->maWinData.mpTrackWin ||
584 pSVData->maWinData.mpFirstFloat || nImplSysDialog;
587 void Application::OverrideSystemSettings( AllSettings& /*rSettings*/ )
591 void Application::MergeSystemSettings( AllSettings& rSettings )
593 vcl::Window* pWindow = ImplGetSVData()->maWinData.mpFirstFrame;
594 if( ! pWindow )
595 pWindow = ImplGetDefaultWindow();
596 if( pWindow )
598 ImplSVData* pSVData = ImplGetSVData();
599 if ( !pSVData->maAppData.mbSettingsInit )
601 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
602 pWindow->ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings );
603 pSVData->maAppData.mbSettingsInit = true;
605 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
606 pWindow->ImplUpdateGlobalSettings( rSettings, false );
610 void Application::SetSettings( const AllSettings& rSettings )
612 const SolarMutexGuard aGuard;
614 ImplSVData* pSVData = ImplGetSVData();
615 if ( !pSVData->maAppData.mpSettings )
617 InitSettings(pSVData);
618 *pSVData->maAppData.mpSettings = rSettings;
620 else
622 AllSettings aOldSettings = *pSVData->maAppData.mpSettings;
623 if (aOldSettings.GetUILanguageTag().getLanguageType() != rSettings.GetUILanguageTag().getLanguageType() &&
624 pSVData->mbResLocaleSet)
626 pSVData->mbResLocaleSet = false;
628 *pSVData->maAppData.mpSettings = rSettings;
629 AllSettingsFlags nChangeFlags = aOldSettings.GetChangeFlags( *pSVData->maAppData.mpSettings );
630 if ( bool(nChangeFlags) )
632 DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, &aOldSettings, nChangeFlags );
634 // notify data change handler
635 ImplCallEventListenersApplicationDataChanged( &aDCEvt);
637 // Update all windows
638 vcl::Window* pFirstFrame = pSVData->maWinData.mpFirstFrame;
639 // Reset data that needs to be re-calculated
640 long nOldDPIX = 0;
641 long nOldDPIY = 0;
642 if ( pFirstFrame )
644 nOldDPIX = pFirstFrame->GetDPIX();
645 nOldDPIY = pFirstFrame->GetDPIY();
646 vcl::Window::ImplInitAppFontData(pFirstFrame);
648 vcl::Window* pFrame = pFirstFrame;
649 while ( pFrame )
651 // call UpdateSettings from ClientWindow in order to prevent updating data twice
652 vcl::Window* pClientWin = pFrame;
653 while ( pClientWin->ImplGetClientWindow() )
654 pClientWin = pClientWin->ImplGetClientWindow();
655 pClientWin->UpdateSettings( rSettings, true );
657 vcl::Window* pTempWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
658 while ( pTempWin )
660 // call UpdateSettings from ClientWindow in order to prevent updating data twice
661 pClientWin = pTempWin;
662 while ( pClientWin->ImplGetClientWindow() )
663 pClientWin = pClientWin->ImplGetClientWindow();
664 pClientWin->UpdateSettings( rSettings, true );
665 pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
668 pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
671 // if DPI resolution for screen output was changed set the new resolution for all
672 // screen compatible VirDev's
673 pFirstFrame = pSVData->maWinData.mpFirstFrame;
674 if ( pFirstFrame )
676 if ( (pFirstFrame->GetDPIX() != nOldDPIX) ||
677 (pFirstFrame->GetDPIY() != nOldDPIY) )
679 VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
680 while ( pVirDev )
682 if ( pVirDev->mbScreenComp &&
683 (pVirDev->GetDPIX() == nOldDPIX) &&
684 (pVirDev->GetDPIY() == nOldDPIY) )
686 pVirDev->SetDPIX( pFirstFrame->GetDPIX() );
687 pVirDev->SetDPIY( pFirstFrame->GetDPIY() );
688 if ( pVirDev->IsMapModeEnabled() )
690 MapMode aMapMode = pVirDev->GetMapMode();
691 pVirDev->SetMapMode();
692 pVirDev->SetMapMode( aMapMode );
696 pVirDev = pVirDev->mpNext;
704 const AllSettings& Application::GetSettings()
706 ImplSVData* pSVData = ImplGetSVData();
707 if ( !pSVData->maAppData.mpSettings )
709 InitSettings(pSVData);
712 return *(pSVData->maAppData.mpSettings);
715 namespace {
717 void InitSettings(ImplSVData* pSVData)
719 assert(!pSVData->maAppData.mpSettings && "initialization should not happen twice!");
721 pSVData->maAppData.mpSettings.reset(new AllSettings());
722 if (!utl::ConfigManager::IsFuzzing())
724 pSVData->maAppData.mpCfgListener = new LocaleConfigurationListener;
725 pSVData->maAppData.mpSettings->GetSysLocale().GetOptions().AddListener( pSVData->maAppData.mpCfgListener );
731 void Application::NotifyAllWindows( DataChangedEvent& rDCEvt )
733 ImplSVData* pSVData = ImplGetSVData();
734 vcl::Window* pFrame = pSVData->maWinData.mpFirstFrame;
735 while ( pFrame )
737 pFrame->NotifyAllChildren( rDCEvt );
739 vcl::Window* pSysWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
740 while ( pSysWin )
742 pSysWin->NotifyAllChildren( rDCEvt );
743 pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
746 pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
750 void Application::ImplCallEventListenersApplicationDataChanged( void* pData )
752 ImplSVData* pSVData = ImplGetSVData();
753 VclWindowEvent aEvent( nullptr, VclEventId::ApplicationDataChanged, pData );
755 pSVData->maAppData.maEventListeners.Call( aEvent );
758 void Application::ImplCallEventListeners( VclSimpleEvent& rEvent )
760 ImplSVData* pSVData = ImplGetSVData();
761 pSVData->maAppData.maEventListeners.Call( rEvent );
764 void Application::AddEventListener( const Link<VclSimpleEvent&,void>& rEventListener )
766 ImplSVData* pSVData = ImplGetSVData();
767 pSVData->maAppData.maEventListeners.addListener( rEventListener );
770 void Application::RemoveEventListener( const Link<VclSimpleEvent&,void>& rEventListener )
772 ImplSVData* pSVData = ImplGetSVData();
773 pSVData->maAppData.maEventListeners.removeListener( rEventListener );
776 void Application::AddKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener )
778 ImplSVData* pSVData = ImplGetSVData();
779 pSVData->maAppData.maKeyListeners.push_back( rKeyListener );
782 void Application::RemoveKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener )
784 ImplSVData* pSVData = ImplGetSVData();
785 auto & rVec = pSVData->maAppData.maKeyListeners;
786 rVec.erase( std::remove(rVec.begin(), rVec.end(), rKeyListener ), rVec.end() );
789 bool Application::HandleKey( VclEventId nEvent, vcl::Window *pWin, KeyEvent* pKeyEvent )
791 // let listeners process the key event
792 VclWindowEvent aEvent( pWin, nEvent, static_cast<void *>(pKeyEvent) );
794 ImplSVData* pSVData = ImplGetSVData();
796 if ( pSVData->maAppData.maKeyListeners.empty() )
797 return false;
799 bool bProcessed = false;
800 // Copy the list, because this can be destroyed when calling a Link...
801 std::vector<Link<VclWindowEvent&,bool>> aCopy( pSVData->maAppData.maKeyListeners );
802 for ( const Link<VclWindowEvent&,bool>& rLink : aCopy )
804 if( rLink.Call( aEvent ) )
806 bProcessed = true;
807 break;
810 return bProcessed;
813 ImplSVEvent * Application::PostKeyEvent( VclEventId nEvent, vcl::Window *pWin, KeyEvent const * pKeyEvent )
815 const SolarMutexGuard aGuard;
816 ImplSVEvent * nEventId = nullptr;
818 if( pWin && pKeyEvent )
820 std::unique_ptr<ImplPostEventData> pPostEventData(new ImplPostEventData( nEvent, pWin, *pKeyEvent ));
822 nEventId = PostUserEvent(
823 LINK( nullptr, Application, PostEventHandler ),
824 pPostEventData.get() );
826 if( nEventId )
828 pPostEventData->mnEventId = nEventId;
829 ImplGetSVData()->maAppData.maPostedEventList.emplace_back( pWin, pPostEventData.release() );
833 return nEventId;
836 ImplSVEvent* Application::PostGestureEvent(VclEventId nEvent, vcl::Window* pWin, GestureEvent const * pGestureEvent)
838 const SolarMutexGuard aGuard;
839 ImplSVEvent * nEventId = nullptr;
841 if (pWin && pGestureEvent)
843 Point aTransformedPosition(pGestureEvent->mnX, pGestureEvent->mnY);
845 aTransformedPosition.AdjustX(pWin->GetOutOffXPixel());
846 aTransformedPosition.AdjustY(pWin->GetOutOffYPixel());
848 const GestureEvent aGestureEvent(
849 sal_Int32(aTransformedPosition.X()),
850 sal_Int32(aTransformedPosition.Y()),
851 pGestureEvent->meEventType,
852 pGestureEvent->mnOffset,
853 pGestureEvent->meOrientation
856 std::unique_ptr<ImplPostEventData> pPostEventData(new ImplPostEventData(nEvent, pWin, aGestureEvent));
858 nEventId = PostUserEvent(
859 LINK( nullptr, Application, PostEventHandler ),
860 pPostEventData.get());
862 if (nEventId)
864 pPostEventData->mnEventId = nEventId;
865 ImplGetSVData()->maAppData.maPostedEventList.emplace_back(pWin, pPostEventData.release());
869 return nEventId;
872 ImplSVEvent* Application::PostMouseEvent( VclEventId nEvent, vcl::Window *pWin, MouseEvent const * pMouseEvent )
874 const SolarMutexGuard aGuard;
875 ImplSVEvent * nEventId = nullptr;
877 if( pWin && pMouseEvent )
879 Point aTransformedPos( pMouseEvent->GetPosPixel() );
881 // LOK uses (0, 0) as the origin of all windows; don't offset.
882 if (!comphelper::LibreOfficeKit::isActive())
884 aTransformedPos.AdjustX(pWin->GetOutOffXPixel());
885 aTransformedPos.AdjustY(pWin->GetOutOffYPixel());
888 const MouseEvent aTransformedEvent( aTransformedPos, pMouseEvent->GetClicks(), pMouseEvent->GetMode(),
889 pMouseEvent->GetButtons(), pMouseEvent->GetModifier() );
891 std::unique_ptr<ImplPostEventData> pPostEventData(new ImplPostEventData( nEvent, pWin, aTransformedEvent ));
893 nEventId = PostUserEvent(
894 LINK( nullptr, Application, PostEventHandler ),
895 pPostEventData.get() );
897 if( nEventId )
899 pPostEventData->mnEventId = nEventId;
900 ImplGetSVData()->maAppData.maPostedEventList.emplace_back( pWin, pPostEventData.release() );
904 return nEventId;
908 IMPL_STATIC_LINK( Application, PostEventHandler, void*, pCallData, void )
910 const SolarMutexGuard aGuard;
911 ImplPostEventData* pData = static_cast< ImplPostEventData * >( pCallData );
912 const void* pEventData;
913 SalEvent nEvent;
914 ImplSVEvent * const nEventId = pData->mnEventId;
916 switch( pData->mnEvent )
918 case VclEventId::WindowMouseMove:
919 nEvent = SalEvent::ExternalMouseMove;
920 pEventData = &pData->maMouseEvent;
921 break;
923 case VclEventId::WindowMouseButtonDown:
924 nEvent = SalEvent::ExternalMouseButtonDown;
925 pEventData = &pData->maMouseEvent;
926 break;
928 case VclEventId::WindowMouseButtonUp:
929 nEvent = SalEvent::ExternalMouseButtonUp;
930 pEventData = &pData->maMouseEvent;
931 break;
933 case VclEventId::WindowKeyInput:
934 nEvent = SalEvent::ExternalKeyInput;
935 pEventData = &pData->maKeyEvent;
936 break;
938 case VclEventId::WindowKeyUp:
939 nEvent = SalEvent::ExternalKeyUp;
940 pEventData = &pData->maKeyEvent;
941 break;
943 case VclEventId::WindowGestureEvent:
944 nEvent = SalEvent::ExternalGesture;
945 pEventData = &pData->maGestureEvent;
946 break;
948 default:
949 nEvent = SalEvent::NONE;
950 pEventData = nullptr;
951 break;
954 if( pData->mpWin && pData->mpWin->mpWindowImpl->mpFrameWindow.get() && pEventData )
955 ImplWindowFrameProc( pData->mpWin->mpWindowImpl->mpFrameWindow.get(), nEvent, pEventData );
957 // remove this event from list of posted events, watch for destruction of internal data
958 auto svdata = ImplGetSVData();
959 ::std::vector< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() );
961 while( aIter != svdata->maAppData.maPostedEventList.end() )
963 if( nEventId == (*aIter).second->mnEventId )
965 delete (*aIter).second;
966 aIter = svdata->maAppData.maPostedEventList.erase( aIter );
968 else
969 ++aIter;
973 void Application::RemoveMouseAndKeyEvents( vcl::Window* pWin )
975 const SolarMutexGuard aGuard;
977 // remove all events for specific window, watch for destruction of internal data
978 auto svdata = ImplGetSVData();
979 ::std::vector< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() );
981 while( aIter != svdata->maAppData.maPostedEventList.end() )
983 if( pWin == (*aIter).first )
985 if( (*aIter).second->mnEventId )
986 RemoveUserEvent( (*aIter).second->mnEventId );
988 delete (*aIter).second;
989 aIter = svdata->maAppData.maPostedEventList.erase( aIter );
991 else
992 ++aIter;
996 ImplSVEvent * Application::PostUserEvent( const Link<void*,void>& rLink, void* pCaller,
997 bool bReferenceLink )
999 vcl::Window* pDefWindow = ImplGetDefaultWindow();
1000 if ( pDefWindow == nullptr )
1001 return nullptr;
1003 std::unique_ptr<ImplSVEvent> pSVEvent(new ImplSVEvent);
1004 pSVEvent->mpData = pCaller;
1005 pSVEvent->maLink = rLink;
1006 pSVEvent->mpWindow = nullptr;
1007 pSVEvent->mbCall = true;
1008 if (bReferenceLink)
1010 SolarMutexGuard aGuard;
1011 // Double check that this is indeed a vcl::Window instance.
1012 assert(dynamic_cast<vcl::Window *>(
1013 static_cast<OutputDevice *>(rLink.GetInstance())) ==
1014 static_cast<vcl::Window *>(rLink.GetInstance()));
1015 pSVEvent->mpInstanceRef = static_cast<vcl::Window *>(rLink.GetInstance());
1018 auto pTmpEvent = pSVEvent.get();
1019 if (!pDefWindow->ImplGetFrame()->PostEvent( std::move(pSVEvent) ))
1020 return nullptr;
1021 return pTmpEvent;
1024 void Application::RemoveUserEvent( ImplSVEvent * nUserEvent )
1026 if(nUserEvent)
1028 SAL_WARN_IF( nUserEvent->mpWindow, "vcl",
1029 "Application::RemoveUserEvent(): Event is send to a window" );
1030 SAL_WARN_IF( !nUserEvent->mbCall, "vcl",
1031 "Application::RemoveUserEvent(): Event is already removed" );
1033 nUserEvent->mpWindow.clear();
1034 nUserEvent->mpInstanceRef.clear();
1035 nUserEvent->mbCall = false;
1039 void Application::LockFontUpdates(bool bLock)
1041 OutputDevice::LockFontUpdates(bLock);
1044 WorkWindow* Application::GetAppWindow()
1046 return ImplGetSVData()->maWinData.mpAppWin;
1049 vcl::Window* Application::GetFocusWindow()
1051 return ImplGetSVData()->maWinData.mpFocusWin;
1054 OutputDevice* Application::GetDefaultDevice()
1056 return ImplGetDefaultWindow();
1059 vcl::Window* Application::GetFirstTopLevelWindow()
1061 ImplSVData* pSVData = ImplGetSVData();
1062 return pSVData->maWinData.mpFirstFrame;
1065 vcl::Window* Application::GetNextTopLevelWindow( vcl::Window const * pWindow )
1067 return pWindow->mpWindowImpl->mpFrameData->mpNextFrame;
1070 long Application::GetTopWindowCount()
1072 long nRet = 0;
1073 ImplSVData* pSVData = ImplGetSVData();
1074 vcl::Window *pWin = pSVData ? pSVData->maWinData.mpFirstFrame.get() : nullptr;
1075 while( pWin )
1077 if( pWin->ImplGetWindow()->IsTopWindow() )
1078 nRet++;
1079 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1081 return nRet;
1084 vcl::Window* Application::GetTopWindow( long nIndex )
1086 long nIdx = 0;
1087 ImplSVData* pSVData = ImplGetSVData();
1088 vcl::Window *pWin = pSVData ? pSVData->maWinData.mpFirstFrame.get() : nullptr;
1089 while( pWin )
1091 if( pWin->ImplGetWindow()->IsTopWindow() )
1093 if( nIdx == nIndex )
1094 return pWin->ImplGetWindow();
1095 else
1096 nIdx++;
1098 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1100 return nullptr;
1103 vcl::Window* Application::GetActiveTopWindow()
1105 vcl::Window *pWin = ImplGetSVData()->maWinData.mpFocusWin;
1106 while( pWin )
1108 if( pWin->IsTopWindow() )
1109 return pWin;
1110 pWin = pWin->mpWindowImpl->mpParent;
1112 return nullptr;
1115 void Application::SetAppName( const OUString& rUniqueName )
1117 ImplSVData* pSVData = ImplGetSVData();
1118 pSVData->maAppData.mxAppName = rUniqueName;
1121 OUString Application::GetAppName()
1123 ImplSVData* pSVData = ImplGetSVData();
1124 if ( pSVData->maAppData.mxAppName )
1125 return *(pSVData->maAppData.mxAppName);
1126 else
1127 return OUString();
1130 OUString Application::GetHWOSConfInfo()
1132 ImplSVData* pSVData = ImplGetSVData();
1133 OUStringBuffer aDetails;
1135 aDetails.append( VclResId(SV_APP_CPUTHREADS) );
1136 aDetails.append( static_cast<sal_Int32>(std::thread::hardware_concurrency()) );
1137 aDetails.append( "; " );
1139 OUString aVersion;
1140 if ( pSVData && pSVData->mpDefInst )
1141 aVersion = pSVData->mpDefInst->getOSVersion();
1142 else
1143 aVersion = "-";
1145 aDetails.append( VclResId(SV_APP_OSVERSION) );
1146 aDetails.append( aVersion );
1147 aDetails.append( "; " );
1149 aDetails.append( VclResId(SV_APP_UIRENDER) );
1150 #if HAVE_FEATURE_OPENGL
1151 if ( OpenGLWrapper::isVCLOpenGLEnabled() )
1152 aDetails.append( VclResId(SV_APP_GL) );
1153 else
1154 #endif
1155 aDetails.append( VclResId(SV_APP_DEFAULT) );
1156 aDetails.append( "; " );
1158 #if (defined LINUX || defined _WIN32 || defined MACOSX)
1159 aDetails.append( SV_APP_VCLBACKEND );
1160 aDetails.append( GetToolkitName() );
1161 aDetails.append( "; " );
1162 #endif
1164 return aDetails.makeStringAndClear();
1167 void Application::SetDisplayName( const OUString& rName )
1169 ImplSVData* pSVData = ImplGetSVData();
1170 pSVData->maAppData.mxDisplayName = rName;
1173 OUString Application::GetDisplayName()
1175 ImplSVData* pSVData = ImplGetSVData();
1176 if ( pSVData->maAppData.mxDisplayName )
1177 return *(pSVData->maAppData.mxDisplayName);
1178 else if ( pSVData->maWinData.mpAppWin )
1179 return pSVData->maWinData.mpAppWin->GetText();
1180 else
1181 return OUString();
1184 unsigned int Application::GetScreenCount()
1186 SalSystem* pSys = ImplGetSalSystem();
1187 return pSys ? pSys->GetDisplayScreenCount() : 0;
1190 bool Application::IsUnifiedDisplay()
1192 SalSystem* pSys = ImplGetSalSystem();
1193 return pSys == nullptr || pSys->IsUnifiedDisplay();
1196 unsigned int Application::GetDisplayBuiltInScreen()
1198 SalSystem* pSys = ImplGetSalSystem();
1199 return pSys ? pSys->GetDisplayBuiltInScreen() : 0;
1202 unsigned int Application::GetDisplayExternalScreen()
1204 // This is really unpleasant, in theory we could have multiple
1205 // external displays etc.
1206 int nExternal(0);
1207 switch (GetDisplayBuiltInScreen())
1209 case 0:
1210 nExternal = 1;
1211 break;
1212 case 1:
1213 nExternal = 0;
1214 break;
1215 default:
1216 // When the built-in display is neither 0 nor 1
1217 // then place the full-screen presentation on the
1218 // first available screen.
1219 nExternal = 0;
1220 break;
1222 return nExternal;
1225 tools::Rectangle Application::GetScreenPosSizePixel( unsigned int nScreen )
1227 SalSystem* pSys = ImplGetSalSystem();
1228 return pSys ? pSys->GetDisplayScreenPosSizePixel( nScreen ) : tools::Rectangle();
1231 namespace {
1232 unsigned long calcDistSquare( const Point& i_rPoint, const tools::Rectangle& i_rRect )
1234 const Point aRectCenter( (i_rRect.Left() + i_rRect.Right())/2,
1235 (i_rRect.Top() + i_rRect.Bottom())/ 2 );
1236 const long nDX = aRectCenter.X() - i_rPoint.X();
1237 const long nDY = aRectCenter.Y() - i_rPoint.Y();
1238 return nDX*nDX + nDY*nDY;
1242 unsigned int Application::GetBestScreen( const tools::Rectangle& i_rRect )
1244 if( !IsUnifiedDisplay() )
1245 return GetDisplayBuiltInScreen();
1247 const unsigned int nScreens = GetScreenCount();
1248 unsigned int nBestMatchScreen = 0;
1249 unsigned long nOverlap = 0;
1250 for( unsigned int i = 0; i < nScreens; i++ )
1252 const tools::Rectangle aCurScreenRect( GetScreenPosSizePixel( i ) );
1253 // if a screen contains the rectangle completely it is obviously the best screen
1254 if( aCurScreenRect.IsInside( i_rRect ) )
1255 return i;
1256 // next the screen which contains most of the area of the rect is the best
1257 tools::Rectangle aIntersection( aCurScreenRect.GetIntersection( i_rRect ) );
1258 if( ! aIntersection.IsEmpty() )
1260 const unsigned long nCurOverlap( aIntersection.GetWidth() * aIntersection.GetHeight() );
1261 if( nCurOverlap > nOverlap )
1263 nOverlap = nCurOverlap;
1264 nBestMatchScreen = i;
1268 if( nOverlap > 0 )
1269 return nBestMatchScreen;
1271 // finally the screen which center is nearest to the rect is the best
1272 const Point aCenter( (i_rRect.Left() + i_rRect.Right())/2,
1273 (i_rRect.Top() + i_rRect.Bottom())/2 );
1274 unsigned long nDist = ULONG_MAX;
1275 for( unsigned int i = 0; i < nScreens; i++ )
1277 const tools::Rectangle aCurScreenRect( GetScreenPosSizePixel( i ) );
1278 const unsigned long nCurDist( calcDistSquare( aCenter, aCurScreenRect ) );
1279 if( nCurDist < nDist )
1281 nBestMatchScreen = i;
1282 nDist = nCurDist;
1285 return nBestMatchScreen;
1288 bool Application::InsertAccel( Accelerator* pAccel )
1290 ImplSVData* pSVData = ImplGetSVData();
1292 if ( !pSVData->maAppData.mpAccelMgr )
1293 pSVData->maAppData.mpAccelMgr = new ImplAccelManager();
1294 return pSVData->maAppData.mpAccelMgr->InsertAccel( pAccel );
1297 void Application::RemoveAccel( Accelerator const * pAccel )
1299 ImplSVData* pSVData = ImplGetSVData();
1301 if ( pSVData->maAppData.mpAccelMgr )
1302 pSVData->maAppData.mpAccelMgr->RemoveAccel( pAccel );
1305 void Application::SetHelp( Help* pHelp )
1307 ImplGetSVData()->maAppData.mpHelp = pHelp;
1310 void Application::UpdateMainThread()
1312 ImplSVData* pSVData = ImplGetSVData();
1313 if (pSVData && pSVData->mpDefInst)
1314 pSVData->mpDefInst->updateMainThread();
1317 Help* Application::GetHelp()
1319 return ImplGetSVData()->maAppData.mpHelp;
1322 OUString Application::GetToolkitName()
1324 ImplSVData* pSVData = ImplGetSVData();
1325 if ( pSVData->maAppData.mxToolkitName )
1326 return *(pSVData->maAppData.mxToolkitName);
1327 else
1328 return OUString();
1331 vcl::Window* Application::GetDefDialogParent()
1333 ImplSVData* pSVData = ImplGetSVData();
1334 // find some useful dialog parent
1336 // always use the topmost parent of the candidate
1337 // window to avoid using dialogs or floaters
1338 // as DefDialogParent
1340 // current focus frame
1341 vcl::Window *pWin = pSVData->maWinData.mpFocusWin;
1342 if (pWin && !pWin->IsMenuFloatingWindow())
1344 while (pWin->mpWindowImpl && pWin->mpWindowImpl->mpParent)
1345 pWin = pWin->mpWindowImpl->mpParent;
1347 // check for corrupted window hierarchy, #122232#, may be we now crash somewhere else
1348 if (!pWin->mpWindowImpl)
1350 OSL_FAIL( "Window hierarchy corrupted!" );
1351 pSVData->maWinData.mpFocusWin = nullptr; // avoid further access
1352 return nullptr;
1355 if ((pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0)
1357 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1361 // last active application frame
1362 pWin = pSVData->maWinData.mpActiveApplicationFrame;
1363 if (pWin)
1365 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1368 // first visible top window (may be totally wrong...)
1369 pWin = pSVData->maWinData.mpFirstFrame;
1370 while (pWin)
1372 if( pWin->ImplGetWindow()->IsTopWindow() &&
1373 pWin->mpWindowImpl->mbReallyVisible &&
1374 (pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0
1377 while( pWin->mpWindowImpl->mpParent )
1378 pWin = pWin->mpWindowImpl->mpParent;
1379 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1381 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1384 // use the desktop
1385 return nullptr;
1388 DialogCancelMode Application::GetDialogCancelMode()
1390 return ImplGetSVData()->maAppData.meDialogCancel;
1393 void Application::SetDialogCancelMode( DialogCancelMode mode )
1395 ImplGetSVData()->maAppData.meDialogCancel = mode;
1398 bool Application::IsDialogCancelEnabled()
1400 return ImplGetSVData()->maAppData.meDialogCancel != DialogCancelMode::Off;
1403 void Application::SetSystemWindowMode( SystemWindowFlags nMode )
1405 ImplGetSVData()->maAppData.mnSysWinMode = nMode;
1408 SystemWindowFlags Application::GetSystemWindowMode()
1410 return ImplGetSVData()->maAppData.mnSysWinMode;
1413 css::uno::Reference< css::awt::XToolkit > Application::GetVCLToolkit()
1415 css::uno::Reference< css::awt::XToolkit > xT;
1416 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
1417 if ( pWrapper )
1418 xT = pWrapper->GetVCLToolkit();
1419 return xT;
1422 #ifdef DISABLE_DYNLOADING
1424 extern "C" { UnoWrapperBase* CreateUnoWrapper(); }
1426 #else
1428 extern "C" { static void thisModule() {} }
1430 #endif
1432 UnoWrapperBase* UnoWrapperBase::GetUnoWrapper( bool bCreateIfNotExist )
1434 ImplSVData* pSVData = ImplGetSVData();
1435 static bool bAlreadyTriedToCreate = false;
1436 if ( !pSVData->mpUnoWrapper && bCreateIfNotExist && !bAlreadyTriedToCreate )
1438 #ifndef DISABLE_DYNLOADING
1439 osl::Module aTkLib;
1440 aTkLib.loadRelative(&thisModule, TK_DLL_NAME);
1441 if (aTkLib.is())
1443 FN_TkCreateUnoWrapper fnCreateWrapper = reinterpret_cast<FN_TkCreateUnoWrapper>(aTkLib.getFunctionSymbol("CreateUnoWrapper"));
1444 if ( fnCreateWrapper )
1446 pSVData->mpUnoWrapper = fnCreateWrapper();
1448 aTkLib.release();
1450 SAL_WARN_IF( !pSVData->mpUnoWrapper, "vcl", "UnoWrapper could not be created!" );
1451 #else
1452 pSVData->mpUnoWrapper = CreateUnoWrapper();
1453 #endif
1454 bAlreadyTriedToCreate = true;
1456 return pSVData->mpUnoWrapper;
1459 void UnoWrapperBase::SetUnoWrapper( UnoWrapperBase* pWrapper )
1461 ImplSVData* pSVData = ImplGetSVData();
1462 SAL_WARN_IF( pSVData->mpUnoWrapper, "vcl", "SetUnoWrapper: Wrapper already exists" );
1463 pSVData->mpUnoWrapper = pWrapper;
1466 css::uno::Reference< css::awt::XDisplayConnection > Application::GetDisplayConnection()
1468 ImplSVData* pSVData = ImplGetSVData();
1470 if( !pSVData->mxDisplayConnection.is() )
1472 pSVData->mxDisplayConnection.set( new vcl::DisplayConnectionDispatch );
1473 pSVData->mxDisplayConnection->start();
1476 return pSVData->mxDisplayConnection.get();
1479 void Application::SetFilterHdl( const Link<ConvertData&,bool>& rLink )
1481 ImplGetSVData()->maGDIData.mpGrfConverter->SetFilterHdl( rLink );
1484 const LocaleDataWrapper& Application::GetAppLocaleDataWrapper()
1486 return GetSettings().GetLocaleDataWrapper();
1489 void Application::EnableHeadlessMode( bool dialogsAreFatal )
1491 DialogCancelMode eNewMode = dialogsAreFatal ? DialogCancelMode::Fatal : DialogCancelMode::Silent;
1492 DialogCancelMode eOldMode = GetDialogCancelMode();
1493 assert(eOldMode == DialogCancelMode::Off || GetDialogCancelMode() == eNewMode);
1494 if (eOldMode != eNewMode)
1495 SetDialogCancelMode( eNewMode );
1498 bool Application::IsHeadlessModeEnabled()
1500 return IsDialogCancelEnabled() || comphelper::LibreOfficeKit::isActive();
1503 void Application::EnableBitmapRendering()
1505 ImplGetSVData()->maAppData.mbRenderToBitmaps = true;
1508 bool Application::IsBitmapRendering()
1510 return ImplGetSVData()->maAppData.mbRenderToBitmaps;
1513 void Application::EnableConsoleOnly()
1515 EnableHeadlessMode(true);
1516 EnableBitmapRendering();
1519 static bool bEventTestingMode = false;
1521 bool Application::IsEventTestingModeEnabled()
1523 return bEventTestingMode;
1526 void Application::EnableEventTestingMode()
1528 bEventTestingMode = true;
1531 static bool bSafeMode = false;
1533 bool Application::IsSafeModeEnabled()
1535 return bSafeMode;
1538 void Application::EnableSafeMode()
1540 bSafeMode = true;
1543 void Application::ShowNativeErrorBox(const OUString& sTitle ,
1544 const OUString& sMessage)
1546 int btn = ImplGetSalSystem()->ShowNativeMessageBox(
1547 sTitle,
1548 sMessage);
1549 if (btn != SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK) {
1550 SAL_WARN( "vcl", "ShowNativeMessageBox returned " << btn);
1554 const OUString& Application::GetDesktopEnvironment()
1556 if (IsHeadlessModeEnabled())
1558 static const OUString aNone("none");
1559 return aNone;
1561 else
1562 return SalGetDesktopEnvironment();
1565 void Application::AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService)
1567 ImplSVData* pSVData = ImplGetSVData();
1568 pSVData->mpDefInst->AddToRecentDocumentList(rFileUrl, rMimeType, rDocumentService);
1571 bool InitAccessBridge()
1573 // Disable MSAA bridge on UNIX
1574 #if defined UNX
1575 return true;
1576 #else
1577 bool bRet = ImplInitAccessBridge();
1579 if( !bRet )
1581 // disable accessibility if the user chooses to continue
1582 AllSettings aSettings = Application::GetSettings();
1583 MiscSettings aMisc = aSettings.GetMiscSettings();
1584 aMisc.SetEnableATToolSupport( false );
1585 aSettings.SetMiscSettings( aMisc );
1586 Application::SetSettings( aSettings );
1588 return bRet;
1589 #endif // !UNX
1592 // MT: AppEvent was in oldsv.cxx, but is still needed...
1593 void Application::AppEvent( const ApplicationEvent& /*rAppEvent*/ )
1597 bool Application::hasNativeFileSelection()
1599 ImplSVData* pSVData = ImplGetSVData();
1600 return pSVData->mpDefInst->hasNativeFileSelection();
1603 Reference< ui::dialogs::XFilePicker2 >
1604 Application::createFilePicker( const Reference< uno::XComponentContext >& xSM )
1606 ImplSVData* pSVData = ImplGetSVData();
1607 return pSVData->mpDefInst->createFilePicker( xSM );
1610 Reference< ui::dialogs::XFolderPicker2 >
1611 Application::createFolderPicker( const Reference< uno::XComponentContext >& xSM )
1613 ImplSVData* pSVData = ImplGetSVData();
1614 return pSVData->mpDefInst->createFolderPicker( xSM );
1617 void Application::setDeInitHook(Link<LinkParamNone*,void> const & hook) {
1618 ImplSVData * pSVData = ImplGetSVData();
1619 assert(!pSVData->maDeInitHook.IsSet());
1620 pSVData->maDeInitHook = hook;
1621 // Fake this for VCLXToolkit ctor instantiated from
1622 // postprocess/CppunitTest_services.mk:
1623 pSVData->maAppData.mbInAppMain = true;
1626 namespace vcl { namespace lok {
1628 void registerPollCallbacks(
1629 LibreOfficeKitPollCallback pPollCallback,
1630 LibreOfficeKitWakeCallback pWakeCallback,
1631 void *pData) {
1633 ImplSVData * pSVData = ImplGetSVData();
1634 if (pSVData)
1636 pSVData->mpPollCallback = pPollCallback;
1637 pSVData->mpWakeCallback = pWakeCallback;
1638 pSVData->mpPollClosure = pData;
1642 void unregisterPollCallbacks()
1644 ImplSVData * pSVData = ImplGetSVData();
1645 if (pSVData)
1647 // Just set mpPollClosure to null as that is what calling this means, that the callback data
1648 // points to an object that no longer exists. In particular, don't set
1649 // pSVData->mpPollCallback to nullptr as that is used to detect whether Unipoll is in use in
1650 // isUnipoll().
1651 pSVData->mpPollClosure = nullptr;
1655 bool isUnipoll()
1657 ImplSVData * pSVData = ImplGetSVData();
1658 return pSVData && pSVData->mpPollCallback != nullptr;
1661 } } // namespace lok, namespace vcl
1663 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */