1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
58 #include "salinst.hxx"
59 #include "salframe.hxx"
60 #include "sallayout.hxx"
63 #include "salimestatus.hxx"
64 #include "displayconnectiondispatch.hxx"
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>
82 using namespace ::com::sun::star
;
83 using namespace ::com::sun::star::uno
;
86 void InitSettings(ImplSVData
* pSVData
);
89 // keycodes handled internally by VCL
93 explicit ImplReservedKey( vcl::KeyCode aKeyCode
)
98 vcl::KeyCode mKeyCode
;
101 typedef std::pair
<ImplReservedKey
*, size_t> ReservedKeys
;
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) )
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
))
137 static ReservedKeys aKeys
139 &ImplReservedKeys
[0],
140 sizeof(ImplReservedKeys
) / sizeof(ImplReservedKey
)
146 struct ImplReservedKeys
147 : public rtl::StaticAggregate
<ReservedKeys
, ImplReservedKeysImpl
> {};
151 typedef UnoWrapperBase
* (SAL_CALL
*FN_TkCreateUnoWrapper
)();
157 vcl::KeyCode maKeyCode
;
162 ImplEventHook
* mpNext
;
164 VCLEventHookProc mpProc
;
167 struct ImplPostEventData
170 VclPtr
<vcl::Window
> mpWin
;
171 ImplSVEvent
* mnEventId
;
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
) {}
189 Application
* GetpApp()
191 ImplSVData
* pSVData
= ImplGetSVData();
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;
207 Application::~Application()
211 ImplGetSVData()->mpApp
= nullptr;
214 int Application::Main()
216 SAL_WARN("vcl", "Application is a base class and should be overridden.");
220 bool Application::QueryExit()
222 WorkWindow
* pAppWin
= ImplGetSVData()->maWinData
.mpAppWin
;
224 // call the close handler of the application window
226 return pAppWin
->Close();
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
)
251 osl_getCommandArg( nParam
, &aParam
.pData
);
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
);
276 void Application::Exception( ExceptionCategory nCategory
)
280 // System has precedence (so do nothing)
281 case ExceptionCategory::System
:
282 case ExceptionCategory::UserInterface
:
286 case ExceptionCategory::ResourceNotLoaded
:
287 Abort("Resource not loaded");
290 Abort("Unknown Error");
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") {
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() )
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();
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
) );
360 VclPtr
<vcl::Window
> GetEventWindow()
362 VclPtr
<vcl::Window
> xWin(Application::GetFirstTopLevelWindow());
365 if (xWin
->IsVisible())
367 xWin
.reset(Application::GetNextTopLevelWindow(xWin
));
372 bool InjectKeyEvent(SvStream
& rStream
)
374 VclPtr
<vcl::Window
> xWin(GetEventWindow());
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;
389 sal_uInt16 nCode
, nCharCode
;
390 rStream
.ReadUInt16(nCode
);
391 rStream
.ReadUInt16(nCharCode
);
395 KeyEvent
aVCLKeyEvt(nCharCode
, nCode
);
396 Application::PostKeyEvent(VCLEVENT_WINDOW_KEYINPUT
, xWin
.get(), &aVCLKeyEvt
);
397 Application::PostKeyEvent(VCLEVENT_WINDOW_KEYUP
, xWin
.get(), &aVCLKeyEvt
);
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();
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();
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
487 // If we have idles, don't wait for the timeout; check for events
488 // and come back as quick as possible.
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
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()
537 while(Scheduler::ProcessTaskScheduling(false) ||
538 ImplYield(false, false, 0))
542 SAL_WARN("vcl.schedule", "Unexpected volume of events to process");
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
566 SAL_WARN_IF(nReleased
== 0, "vcl", "SolarMutexReleaser without SolarMutex");
568 if (nReleased
== 0 || ImplGetSVData()->mbDeInit
) //do not Yield in DeInitVCL
569 AcquireSolarMutex(nReleased
);
571 ImplYield(false, false, nReleased
);
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
);
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
655 if ( pSVData
->maWinData
.mpCaptureWin
|| pSVData
->maWinData
.mpTrackWin
||
656 pSVData
->maWinData
.mpFirstFloat
|| nImplSysDialog
)
662 void Application::OverrideSystemSettings( AllSettings
& /*rSettings*/ )
666 void Application::MergeSystemSettings( AllSettings
& rSettings
)
668 vcl::Window
* pWindow
= ImplGetSVData()->maWinData
.mpFirstFrame
;
670 pWindow
= ImplGetDefaultWindow();
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() );
698 AllSettings aOldSettings
= *pSVData
->maAppData
.mpSettings
;
699 if( aOldSettings
.GetUILanguageTag().getLanguageType() != rSettings
.GetUILanguageTag().getLanguageType() &&
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
721 nOldDPIX
= pFirstFrame
->GetDPIX();
722 nOldDPIY
= pFirstFrame
->GetDPIY();
723 vcl::Window::ImplInitAppFontData(pFirstFrame
);
725 vcl::Window
* pFrame
= pFirstFrame
;
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
;
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
;
756 if ( (pFirstFrame
->GetDPIX() != nOldDPIX
) ||
757 (pFirstFrame
->GetDPIY() != nOldDPIY
) )
759 VirtualDevice
* pVirDev
= pSVData
->maGDIData
.mpFirstVirDev
;
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
);
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
;
817 pFrame
->NotifyAllChildren( rDCEvt
);
819 vcl::Window
* pSysWin
= pFrame
->mpWindowImpl
->mpFrameData
->mpFirstOverlap
;
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
)
890 if ( pSVData
->maAppData
.mpKeyListeners
->empty() )
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
) )
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
),
922 pPostEventData
->mnEventId
= nEventId
;
923 ImplGetSVData()->maAppData
.maPostedEventList
.push_back( ImplPostEventPair( pWin
, pPostEventData
) );
926 delete pPostEventData
;
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
),
955 pPostEventData
->mnEventId
= nEventId
;
956 ImplGetSVData()->maAppData
.maPostedEventList
.push_back( ImplPostEventPair( pWin
, pPostEventData
) );
959 delete pPostEventData
;
966 IMPL_STATIC_LINK( Application
, PostEventHandler
, void*, pCallData
, void )
968 const SolarMutexGuard aGuard
;
969 ImplPostEventData
* pData
= static_cast< ImplPostEventData
* >( pCallData
);
970 const void* pEventData
;
972 ImplSVEvent
* const nEventId
= pData
->mnEventId
;
974 switch( pData
->mnEvent
)
976 case VCLEVENT_WINDOW_MOUSEMOVE
:
977 nEvent
= SalEvent::ExternalMouseMove
;
978 pEventData
= &pData
->maMouseEvent
;
981 case VCLEVENT_WINDOW_MOUSEBUTTONDOWN
:
982 nEvent
= SalEvent::ExternalMouseButtonDown
;
983 pEventData
= &pData
->maMouseEvent
;
986 case VCLEVENT_WINDOW_MOUSEBUTTONUP
:
987 nEvent
= SalEvent::ExternalMouseButtonUp
;
988 pEventData
= &pData
->maMouseEvent
;
991 case VCLEVENT_WINDOW_KEYINPUT
:
992 nEvent
= SalEvent::ExternalKeyInput
;
993 pEventData
= &pData
->maKeyEvent
;
996 case VCLEVENT_WINDOW_KEYUP
:
997 nEvent
= SalEvent::ExternalKeyUp
;
998 pEventData
= &pData
->maKeyEvent
;
1001 case VCLEVENT_WINDOW_ZOOM
:
1002 nEvent
= SalEvent::ExternalZoom
;
1003 pEventData
= &pData
->maZoomEvent
;
1006 case VCLEVENT_WINDOW_SCROLL
:
1007 nEvent
= SalEvent::ExternalScroll
;
1008 pEventData
= &pData
->maScrollEvent
;
1012 nEvent
= SalEvent::NONE
;
1013 pEventData
= nullptr;
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
);
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
);
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;
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
) )
1086 void Application::RemoveUserEvent( ImplSVEvent
* 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()
1130 ImplSVData
* pSVData
= ImplGetSVData();
1131 vcl::Window
*pWin
= pSVData
? pSVData
->maWinData
.mpFirstFrame
.get() : nullptr;
1134 if( pWin
->ImplGetWindow()->IsTopWindow() )
1136 pWin
= pWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1141 vcl::Window
* Application::GetTopWindow( long nIndex
)
1144 ImplSVData
* pSVData
= ImplGetSVData();
1145 vcl::Window
*pWin
= pSVData
? pSVData
->maWinData
.mpFirstFrame
.get() : nullptr;
1148 if( pWin
->ImplGetWindow()->IsTopWindow() )
1150 if( nIdx
== nIndex
)
1151 return pWin
->ImplGetWindow();
1155 pWin
= pWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1160 vcl::Window
* Application::GetActiveTopWindow()
1162 vcl::Window
*pWin
= ImplGetSVData()->maWinData
.mpFocusWin
;
1165 if( pWin
->IsTopWindow() )
1167 pWin
= pWin
->mpWindowImpl
->mpParent
;
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
);
1180 *(pSVData
->maAppData
.mpAppName
) = rUniqueName
;
1183 OUString
Application::GetAppName()
1185 ImplSVData
* pSVData
= ImplGetSVData();
1186 if ( pSVData
->maAppData
.mpAppName
)
1187 return *(pSVData
->maAppData
.mpAppName
);
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( "; " );
1203 if ( pSVData
&& pSVData
->mpDefInst
)
1204 aVersion
= pSVData
->mpDefInst
->getOSVersion();
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() );
1218 aDetails
.append( VclResId(SV_APP_DEFAULT
).toString() );
1219 aDetails
.append( "; " );
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( "; " );
1228 aDetails
.append( VclResId(SV_APP_LAYOUT_ENGINE
).toString() );
1229 if (SalLayout::UseCommonLayout())
1230 aDetails
.append( VclResId(SV_APP_LAYOUT_NEW
).toString() );
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
);
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();
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.
1283 switch (GetDisplayBuiltInScreen())
1292 // When the built-in display is neither 0 nor 1
1293 // then place the full-screen presentation on the
1294 // first available screen.
1301 Rectangle
Application::GetScreenPosSizePixel( unsigned int nScreen
)
1303 SalSystem
* pSys
= ImplGetSalSystem();
1304 return pSys
? pSys
->GetDisplayScreenPosSizePixel( nScreen
) : Rectangle();
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
) )
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
;
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
;
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();
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
);
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
1431 if ((pWin
->mpWindowImpl
->mnStyle
& WB_INTROWIN
) == 0)
1433 return pWin
->mpWindowImpl
->mpFrameWindow
->ImplGetWindow();
1437 // last active application frame
1438 pWin
= pSVData
->maWinData
.mpActiveApplicationFrame
;
1441 return pWin
->mpWindowImpl
->mpFrameWindow
->ImplGetWindow();
1444 // first visible top window (may be totally wrong....)
1445 pWin
= pSVData
->maWinData
.mpFirstFrame
;
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
;
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();
1494 xT
= pWrapper
->GetVCLToolkit();
1498 #ifdef DISABLE_DYNLOADING
1500 extern "C" { UnoWrapperBase
* CreateUnoWrapper(); }
1504 extern "C" { static void SAL_CALL
thisModule() {} }
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
1516 OUString
aLibName(TK_DLL_NAME
);
1517 aTkLib
.loadRelative(&thisModule
, aLibName
);
1520 FN_TkCreateUnoWrapper fnCreateWrapper
= reinterpret_cast<FN_TkCreateUnoWrapper
>(aTkLib
.getFunctionSymbol("CreateUnoWrapper"));
1521 if ( fnCreateWrapper
)
1523 pSVData
->mpUnoWrapper
= fnCreateWrapper();
1527 SAL_WARN_IF( !pSVData
->mpUnoWrapper
, "vcl", "UnoWrapper could not be created!" );
1529 pSVData
->mpUnoWrapper
= CreateUnoWrapper();
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
)
1572 pHotKeyData
= pHotKeyData
->mpNext
;
1578 void ImplFreeHotKeyData()
1580 ImplSVData
* pSVData
= ImplGetSVData();
1581 ImplHotKey
* pTempHotKeyData
;
1582 ImplHotKey
* pHotKeyData
= pSVData
->maAppData
.mpFirstHotKey
;
1583 while ( pHotKeyData
)
1585 pTempHotKeyData
= pHotKeyData
->mpNext
;
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();
1612 ImplEventHook
* pTempEventHookData
;
1613 ImplEventHook
* pEventHookData
= pSVData
->maAppData
.mpFirstEventHook
;
1614 while ( pEventHookData
)
1616 pTempEventHookData
= pEventHookData
->mpNext
;
1617 nRet
= pEventHookData
->mpProc( rEvt
, pEventHookData
->mpUserData
);
1620 pEventHookData
= pTempEventHookData
;
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()
1674 void Application::EnableSafeMode()
1679 void Application::ShowNativeErrorBox(const OUString
& sTitle
,
1680 const OUString
& sMessage
)
1682 int btn
= ImplGetSalSystem()->ShowNativeMessageBox(
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");
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
1741 bool bRet
= ImplInitAccessBridge();
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
);
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: */