Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / vcl / source / app / svapp.cxx
blob3fcf82b4e59c7d7791950baf073d082787352f60
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 "salsys.hxx"
61 #include "svdata.hxx"
62 #include "salimestatus.hxx"
63 #include "displayconnectiondispatch.hxx"
64 #include "window.h"
65 #include "accmgr.hxx"
66 #include "svids.hrc"
68 #include <com/sun/star/uno/Reference.h>
69 #include <com/sun/star/awt/XToolkit.hpp>
70 #include <com/sun/star/frame/Desktop.hpp>
71 #include <com/sun/star/uno/XNamingService.hpp>
72 #include <com/sun/star/util/XModifiable.hpp>
73 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
74 #include <comphelper/solarmutex.hxx>
75 #include <osl/process.h>
77 #include <cassert>
78 #include <utility>
79 #include <thread>
81 using namespace ::com::sun::star;
82 using namespace ::com::sun::star::uno;
84 namespace {
85 void InitSettings(ImplSVData* pSVData);
88 // keycodes handled internally by VCL
89 class ImplReservedKey
91 public:
92 explicit ImplReservedKey( vcl::KeyCode aKeyCode )
93 : mKeyCode(aKeyCode)
97 vcl::KeyCode mKeyCode;
100 typedef std::pair<ImplReservedKey*, size_t> ReservedKeys;
101 namespace
103 struct ImplReservedKeysImpl
105 ReservedKeys* operator()()
107 static ImplReservedKey ImplReservedKeys[] =
109 ImplReservedKey(vcl::KeyCode(KEY_F1,0) ),
110 ImplReservedKey(vcl::KeyCode(KEY_F1,KEY_SHIFT) ),
111 ImplReservedKey(vcl::KeyCode(KEY_F1,KEY_MOD1) ),
112 ImplReservedKey(vcl::KeyCode(KEY_F2,KEY_SHIFT) ),
113 ImplReservedKey(vcl::KeyCode(KEY_F4,KEY_MOD1) ),
114 ImplReservedKey(vcl::KeyCode(KEY_F4,KEY_MOD2) ),
115 ImplReservedKey(vcl::KeyCode(KEY_F4,KEY_MOD1|KEY_MOD2) ),
116 ImplReservedKey(vcl::KeyCode(KEY_F6,0) ),
117 ImplReservedKey(vcl::KeyCode(KEY_F6,KEY_MOD1) ),
118 ImplReservedKey(vcl::KeyCode(KEY_F6,KEY_SHIFT) ),
119 ImplReservedKey(vcl::KeyCode(KEY_F6,KEY_MOD1|KEY_SHIFT) ),
120 ImplReservedKey(vcl::KeyCode(KEY_F10,0) )
121 #ifdef UNX
123 ImplReservedKey(vcl::KeyCode(KEY_1,KEY_SHIFT|KEY_MOD1)),
124 ImplReservedKey(vcl::KeyCode(KEY_2,KEY_SHIFT|KEY_MOD1)),
125 ImplReservedKey(vcl::KeyCode(KEY_3,KEY_SHIFT|KEY_MOD1)),
126 ImplReservedKey(vcl::KeyCode(KEY_4,KEY_SHIFT|KEY_MOD1)),
127 ImplReservedKey(vcl::KeyCode(KEY_5,KEY_SHIFT|KEY_MOD1)),
128 ImplReservedKey(vcl::KeyCode(KEY_6,KEY_SHIFT|KEY_MOD1)),
129 ImplReservedKey(vcl::KeyCode(KEY_7,KEY_SHIFT|KEY_MOD1)),
130 ImplReservedKey(vcl::KeyCode(KEY_8,KEY_SHIFT|KEY_MOD1)),
131 ImplReservedKey(vcl::KeyCode(KEY_9,KEY_SHIFT|KEY_MOD1)),
132 ImplReservedKey(vcl::KeyCode(KEY_0,KEY_SHIFT|KEY_MOD1)),
133 ImplReservedKey(vcl::KeyCode(KEY_ADD,KEY_SHIFT|KEY_MOD1))
134 #endif
136 static ReservedKeys aKeys
138 &ImplReservedKeys[0],
139 sizeof(ImplReservedKeys) / sizeof(ImplReservedKey)
141 return &aKeys;
145 struct ImplReservedKeys
146 : public rtl::StaticAggregate<ReservedKeys, ImplReservedKeysImpl> {};
149 extern "C" {
150 typedef UnoWrapperBase* (SAL_CALL *FN_TkCreateUnoWrapper)();
153 struct ImplHotKey
155 ImplHotKey* mpNext;
156 vcl::KeyCode maKeyCode;
159 struct ImplEventHook
161 ImplEventHook* mpNext;
162 void* mpUserData;
163 VCLEventHookProc mpProc;
166 struct ImplPostEventData
168 VclEventId mnEvent;
169 VclPtr<vcl::Window> mpWin;
170 ImplSVEvent * mnEventId;
171 KeyEvent maKeyEvent;
172 MouseEvent maMouseEvent;
174 ImplPostEventData( VclEventId nEvent, vcl::Window* pWin, const KeyEvent& rKeyEvent ) :
175 mnEvent( nEvent ), mpWin( pWin ), mnEventId( nullptr ), maKeyEvent( rKeyEvent ) {}
176 ImplPostEventData( VclEventId nEvent, vcl::Window* pWin, const MouseEvent& rMouseEvent ) :
177 mnEvent( nEvent ), mpWin( pWin ), mnEventId( nullptr ), maMouseEvent( rMouseEvent ) {}
180 Application* GetpApp()
182 ImplSVData* pSVData = ImplGetSVData();
183 if ( !pSVData )
184 return nullptr;
185 return pSVData->mpApp;
188 Application::Application()
190 // useful for themes at least, perhaps extensions too
191 OUString aVar("LIBO_VERSION"), aValue(LIBO_VERSION_DOTTED);
192 osl_setEnvironment(aVar.pData, aValue.pData);
194 ImplGetSVData()->mpApp = this;
195 InitSalData();
198 Application::~Application()
200 ImplDeInitSVData();
201 DeInitSalData();
202 ImplGetSVData()->mpApp = nullptr;
205 int Application::Main()
207 SAL_WARN("vcl", "Application is a base class and should be overridden.");
208 return EXIT_SUCCESS;
211 bool Application::QueryExit()
213 WorkWindow* pAppWin = ImplGetSVData()->maWinData.mpAppWin;
215 // call the close handler of the application window
216 if ( pAppWin )
217 return pAppWin->Close();
218 else
219 return true;
222 void Application::Init()
226 void Application::InitFinished()
230 void Application::DeInit()
234 sal_uInt16 Application::GetCommandLineParamCount()
236 return (sal_uInt16)osl_getCommandArgCount();
239 OUString Application::GetCommandLineParam( sal_uInt16 nParam )
241 OUString aParam;
242 osl_getCommandArg( nParam, &aParam.pData );
243 return aParam;
246 OUString Application::GetAppFileName()
248 ImplSVData* pSVData = ImplGetSVData();
249 SAL_WARN_IF( !pSVData->maAppData.mpAppFileName, "vcl", "AppFileName should be set to something after SVMain!" );
250 if ( pSVData->maAppData.mpAppFileName )
251 return *pSVData->maAppData.mpAppFileName;
254 * provide a fallback for people without initialized vcl here (like setup
255 * in responsefile mode)
257 OUString aAppFileName;
258 OUString aExeFileName;
259 osl_getExecutableFile(&aExeFileName.pData);
261 // convert path to native file format
262 osl::FileBase::getSystemPathFromFileURL(aExeFileName, aAppFileName);
264 return aAppFileName;
267 void Application::Exception( ExceptionCategory nCategory )
269 switch ( nCategory )
271 // System has precedence (so do nothing)
272 case ExceptionCategory::System:
273 case ExceptionCategory::UserInterface:
274 break;
276 #ifdef DBG_UTIL
277 case ExceptionCategory::ResourceNotLoaded:
278 Abort("Resource not loaded");
279 break;
280 default:
281 Abort("Unknown Error");
282 break;
283 #else
284 default:
285 Abort(OUString());
286 break;
287 #endif
291 void Application::Abort( const OUString& rErrorText )
293 //HACK: Dump core iff --norestore command line argument is given (assuming
294 // this process is run by developers who are interested in cores, vs. end
295 // users who are not):
296 bool dumpCore = false;
297 sal_uInt16 n = GetCommandLineParamCount();
298 for (sal_uInt16 i = 0; i != n; ++i) {
299 if (GetCommandLineParam(i) == "--norestore") {
300 dumpCore = true;
301 break;
305 SalAbort( rErrorText, dumpCore );
308 sal_uLong Application::GetReservedKeyCodeCount()
310 return ImplReservedKeys::get()->second;
313 const vcl::KeyCode* Application::GetReservedKeyCode( sal_uLong i )
315 if( i >= GetReservedKeyCodeCount() )
316 return nullptr;
317 else
318 return &ImplReservedKeys::get()->first[i].mKeyCode;
321 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplEndAllPopupsMsg, void*, void )
323 ImplSVData* pSVData = ImplGetSVData();
324 while (pSVData->maWinData.mpFirstFloat)
325 pSVData->maWinData.mpFirstFloat->EndPopupMode(FloatWinPopupEndFlags::Cancel);
328 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplEndAllDialogsMsg, void*, void )
330 vcl::Window* pAppWindow = Application::GetFirstTopLevelWindow();
331 while (pAppWindow)
333 Dialog::EndAllDialogs(pAppWindow);
334 pAppWindow = Application::GetNextTopLevelWindow(pAppWindow);
338 void Application::EndAllDialogs()
340 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplEndAllDialogsMsg ) );
343 void Application::EndAllPopups()
345 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplEndAllPopupsMsg ) );
349 namespace
351 VclPtr<vcl::Window> GetEventWindow()
353 VclPtr<vcl::Window> xWin(Application::GetFirstTopLevelWindow());
354 while (xWin)
356 if (xWin->IsVisible())
357 break;
358 xWin.reset(Application::GetNextTopLevelWindow(xWin));
360 return xWin;
363 bool InjectKeyEvent(SvStream& rStream)
365 VclPtr<vcl::Window> xWin(GetEventWindow());
366 if (!xWin)
367 return false;
369 // skip the first available cycle and insert on the next one when we
370 // are trying the initial event, flagged by a triggered but undeleted
371 // mpEventTestingIdle
372 ImplSVData* pSVData = ImplGetSVData();
373 if (pSVData->maAppData.mpEventTestingIdle)
375 delete pSVData->maAppData.mpEventTestingIdle;
376 pSVData->maAppData.mpEventTestingIdle = nullptr;
377 return false;
380 sal_uInt16 nCode, nCharCode;
381 rStream.ReadUInt16(nCode);
382 rStream.ReadUInt16(nCharCode);
383 if (!rStream.good())
384 return false;
386 KeyEvent aVCLKeyEvt(nCharCode, nCode);
387 Application::PostKeyEvent(VclEventId::WindowKeyInput, xWin.get(), &aVCLKeyEvt);
388 Application::PostKeyEvent(VclEventId::WindowKeyUp, xWin.get(), &aVCLKeyEvt);
389 return true;
392 void CloseDialogsAndQuit()
394 Application::EndAllPopups();
395 Application::EndAllDialogs();
396 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplPrepareExitMsg ) );
400 IMPL_LINK_NOARG(ImplSVAppData, VclEventTestingHdl, Timer *, void)
402 if (Application::AnyInput())
404 mpEventTestingIdle->Start();
406 else
408 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplVclEventTestingHdl ) );
412 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplVclEventTestingHdl, void*, void )
414 ImplSVData* pSVData = ImplGetSVData();
415 SAL_INFO("vcl.eventtesting", "EventTestLimit is " << pSVData->maAppData.mnEventTestLimit);
416 if (pSVData->maAppData.mnEventTestLimit == 0)
418 delete pSVData->maAppData.mpEventTestInput;
419 SAL_INFO("vcl.eventtesting", "Event Limit reached, exiting" << pSVData->maAppData.mnEventTestLimit);
420 CloseDialogsAndQuit();
422 else
424 if (InjectKeyEvent(*pSVData->maAppData.mpEventTestInput))
425 --pSVData->maAppData.mnEventTestLimit;
426 if (!pSVData->maAppData.mpEventTestInput->good())
428 SAL_INFO("vcl.eventtesting", "Event Input exhausted, exit next cycle");
429 pSVData->maAppData.mnEventTestLimit = 0;
431 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplVclEventTestingHdl ) );
435 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplPrepareExitMsg, void*, void )
437 //now close top level frames
438 (void)GetpApp()->QueryExit();
441 void Application::Execute()
443 ImplSVData* pSVData = ImplGetSVData();
444 pSVData->maAppData.mbInAppExecute = true;
445 pSVData->maAppData.mbAppQuit = false;
447 if (Application::IsEventTestingModeEnabled())
449 pSVData->maAppData.mnEventTestLimit = 50;
450 pSVData->maAppData.mpEventTestingIdle = new Idle("eventtesting");
451 pSVData->maAppData.mpEventTestingIdle->SetInvokeHandler(LINK(&(pSVData->maAppData), ImplSVAppData, VclEventTestingHdl));
452 pSVData->maAppData.mpEventTestingIdle->SetPriority(TaskPriority::MEDIUM);
453 pSVData->maAppData.mpEventTestInput = new SvFileStream("eventtesting", StreamMode::READ);
454 pSVData->maAppData.mpEventTestingIdle->Start();
457 while ( !pSVData->maAppData.mbAppQuit )
458 Application::Yield();
460 pSVData->maAppData.mbInAppExecute = false;
463 inline bool ImplYield(bool i_bWait, bool i_bAllEvents, sal_uLong const nReleased)
465 ImplSVData* pSVData = ImplGetSVData();
467 SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait ? "wait" : "no wait") <<
468 ": " << (i_bAllEvents ? "all events" : "one event") << ": " << nReleased);
470 bool bHasActiveIdles = false;
471 sal_uInt64 nMinTimeout = 0;
472 if (nReleased == 0) // else thread doesn't have SolarMutex so avoid race
473 nMinTimeout = Scheduler::CalculateMinimumTimeout(bHasActiveIdles);
475 // FIXME: should use returned value as param to DoYield
476 (void)nMinTimeout;
478 // If we have idles, don't wait for the timeout; check for events
479 // and come back as quick as possible.
480 if (bHasActiveIdles)
481 i_bWait = false;
483 // TODO: there's a data race here on WNT only because ImplYield may be
484 // called without SolarMutex; if we can get rid of LazyDelete (with VclPtr)
485 // then the only remaining use of mnDispatchLevel is in OSX specific code
486 // so that would effectively eliminate the race on WNT
487 pSVData->maAppData.mnDispatchLevel++;
489 // do not wait for events if application was already quit; in that
490 // case only dispatch events already available
491 // do not wait for events either if the app decided that it is too busy for timers
492 // (feature added for the slideshow)
493 SalYieldResult eResult =
494 pSVData->mpDefInst->DoYield(
495 i_bWait && !pSVData->maAppData.mbAppQuit,
496 i_bAllEvents, nReleased);
498 SAL_INFO("vcl.schedule", "DoYield with " << (bHasActiveIdles ? "active idles" : "no idles") <<
499 " returns: " << (eResult == SalYieldResult::EVENT ? "processed event" : "timeout"));
501 pSVData->maAppData.mnDispatchLevel--;
503 DBG_TESTSOLARMUTEX(); // must be locked on return from Yield
505 if (nReleased == 0) // tdf#99383 don't run stuff from ReAcquireSolarMutex
507 // Process all Tasks
508 Scheduler::ProcessTaskScheduling(eResult != SalYieldResult::EVENT);
511 // flush lazy deleted objects
512 if( pSVData->maAppData.mnDispatchLevel == 0 )
513 vcl::LazyDelete::flush();
515 SAL_INFO("vcl.schedule", "Leave ImplYield");
517 return bHasActiveIdles || eResult == SalYieldResult::EVENT;
520 void Application::Reschedule( bool i_bAllEvents )
522 ImplYield(false, i_bAllEvents, 0);
525 void Scheduler::ProcessEventsToSignal(bool& bSignal)
527 while(!bSignal && (Scheduler::ProcessTaskScheduling( true ) ||
528 ImplYield(false, false, 0)))
533 void Scheduler::ProcessEventsToIdle()
535 int nSanity = 1000;
536 while(Scheduler::ProcessTaskScheduling( true ) ||
537 ImplYield(false, false, 0))
539 if (nSanity-- < 0)
541 SAL_WARN("vcl.schedule", "Unexpected volume of events to process");
542 break;
547 extern "C" {
548 /// used by unit tests that test only via the LOK API
549 SAL_DLLPUBLIC_EXPORT void unit_lok_process_events_to_idle()
551 const SolarMutexGuard aGuard;
552 Scheduler::ProcessEventsToIdle();
556 void Application::Yield()
558 ImplYield(true, false, 0);
561 void Application::ReAcquireSolarMutex(sal_uLong const nReleased)
563 // 0 would mean that events/timers will be handled without locking
564 // SolarMutex (racy)
565 SAL_WARN_IF(nReleased == 0, "vcl", "SolarMutexReleaser without SolarMutex");
566 #ifdef _WIN32
567 if (nReleased == 0 || ImplGetSVData()->mbDeInit) //do not Yield in DeInitVCL
568 AcquireSolarMutex(nReleased);
569 else
570 ImplYield(false, false, nReleased);
571 #else
572 // a) Yield is not needed on non-WNT platforms
573 // b) some Yield implementations for X11 (e.g. kde4) make it non-obvious
574 // how to use nReleased
575 // c) would require a review of what all Yield implementations do
576 // currently _before_ releasing SolarMutex that would run without lock
577 AcquireSolarMutex(nReleased);
578 #endif
581 IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplQuitMsg, void*, void )
583 ImplGetSVData()->maAppData.mbAppQuit = true;
586 void Application::Quit()
588 Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplQuitMsg ) );
591 comphelper::SolarMutex& Application::GetSolarMutex()
593 ImplSVData* pSVData = ImplGetSVData();
594 return *(pSVData->mpDefInst->GetYieldMutex());
597 oslThreadIdentifier Application::GetMainThreadIdentifier()
599 return ImplGetSVData()->mnMainThreadId;
602 sal_uLong Application::ReleaseSolarMutex()
604 ImplSVData* pSVData = ImplGetSVData();
605 return pSVData->mpDefInst->ReleaseYieldMutex();
608 void Application::AcquireSolarMutex( sal_uLong nCount )
610 ImplSVData* pSVData = ImplGetSVData();
611 pSVData->mpDefInst->AcquireYieldMutex( nCount );
614 bool Application::IsInMain()
616 ImplSVData* pSVData = ImplGetSVData();
617 return pSVData && pSVData->maAppData.mbInAppMain;
620 bool Application::IsInExecute()
622 return ImplGetSVData()->maAppData.mbInAppExecute;
625 bool Application::IsInModalMode()
627 return (ImplGetSVData()->maAppData.mnModalMode != 0);
630 sal_uInt16 Application::GetDispatchLevel()
632 return ImplGetSVData()->maAppData.mnDispatchLevel;
635 bool Application::AnyInput( VclInputFlags nType )
637 return ImplGetSVData()->mpDefInst->AnyInput( nType );
640 sal_uInt64 Application::GetLastInputInterval()
642 return (tools::Time::GetSystemTicks()-ImplGetSVData()->maAppData.mnLastInputTime);
645 bool Application::IsUICaptured()
647 ImplSVData* pSVData = ImplGetSVData();
649 // If mouse was captured, or if in tracking- or in select-mode of a floatingwindow (e.g. menus
650 // or pulldown toolboxes) another window should be created
651 // D&D active !!!
652 return pSVData->maWinData.mpCaptureWin || pSVData->maWinData.mpTrackWin ||
653 pSVData->maWinData.mpFirstFloat || nImplSysDialog;
656 void Application::OverrideSystemSettings( AllSettings& /*rSettings*/ )
660 void Application::MergeSystemSettings( AllSettings& rSettings )
662 vcl::Window* pWindow = ImplGetSVData()->maWinData.mpFirstFrame;
663 if( ! pWindow )
664 pWindow = ImplGetDefaultWindow();
665 if( pWindow )
667 ImplSVData* pSVData = ImplGetSVData();
668 if ( !pSVData->maAppData.mbSettingsInit )
670 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
671 pWindow->ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings );
672 pSVData->maAppData.mbSettingsInit = true;
674 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
675 pWindow->ImplUpdateGlobalSettings( rSettings, false );
679 void Application::SetSettings( const AllSettings& rSettings )
681 const SolarMutexGuard aGuard;
683 ImplSVData* pSVData = ImplGetSVData();
684 if ( !pSVData->maAppData.mpSettings )
686 InitSettings(pSVData);
687 *pSVData->maAppData.mpSettings = rSettings;
688 ResMgr::SetDefaultLocale( rSettings.GetUILanguageTag() );
690 else
692 AllSettings aOldSettings = *pSVData->maAppData.mpSettings;
693 if( aOldSettings.GetUILanguageTag().getLanguageType() != rSettings.GetUILanguageTag().getLanguageType() &&
694 pSVData->mpResMgr )
696 delete pSVData->mpResMgr;
697 pSVData->mpResMgr = nullptr;
699 ResMgr::SetDefaultLocale( rSettings.GetUILanguageTag() );
700 *pSVData->maAppData.mpSettings = rSettings;
701 AllSettingsFlags nChangeFlags = aOldSettings.GetChangeFlags( *pSVData->maAppData.mpSettings );
702 if ( bool(nChangeFlags) )
704 DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, &aOldSettings, nChangeFlags );
706 // notify data change handler
707 ImplCallEventListeners( VclEventId::ApplicationDataChanged, nullptr, &aDCEvt);
709 // Update all windows
710 vcl::Window* pFirstFrame = pSVData->maWinData.mpFirstFrame;
711 // Reset data that needs to be re-calculated
712 long nOldDPIX = 0;
713 long nOldDPIY = 0;
714 if ( pFirstFrame )
716 nOldDPIX = pFirstFrame->GetDPIX();
717 nOldDPIY = pFirstFrame->GetDPIY();
718 vcl::Window::ImplInitAppFontData(pFirstFrame);
720 vcl::Window* pFrame = pFirstFrame;
721 while ( pFrame )
723 // call UpdateSettings from ClientWindow in order to prevent updating data twice
724 vcl::Window* pClientWin = pFrame;
725 while ( pClientWin->ImplGetClientWindow() )
726 pClientWin = pClientWin->ImplGetClientWindow();
727 pClientWin->UpdateSettings( rSettings, true );
729 vcl::Window* pTempWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
730 while ( pTempWin )
732 // call UpdateSettings from ClientWindow in order to prevent updating data twice
733 pClientWin = pTempWin;
734 while ( pClientWin->ImplGetClientWindow() )
735 pClientWin = pClientWin->ImplGetClientWindow();
736 pClientWin->UpdateSettings( rSettings, true );
737 pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
740 pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
743 // if DPI resolution for screen output was changed set the new resolution for all
744 // screen compatible VirDev's
745 pFirstFrame = pSVData->maWinData.mpFirstFrame;
746 if ( pFirstFrame )
748 if ( (pFirstFrame->GetDPIX() != nOldDPIX) ||
749 (pFirstFrame->GetDPIY() != nOldDPIY) )
751 VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
752 while ( pVirDev )
754 if ( pVirDev->mbScreenComp &&
755 (pVirDev->GetDPIX() == nOldDPIX) &&
756 (pVirDev->GetDPIY() == nOldDPIY) )
758 pVirDev->SetDPIX( pFirstFrame->GetDPIX() );
759 pVirDev->SetDPIY( pFirstFrame->GetDPIY() );
760 if ( pVirDev->IsMapModeEnabled() )
762 MapMode aMapMode = pVirDev->GetMapMode();
763 pVirDev->SetMapMode();
764 pVirDev->SetMapMode( aMapMode );
768 pVirDev = pVirDev->mpNext;
776 const AllSettings& Application::GetSettings()
778 ImplSVData* pSVData = ImplGetSVData();
779 if ( !pSVData->maAppData.mpSettings )
781 InitSettings(pSVData);
784 return *(pSVData->maAppData.mpSettings);
787 namespace {
789 void InitSettings(ImplSVData* pSVData)
791 assert(!pSVData->maAppData.mpSettings && "initialization should not happen twice!");
793 pSVData->maAppData.mpSettings = new AllSettings();
794 if (!utl::ConfigManager::IsAvoidConfig())
796 pSVData->maAppData.mpCfgListener = new LocaleConfigurationListener;
797 pSVData->maAppData.mpSettings->GetSysLocale().GetOptions().AddListener( pSVData->maAppData.mpCfgListener );
803 void Application::NotifyAllWindows( DataChangedEvent& rDCEvt )
805 ImplSVData* pSVData = ImplGetSVData();
806 vcl::Window* pFrame = pSVData->maWinData.mpFirstFrame;
807 while ( pFrame )
809 pFrame->NotifyAllChildren( rDCEvt );
811 vcl::Window* pSysWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
812 while ( pSysWin )
814 pSysWin->NotifyAllChildren( rDCEvt );
815 pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
818 pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
822 void Application::ImplCallEventListeners( VclEventId nEvent, vcl::Window *pWin, void* pData )
824 ImplSVData* pSVData = ImplGetSVData();
825 VclWindowEvent aEvent( pWin, nEvent, pData );
827 if ( pSVData->maAppData.mpEventListeners )
828 pSVData->maAppData.mpEventListeners->Call( aEvent );
831 void Application::ImplCallEventListeners( VclSimpleEvent& rEvent )
833 ImplSVData* pSVData = ImplGetSVData();
835 if ( pSVData->maAppData.mpEventListeners )
836 pSVData->maAppData.mpEventListeners->Call( rEvent );
839 void Application::AddEventListener( const Link<VclSimpleEvent&,void>& rEventListener )
841 ImplSVData* pSVData = ImplGetSVData();
842 if( !pSVData->maAppData.mpEventListeners )
843 pSVData->maAppData.mpEventListeners = new VclEventListeners;
844 pSVData->maAppData.mpEventListeners->addListener( rEventListener );
847 void Application::RemoveEventListener( const Link<VclSimpleEvent&,void>& rEventListener )
849 ImplSVData* pSVData = ImplGetSVData();
850 if( pSVData->maAppData.mpEventListeners )
851 pSVData->maAppData.mpEventListeners->removeListener( rEventListener );
854 void Application::AddKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener )
856 ImplSVData* pSVData = ImplGetSVData();
857 if( !pSVData->maAppData.mpKeyListeners )
858 pSVData->maAppData.mpKeyListeners = new SVAppKeyListeners;
859 pSVData->maAppData.mpKeyListeners->push_back( rKeyListener );
862 void Application::RemoveKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener )
864 ImplSVData* pSVData = ImplGetSVData();
865 if( pSVData->maAppData.mpKeyListeners )
867 auto pVec = pSVData->maAppData.mpKeyListeners;
868 pVec->erase( std::remove(pVec->begin(), pVec->end(), rKeyListener ), pVec->end() );
872 bool Application::HandleKey( VclEventId nEvent, vcl::Window *pWin, KeyEvent* pKeyEvent )
874 // let listeners process the key event
875 VclWindowEvent aEvent( pWin, nEvent, static_cast<void *>(pKeyEvent) );
877 ImplSVData* pSVData = ImplGetSVData();
879 if ( !pSVData->maAppData.mpKeyListeners )
880 return false;
882 if ( pSVData->maAppData.mpKeyListeners->empty() )
883 return false;
885 bool bProcessed = false;
886 // Copy the list, because this can be destroyed when calling a Link...
887 std::vector<Link<VclWindowEvent&,bool>> aCopy( *pSVData->maAppData.mpKeyListeners );
888 for ( Link<VclWindowEvent&,bool>& rLink : aCopy )
890 if( rLink.Call( aEvent ) )
892 bProcessed = true;
893 break;
896 return bProcessed;
899 ImplSVEvent * Application::PostKeyEvent( VclEventId nEvent, vcl::Window *pWin, KeyEvent* pKeyEvent )
901 const SolarMutexGuard aGuard;
902 ImplSVEvent * nEventId = nullptr;
904 if( pWin && pKeyEvent )
906 ImplPostEventData* pPostEventData = new ImplPostEventData( nEvent, pWin, *pKeyEvent );
908 nEventId = PostUserEvent(
909 LINK( nullptr, Application, PostEventHandler ),
910 pPostEventData );
912 if( nEventId )
914 pPostEventData->mnEventId = nEventId;
915 ImplGetSVData()->maAppData.maPostedEventList.push_back( ImplPostEventPair( pWin, pPostEventData ) );
917 else
918 delete pPostEventData;
921 return nEventId;
924 ImplSVEvent * Application::PostMouseEvent( VclEventId nEvent, vcl::Window *pWin, MouseEvent* pMouseEvent )
926 const SolarMutexGuard aGuard;
927 ImplSVEvent * nEventId = nullptr;
929 if( pWin && pMouseEvent )
931 Point aTransformedPos( pMouseEvent->GetPosPixel() );
933 aTransformedPos.X() += pWin->GetOutOffXPixel();
934 aTransformedPos.Y() += pWin->GetOutOffYPixel();
936 const MouseEvent aTransformedEvent( aTransformedPos, pMouseEvent->GetClicks(), pMouseEvent->GetMode(),
937 pMouseEvent->GetButtons(), pMouseEvent->GetModifier() );
939 ImplPostEventData* pPostEventData = new ImplPostEventData( nEvent, pWin, aTransformedEvent );
941 nEventId = PostUserEvent(
942 LINK( nullptr, Application, PostEventHandler ),
943 pPostEventData );
945 if( nEventId )
947 pPostEventData->mnEventId = nEventId;
948 ImplGetSVData()->maAppData.maPostedEventList.push_back( ImplPostEventPair( pWin, pPostEventData ) );
950 else
951 delete pPostEventData;
954 return nEventId;
958 IMPL_STATIC_LINK( Application, PostEventHandler, void*, pCallData, void )
960 const SolarMutexGuard aGuard;
961 ImplPostEventData* pData = static_cast< ImplPostEventData * >( pCallData );
962 const void* pEventData;
963 SalEvent nEvent;
964 ImplSVEvent * const nEventId = pData->mnEventId;
966 switch( pData->mnEvent )
968 case VclEventId::WindowMouseMove:
969 nEvent = SalEvent::ExternalMouseMove;
970 pEventData = &pData->maMouseEvent;
971 break;
973 case VclEventId::WindowMouseButtonDown:
974 nEvent = SalEvent::ExternalMouseButtonDown;
975 pEventData = &pData->maMouseEvent;
976 break;
978 case VclEventId::WindowMouseButtonUp:
979 nEvent = SalEvent::ExternalMouseButtonUp;
980 pEventData = &pData->maMouseEvent;
981 break;
983 case VclEventId::WindowKeyInput:
984 nEvent = SalEvent::ExternalKeyInput;
985 pEventData = &pData->maKeyEvent;
986 break;
988 case VclEventId::WindowKeyUp:
989 nEvent = SalEvent::ExternalKeyUp;
990 pEventData = &pData->maKeyEvent;
991 break;
993 default:
994 nEvent = SalEvent::NONE;
995 pEventData = nullptr;
996 break;
999 if( pData->mpWin && pData->mpWin.get()->mpWindowImpl->mpFrameWindow.get() && pEventData )
1000 ImplWindowFrameProc( pData->mpWin.get()->mpWindowImpl->mpFrameWindow.get(), nEvent, pEventData );
1002 // remove this event from list of posted events, watch for destruction of internal data
1003 auto svdata = ImplGetSVData();
1004 ::std::list< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() );
1006 while( aIter != svdata->maAppData.maPostedEventList.end() )
1008 if( nEventId == (*aIter).second->mnEventId )
1010 delete (*aIter).second;
1011 aIter = svdata->maAppData.maPostedEventList.erase( aIter );
1013 else
1014 ++aIter;
1018 void Application::RemoveMouseAndKeyEvents( vcl::Window* pWin )
1020 const SolarMutexGuard aGuard;
1022 // remove all events for specific window, watch for destruction of internal data
1023 auto svdata = ImplGetSVData();
1024 ::std::list< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() );
1026 while( aIter != svdata->maAppData.maPostedEventList.end() )
1028 if( pWin == (*aIter).first )
1030 if( (*aIter).second->mnEventId )
1031 RemoveUserEvent( (*aIter).second->mnEventId );
1033 delete (*aIter).second;
1034 aIter = svdata->maAppData.maPostedEventList.erase( aIter );
1036 else
1037 ++aIter;
1041 ImplSVEvent * Application::PostUserEvent( const Link<void*,void>& rLink, void* pCaller,
1042 bool bReferenceLink )
1044 ImplSVEvent* pSVEvent = new ImplSVEvent;
1045 pSVEvent->mpData = pCaller;
1046 pSVEvent->maLink = rLink;
1047 pSVEvent->mpWindow = nullptr;
1048 pSVEvent->mbCall = true;
1049 if (bReferenceLink)
1051 SolarMutexGuard aGuard;
1052 // Double check that this is indeed a vcl::Window instance.
1053 assert(dynamic_cast<vcl::Window *>(
1054 static_cast<vcl::Window *>(rLink.GetInstance())) ==
1055 static_cast<vcl::Window *>(rLink.GetInstance()));
1056 pSVEvent->mpInstanceRef = static_cast<vcl::Window *>(rLink.GetInstance());
1059 vcl::Window* pDefWindow = ImplGetDefaultWindow();
1060 if ( pDefWindow == nullptr || !pDefWindow->ImplGetFrame()->PostEvent( pSVEvent ) )
1062 delete pSVEvent;
1063 pSVEvent = nullptr;
1065 return pSVEvent;
1068 void Application::RemoveUserEvent( ImplSVEvent * nUserEvent )
1070 if(nUserEvent)
1072 SAL_WARN_IF( nUserEvent->mpWindow, "vcl",
1073 "Application::RemoveUserEvent(): Event is send to a window" );
1074 SAL_WARN_IF( !nUserEvent->mbCall, "vcl",
1075 "Application::RemoveUserEvent(): Event is already removed" );
1077 nUserEvent->mpWindow.clear();
1078 nUserEvent->mpInstanceRef.clear();
1079 nUserEvent->mbCall = false;
1083 WorkWindow* Application::GetAppWindow()
1085 return ImplGetSVData()->maWinData.mpAppWin;
1088 vcl::Window* Application::GetFocusWindow()
1090 return ImplGetSVData()->maWinData.mpFocusWin;
1093 OutputDevice* Application::GetDefaultDevice()
1095 return ImplGetDefaultWindow();
1098 vcl::Window* Application::GetFirstTopLevelWindow()
1100 ImplSVData* pSVData = ImplGetSVData();
1101 return pSVData->maWinData.mpFirstFrame;
1104 vcl::Window* Application::GetNextTopLevelWindow( vcl::Window* pWindow )
1106 return pWindow->mpWindowImpl->mpFrameData->mpNextFrame;
1109 long Application::GetTopWindowCount()
1111 long nRet = 0;
1112 ImplSVData* pSVData = ImplGetSVData();
1113 vcl::Window *pWin = pSVData ? pSVData->maWinData.mpFirstFrame.get() : nullptr;
1114 while( pWin )
1116 if( pWin->ImplGetWindow()->IsTopWindow() )
1117 nRet++;
1118 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1120 return nRet;
1123 vcl::Window* Application::GetTopWindow( long nIndex )
1125 long nIdx = 0;
1126 ImplSVData* pSVData = ImplGetSVData();
1127 vcl::Window *pWin = pSVData ? pSVData->maWinData.mpFirstFrame.get() : nullptr;
1128 while( pWin )
1130 if( pWin->ImplGetWindow()->IsTopWindow() )
1132 if( nIdx == nIndex )
1133 return pWin->ImplGetWindow();
1134 else
1135 nIdx++;
1137 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1139 return nullptr;
1142 vcl::Window* Application::GetActiveTopWindow()
1144 vcl::Window *pWin = ImplGetSVData()->maWinData.mpFocusWin;
1145 while( pWin )
1147 if( pWin->IsTopWindow() )
1148 return pWin;
1149 pWin = pWin->mpWindowImpl->mpParent;
1151 return nullptr;
1154 void Application::SetAppName( const OUString& rUniqueName )
1156 ImplSVData* pSVData = ImplGetSVData();
1158 // create if does not exist
1159 if ( !pSVData->maAppData.mpAppName )
1160 pSVData->maAppData.mpAppName = new OUString( rUniqueName );
1161 else
1162 *(pSVData->maAppData.mpAppName) = rUniqueName;
1165 OUString Application::GetAppName()
1167 ImplSVData* pSVData = ImplGetSVData();
1168 if ( pSVData->maAppData.mpAppName )
1169 return *(pSVData->maAppData.mpAppName);
1170 else
1171 return OUString();
1174 OUString Application::GetHWOSConfInfo()
1176 ImplSVData* pSVData = ImplGetSVData();
1177 OUStringBuffer aDetails;
1179 aDetails.append( VclResId(SV_APP_CPUTHREADS) );
1180 aDetails.append( (sal_Int32)
1181 std::thread::hardware_concurrency() );
1182 aDetails.append( "; " );
1184 OUString aVersion;
1185 if ( pSVData && pSVData->mpDefInst )
1186 aVersion = pSVData->mpDefInst->getOSVersion();
1187 else
1188 aVersion = "-";
1190 aDetails.append( VclResId(SV_APP_OSVERSION) );
1191 aDetails.append( aVersion );
1192 aDetails.append( "; " );
1194 aDetails.append( VclResId(SV_APP_UIRENDER) );
1195 #if HAVE_FEATURE_OPENGL
1196 if ( OpenGLWrapper::isVCLOpenGLEnabled() )
1197 aDetails.append( VclResId(SV_APP_GL) );
1198 else
1199 #endif
1200 aDetails.append( VclResId(SV_APP_DEFAULT) );
1201 aDetails.append( "; " );
1203 #ifdef LINUX
1204 // Only linux has different backends, so don't show blank for others.
1205 aDetails.append( VclResId(SV_APP_VCLBACKEND) );
1206 aDetails.append( GetToolkitName() );
1207 aDetails.append( "; " );
1208 #endif
1210 return aDetails.makeStringAndClear();
1213 void Application::SetDisplayName( const OUString& rName )
1215 ImplSVData* pSVData = ImplGetSVData();
1217 // create if does not exist
1218 if ( !pSVData->maAppData.mpDisplayName )
1219 pSVData->maAppData.mpDisplayName = new OUString( rName );
1220 else
1221 *(pSVData->maAppData.mpDisplayName) = rName;
1224 OUString Application::GetDisplayName()
1226 ImplSVData* pSVData = ImplGetSVData();
1227 if ( pSVData->maAppData.mpDisplayName )
1228 return *(pSVData->maAppData.mpDisplayName);
1229 else if ( pSVData->maWinData.mpAppWin )
1230 return pSVData->maWinData.mpAppWin->GetText();
1231 else
1232 return OUString();
1235 unsigned int Application::GetScreenCount()
1237 SalSystem* pSys = ImplGetSalSystem();
1238 return pSys ? pSys->GetDisplayScreenCount() : 0;
1241 bool Application::IsUnifiedDisplay()
1243 SalSystem* pSys = ImplGetSalSystem();
1244 return pSys == nullptr || pSys->IsUnifiedDisplay();
1247 unsigned int Application::GetDisplayBuiltInScreen()
1249 SalSystem* pSys = ImplGetSalSystem();
1250 return pSys ? pSys->GetDisplayBuiltInScreen() : 0;
1253 unsigned int Application::GetDisplayExternalScreen()
1255 // This is really unpleasant, in theory we could have multiple
1256 // external displays etc.
1257 int nExternal(0);
1258 switch (GetDisplayBuiltInScreen())
1260 case 0:
1261 nExternal = 1;
1262 break;
1263 case 1:
1264 nExternal = 0;
1265 break;
1266 default:
1267 // When the built-in display is neither 0 nor 1
1268 // then place the full-screen presentation on the
1269 // first available screen.
1270 nExternal = 0;
1271 break;
1273 return nExternal;
1276 tools::Rectangle Application::GetScreenPosSizePixel( unsigned int nScreen )
1278 SalSystem* pSys = ImplGetSalSystem();
1279 return pSys ? pSys->GetDisplayScreenPosSizePixel( nScreen ) : tools::Rectangle();
1282 namespace {
1283 unsigned long calcDistSquare( const Point& i_rPoint, const tools::Rectangle& i_rRect )
1285 const Point aRectCenter( (i_rRect.Left() + i_rRect.Right())/2,
1286 (i_rRect.Top() + i_rRect.Bottom())/ 2 );
1287 const long nDX = aRectCenter.X() - i_rPoint.X();
1288 const long nDY = aRectCenter.Y() - i_rPoint.Y();
1289 return nDX*nDX + nDY*nDY;
1293 unsigned int Application::GetBestScreen( const tools::Rectangle& i_rRect )
1295 if( !IsUnifiedDisplay() )
1296 return GetDisplayBuiltInScreen();
1298 const unsigned int nScreens = GetScreenCount();
1299 unsigned int nBestMatchScreen = 0;
1300 unsigned long nOverlap = 0;
1301 for( unsigned int i = 0; i < nScreens; i++ )
1303 const tools::Rectangle aCurScreenRect( GetScreenPosSizePixel( i ) );
1304 // if a screen contains the rectangle completely it is obviously the best screen
1305 if( aCurScreenRect.IsInside( i_rRect ) )
1306 return i;
1307 // next the screen which contains most of the area of the rect is the best
1308 tools::Rectangle aIntersection( aCurScreenRect.GetIntersection( i_rRect ) );
1309 if( ! aIntersection.IsEmpty() )
1311 const unsigned long nCurOverlap( aIntersection.GetWidth() * aIntersection.GetHeight() );
1312 if( nCurOverlap > nOverlap )
1314 nOverlap = nCurOverlap;
1315 nBestMatchScreen = i;
1319 if( nOverlap > 0 )
1320 return nBestMatchScreen;
1322 // finally the screen which center is nearest to the rect is the best
1323 const Point aCenter( (i_rRect.Left() + i_rRect.Right())/2,
1324 (i_rRect.Top() + i_rRect.Bottom())/2 );
1325 unsigned long nDist = ULONG_MAX;
1326 for( unsigned int i = 0; i < nScreens; i++ )
1328 const tools::Rectangle aCurScreenRect( GetScreenPosSizePixel( i ) );
1329 const unsigned long nCurDist( calcDistSquare( aCenter, aCurScreenRect ) );
1330 if( nCurDist < nDist )
1332 nBestMatchScreen = i;
1333 nDist = nCurDist;
1336 return nBestMatchScreen;
1339 bool Application::InsertAccel( Accelerator* pAccel )
1341 ImplSVData* pSVData = ImplGetSVData();
1343 if ( !pSVData->maAppData.mpAccelMgr )
1344 pSVData->maAppData.mpAccelMgr = new ImplAccelManager();
1345 return pSVData->maAppData.mpAccelMgr->InsertAccel( pAccel );
1348 void Application::RemoveAccel( Accelerator* pAccel )
1350 ImplSVData* pSVData = ImplGetSVData();
1352 if ( pSVData->maAppData.mpAccelMgr )
1353 pSVData->maAppData.mpAccelMgr->RemoveAccel( pAccel );
1356 void Application::SetHelp( Help* pHelp )
1358 ImplGetSVData()->maAppData.mpHelp = pHelp;
1361 Help* Application::GetHelp()
1363 return ImplGetSVData()->maAppData.mpHelp;
1366 OUString Application::GetToolkitName()
1368 ImplSVData* pSVData = ImplGetSVData();
1369 if ( pSVData->maAppData.mpToolkitName )
1370 return *(pSVData->maAppData.mpToolkitName);
1371 else
1372 return OUString();
1375 vcl::Window* Application::GetDefDialogParent()
1377 ImplSVData* pSVData = ImplGetSVData();
1378 // find some useful dialog parent
1380 // always use the topmost parent of the candidate
1381 // window to avoid using dialogs or floaters
1382 // as DefDialogParent
1384 // current focus frame
1385 vcl::Window *pWin = pSVData->maWinData.mpFocusWin;
1386 if (pWin && !pWin->IsMenuFloatingWindow())
1388 while (pWin->mpWindowImpl && pWin->mpWindowImpl->mpParent)
1389 pWin = pWin->mpWindowImpl->mpParent;
1391 // check for corrupted window hierarchy, #122232#, may be we now crash somewhere else
1392 if (!pWin->mpWindowImpl)
1394 OSL_FAIL( "Window hierarchy corrupted!" );
1395 pSVData->maWinData.mpFocusWin = nullptr; // avoid further access
1396 return nullptr;
1399 if ((pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0)
1401 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1405 // last active application frame
1406 pWin = pSVData->maWinData.mpActiveApplicationFrame;
1407 if (pWin)
1409 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1412 // first visible top window (may be totally wrong....)
1413 pWin = pSVData->maWinData.mpFirstFrame;
1414 while (pWin)
1416 if( pWin->ImplGetWindow()->IsTopWindow() &&
1417 pWin->mpWindowImpl->mbReallyVisible &&
1418 (pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0
1421 while( pWin->mpWindowImpl->mpParent )
1422 pWin = pWin->mpWindowImpl->mpParent;
1423 return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1425 pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1428 // use the desktop
1429 return nullptr;
1432 Application::DialogCancelMode Application::GetDialogCancelMode()
1434 return ImplGetSVData()->maAppData.meDialogCancel;
1437 void Application::SetDialogCancelMode( DialogCancelMode mode )
1439 ImplGetSVData()->maAppData.meDialogCancel = mode;
1442 bool Application::IsDialogCancelEnabled()
1444 return ImplGetSVData()->maAppData.meDialogCancel != DialogCancelMode::Off;
1447 void Application::SetSystemWindowMode( SystemWindowFlags nMode )
1449 ImplGetSVData()->maAppData.mnSysWinMode = nMode;
1452 SystemWindowFlags Application::GetSystemWindowMode()
1454 return ImplGetSVData()->maAppData.mnSysWinMode;
1457 css::uno::Reference< css::awt::XToolkit > Application::GetVCLToolkit()
1459 css::uno::Reference< css::awt::XToolkit > xT;
1460 UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
1461 if ( pWrapper )
1462 xT = pWrapper->GetVCLToolkit();
1463 return xT;
1466 #ifdef DISABLE_DYNLOADING
1468 extern "C" { UnoWrapperBase* CreateUnoWrapper(); }
1470 #else
1472 extern "C" { static void SAL_CALL thisModule() {} }
1474 #endif
1476 UnoWrapperBase* Application::GetUnoWrapper( bool bCreateIfNotExist )
1478 ImplSVData* pSVData = ImplGetSVData();
1479 static bool bAlreadyTriedToCreate = false;
1480 if ( !pSVData->mpUnoWrapper && bCreateIfNotExist && !bAlreadyTriedToCreate )
1482 #ifndef DISABLE_DYNLOADING
1483 osl::Module aTkLib;
1484 OUString aLibName(TK_DLL_NAME);
1485 aTkLib.loadRelative(&thisModule, aLibName);
1486 if (aTkLib.is())
1488 FN_TkCreateUnoWrapper fnCreateWrapper = reinterpret_cast<FN_TkCreateUnoWrapper>(aTkLib.getFunctionSymbol("CreateUnoWrapper"));
1489 if ( fnCreateWrapper )
1491 pSVData->mpUnoWrapper = fnCreateWrapper();
1493 aTkLib.release();
1495 SAL_WARN_IF( !pSVData->mpUnoWrapper, "vcl", "UnoWrapper could not be created!" );
1496 #else
1497 pSVData->mpUnoWrapper = CreateUnoWrapper();
1498 #endif
1499 bAlreadyTriedToCreate = true;
1501 return pSVData->mpUnoWrapper;
1504 void Application::SetUnoWrapper( UnoWrapperBase* pWrapper )
1506 ImplSVData* pSVData = ImplGetSVData();
1507 SAL_WARN_IF( pSVData->mpUnoWrapper, "vcl", "SetUnoWrapper: Wrapper already exists" );
1508 pSVData->mpUnoWrapper = pWrapper;
1511 css::uno::Reference< css::awt::XDisplayConnection > Application::GetDisplayConnection()
1513 ImplSVData* pSVData = ImplGetSVData();
1515 if( !pSVData->mxDisplayConnection.is() )
1517 pSVData->mxDisplayConnection.set( new vcl::DisplayConnectionDispatch );
1518 pSVData->mxDisplayConnection->start();
1521 return pSVData->mxDisplayConnection.get();
1524 void Application::SetFilterHdl( const Link<ConvertData&,bool>& rLink )
1526 ImplGetSVData()->maGDIData.mpGrfConverter->SetFilterHdl( rLink );
1529 bool ImplCallHotKey( const vcl::KeyCode& rKeyCode )
1531 ImplSVData* pSVData = ImplGetSVData();
1532 ImplHotKey* pHotKeyData = pSVData->maAppData.mpFirstHotKey;
1533 while ( pHotKeyData )
1535 if ( pHotKeyData->maKeyCode == rKeyCode )
1537 return true;
1540 pHotKeyData = pHotKeyData->mpNext;
1543 return false;
1546 void ImplFreeHotKeyData()
1548 ImplSVData* pSVData = ImplGetSVData();
1549 ImplHotKey* pTempHotKeyData;
1550 ImplHotKey* pHotKeyData = pSVData->maAppData.mpFirstHotKey;
1551 while ( pHotKeyData )
1553 pTempHotKeyData = pHotKeyData->mpNext;
1554 delete pHotKeyData;
1555 pHotKeyData = pTempHotKeyData;
1558 pSVData->maAppData.mpFirstHotKey = nullptr;
1561 void ImplFreeEventHookData()
1563 ImplSVData* pSVData = ImplGetSVData();
1564 ImplEventHook* pTempEventHookData;
1565 ImplEventHook* pEventHookData = pSVData->maAppData.mpFirstEventHook;
1566 while ( pEventHookData )
1568 pTempEventHookData = pEventHookData->mpNext;
1569 delete pEventHookData;
1570 pEventHookData = pTempEventHookData;
1573 pSVData->maAppData.mpFirstEventHook = nullptr;
1576 long Application::CallEventHooks( NotifyEvent& rEvt )
1578 ImplSVData* pSVData = ImplGetSVData();
1579 long nRet = 0;
1580 ImplEventHook* pTempEventHookData;
1581 ImplEventHook* pEventHookData = pSVData->maAppData.mpFirstEventHook;
1582 while ( pEventHookData )
1584 pTempEventHookData = pEventHookData->mpNext;
1585 nRet = pEventHookData->mpProc( rEvt, pEventHookData->mpUserData );
1586 if ( nRet )
1587 break;
1588 pEventHookData = pTempEventHookData;
1591 return nRet;
1594 const LocaleDataWrapper& Application::GetAppLocaleDataWrapper()
1596 return GetSettings().GetLocaleDataWrapper();
1599 void Application::EnableHeadlessMode( bool dialogsAreFatal )
1601 SetDialogCancelMode(
1602 dialogsAreFatal ? DialogCancelMode::Fatal : DialogCancelMode::Silent );
1605 bool Application::IsHeadlessModeEnabled()
1607 return IsDialogCancelEnabled();
1610 static bool bConsoleOnly = false;
1612 bool Application::IsConsoleOnly()
1614 return bConsoleOnly;
1617 void Application::EnableConsoleOnly()
1619 EnableHeadlessMode(true);
1620 bConsoleOnly = true;
1623 static bool bEventTestingMode = false;
1625 bool Application::IsEventTestingModeEnabled()
1627 return bEventTestingMode;
1630 void Application::EnableEventTestingMode()
1632 bEventTestingMode = true;
1635 static bool bSafeMode = false;
1637 bool Application::IsSafeModeEnabled()
1639 return bSafeMode;
1642 void Application::EnableSafeMode()
1644 bSafeMode = true;
1647 void Application::ShowNativeErrorBox(const OUString& sTitle ,
1648 const OUString& sMessage)
1650 int btn = ImplGetSalSystem()->ShowNativeMessageBox(
1651 sTitle,
1652 sMessage);
1653 if (btn != SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK) {
1654 SAL_WARN( "vcl", "ShowNativeMessageBox returned " << btn);
1658 bool Application::CanToggleImeStatusWindow()
1660 ImplSVData* pSVData = ImplGetSVData();
1661 if( ! pSVData->mpImeStatus )
1662 pSVData->mpImeStatus = pSVData->mpDefInst->CreateI18NImeStatus();
1663 return pSVData->mpImeStatus->canToggle();
1666 void Application::ShowImeStatusWindow(bool bShow)
1668 ImplGetSVData()->maAppData.meShowImeStatusWindow = bShow
1669 ? ImplSVAppData::ImeStatusWindowMode_SHOW
1670 : ImplSVAppData::ImeStatusWindowMode_HIDE;
1672 ImplSVData* pSVData = ImplGetSVData();
1673 if( ! pSVData->mpImeStatus )
1674 pSVData->mpImeStatus = pSVData->mpDefInst->CreateI18NImeStatus();
1675 pSVData->mpImeStatus->toggle();
1678 bool Application::GetShowImeStatusWindowDefault()
1680 rtl_TextEncodingInfo aInfo;
1681 aInfo.StructSize = sizeof aInfo;
1682 return rtl_getTextEncodingInfo(osl_getThreadTextEncoding(), &aInfo)
1683 && aInfo.MaximumCharSize > 1;
1686 const OUString& Application::GetDesktopEnvironment()
1688 if (IsHeadlessModeEnabled())
1690 static OUString aNone("none");
1691 return aNone;
1693 else
1694 return SalGetDesktopEnvironment();
1697 void Application::AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService)
1699 ImplSVData* pSVData = ImplGetSVData();
1700 pSVData->mpDefInst->AddToRecentDocumentList(rFileUrl, rMimeType, rDocumentService);
1703 bool InitAccessBridge()
1705 // Disable MSAA bridge on UNIX
1706 #if defined UNX
1707 return true;
1708 #else
1709 bool bRet = ImplInitAccessBridge();
1711 if( !bRet )
1713 // disable accessibility if the user chooses to continue
1714 AllSettings aSettings = Application::GetSettings();
1715 MiscSettings aMisc = aSettings.GetMiscSettings();
1716 aMisc.SetEnableATToolSupport( false );
1717 aSettings.SetMiscSettings( aMisc );
1718 Application::SetSettings( aSettings );
1720 return bRet;
1721 #endif // !UNX
1724 // MT: AppEvent was in oldsv.cxx, but is still needed...
1725 void Application::AppEvent( const ApplicationEvent& /*rAppEvent*/ )
1729 bool Application::hasNativeFileSelection()
1731 ImplSVData* pSVData = ImplGetSVData();
1732 return pSVData->mpDefInst->hasNativeFileSelection();
1735 Reference< ui::dialogs::XFilePicker2 >
1736 Application::createFilePicker( const Reference< uno::XComponentContext >& xSM )
1738 ImplSVData* pSVData = ImplGetSVData();
1739 return pSVData->mpDefInst->createFilePicker( xSM );
1742 Reference< ui::dialogs::XFolderPicker2 >
1743 Application::createFolderPicker( const Reference< uno::XComponentContext >& xSM )
1745 ImplSVData* pSVData = ImplGetSVData();
1746 return pSVData->mpDefInst->createFolderPicker( xSM );
1749 void Application::setDeInitHook(Link<LinkParamNone*,void> const & hook) {
1750 ImplSVData * pSVData = ImplGetSVData();
1751 assert(!pSVData->maDeInitHook.IsSet());
1752 pSVData->maDeInitHook = hook;
1753 // Fake this for VCLXToolkit ctor instantiated from
1754 // postprocess/CppunitTest_services.mk:
1755 pSVData->maAppData.mbInAppMain = true;
1758 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */