build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / app / svapp.cxx
blobc412728cd6a4fc60412820dea0fac51e537efe83
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 <comphelper/processfactory.hxx>
24 #include <osl/module.h>
25 #include <osl/file.hxx>
26 #include <osl/thread.h>
28 #include <rtl/tencinfo.h>
29 #include <rtl/instance.hxx>
31 #include <tools/debug.hxx>
32 #include <tools/time.hxx>
34 #include <i18nlangtag/mslangid.hxx>
36 #include <unotools/configmgr.hxx>
37 #include <unotools/syslocaleoptions.hxx>
39 #include <vcl/dialog.hxx>
40 #include <vcl/floatwin.hxx>
41 #include <vcl/settings.hxx>
42 #include <vcl/keycod.hxx>
43 #include <vcl/event.hxx>
44 #include <vcl/vclevent.hxx>
45 #include <vcl/virdev.hxx>
46 #include <vcl/wrkwin.hxx>
47 #include <vcl/svapp.hxx>
48 #include <vcl/cvtgrf.hxx>
49 #include <vcl/unowrap.hxx>
50 #include <vcl/timer.hxx>
51 #include <vcl/scheduler.hxx>
52 #include <vcl/unohelp.hxx>
53 #include <vcl/lazydelete.hxx>
54 #if HAVE_FEATURE_OPENGL
55 #include <vcl/opengl/OpenGLWrapper.hxx>
56 #endif
58 #include "salinst.hxx"
59 #include "salframe.hxx"
60 #include "sallayout.hxx"
61 #include "salsys.hxx"
62 #include "svdata.hxx"
63 #include "salimestatus.hxx"
64 #include "displayconnectiondispatch.hxx"
65 #include "window.h"
66 #include "accmgr.hxx"
67 #include "svids.hrc"
69 #include <com/sun/star/uno/Reference.h>
70 #include <com/sun/star/awt/XToolkit.hpp>
71 #include <com/sun/star/frame/Desktop.hpp>
72 #include <com/sun/star/uno/XNamingService.hpp>
73 #include <com/sun/star/util/XModifiable.hpp>
74 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
75 #include <comphelper/solarmutex.hxx>
76 #include <osl/process.h>
78 #include <cassert>
79 #include <utility>
80 #include <thread>
82 using namespace ::com::sun::star;
83 using namespace ::com::sun::star::uno;
85 namespace {
86 void InitSettings(ImplSVData* pSVData);
89 // keycodes handled internally by VCL
90 class ImplReservedKey
92 public:
93 explicit ImplReservedKey( vcl::KeyCode aKeyCode )
94 : mKeyCode(aKeyCode)
98 vcl::KeyCode mKeyCode;
101 typedef std::pair<ImplReservedKey*, size_t> ReservedKeys;
102 namespace
104 struct ImplReservedKeysImpl
106 ReservedKeys* operator()()
108 static ImplReservedKey ImplReservedKeys[] =
110 ImplReservedKey(vcl::KeyCode(KEY_F1,0) ),
111 ImplReservedKey(vcl::KeyCode(KEY_F1,KEY_SHIFT) ),
112 ImplReservedKey(vcl::KeyCode(KEY_F1,KEY_MOD1) ),
113 ImplReservedKey(vcl::KeyCode(KEY_F2,KEY_SHIFT) ),
114 ImplReservedKey(vcl::KeyCode(KEY_F4,KEY_MOD1) ),
115 ImplReservedKey(vcl::KeyCode(KEY_F4,KEY_MOD2) ),
116 ImplReservedKey(vcl::KeyCode(KEY_F4,KEY_MOD1|KEY_MOD2) ),
117 ImplReservedKey(vcl::KeyCode(KEY_F6,0) ),
118 ImplReservedKey(vcl::KeyCode(KEY_F6,KEY_MOD1) ),
119 ImplReservedKey(vcl::KeyCode(KEY_F6,KEY_SHIFT) ),
120 ImplReservedKey(vcl::KeyCode(KEY_F6,KEY_MOD1|KEY_SHIFT) ),
121 ImplReservedKey(vcl::KeyCode(KEY_F10,0) )
122 #ifdef UNX
124 ImplReservedKey(vcl::KeyCode(KEY_1,KEY_SHIFT|KEY_MOD1)),
125 ImplReservedKey(vcl::KeyCode(KEY_2,KEY_SHIFT|KEY_MOD1)),
126 ImplReservedKey(vcl::KeyCode(KEY_3,KEY_SHIFT|KEY_MOD1)),
127 ImplReservedKey(vcl::KeyCode(KEY_4,KEY_SHIFT|KEY_MOD1)),
128 ImplReservedKey(vcl::KeyCode(KEY_5,KEY_SHIFT|KEY_MOD1)),
129 ImplReservedKey(vcl::KeyCode(KEY_6,KEY_SHIFT|KEY_MOD1)),
130 ImplReservedKey(vcl::KeyCode(KEY_7,KEY_SHIFT|KEY_MOD1)),
131 ImplReservedKey(vcl::KeyCode(KEY_8,KEY_SHIFT|KEY_MOD1)),
132 ImplReservedKey(vcl::KeyCode(KEY_9,KEY_SHIFT|KEY_MOD1)),
133 ImplReservedKey(vcl::KeyCode(KEY_0,KEY_SHIFT|KEY_MOD1)),
134 ImplReservedKey(vcl::KeyCode(KEY_ADD,KEY_SHIFT|KEY_MOD1))
135 #endif
137 static ReservedKeys aKeys
139 &ImplReservedKeys[0],
140 sizeof(ImplReservedKeys) / sizeof(ImplReservedKey)
142 return &aKeys;
146 struct ImplReservedKeys
147 : public rtl::StaticAggregate<ReservedKeys, ImplReservedKeysImpl> {};
150 extern "C" {
151 typedef UnoWrapperBase* (SAL_CALL *FN_TkCreateUnoWrapper)();
154 struct ImplHotKey
156 ImplHotKey* mpNext;
157 vcl::KeyCode maKeyCode;
160 struct ImplEventHook
162 ImplEventHook* mpNext;
163 void* mpUserData;
164 VCLEventHookProc mpProc;
167 struct ImplPostEventData
169 sal_uLong mnEvent;
170 VclPtr<vcl::Window> mpWin;
171 ImplSVEvent * mnEventId;
172 KeyEvent maKeyEvent;
173 MouseEvent maMouseEvent;
174 ZoomEvent maZoomEvent;
175 ScrollEvent maScrollEvent;
177 ImplPostEventData( sal_uLong nEvent, vcl::Window* pWin, const KeyEvent& rKeyEvent ) :
178 mnEvent( nEvent ), mpWin( pWin ), mnEventId( nullptr ), maKeyEvent( rKeyEvent ) {}
179 ImplPostEventData( sal_uLong nEvent, vcl::Window* pWin, const MouseEvent& rMouseEvent ) :
180 mnEvent( nEvent ), mpWin( pWin ), mnEventId( nullptr ), maMouseEvent( rMouseEvent ) {}
181 #if !HAVE_FEATURE_DESKTOP
182 ImplPostEventData( sal_uLong nEvent, vcl::Window* pWin, const ZoomEvent& rZoomEvent ) :
183 mnEvent( nEvent ), mpWin( pWin ), mnEventId( 0 ), maZoomEvent( rZoomEvent ) {}
184 ImplPostEventData( sal_uLong nEvent, vcl::Window* pWin, const ScrollEvent& rScrollEvent ) :
185 mnEvent( nEvent ), mpWin( pWin ), mnEventId( 0 ), maScrollEvent( rScrollEvent ) {}
186 #endif
189 Application* GetpApp()
191 ImplSVData* pSVData = ImplGetSVData();
192 if ( !pSVData )
193 return nullptr;
194 return pSVData->mpApp;
197 Application::Application()
199 // useful for themes at least, perhaps extensions too
200 OUString aVar("LIBO_VERSION"), aValue(LIBO_VERSION_DOTTED);
201 osl_setEnvironment(aVar.pData, aValue.pData);
203 ImplGetSVData()->mpApp = this;
204 InitSalData();
207 Application::~Application()
209 ImplDeInitSVData();
210 DeInitSalData();
211 ImplGetSVData()->mpApp = nullptr;
214 int Application::Main()
216 SAL_WARN("vcl", "Application is a base class and should be overridden.");
217 return EXIT_SUCCESS;
220 bool Application::QueryExit()
222 WorkWindow* pAppWin = ImplGetSVData()->maWinData.mpAppWin;
224 // call the close handler of the application window
225 if ( pAppWin )
226 return pAppWin->Close();
227 else
228 return true;
231 void Application::Init()
235 void Application::InitFinished()
239 void Application::DeInit()
243 sal_uInt16 Application::GetCommandLineParamCount()
245 return (sal_uInt16)osl_getCommandArgCount();
248 OUString Application::GetCommandLineParam( sal_uInt16 nParam )
250 OUString aParam;
251 osl_getCommandArg( nParam, &aParam.pData );
252 return aParam;
255 OUString Application::GetAppFileName()
257 ImplSVData* pSVData = ImplGetSVData();
258 SAL_WARN_IF( !pSVData->maAppData.mpAppFileName, "vcl", "AppFileName should be set to something after SVMain!" );
259 if ( pSVData->maAppData.mpAppFileName )
260 return *pSVData->maAppData.mpAppFileName;
263 * provide a fallback for people without initialized vcl here (like setup
264 * in responsefile mode)
266 OUString aAppFileName;
267 OUString aExeFileName;
268 osl_getExecutableFile(&aExeFileName.pData);
270 // convert path to native file format
271 osl::FileBase::getSystemPathFromFileURL(aExeFileName, aAppFileName);
273 return aAppFileName;
276 void Application::Exception( ExceptionCategory nCategory )
278 switch ( nCategory )
280 // System has precedence (so do nothing)
281 case ExceptionCategory::System:
282 case ExceptionCategory::UserInterface:
283 break;
285 #ifdef DBG_UTIL
286 case ExceptionCategory::ResourceNotLoaded:
287 Abort("Resource not loaded");
288 break;
289 default:
290 Abort("Unknown Error");
291 break;
292 #else
293 default:
294 Abort(OUString());
295 break;
296 #endif
300 void Application::Abort( const OUString& rErrorText )
302 //HACK: Dump core iff --norestore command line argument is given (assuming
303 // this process is run by developers who are interested in cores, vs. end
304 // users who are not):
305 bool dumpCore = false;
306 sal_uInt16 n = GetCommandLineParamCount();
307 for (sal_uInt16 i = 0; i != n; ++i) {
308 if (GetCommandLineParam(i) == "--norestore") {
309 dumpCore = true;
310 break;
314 SalAbort( rErrorText, dumpCore );
317 sal_uLong Application::GetReservedKeyCodeCount()
319 return ImplReservedKeys::get()->second;
322 const vcl::KeyCode* Application::GetReservedKeyCode( sal_uLong i )
324 if( i >= GetReservedKeyCodeCount() )
325 return nullptr;
326 else
327 return &ImplReservedKeys::get()->first[i].mKeyCode;
330 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplEndAllPopupsMsg, void*, void )
332 ImplSVData* pSVData = ImplGetSVData();
333 while (pSVData->maWinData.mpFirstFloat)
334 pSVData->maWinData.mpFirstFloat->EndPopupMode(FloatWinPopupEndFlags::Cancel);
337 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplEndAllDialogsMsg, void*, void )
339 vcl::Window* pAppWindow = Application::GetFirstTopLevelWindow();
340 while (pAppWindow)
342 Dialog::EndAllDialogs(pAppWindow);
343 pAppWindow = Application::GetNextTopLevelWindow(pAppWindow);
347 void Application::EndAllDialogs()
349 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplEndAllDialogsMsg ) );
352 void Application::EndAllPopups()
354 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplEndAllPopupsMsg ) );
358 namespace
360 VclPtr<vcl::Window> GetEventWindow()
362 VclPtr<vcl::Window> xWin(Application::GetFirstTopLevelWindow());
363 while (xWin)
365 if (xWin->IsVisible())
366 break;
367 xWin.reset(Application::GetNextTopLevelWindow(xWin));
369 return xWin;
372 bool InjectKeyEvent(SvStream& rStream)
374 VclPtr<vcl::Window> xWin(GetEventWindow());
375 if (!xWin)
376 return false;
378 // skip the first available cycle and insert on the next one when we
379 // are trying the initial event, flagged by a triggered but undeleted
380 // mpEventTestingIdle
381 ImplSVData* pSVData = ImplGetSVData();
382 if (pSVData->maAppData.mpEventTestingIdle)
384 delete pSVData->maAppData.mpEventTestingIdle;
385 pSVData->maAppData.mpEventTestingIdle = nullptr;
386 return false;
389 sal_uInt16 nCode, nCharCode;
390 rStream.ReadUInt16(nCode);
391 rStream.ReadUInt16(nCharCode);
392 if (!rStream.good())
393 return false;
395 KeyEvent aVCLKeyEvt(nCharCode, nCode);
396 Application::PostKeyEvent(VCLEVENT_WINDOW_KEYINPUT, xWin.get(), &aVCLKeyEvt);
397 Application::PostKeyEvent(VCLEVENT_WINDOW_KEYUP, xWin.get(), &aVCLKeyEvt);
398 return true;
401 void CloseDialogsAndQuit()
403 Application::EndAllPopups();
404 Application::EndAllDialogs();
405 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplPrepareExitMsg ) );
409 IMPL_LINK_NOARG(ImplSVAppData, VclEventTestingHdl, Idle *, void)
411 if (Application::AnyInput())
413 mpEventTestingIdle->Start();
415 else
417 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplVclEventTestingHdl ) );
421 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplVclEventTestingHdl, void*, void )
423 ImplSVData* pSVData = ImplGetSVData();
424 SAL_INFO("vcl.eventtesting", "EventTestLimit is " << pSVData->maAppData.mnEventTestLimit);
425 if (pSVData->maAppData.mnEventTestLimit == 0)
427 delete pSVData->maAppData.mpEventTestInput;
428 SAL_INFO("vcl.eventtesting", "Event Limit reached, exiting" << pSVData->maAppData.mnEventTestLimit);
429 CloseDialogsAndQuit();
431 else
433 if (InjectKeyEvent(*pSVData->maAppData.mpEventTestInput))
434 --pSVData->maAppData.mnEventTestLimit;
435 if (!pSVData->maAppData.mpEventTestInput->good())
437 SAL_INFO("vcl.eventtesting", "Event Input exhausted, exit next cycle");
438 pSVData->maAppData.mnEventTestLimit = 0;
440 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplVclEventTestingHdl ) );
444 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplPrepareExitMsg, void*, void )
446 //now close top level frames
447 (void)GetpApp()->QueryExit();
450 void Application::Execute()
452 ImplSVData* pSVData = ImplGetSVData();
453 pSVData->maAppData.mbInAppExecute = true;
454 pSVData->maAppData.mbAppQuit = false;
456 if (Application::IsEventTestingModeEnabled())
458 pSVData->maAppData.mnEventTestLimit = 50;
459 pSVData->maAppData.mpEventTestingIdle = new Idle("eventtesting");
460 pSVData->maAppData.mpEventTestingIdle->SetIdleHdl(LINK(&(pSVData->maAppData), ImplSVAppData, VclEventTestingHdl));
461 pSVData->maAppData.mpEventTestingIdle->SetPriority(SchedulerPriority::MEDIUM);
462 pSVData->maAppData.mpEventTestInput = new SvFileStream("eventtesting", StreamMode::READ);
463 pSVData->maAppData.mpEventTestingIdle->Start();
466 while ( !pSVData->maAppData.mbAppQuit )
467 Application::Yield();
469 pSVData->maAppData.mbInAppExecute = false;
472 inline bool ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased)
474 ImplSVData* pSVData = ImplGetSVData();
476 SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait ? "wait" : "no wait") <<
477 ": " << (i_bAllEvents ? "all events" : "one event") << ": " << nReleased);
479 bool bHasActiveIdles = false;
480 sal_uInt64 nMinTimeout = 0;
481 if (nReleased == 0) // else thread doesn't have SolarMutex so avoid race
482 nMinTimeout = Scheduler::CalculateMinimumTimeout(bHasActiveIdles);
484 // FIXME: should use returned value as param to DoYield
485 (void)nMinTimeout;
487 // If we have idles, don't wait for the timeout; check for events
488 // and come back as quick as possible.
489 if (bHasActiveIdles)
490 i_bWait = false;
492 // TODO: there's a data race here on WNT only because ImplYield may be
493 // called without SolarMutex; if we can get rid of LazyDelete (with VclPtr)
494 // then the only remaining use of mnDispatchLevel is in OSX specific code
495 // so that would effectively eliminate the race on WNT
496 pSVData->maAppData.mnDispatchLevel++;
498 // do not wait for events if application was already quit; in that
499 // case only dispatch events already available
500 // do not wait for events either if the app decided that it is too busy for timers
501 // (feature added for the slideshow)
502 SalYieldResult eResult =
503 pSVData->mpDefInst->DoYield(
504 i_bWait && !pSVData->maAppData.mbAppQuit,
505 i_bAllEvents, nReleased);
507 SAL_INFO("vcl.schedule", "DoYield with " << (bHasActiveIdles ? "active idles" : "no idles") <<
508 " returns: " << (eResult == SalYieldResult::EVENT ? "processed event" : "timeout"));
510 pSVData->maAppData.mnDispatchLevel--;
512 DBG_TESTSOLARMUTEX(); // must be locked on return from Yield
514 if (nReleased == 0) // tdf#99383 don't run stuff from ReAcquireSolarMutex
516 // Process all Tasks
517 Scheduler::ProcessTaskScheduling(eResult == SalYieldResult::EVENT);
520 // flush lazy deleted objects
521 if( pSVData->maAppData.mnDispatchLevel == 0 )
522 vcl::LazyDelete::flush();
524 SAL_INFO("vcl.schedule", "Leave ImplYield");
526 return bHasActiveIdles || eResult == SalYieldResult::EVENT;
529 void Application::Reschedule( bool i_bAllEvents )
531 ImplYield(false, i_bAllEvents, 0);
534 void Scheduler::ProcessEventsToIdle()
536 int nSanity = 1000;
537 while(Scheduler::ProcessTaskScheduling(false) ||
538 ImplYield(false, false, 0))
540 if (nSanity-- < 0)
542 SAL_WARN("vcl.schedule", "Unexpected volume of events to process");
543 break;
548 extern "C" {
549 /// used by unit tests that test only via the LOK API
550 SAL_DLLPUBLIC_EXPORT void unit_lok_process_events_to_idle()
552 const SolarMutexGuard aGuard;
553 Scheduler::ProcessEventsToIdle();
557 void Application::Yield()
559 ImplYield(true, false, 0);
562 void Application::ReAcquireSolarMutex(sal_uLong const nReleased)
564 // 0 would mean that events/timers will be handled without locking
565 // SolarMutex (racy)
566 SAL_WARN_IF(nReleased == 0, "vcl", "SolarMutexReleaser without SolarMutex");
567 #ifdef _WIN32
568 if (nReleased == 0 || ImplGetSVData()->mbDeInit) //do not Yield in DeInitVCL
569 AcquireSolarMutex(nReleased);
570 else
571 ImplYield(false, false, nReleased);
572 #else
573 // a) Yield is not needed on non-WNT platforms
574 // b) some Yield implementations for X11 (e.g. kde4) make it non-obvious
575 // how to use nReleased
576 // c) would require a review of what all Yield implementations do
577 // currently _before_ releasing SolarMutex that would run without lock
578 AcquireSolarMutex(nReleased);
579 #endif
582 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplQuitMsg, void*, void )
584 ImplGetSVData()->maAppData.mbAppQuit = true;
587 void Application::Quit()
589 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplQuitMsg ) );
592 comphelper::SolarMutex& Application::GetSolarMutex()
594 ImplSVData* pSVData = ImplGetSVData();
595 return *(pSVData->mpDefInst->GetYieldMutex());
598 oslThreadIdentifier Application::GetMainThreadIdentifier()
600 return ImplGetSVData()->mnMainThreadId;
603 sal_uLong Application::ReleaseSolarMutex()
605 ImplSVData* pSVData = ImplGetSVData();
606 return pSVData->mpDefInst->ReleaseYieldMutex();
609 void Application::AcquireSolarMutex( sal_uLong nCount )
611 ImplSVData* pSVData = ImplGetSVData();
612 pSVData->mpDefInst->AcquireYieldMutex( nCount );
615 bool Application::IsInMain()
617 ImplSVData* pSVData = ImplGetSVData();
618 return pSVData && pSVData->maAppData.mbInAppMain;
621 bool Application::IsInExecute()
623 return ImplGetSVData()->maAppData.mbInAppExecute;
626 bool Application::IsInModalMode()
628 return (ImplGetSVData()->maAppData.mnModalMode != 0);
631 sal_uInt16 Application::GetDispatchLevel()
633 return ImplGetSVData()->maAppData.mnDispatchLevel;
636 bool Application::AnyInput( VclInputFlags nType )
638 return ImplGetSVData()->mpDefInst->AnyInput( nType );
641 sal_uInt64 Application::GetLastInputInterval()
643 return (tools::Time::GetSystemTicks()-ImplGetSVData()->maAppData.mnLastInputTime);
646 extern int nImplSysDialog;
648 bool Application::IsUICaptured()
650 ImplSVData* pSVData = ImplGetSVData();
652 // If mouse was captured, or if in tracking- or in select-mode of a floatingwindow (e.g. menus
653 // or pulldown toolboxes) another window should be created
654 // D&D active !!!
655 if ( pSVData->maWinData.mpCaptureWin || pSVData->maWinData.mpTrackWin ||
656 pSVData->maWinData.mpFirstFloat || nImplSysDialog )
657 return true;
658 else
659 return false;
662 void Application::OverrideSystemSettings( AllSettings& /*rSettings*/ )
666 void Application::MergeSystemSettings( AllSettings& rSettings )
668 vcl::Window* pWindow = ImplGetSVData()->maWinData.mpFirstFrame;
669 if( ! pWindow )
670 pWindow = ImplGetDefaultWindow();
671 if( pWindow )
673 ImplSVData* pSVData = ImplGetSVData();
674 if ( !pSVData->maAppData.mbSettingsInit )
676 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
677 pWindow->ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings );
678 pSVData->maAppData.mbSettingsInit = true;
680 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
681 pWindow->ImplUpdateGlobalSettings( rSettings, false );
685 void Application::SetSettings( const AllSettings& rSettings )
687 const SolarMutexGuard aGuard;
689 ImplSVData* pSVData = ImplGetSVData();
690 if ( !pSVData->maAppData.mpSettings )
692 InitSettings(pSVData);
693 *pSVData->maAppData.mpSettings = rSettings;
694 ResMgr::SetDefaultLocale( rSettings.GetUILanguageTag() );
696 else
698 AllSettings aOldSettings = *pSVData->maAppData.mpSettings;
699 if( aOldSettings.GetUILanguageTag().getLanguageType() != rSettings.GetUILanguageTag().getLanguageType() &&
700 pSVData->mpResMgr )
702 pSVData->mpResMgr.reset();
704 ResMgr::SetDefaultLocale( rSettings.GetUILanguageTag() );
705 *pSVData->maAppData.mpSettings = rSettings;
706 AllSettingsFlags nChangeFlags = aOldSettings.GetChangeFlags( *pSVData->maAppData.mpSettings );
707 if ( bool(nChangeFlags) )
709 DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, &aOldSettings, nChangeFlags );
711 // notify data change handler
712 ImplCallEventListeners( VCLEVENT_APPLICATION_DATACHANGED, nullptr, &aDCEvt);
714 // Update all windows
715 vcl::Window* pFirstFrame = pSVData->maWinData.mpFirstFrame;
716 // Reset data that needs to be re-calculated
717 long nOldDPIX = 0;
718 long nOldDPIY = 0;
719 if ( pFirstFrame )
721 nOldDPIX = pFirstFrame->GetDPIX();
722 nOldDPIY = pFirstFrame->GetDPIY();
723 vcl::Window::ImplInitAppFontData(pFirstFrame);
725 vcl::Window* pFrame = pFirstFrame;
726 while ( pFrame )
728 // restore AppFont cache data
729 pFrame->mpWindowImpl->mpFrameData->meMapUnit = MapUnit::MapPixel;
731 // call UpdateSettings from ClientWindow in order to prevent updating data twice
732 vcl::Window* pClientWin = pFrame;
733 while ( pClientWin->ImplGetClientWindow() )
734 pClientWin = pClientWin->ImplGetClientWindow();
735 pClientWin->UpdateSettings( rSettings, true );
737 vcl::Window* pTempWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
738 while ( pTempWin )
740 // call UpdateSettings from ClientWindow in order to prevent updating data twice
741 pClientWin = pTempWin;
742 while ( pClientWin->ImplGetClientWindow() )
743 pClientWin = pClientWin->ImplGetClientWindow();
744 pClientWin->UpdateSettings( rSettings, true );
745 pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
748 pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
751 // if DPI resolution for screen output was changed set the new resolution for all
752 // screen compatible VirDev's
753 pFirstFrame = pSVData->maWinData.mpFirstFrame;
754 if ( pFirstFrame )
756 if ( (pFirstFrame->GetDPIX() != nOldDPIX) ||
757 (pFirstFrame->GetDPIY() != nOldDPIY) )
759 VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
760 while ( pVirDev )
762 if ( pVirDev->mbScreenComp &&
763 (pVirDev->GetDPIX() == nOldDPIX) &&
764 (pVirDev->GetDPIY() == nOldDPIY) )
766 pVirDev->SetDPIX( pFirstFrame->GetDPIX() );
767 pVirDev->SetDPIY( pFirstFrame->GetDPIY() );
768 if ( pVirDev->IsMapModeEnabled() )
770 MapMode aMapMode = pVirDev->GetMapMode();
771 pVirDev->SetMapMode();
772 pVirDev->SetMapMode( aMapMode );
776 pVirDev = pVirDev->mpNext;
784 const AllSettings& Application::GetSettings()
786 ImplSVData* pSVData = ImplGetSVData();
787 if ( !pSVData->maAppData.mpSettings )
789 InitSettings(pSVData);
792 return *(pSVData->maAppData.mpSettings);
795 namespace {
797 void InitSettings(ImplSVData* pSVData)
799 assert(!pSVData->maAppData.mpSettings && "initialization should not happen twice!");
801 pSVData->maAppData.mpSettings = new AllSettings();
802 if (!utl::ConfigManager::IsAvoidConfig())
804 pSVData->maAppData.mpCfgListener = new LocaleConfigurationListener;
805 pSVData->maAppData.mpSettings->GetSysLocale().GetOptions().AddListener( pSVData->maAppData.mpCfgListener );
811 void Application::NotifyAllWindows( DataChangedEvent& rDCEvt )
813 ImplSVData* pSVData = ImplGetSVData();
814 vcl::Window* pFrame = pSVData->maWinData.mpFirstFrame;
815 while ( pFrame )
817 pFrame->NotifyAllChildren( rDCEvt );
819 vcl::Window* pSysWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
820 while ( pSysWin )
822 pSysWin->NotifyAllChildren( rDCEvt );
823 pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
826 pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
830 void Application::ImplCallEventListeners( sal_uLong nEvent, vcl::Window *pWin, void* pData )
832 ImplSVData* pSVData = ImplGetSVData();
833 VclWindowEvent aEvent( pWin, nEvent, pData );
835 if ( pSVData->maAppData.mpEventListeners )
836 pSVData->maAppData.mpEventListeners->Call( aEvent );
839 void Application::ImplCallEventListeners( VclSimpleEvent& rEvent )
841 ImplSVData* pSVData = ImplGetSVData();
843 if ( pSVData->maAppData.mpEventListeners )
844 pSVData->maAppData.mpEventListeners->Call( rEvent );
847 void Application::AddEventListener( const Link<VclSimpleEvent&,void>& rEventListener )
849 ImplSVData* pSVData = ImplGetSVData();
850 if( !pSVData->maAppData.mpEventListeners )
851 pSVData->maAppData.mpEventListeners = new VclEventListeners;
852 pSVData->maAppData.mpEventListeners->addListener( rEventListener );
855 void Application::RemoveEventListener( const Link<VclSimpleEvent&,void>& rEventListener )
857 ImplSVData* pSVData = ImplGetSVData();
858 if( pSVData->maAppData.mpEventListeners )
859 pSVData->maAppData.mpEventListeners->removeListener( rEventListener );
862 void Application::AddKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener )
864 ImplSVData* pSVData = ImplGetSVData();
865 if( !pSVData->maAppData.mpKeyListeners )
866 pSVData->maAppData.mpKeyListeners = new SVAppKeyListeners;
867 pSVData->maAppData.mpKeyListeners->push_back( rKeyListener );
870 void Application::RemoveKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener )
872 ImplSVData* pSVData = ImplGetSVData();
873 if( pSVData->maAppData.mpKeyListeners )
875 auto pVec = pSVData->maAppData.mpKeyListeners;
876 pVec->erase( std::remove(pVec->begin(), pVec->end(), rKeyListener ), pVec->end() );
880 bool Application::HandleKey( sal_uLong nEvent, vcl::Window *pWin, KeyEvent* pKeyEvent )
882 // let listeners process the key event
883 VclWindowEvent aEvent( pWin, nEvent, static_cast<void *>(pKeyEvent) );
885 ImplSVData* pSVData = ImplGetSVData();
887 if ( !pSVData->maAppData.mpKeyListeners )
888 return false;
890 if ( pSVData->maAppData.mpKeyListeners->empty() )
891 return false;
893 bool bProcessed = false;
894 // Copy the list, because this can be destroyed when calling a Link...
895 std::vector<Link<VclWindowEvent&,bool>> aCopy( *pSVData->maAppData.mpKeyListeners );
896 for ( Link<VclWindowEvent&,bool>& rLink : aCopy )
898 if( rLink.Call( aEvent ) )
900 bProcessed = true;
901 break;
904 return bProcessed;
907 ImplSVEvent * Application::PostKeyEvent( sal_uLong nEvent, vcl::Window *pWin, KeyEvent* pKeyEvent )
909 const SolarMutexGuard aGuard;
910 ImplSVEvent * nEventId = nullptr;
912 if( pWin && pKeyEvent )
914 ImplPostEventData* pPostEventData = new ImplPostEventData( nEvent, pWin, *pKeyEvent );
916 nEventId = PostUserEvent(
917 LINK( nullptr, Application, PostEventHandler ),
918 pPostEventData );
920 if( nEventId )
922 pPostEventData->mnEventId = nEventId;
923 ImplGetSVData()->maAppData.maPostedEventList.push_back( ImplPostEventPair( pWin, pPostEventData ) );
925 else
926 delete pPostEventData;
929 return nEventId;
932 ImplSVEvent * Application::PostMouseEvent( sal_uLong nEvent, vcl::Window *pWin, MouseEvent* pMouseEvent )
934 const SolarMutexGuard aGuard;
935 ImplSVEvent * nEventId = nullptr;
937 if( pWin && pMouseEvent )
939 Point aTransformedPos( pMouseEvent->GetPosPixel() );
941 aTransformedPos.X() += pWin->GetOutOffXPixel();
942 aTransformedPos.Y() += pWin->GetOutOffYPixel();
944 const MouseEvent aTransformedEvent( aTransformedPos, pMouseEvent->GetClicks(), pMouseEvent->GetMode(),
945 pMouseEvent->GetButtons(), pMouseEvent->GetModifier() );
947 ImplPostEventData* pPostEventData = new ImplPostEventData( nEvent, pWin, aTransformedEvent );
949 nEventId = PostUserEvent(
950 LINK( nullptr, Application, PostEventHandler ),
951 pPostEventData );
953 if( nEventId )
955 pPostEventData->mnEventId = nEventId;
956 ImplGetSVData()->maAppData.maPostedEventList.push_back( ImplPostEventPair( pWin, pPostEventData ) );
958 else
959 delete pPostEventData;
962 return nEventId;
966 IMPL_STATIC_LINK( Application, PostEventHandler, void*, pCallData, void )
968 const SolarMutexGuard aGuard;
969 ImplPostEventData* pData = static_cast< ImplPostEventData * >( pCallData );
970 const void* pEventData;
971 SalEvent nEvent;
972 ImplSVEvent * const nEventId = pData->mnEventId;
974 switch( pData->mnEvent )
976 case VCLEVENT_WINDOW_MOUSEMOVE:
977 nEvent = SalEvent::ExternalMouseMove;
978 pEventData = &pData->maMouseEvent;
979 break;
981 case VCLEVENT_WINDOW_MOUSEBUTTONDOWN:
982 nEvent = SalEvent::ExternalMouseButtonDown;
983 pEventData = &pData->maMouseEvent;
984 break;
986 case VCLEVENT_WINDOW_MOUSEBUTTONUP:
987 nEvent = SalEvent::ExternalMouseButtonUp;
988 pEventData = &pData->maMouseEvent;
989 break;
991 case VCLEVENT_WINDOW_KEYINPUT:
992 nEvent = SalEvent::ExternalKeyInput;
993 pEventData = &pData->maKeyEvent;
994 break;
996 case VCLEVENT_WINDOW_KEYUP:
997 nEvent = SalEvent::ExternalKeyUp;
998 pEventData = &pData->maKeyEvent;
999 break;
1001 case VCLEVENT_WINDOW_ZOOM:
1002 nEvent = SalEvent::ExternalZoom;
1003 pEventData = &pData->maZoomEvent;
1004 break;
1006 case VCLEVENT_WINDOW_SCROLL:
1007 nEvent = SalEvent::ExternalScroll;
1008 pEventData = &pData->maScrollEvent;
1009 break;
1011 default:
1012 nEvent = SalEvent::NONE;
1013 pEventData = nullptr;
1014 break;
1017 if( pData->mpWin && pData->mpWin.get()->mpWindowImpl->mpFrameWindow.get() && pEventData )
1018 ImplWindowFrameProc( pData->mpWin.get()->mpWindowImpl->mpFrameWindow.get(), nEvent, pEventData );
1020 // remove this event from list of posted events, watch for destruction of internal data
1021 auto svdata = ImplGetSVData();
1022 ::std::list< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() );
1024 while( aIter != svdata->maAppData.maPostedEventList.end() )
1026 if( nEventId == (*aIter).second->mnEventId )
1028 delete (*aIter).second;
1029 aIter = svdata->maAppData.maPostedEventList.erase( aIter );
1031 else
1032 ++aIter;
1036 void Application::RemoveMouseAndKeyEvents( vcl::Window* pWin )
1038 const SolarMutexGuard aGuard;
1040 // remove all events for specific window, watch for destruction of internal data
1041 auto svdata = ImplGetSVData();
1042 ::std::list< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() );
1044 while( aIter != svdata->maAppData.maPostedEventList.end() )
1046 if( pWin == (*aIter).first )
1048 if( (*aIter).second->mnEventId )
1049 RemoveUserEvent( (*aIter).second->mnEventId );
1051 delete (*aIter).second;
1052 aIter = svdata->maAppData.maPostedEventList.erase( aIter );
1054 else
1055 ++aIter;
1059 ImplSVEvent * Application::PostUserEvent( const Link<void*,void>& rLink, void* pCaller,
1060 bool bReferenceLink )
1062 ImplSVEvent* pSVEvent = new ImplSVEvent;
1063 pSVEvent->mpData = pCaller;
1064 pSVEvent->maLink = rLink;
1065 pSVEvent->mpWindow = nullptr;
1066 pSVEvent->mbCall = true;
1067 if (bReferenceLink)
1069 SolarMutexGuard aGuard;
1070 // Double check that this is indeed a vcl::Window instance.
1071 assert(dynamic_cast<vcl::Window *>(
1072 static_cast<vcl::Window *>(rLink.GetInstance())) ==
1073 static_cast<vcl::Window *>(rLink.GetInstance()));
1074 pSVEvent->mpInstanceRef = static_cast<vcl::Window *>(rLink.GetInstance());
1077 vcl::Window* pDefWindow = ImplGetDefaultWindow();
1078 if ( pDefWindow == nullptr || !pDefWindow->ImplGetFrame()->PostEvent( pSVEvent ) )
1080 delete pSVEvent;
1081 pSVEvent = nullptr;
1083 return pSVEvent;
1086 void Application::RemoveUserEvent( ImplSVEvent * nUserEvent )
1088 if(nUserEvent)
1090 SAL_WARN_IF( nUserEvent->mpWindow, "vcl",
1091 "Application::RemoveUserEvent(): Event is send to a window" );
1092 SAL_WARN_IF( !nUserEvent->mbCall, "vcl",
1093 "Application::RemoveUserEvent(): Event is already removed" );
1095 nUserEvent->mpWindow.clear();
1096 nUserEvent->mpInstanceRef.clear();
1097 nUserEvent->mbCall = false;
1101 WorkWindow* Application::GetAppWindow()
1103 return ImplGetSVData()->maWinData.mpAppWin;
1106 vcl::Window* Application::GetFocusWindow()
1108 return ImplGetSVData()->maWinData.mpFocusWin;
1111 OutputDevice* Application::GetDefaultDevice()
1113 return ImplGetDefaultWindow();
1116 vcl::Window* Application::GetFirstTopLevelWindow()
1118 ImplSVData* pSVData = ImplGetSVData();
1119 return pSVData->maWinData.mpFirstFrame;
1122 vcl::Window* Application::GetNextTopLevelWindow( vcl::Window* pWindow )
1124 return pWindow->mpWindowImpl->mpFrameData->mpNextFrame;
1127 long Application::GetTopWindowCount()
1129 long nRet = 0;
1130 ImplSVData* pSVData = ImplGetSVData();
1131 vcl::Window *pWin = pSVData ? pSVData->maWinData.mpFirstFrame.get() : nullptr;
1132 while( pWin )
1134 if( pWin->ImplGetWindow()->IsTopWindow() )
1135 nRet++;
1136 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1138 return nRet;
1141 vcl::Window* Application::GetTopWindow( long nIndex )
1143 long nIdx = 0;
1144 ImplSVData* pSVData = ImplGetSVData();
1145 vcl::Window *pWin = pSVData ? pSVData->maWinData.mpFirstFrame.get() : nullptr;
1146 while( pWin )
1148 if( pWin->ImplGetWindow()->IsTopWindow() )
1150 if( nIdx == nIndex )
1151 return pWin->ImplGetWindow();
1152 else
1153 nIdx++;
1155 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1157 return nullptr;
1160 vcl::Window* Application::GetActiveTopWindow()
1162 vcl::Window *pWin = ImplGetSVData()->maWinData.mpFocusWin;
1163 while( pWin )
1165 if( pWin->IsTopWindow() )
1166 return pWin;
1167 pWin = pWin->mpWindowImpl->mpParent;
1169 return nullptr;
1172 void Application::SetAppName( const OUString& rUniqueName )
1174 ImplSVData* pSVData = ImplGetSVData();
1176 // create if does not exist
1177 if ( !pSVData->maAppData.mpAppName )
1178 pSVData->maAppData.mpAppName = new OUString( rUniqueName );
1179 else
1180 *(pSVData->maAppData.mpAppName) = rUniqueName;
1183 OUString Application::GetAppName()
1185 ImplSVData* pSVData = ImplGetSVData();
1186 if ( pSVData->maAppData.mpAppName )
1187 return *(pSVData->maAppData.mpAppName);
1188 else
1189 return OUString();
1192 OUString Application::GetHWOSConfInfo()
1194 ImplSVData* pSVData = ImplGetSVData();
1195 OUStringBuffer aDetails;
1197 aDetails.append( VclResId(SV_APP_CPUTHREADS).toString() );
1198 aDetails.append( (sal_Int32)
1199 std::thread::hardware_concurrency() );
1200 aDetails.append( "; " );
1202 OUString aVersion;
1203 if ( pSVData && pSVData->mpDefInst )
1204 aVersion = pSVData->mpDefInst->getOSVersion();
1205 else
1206 aVersion = "-";
1208 aDetails.append( VclResId(SV_APP_OSVERSION).toString() );
1209 aDetails.append( aVersion );
1210 aDetails.append( "; " );
1212 aDetails.append( VclResId(SV_APP_UIRENDER).toString() );
1213 #if HAVE_FEATURE_OPENGL
1214 if ( OpenGLWrapper::isVCLOpenGLEnabled() )
1215 aDetails.append( VclResId(SV_APP_GL).toString() );
1216 else
1217 #endif
1218 aDetails.append( VclResId(SV_APP_DEFAULT).toString() );
1219 aDetails.append( "; " );
1221 #ifdef LINUX
1222 // Only linux has different backends, so don't show blank for others.
1223 aDetails.append( VclResId(SV_APP_VCLBACKEND).toString() );
1224 aDetails.append( GetToolkitName() );
1225 aDetails.append( "; " );
1226 #endif
1228 aDetails.append( VclResId(SV_APP_LAYOUT_ENGINE).toString() );
1229 if (SalLayout::UseCommonLayout())
1230 aDetails.append( VclResId(SV_APP_LAYOUT_NEW).toString() );
1231 else
1232 aDetails.append( VclResId(SV_APP_LAYOUT_OLD).toString() );
1233 aDetails.append( "; " );
1235 return aDetails.makeStringAndClear();
1238 void Application::SetDisplayName( const OUString& rName )
1240 ImplSVData* pSVData = ImplGetSVData();
1242 // create if does not exist
1243 if ( !pSVData->maAppData.mpDisplayName )
1244 pSVData->maAppData.mpDisplayName = new OUString( rName );
1245 else
1246 *(pSVData->maAppData.mpDisplayName) = rName;
1249 OUString Application::GetDisplayName()
1251 ImplSVData* pSVData = ImplGetSVData();
1252 if ( pSVData->maAppData.mpDisplayName )
1253 return *(pSVData->maAppData.mpDisplayName);
1254 else if ( pSVData->maWinData.mpAppWin )
1255 return pSVData->maWinData.mpAppWin->GetText();
1256 else
1257 return OUString("");
1260 unsigned int Application::GetScreenCount()
1262 SalSystem* pSys = ImplGetSalSystem();
1263 return pSys ? pSys->GetDisplayScreenCount() : 0;
1266 bool Application::IsUnifiedDisplay()
1268 SalSystem* pSys = ImplGetSalSystem();
1269 return pSys == nullptr || pSys->IsUnifiedDisplay();
1272 unsigned int Application::GetDisplayBuiltInScreen()
1274 SalSystem* pSys = ImplGetSalSystem();
1275 return pSys ? pSys->GetDisplayBuiltInScreen() : 0;
1278 unsigned int Application::GetDisplayExternalScreen()
1280 // This is really unpleasant, in theory we could have multiple
1281 // external displays etc.
1282 int nExternal(0);
1283 switch (GetDisplayBuiltInScreen())
1285 case 0:
1286 nExternal = 1;
1287 break;
1288 case 1:
1289 nExternal = 0;
1290 break;
1291 default:
1292 // When the built-in display is neither 0 nor 1
1293 // then place the full-screen presentation on the
1294 // first available screen.
1295 nExternal = 0;
1296 break;
1298 return nExternal;
1301 Rectangle Application::GetScreenPosSizePixel( unsigned int nScreen )
1303 SalSystem* pSys = ImplGetSalSystem();
1304 return pSys ? pSys->GetDisplayScreenPosSizePixel( nScreen ) : Rectangle();
1307 namespace {
1308 unsigned long calcDistSquare( const Point& i_rPoint, const Rectangle& i_rRect )
1310 const Point aRectCenter( (i_rRect.Left() + i_rRect.Right())/2,
1311 (i_rRect.Top() + i_rRect.Bottom())/ 2 );
1312 const long nDX = aRectCenter.X() - i_rPoint.X();
1313 const long nDY = aRectCenter.Y() - i_rPoint.Y();
1314 return nDX*nDX + nDY*nDY;
1318 unsigned int Application::GetBestScreen( const Rectangle& i_rRect )
1320 if( !IsUnifiedDisplay() )
1321 return GetDisplayBuiltInScreen();
1323 const unsigned int nScreens = GetScreenCount();
1324 unsigned int nBestMatchScreen = 0;
1325 unsigned long nOverlap = 0;
1326 for( unsigned int i = 0; i < nScreens; i++ )
1328 const Rectangle aCurScreenRect( GetScreenPosSizePixel( i ) );
1329 // if a screen contains the rectangle completely it is obviously the best screen
1330 if( aCurScreenRect.IsInside( i_rRect ) )
1331 return i;
1332 // next the screen which contains most of the area of the rect is the best
1333 Rectangle aIntersection( aCurScreenRect.GetIntersection( i_rRect ) );
1334 if( ! aIntersection.IsEmpty() )
1336 const unsigned long nCurOverlap( aIntersection.GetWidth() * aIntersection.GetHeight() );
1337 if( nCurOverlap > nOverlap )
1339 nOverlap = nCurOverlap;
1340 nBestMatchScreen = i;
1344 if( nOverlap > 0 )
1345 return nBestMatchScreen;
1347 // finally the screen which center is nearest to the rect is the best
1348 const Point aCenter( (i_rRect.Left() + i_rRect.Right())/2,
1349 (i_rRect.Top() + i_rRect.Bottom())/2 );
1350 unsigned long nDist = ULONG_MAX;
1351 for( unsigned int i = 0; i < nScreens; i++ )
1353 const Rectangle aCurScreenRect( GetScreenPosSizePixel( i ) );
1354 const unsigned long nCurDist( calcDistSquare( aCenter, aCurScreenRect ) );
1355 if( nCurDist < nDist )
1357 nBestMatchScreen = i;
1358 nDist = nCurDist;
1361 return nBestMatchScreen;
1364 bool Application::InsertAccel( Accelerator* pAccel )
1366 ImplSVData* pSVData = ImplGetSVData();
1368 if ( !pSVData->maAppData.mpAccelMgr )
1369 pSVData->maAppData.mpAccelMgr = new ImplAccelManager();
1370 return pSVData->maAppData.mpAccelMgr->InsertAccel( pAccel );
1373 void Application::RemoveAccel( Accelerator* pAccel )
1375 ImplSVData* pSVData = ImplGetSVData();
1377 if ( pSVData->maAppData.mpAccelMgr )
1378 pSVData->maAppData.mpAccelMgr->RemoveAccel( pAccel );
1381 void Application::SetHelp( Help* pHelp )
1383 ImplGetSVData()->maAppData.mpHelp = pHelp;
1386 void Application::UpdateMainThread()
1388 ImplSVData* pSVData = ImplGetSVData();
1389 if (pSVData)
1390 pSVData->mnMainThreadId = osl::Thread::getCurrentIdentifier();
1393 Help* Application::GetHelp()
1395 return ImplGetSVData()->maAppData.mpHelp;
1398 OUString Application::GetToolkitName()
1400 ImplSVData* pSVData = ImplGetSVData();
1401 if ( pSVData->maAppData.mpToolkitName )
1402 return *(pSVData->maAppData.mpToolkitName);
1403 else
1404 return OUString();
1407 vcl::Window* Application::GetDefDialogParent()
1409 ImplSVData* pSVData = ImplGetSVData();
1410 // find some useful dialog parent
1412 // always use the topmost parent of the candidate
1413 // window to avoid using dialogs or floaters
1414 // as DefDialogParent
1416 // current focus frame
1417 vcl::Window *pWin = pSVData->maWinData.mpFocusWin;
1418 if (pWin && !pWin->IsMenuFloatingWindow())
1420 while (pWin->mpWindowImpl && pWin->mpWindowImpl->mpParent)
1421 pWin = pWin->mpWindowImpl->mpParent;
1423 // check for corrupted window hierarchy, #122232#, may be we now crash somewhere else
1424 if (!pWin->mpWindowImpl)
1426 OSL_FAIL( "Window hierarchy corrupted!" );
1427 pSVData->maWinData.mpFocusWin = nullptr; // avoid further access
1428 return nullptr;
1431 if ((pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0)
1433 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1437 // last active application frame
1438 pWin = pSVData->maWinData.mpActiveApplicationFrame;
1439 if (pWin)
1441 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1444 // first visible top window (may be totally wrong....)
1445 pWin = pSVData->maWinData.mpFirstFrame;
1446 while (pWin)
1448 if( pWin->ImplGetWindow()->IsTopWindow() &&
1449 pWin->mpWindowImpl->mbReallyVisible &&
1450 (pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0
1453 while( pWin->mpWindowImpl->mpParent )
1454 pWin = pWin->mpWindowImpl->mpParent;
1455 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1457 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1460 // use the desktop
1461 return nullptr;
1464 Application::DialogCancelMode Application::GetDialogCancelMode()
1466 return ImplGetSVData()->maAppData.meDialogCancel;
1469 void Application::SetDialogCancelMode( DialogCancelMode mode )
1471 ImplGetSVData()->maAppData.meDialogCancel = mode;
1474 bool Application::IsDialogCancelEnabled()
1476 return ImplGetSVData()->maAppData.meDialogCancel != DialogCancelMode::Off;
1479 void Application::SetSystemWindowMode( SystemWindowFlags nMode )
1481 ImplGetSVData()->maAppData.mnSysWinMode = nMode;
1484 SystemWindowFlags Application::GetSystemWindowMode()
1486 return ImplGetSVData()->maAppData.mnSysWinMode;
1489 css::uno::Reference< css::awt::XToolkit > Application::GetVCLToolkit()
1491 css::uno::Reference< css::awt::XToolkit > xT;
1492 UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
1493 if ( pWrapper )
1494 xT = pWrapper->GetVCLToolkit();
1495 return xT;
1498 #ifdef DISABLE_DYNLOADING
1500 extern "C" { UnoWrapperBase* CreateUnoWrapper(); }
1502 #else
1504 extern "C" { static void SAL_CALL thisModule() {} }
1506 #endif
1508 UnoWrapperBase* Application::GetUnoWrapper( bool bCreateIfNotExist )
1510 ImplSVData* pSVData = ImplGetSVData();
1511 static bool bAlreadyTriedToCreate = false;
1512 if ( !pSVData->mpUnoWrapper && bCreateIfNotExist && !bAlreadyTriedToCreate )
1514 #ifndef DISABLE_DYNLOADING
1515 osl::Module aTkLib;
1516 OUString aLibName(TK_DLL_NAME);
1517 aTkLib.loadRelative(&thisModule, aLibName);
1518 if (aTkLib.is())
1520 FN_TkCreateUnoWrapper fnCreateWrapper = reinterpret_cast<FN_TkCreateUnoWrapper>(aTkLib.getFunctionSymbol("CreateUnoWrapper"));
1521 if ( fnCreateWrapper )
1523 pSVData->mpUnoWrapper = fnCreateWrapper();
1525 aTkLib.release();
1527 SAL_WARN_IF( !pSVData->mpUnoWrapper, "vcl", "UnoWrapper could not be created!" );
1528 #else
1529 pSVData->mpUnoWrapper = CreateUnoWrapper();
1530 #endif
1531 bAlreadyTriedToCreate = true;
1533 return pSVData->mpUnoWrapper;
1536 void Application::SetUnoWrapper( UnoWrapperBase* pWrapper )
1538 ImplSVData* pSVData = ImplGetSVData();
1539 SAL_WARN_IF( pSVData->mpUnoWrapper, "vcl", "SetUnoWrapper: Wrapper already exists" );
1540 pSVData->mpUnoWrapper = pWrapper;
1543 css::uno::Reference< css::awt::XDisplayConnection > Application::GetDisplayConnection()
1545 ImplSVData* pSVData = ImplGetSVData();
1547 if( !pSVData->mxDisplayConnection.is() )
1549 pSVData->mxDisplayConnection.set( new vcl::DisplayConnectionDispatch );
1550 pSVData->mxDisplayConnection->start();
1553 return pSVData->mxDisplayConnection.get();
1556 void Application::SetFilterHdl( const Link<ConvertData&,bool>& rLink )
1558 ImplGetSVData()->maGDIData.mpGrfConverter->SetFilterHdl( rLink );
1561 bool ImplCallHotKey( const vcl::KeyCode& rKeyCode )
1563 ImplSVData* pSVData = ImplGetSVData();
1564 ImplHotKey* pHotKeyData = pSVData->maAppData.mpFirstHotKey;
1565 while ( pHotKeyData )
1567 if ( pHotKeyData->maKeyCode == rKeyCode )
1569 return true;
1572 pHotKeyData = pHotKeyData->mpNext;
1575 return false;
1578 void ImplFreeHotKeyData()
1580 ImplSVData* pSVData = ImplGetSVData();
1581 ImplHotKey* pTempHotKeyData;
1582 ImplHotKey* pHotKeyData = pSVData->maAppData.mpFirstHotKey;
1583 while ( pHotKeyData )
1585 pTempHotKeyData = pHotKeyData->mpNext;
1586 delete pHotKeyData;
1587 pHotKeyData = pTempHotKeyData;
1590 pSVData->maAppData.mpFirstHotKey = nullptr;
1593 void ImplFreeEventHookData()
1595 ImplSVData* pSVData = ImplGetSVData();
1596 ImplEventHook* pTempEventHookData;
1597 ImplEventHook* pEventHookData = pSVData->maAppData.mpFirstEventHook;
1598 while ( pEventHookData )
1600 pTempEventHookData = pEventHookData->mpNext;
1601 delete pEventHookData;
1602 pEventHookData = pTempEventHookData;
1605 pSVData->maAppData.mpFirstEventHook = nullptr;
1608 long Application::CallEventHooks( NotifyEvent& rEvt )
1610 ImplSVData* pSVData = ImplGetSVData();
1611 long nRet = 0;
1612 ImplEventHook* pTempEventHookData;
1613 ImplEventHook* pEventHookData = pSVData->maAppData.mpFirstEventHook;
1614 while ( pEventHookData )
1616 pTempEventHookData = pEventHookData->mpNext;
1617 nRet = pEventHookData->mpProc( rEvt, pEventHookData->mpUserData );
1618 if ( nRet )
1619 break;
1620 pEventHookData = pTempEventHookData;
1623 return nRet;
1626 const LocaleDataWrapper& Application::GetAppLocaleDataWrapper()
1628 return GetSettings().GetLocaleDataWrapper();
1631 void Application::EnableHeadlessMode( bool dialogsAreFatal )
1633 SetDialogCancelMode(
1634 dialogsAreFatal ? DialogCancelMode::Fatal : DialogCancelMode::Silent );
1637 bool Application::IsHeadlessModeEnabled()
1639 return IsDialogCancelEnabled();
1642 static bool bConsoleOnly = false;
1644 bool Application::IsConsoleOnly()
1646 return bConsoleOnly;
1649 void Application::EnableConsoleOnly()
1651 EnableHeadlessMode(true);
1652 bConsoleOnly = true;
1655 static bool bEventTestingMode = false;
1657 bool Application::IsEventTestingModeEnabled()
1659 return bEventTestingMode;
1662 void Application::EnableEventTestingMode()
1664 bEventTestingMode = true;
1667 static bool bSafeMode = false;
1669 bool Application::IsSafeModeEnabled()
1671 return bSafeMode;
1674 void Application::EnableSafeMode()
1676 bSafeMode = true;
1679 void Application::ShowNativeErrorBox(const OUString& sTitle ,
1680 const OUString& sMessage)
1682 int btn = ImplGetSalSystem()->ShowNativeMessageBox(
1683 sTitle,
1684 sMessage);
1685 if (btn != SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK) {
1686 OSL_TRACE("ShowNativeMessageBox returned %d", btn);
1690 bool Application::CanToggleImeStatusWindow()
1692 ImplSVData* pSVData = ImplGetSVData();
1693 if( ! pSVData->mpImeStatus )
1694 pSVData->mpImeStatus = pSVData->mpDefInst->CreateI18NImeStatus();
1695 return pSVData->mpImeStatus->canToggle();
1698 void Application::ShowImeStatusWindow(bool bShow)
1700 ImplGetSVData()->maAppData.meShowImeStatusWindow = bShow
1701 ? ImplSVAppData::ImeStatusWindowMode_SHOW
1702 : ImplSVAppData::ImeStatusWindowMode_HIDE;
1704 ImplSVData* pSVData = ImplGetSVData();
1705 if( ! pSVData->mpImeStatus )
1706 pSVData->mpImeStatus = pSVData->mpDefInst->CreateI18NImeStatus();
1707 pSVData->mpImeStatus->toggle();
1710 bool Application::GetShowImeStatusWindowDefault()
1712 rtl_TextEncodingInfo aInfo;
1713 aInfo.StructSize = sizeof aInfo;
1714 return rtl_getTextEncodingInfo(osl_getThreadTextEncoding(), &aInfo)
1715 && aInfo.MaximumCharSize > 1;
1718 const OUString& Application::GetDesktopEnvironment()
1720 if (IsHeadlessModeEnabled())
1722 static OUString aNone("none");
1723 return aNone;
1725 else
1726 return SalGetDesktopEnvironment();
1729 void Application::AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService)
1731 ImplSVData* pSVData = ImplGetSVData();
1732 pSVData->mpDefInst->AddToRecentDocumentList(rFileUrl, rMimeType, rDocumentService);
1735 bool InitAccessBridge()
1737 // Disable MSAA bridge on UNIX
1738 #if defined UNX
1739 return true;
1740 #else
1741 bool bRet = ImplInitAccessBridge();
1743 if( !bRet )
1745 // disable accessibility if the user chooses to continue
1746 AllSettings aSettings = Application::GetSettings();
1747 MiscSettings aMisc = aSettings.GetMiscSettings();
1748 aMisc.SetEnableATToolSupport( false );
1749 aSettings.SetMiscSettings( aMisc );
1750 Application::SetSettings( aSettings );
1752 return bRet;
1753 #endif // !UNX
1756 // MT: AppEvent was in oldsv.cxx, but is still needed...
1757 void Application::AppEvent( const ApplicationEvent& /*rAppEvent*/ )
1761 bool Application::hasNativeFileSelection()
1763 ImplSVData* pSVData = ImplGetSVData();
1764 return pSVData->mpDefInst->hasNativeFileSelection();
1767 Reference< ui::dialogs::XFilePicker2 >
1768 Application::createFilePicker( const Reference< uno::XComponentContext >& xSM )
1770 ImplSVData* pSVData = ImplGetSVData();
1771 return pSVData->mpDefInst->createFilePicker( xSM );
1774 Reference< ui::dialogs::XFolderPicker2 >
1775 Application::createFolderPicker( const Reference< uno::XComponentContext >& xSM )
1777 ImplSVData* pSVData = ImplGetSVData();
1778 return pSVData->mpDefInst->createFolderPicker( xSM );
1781 void Application::setDeInitHook(Link<LinkParamNone*,void> const & hook) {
1782 ImplSVData * pSVData = ImplGetSVData();
1783 assert(!pSVData->maDeInitHook.IsSet());
1784 pSVData->maDeInitHook = hook;
1785 // Fake this for VCLXToolkit ctor instantiated from
1786 // postprocess/CppunitTest_services.mk:
1787 pSVData->maAppData.mbInAppMain = true;
1790 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */