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>
21 #include <config_version.h>
23 #include <osl/diagnose.h>
24 #include <osl/file.hxx>
25 #include <osl/thread.hxx>
26 #include <osl/module.hxx>
27 #include <rtl/ustrbuf.hxx>
29 #include <sal/log.hxx>
31 #include <tools/debug.hxx>
32 #include <tools/time.hxx>
33 #include <tools/stream.hxx>
34 #include <tools/json_writer.hxx>
36 #include <comphelper/configuration.hxx>
37 #include <unotools/resmgr.hxx>
38 #include <unotools/syslocale.hxx>
39 #include <unotools/syslocaleoptions.hxx>
41 #include <vcl/toolkit/dialog.hxx>
42 #include <vcl/dialoghelper.hxx>
43 #include <vcl/lok.hxx>
44 #include <vcl/toolkit/floatwin.hxx>
45 #include <vcl/settings.hxx>
46 #include <vcl/keycod.hxx>
47 #include <vcl/event.hxx>
48 #include <vcl/vclevent.hxx>
49 #include <vcl/virdev.hxx>
50 #include <vcl/wrkwin.hxx>
51 #include <vcl/svapp.hxx>
52 #include <vcl/cvtgrf.hxx>
53 #include <vcl/toolkit/unowrap.hxx>
54 #include <vcl/timer.hxx>
55 #include <vcl/scheduler.hxx>
56 #include <vcl/skia/SkiaHelper.hxx>
59 #include <salinst.hxx>
60 #include <graphic/Manager.hxx>
61 #include <salframe.hxx>
64 #include <displayconnectiondispatch.hxx>
67 #include <strings.hrc>
68 #include <strings.hxx>
69 #if OSL_DEBUG_LEVEL > 0
70 #include <schedulerimpl.hxx>
73 #include <com/sun/star/uno/Reference.h>
74 #include <com/sun/star/awt/XToolkit.hpp>
75 #include <comphelper/lok.hxx>
76 #include <comphelper/threadpool.hxx>
77 #include <comphelper/solarmutex.hxx>
78 #include <osl/process.h>
81 #include <svl/poolitem.hxx>
82 #include <svl/itemset.hxx>
83 #include <svl/itempool.hxx>
88 #include <string_view>
92 using namespace ::com::sun::star
;
93 using namespace ::com::sun::star::uno
;
96 void InitSettings(ImplSVData
* pSVData
);
99 // keycodes handled internally by VCL
100 vcl::KeyCode
const ReservedKeys
[]
102 vcl::KeyCode(KEY_F1
,0) , // Help
103 vcl::KeyCode(KEY_F1
,KEY_SHIFT
) , // Context help
104 vcl::KeyCode(KEY_F2
,KEY_SHIFT
) , // Activate extended tooltips
105 vcl::KeyCode(KEY_F4
,KEY_MOD1
) , // Close document
106 vcl::KeyCode(KEY_F4
,KEY_MOD2
) , // Close document
107 vcl::KeyCode(KEY_F6
,0) , // Set focus to next visible subwindow
108 vcl::KeyCode(KEY_F6
,KEY_MOD1
) , // Set focus to the document canvas/data source
109 vcl::KeyCode(KEY_F6
,KEY_SHIFT
) , // Set focus to previous subwindow
110 vcl::KeyCode(KEY_F10
,0) // Activate the first menu
114 typedef UnoWrapperBase
* (*FN_TkCreateUnoWrapper
)();
117 struct ImplPostEventData
119 VclPtr
<vcl::Window
> mpWin
;
120 ImplSVEvent
* mnEventId
;
121 MouseEvent maMouseEvent
;
124 GestureEventPan maGestureEvent
;
126 ImplPostEventData(VclEventId nEvent
, vcl::Window
* pWin
, const KeyEvent
& rKeyEvent
)
130 , maKeyEvent(rKeyEvent
)
132 ImplPostEventData(VclEventId nEvent
, vcl::Window
* pWin
, const MouseEvent
& rMouseEvent
)
135 , maMouseEvent(rMouseEvent
)
138 ImplPostEventData(VclEventId nEvent
, vcl::Window
* pWin
, const GestureEventPan
& rGestureEvent
)
142 , maGestureEvent(rGestureEvent
)
146 Application
* GetpApp()
148 ImplSVData
* pSVData
= ImplGetSVData();
151 return pSVData
->mpApp
;
154 Application::Application()
156 // useful for themes at least, perhaps extensions too
157 OUString
aVar(u
"LIBO_VERSION"_ustr
), aValue(u
"" LIBO_VERSION_DOTTED
""_ustr
);
158 osl_setEnvironment(aVar
.pData
, aValue
.pData
);
160 ImplGetSVData()->mpApp
= this;
161 m_pCallbackData
= nullptr;
162 m_pCallback
= nullptr;
165 Application::~Application()
168 ImplGetSVData()->mpApp
= nullptr;
171 // svx/source/dialog/framelinkarray.cxx
172 // class Cell final : public SfxPoolItem
173 // const Cell OBJ_CELL_NONE;
174 // being a static held SfxPoolItem which is not yet de-initialized here
175 // number often is (1), even higher with other modules loaded (like 5).
176 // These get de-allocated reliably in module-deinitializations, so this
177 // is no memory loss. These counters are more to be able to have an eye
178 // on amounts of SfxPoolItems used during office usage and to be able to
179 // detect if an error in future changes may lead to memory losses - these
180 // would show in dramatically higher numbers then immediately
181 SAL_INFO("vcl.items", "ITEM: " << getAllocatedSfxPoolItemCount() << " SfxPoolItems still allocated at shutdown");
182 SAL_INFO("vcl.items", "ITEM: " << getUsedSfxPoolItemCount() << " SfxPoolItems were incarnated during runtime");
184 // Same mechanism for SfxItemSet(s)
185 SAL_INFO("vcl.items", "ITEM: " << getAllocatedSfxItemSetCount() << " SfxItemSets still allocated at shutdown");
186 SAL_INFO("vcl.items", "ITEM: " << getUsedSfxItemSetCount() << " SfxItemSets were incarnated during runtime");
188 // Same mechanism for PoolItemHolder(s)
189 SAL_INFO("vcl.items", "ITEM: " << getAllocatedSfxPoolItemHolderCount() << " SfxPoolItemHolders still allocated at shutdown");
190 SAL_INFO("vcl.items", "ITEM: " << getUsedSfxPoolItemHolderCount() << " SfxPoolItemHolders were incarnated during runtime");
192 // Additional call to list still incarnated SfxPoolItems (under 'svl.items')
193 listAllocatedSfxPoolItems();
195 // List SfxPoolItems with highest RefCounts, these are the best
196 // candidates to add a ItemInstanceManager mechanism
197 listSfxPoolItemsWithHighestUsage(20);
198 listSfxItemSetUsage();
202 int Application::Main()
204 SAL_WARN("vcl", "Application is a base class and should be overridden.");
208 bool Application::QueryExit()
210 WorkWindow
* pAppWin
= ImplGetSVData()->maFrameData
.mpAppWin
;
212 // call the close handler of the application window
214 return pAppWin
->Close();
219 void Application::Shutdown()
223 void Application::Init()
227 void Application::InitFinished()
231 void Application::DeInit()
235 sal_uInt16
Application::GetCommandLineParamCount()
237 return static_cast<sal_uInt16
>(osl_getCommandArgCount());
240 OUString
Application::GetCommandLineParam( sal_uInt16 nParam
)
243 osl_getCommandArg( nParam
, &aParam
.pData
);
247 OUString
Application::GetAppFileName()
249 ImplSVData
* pSVData
= ImplGetSVData();
250 SAL_WARN_IF( !pSVData
->maAppData
.mxAppFileName
, "vcl", "AppFileName should be set to something after SVMain!" );
251 if ( pSVData
->maAppData
.mxAppFileName
)
252 return *pSVData
->maAppData
.mxAppFileName
;
255 * provide a fallback for people without initialized vcl here (like setup
256 * in responsefile mode)
258 OUString aAppFileName
;
259 OUString aExeFileName
;
260 osl_getExecutableFile(&aExeFileName
.pData
);
262 // convert path to native file format
263 osl::FileBase::getSystemPathFromFileURL(aExeFileName
, aAppFileName
);
268 void Application::Exception( ExceptionCategory nCategory
)
272 // System has precedence (so do nothing)
273 case ExceptionCategory::System
:
274 case ExceptionCategory::UserInterface
:
277 Abort(u
"Unknown Error"_ustr
);
282 void Application::Abort( const OUString
& rErrorText
)
284 //HACK: Dump core iff --norestore command line argument is given (assuming
285 // this process is run by developers who are interested in cores, vs. end
286 // users who are not):
287 #if OSL_DEBUG_LEVEL > 0
288 bool dumpCore
= true;
290 bool dumpCore
= false;
291 sal_uInt16 n
= GetCommandLineParamCount();
292 for (sal_uInt16 i
= 0; i
!= n
; ++i
) {
293 if (GetCommandLineParam(i
) == "--norestore") {
300 SalAbort( rErrorText
, dumpCore
);
303 size_t Application::GetReservedKeyCodeCount()
305 return SAL_N_ELEMENTS(ReservedKeys
);
308 const vcl::KeyCode
* Application::GetReservedKeyCode( size_t i
)
310 if( i
>= GetReservedKeyCodeCount() )
313 return &ReservedKeys
[i
];
316 void Application::notifyWindow(vcl::LOKWindowId
/*nLOKWindowId*/,
317 const OUString
& /*rAction*/,
318 const std::vector
<vcl::LOKPayloadItem
>& /*rPayload = std::vector<LOKPayloadItem>()*/) const
320 SAL_WARN("vcl", "Invoked not implemented method: Application::notifyWindow");
323 OString
Application::dumpNotifyState() const
325 SAL_WARN("vcl", "Invoked not implemented method: Application::dumpNotifyState");
326 return "notimpl"_ostr
;
329 void Application::libreOfficeKitViewCallback(int nType
, const OString
& pPayload
) const
331 if (!comphelper::LibreOfficeKit::isActive())
336 m_pCallback(nType
, pPayload
.getStr(), m_pCallbackData
);
340 void Application::notifyInvalidation(tools::Rectangle
const* /*pRect*/) const
344 void Application::Execute()
346 ImplSVData
* pSVData
= ImplGetSVData();
347 pSVData
->maAppData
.mbInAppExecute
= true;
348 pSVData
->maAppData
.mbAppQuit
= false;
351 if (!pSVData
->mpDefInst
->DoExecute(nExitCode
))
353 if (Application::IsUseSystemEventLoop())
355 SAL_WARN("vcl.schedule", "Can't omit DoExecute when running on system event loop!");
358 while (!pSVData
->maAppData
.mbAppQuit
)
360 Application::Yield();
361 SolarMutexReleaser releaser
; // Give a chance for the waiting threads to lock the mutex
362 pSVData
->m_inExecuteCondtion
.set();
366 pSVData
->maAppData
.mbInAppExecute
= false;
368 GetpApp()->Shutdown();
371 static bool ImplYield(bool i_bWait
, bool i_bAllEvents
)
373 ImplSVData
* pSVData
= ImplGetSVData();
375 SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait
? "wait" : "no wait") <<
376 ": " << (i_bAllEvents
? "all events" : "one event"));
378 // there's a data race here on WNT only because ImplYield may be
379 // called without SolarMutex; but the only remaining use of mnDispatchLevel
380 // is in OSX specific code
381 pSVData
->maAppData
.mnDispatchLevel
++;
383 // do not wait for events if application was already quit; in that
384 // case only dispatch events already available
385 bool bProcessedEvent
= pSVData
->mpDefInst
->DoYield(
386 i_bWait
&& !pSVData
->maAppData
.mbAppQuit
, i_bAllEvents
);
388 pSVData
->maAppData
.mnDispatchLevel
--;
390 DBG_TESTSOLARMUTEX(); // must be locked on return from Yield
392 SAL_INFO("vcl.schedule", "Leave ImplYield with return " << bProcessedEvent
);
393 return bProcessedEvent
;
396 bool Application::Reschedule( bool i_bAllEvents
)
398 static const bool bAbort
= Application::IsUseSystemEventLoop();
401 SAL_WARN("vcl.schedule", "Application::Reschedule(" << i_bAllEvents
<< ")");
404 return ImplYield(false, i_bAllEvents
);
407 bool Application::IsUseSystemEventLoop()
409 return ImplGetSVData()->maAppData
.m_bUseSystemLoop
;
412 void Scheduler::ProcessEventsToIdle()
414 #if OSL_DEBUG_LEVEL > 0
415 const ImplSVData
* pSVData
= ImplGetSVData();
416 if (pSVData
->mpDefInst
->IsMainThread())
417 assert(pSVData
->maSchedCtx
.mnIdlesLockCount
== 0);
420 while (ImplYield(false, true))
422 if (0 == ++nSanity
% 1000)
424 SAL_WARN("vcl.schedule", "ProcessEventsToIdle: " << nSanity
);
427 #if OSL_DEBUG_LEVEL > 0
428 // If we yield from a non-main thread we just can guarantee that all idle
429 // events were processed at some point, but our check can't prevent further
430 // processing in the main thread, which may add new events, so skip it.
431 if ( !pSVData
->mpDefInst
->IsMainThread() )
433 for (int nTaskPriority
= 0; nTaskPriority
< PRIO_COUNT
; ++nTaskPriority
)
435 const ImplSchedulerData
* pSchedulerData
= pSVData
->maSchedCtx
.mpFirstSchedulerData
[nTaskPriority
];
436 while (pSchedulerData
)
438 assert(!pSchedulerData
->mbInScheduler
);
439 if (pSchedulerData
->mpTask
)
441 Idle
*pIdle
= dynamic_cast<Idle
*>(pSchedulerData
->mpTask
);
442 if (pIdle
&& pIdle
->IsActive())
444 SAL_WARN("vcl.schedule",
447 << (pIdle
->GetDebugName() ? pIdle
->GetDebugName() : "(nullptr)"));
450 pSchedulerData
= pSchedulerData
->mpNext
;
457 /// used by unit tests that test only via the LOK API
458 SAL_DLLPUBLIC_EXPORT
void unit_lok_process_events_to_idle()
460 const SolarMutexGuard aGuard
;
461 Scheduler::ProcessEventsToIdle();
465 void Application::Yield()
467 static const bool bAbort
= Application::IsUseSystemEventLoop();
470 SAL_WARN("vcl.schedule", "Application::Yield()");
473 ImplYield(true, false);
476 IMPL_STATIC_LINK_NOARG( ImplSVAppData
, ImplQuitMsg
, void*, void )
478 assert(ImplGetSVData()->maAppData
.mbAppQuit
);
479 ImplGetSVData()->mpDefInst
->DoQuit();
482 void Application::Quit()
484 ImplGetSVData()->maAppData
.mbAppQuit
= true;
485 Application::PostUserEvent( LINK( nullptr, ImplSVAppData
, ImplQuitMsg
) );
488 comphelper::SolarMutex
& Application::GetSolarMutex()
490 ImplSVData
* pSVData
= ImplGetSVData();
491 return *(pSVData
->mpDefInst
->GetYieldMutex());
494 bool Application::IsMainThread()
496 return ImplGetSVData()->mnMainThreadId
== osl::Thread::getCurrentIdentifier();
499 sal_uInt32
Application::ReleaseSolarMutex()
501 ImplSVData
* pSVData
= ImplGetSVData();
502 return pSVData
->mpDefInst
->ReleaseYieldMutex(true);
505 void Application::AcquireSolarMutex( sal_uInt32 nCount
)
507 ImplSVData
* pSVData
= ImplGetSVData();
508 pSVData
->mpDefInst
->AcquireYieldMutex( nCount
);
511 bool Application::IsInMain()
513 ImplSVData
* pSVData
= ImplGetSVData();
514 return pSVData
&& pSVData
->maAppData
.mbInAppMain
;
517 bool Application::IsInExecute()
519 return ImplGetSVData()->maAppData
.mbInAppExecute
;
522 bool Application::IsQuit()
524 return ImplGetSVData()->maAppData
.mbAppQuit
;
527 bool Application::IsInModalMode()
529 return (ImplGetSVData()->maAppData
.mnModalMode
!= 0);
532 sal_uInt16
Application::GetDispatchLevel()
534 return ImplGetSVData()->maAppData
.mnDispatchLevel
;
537 bool Application::AnyInput( VclInputFlags nType
)
539 return ImplGetSVData()->mpDefInst
->AnyInput( nType
);
542 sal_uInt64
Application::GetLastInputInterval()
544 return (tools::Time::GetSystemTicks()-ImplGetSVData()->maAppData
.mnLastInputTime
);
547 bool Application::IsUICaptured()
549 ImplSVData
* pSVData
= ImplGetSVData();
551 // If mouse was captured, or if in tracking- or in select-mode of a floatingwindow (e.g. menus
552 // or pulldown toolboxes) another window should be created
554 return pSVData
->mpWinData
->mpCaptureWin
|| pSVData
->mpWinData
->mpTrackWin
555 || pSVData
->mpWinData
->mpFirstFloat
|| nImplSysDialog
;
558 void Application::OverrideSystemSettings( AllSettings
& /*rSettings*/ )
562 void Application::MergeSystemSettings( AllSettings
& rSettings
)
564 vcl::Window
* pWindow
= ImplGetSVData()->maFrameData
.mpFirstFrame
;
566 pWindow
= ImplGetDefaultWindow();
569 ImplSVData
* pSVData
= ImplGetSVData();
570 if ( !pSVData
->maAppData
.mbSettingsInit
)
572 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
573 pWindow
->ImplUpdateGlobalSettings( *pSVData
->maAppData
.mxSettings
);
574 pSVData
->maAppData
.mbSettingsInit
= true;
576 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
577 pWindow
->ImplUpdateGlobalSettings( rSettings
, false );
581 void Application::SetSettings( const AllSettings
& rSettings
)
583 const SolarMutexGuard aGuard
;
585 ImplSVData
* pSVData
= ImplGetSVData();
586 if ( !pSVData
->maAppData
.mxSettings
)
588 InitSettings(pSVData
);
589 *pSVData
->maAppData
.mxSettings
= rSettings
;
593 AllSettings aOldSettings
= *pSVData
->maAppData
.mxSettings
;
594 if (aOldSettings
.GetUILanguageTag().getLanguageType() != rSettings
.GetUILanguageTag().getLanguageType() &&
595 pSVData
->mbResLocaleSet
)
597 pSVData
->mbResLocaleSet
= false;
599 *pSVData
->maAppData
.mxSettings
= rSettings
;
600 AllSettingsFlags nChangeFlags
= aOldSettings
.GetChangeFlags( *pSVData
->maAppData
.mxSettings
);
601 if ( bool(nChangeFlags
) )
603 DataChangedEvent
aDCEvt( DataChangedEventType::SETTINGS
, &aOldSettings
, nChangeFlags
);
605 // notify data change handler
606 ImplCallEventListenersApplicationDataChanged( &aDCEvt
);
608 // Update all windows
609 vcl::Window
* pFirstFrame
= pSVData
->maFrameData
.mpFirstFrame
;
610 // Reset data that needs to be re-calculated
611 tools::Long nOldDPIX
= 0;
612 tools::Long nOldDPIY
= 0;
615 nOldDPIX
= pFirstFrame
->GetOutDev()->GetDPIX();
616 nOldDPIY
= pFirstFrame
->GetOutDev()->GetDPIY();
617 vcl::Window::ImplInitAppFontData(pFirstFrame
);
619 vcl::Window
* pFrame
= pFirstFrame
;
622 // call UpdateSettings from ClientWindow in order to prevent updating data twice
623 vcl::Window
* pClientWin
= pFrame
;
624 while ( pClientWin
->ImplGetClientWindow() )
625 pClientWin
= pClientWin
->ImplGetClientWindow();
626 pClientWin
->UpdateSettings( rSettings
, true );
628 vcl::Window
* pTempWin
= pFrame
->mpWindowImpl
->mpFrameData
->mpFirstOverlap
;
631 // call UpdateSettings from ClientWindow in order to prevent updating data twice
632 pClientWin
= pTempWin
;
633 while ( pClientWin
->ImplGetClientWindow() )
634 pClientWin
= pClientWin
->ImplGetClientWindow();
635 pClientWin
->UpdateSettings( rSettings
, true );
636 pTempWin
= pTempWin
->mpWindowImpl
->mpNextOverlap
;
639 pFrame
= pFrame
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
642 // if DPI resolution for screen output was changed set the new resolution for all
643 // screen compatible VirDev's
644 pFirstFrame
= pSVData
->maFrameData
.mpFirstFrame
;
647 if ( (pFirstFrame
->GetOutDev()->GetDPIX() != nOldDPIX
) ||
648 (pFirstFrame
->GetOutDev()->GetDPIY() != nOldDPIY
) )
650 VirtualDevice
* pVirDev
= pSVData
->maGDIData
.mpFirstVirDev
;
653 if ( pVirDev
->mbScreenComp
&&
654 (pVirDev
->GetDPIX() == nOldDPIX
) &&
655 (pVirDev
->GetDPIY() == nOldDPIY
) )
657 pVirDev
->SetDPIX( pFirstFrame
->GetOutDev()->GetDPIX() );
658 pVirDev
->SetDPIY( pFirstFrame
->GetOutDev()->GetDPIY() );
659 if ( pVirDev
->IsMapModeEnabled() )
661 MapMode aMapMode
= pVirDev
->GetMapMode();
662 pVirDev
->SetMapMode();
663 pVirDev
->SetMapMode( aMapMode
);
667 pVirDev
= pVirDev
->mpNext
;
675 const AllSettings
& Application::GetSettings()
677 ImplSVData
* pSVData
= ImplGetSVData();
678 if ( !pSVData
->maAppData
.mxSettings
)
680 InitSettings(pSVData
);
683 return *(pSVData
->maAppData
.mxSettings
);
688 void InitSettings(ImplSVData
* pSVData
)
690 assert(!pSVData
->maAppData
.mxSettings
&& "initialization should not happen twice!");
692 pSVData
->maAppData
.mxSettings
.emplace();
693 if (!comphelper::IsFuzzing())
695 pSVData
->maAppData
.mpCfgListener
= new LocaleConfigurationListener
;
696 pSVData
->maAppData
.mxSettings
->GetSysLocale().GetOptions().AddListener( pSVData
->maAppData
.mpCfgListener
);
702 void Application::NotifyAllWindows( DataChangedEvent
& rDCEvt
)
704 ImplSVData
* pSVData
= ImplGetSVData();
705 vcl::Window
* pFrame
= pSVData
->maFrameData
.mpFirstFrame
;
708 pFrame
->NotifyAllChildren( rDCEvt
);
710 vcl::Window
* pSysWin
= pFrame
->mpWindowImpl
->mpFrameData
->mpFirstOverlap
;
713 pSysWin
->NotifyAllChildren( rDCEvt
);
714 pSysWin
= pSysWin
->mpWindowImpl
->mpNextOverlap
;
717 pFrame
= pFrame
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
721 void Application::ImplCallEventListenersApplicationDataChanged( void* pData
)
723 ImplSVData
* pSVData
= ImplGetSVData();
724 VclWindowEvent
aEvent( nullptr, VclEventId::ApplicationDataChanged
, pData
);
726 pSVData
->maAppData
.maEventListeners
.Call( aEvent
);
729 void Application::ImplCallEventListeners( VclSimpleEvent
& rEvent
)
731 ImplSVData
* pSVData
= ImplGetSVData();
732 pSVData
->maAppData
.maEventListeners
.Call( rEvent
);
735 void Application::AddEventListener( const Link
<VclSimpleEvent
&,void>& rEventListener
)
737 ImplSVData
* pSVData
= ImplGetSVData();
738 pSVData
->maAppData
.maEventListeners
.addListener( rEventListener
);
741 void Application::RemoveEventListener( const Link
<VclSimpleEvent
&,void>& rEventListener
)
743 ImplSVData
* pSVData
= ImplGetSVData();
744 pSVData
->maAppData
.maEventListeners
.removeListener( rEventListener
);
747 void Application::AddKeyListener( const Link
<VclWindowEvent
&,bool>& rKeyListener
)
749 ImplSVData
* pSVData
= ImplGetSVData();
750 pSVData
->maAppData
.maKeyListeners
.push_back( rKeyListener
);
753 void Application::RemoveKeyListener( const Link
<VclWindowEvent
&,bool>& rKeyListener
)
755 ImplSVData
* pSVData
= ImplGetSVData();
756 auto & rVec
= pSVData
->maAppData
.maKeyListeners
;
757 std::erase(rVec
, rKeyListener
);
760 bool Application::HandleKey( VclEventId nEvent
, vcl::Window
*pWin
, KeyEvent
* pKeyEvent
)
762 // let listeners process the key event
763 VclWindowEvent
aEvent( pWin
, nEvent
, static_cast<void *>(pKeyEvent
) );
765 ImplSVData
* pSVData
= ImplGetSVData();
767 if ( pSVData
->maAppData
.maKeyListeners
.empty() )
770 bool bProcessed
= false;
771 // Copy the list, because this can be destroyed when calling a Link...
772 std::vector
<Link
<VclWindowEvent
&,bool>> aCopy( pSVData
->maAppData
.maKeyListeners
);
773 for ( const Link
<VclWindowEvent
&,bool>& rLink
: aCopy
)
775 if( rLink
.Call( aEvent
) )
784 ImplSVEvent
* Application::PostKeyEvent( VclEventId nEvent
, vcl::Window
*pWin
, KeyEvent
const * pKeyEvent
)
786 const SolarMutexGuard aGuard
;
787 ImplSVEvent
* nEventId
= nullptr;
789 if( pWin
&& pKeyEvent
)
791 std::unique_ptr
<ImplPostEventData
> pPostEventData(new ImplPostEventData( nEvent
, pWin
, *pKeyEvent
));
793 nEventId
= PostUserEvent(
794 LINK( nullptr, Application
, PostEventHandler
),
795 pPostEventData
.get() );
799 pPostEventData
->mnEventId
= nEventId
;
800 ImplGetSVData()->maAppData
.maPostedEventList
.emplace_back( pWin
, pPostEventData
.release() );
807 ImplSVEvent
* Application::PostGestureEvent(VclEventId nEvent
, vcl::Window
* pWin
,
808 GestureEventPan
const * pGestureEvent
)
810 const SolarMutexGuard aGuard
;
811 ImplSVEvent
* nEventId
= nullptr;
813 if (pWin
&& pGestureEvent
)
815 Point
aTransformedPosition(pGestureEvent
->mnX
, pGestureEvent
->mnY
);
817 aTransformedPosition
.AdjustX(pWin
->GetOutOffXPixel());
818 aTransformedPosition
.AdjustY(pWin
->GetOutOffYPixel());
820 const GestureEventPan
aGestureEvent(
821 sal_Int32(aTransformedPosition
.X()),
822 sal_Int32(aTransformedPosition
.Y()),
823 pGestureEvent
->meEventType
,
824 pGestureEvent
->mnOffset
,
825 pGestureEvent
->meOrientation
828 std::unique_ptr
<ImplPostEventData
> pPostEventData(new ImplPostEventData(nEvent
, pWin
, aGestureEvent
));
830 nEventId
= PostUserEvent(
831 LINK( nullptr, Application
, PostEventHandler
),
832 pPostEventData
.get());
836 pPostEventData
->mnEventId
= nEventId
;
837 ImplGetSVData()->maAppData
.maPostedEventList
.emplace_back(pWin
, pPostEventData
.release());
844 bool Application::LOKHandleMouseEvent(VclEventId nEvent
, vcl::Window
* pWindow
, const MouseEvent
* pEvent
)
846 bool bSuccess
= false;
847 SalMouseEvent aMouseEvent
;
855 aMouseEvent
.mnTime
= tools::Time::GetSystemTicks();
856 aMouseEvent
.mnX
= pEvent
->GetPosPixel().X();
857 aMouseEvent
.mnY
= pEvent
->GetPosPixel().Y();
858 aMouseEvent
.mnCode
= pEvent
->GetButtons() | pEvent
->GetModifier();
862 case VclEventId::WindowMouseMove
:
863 aMouseEvent
.mnButton
= 0;
864 bSuccess
= ImplLOKHandleMouseEvent(pWindow
, NotifyEventType::MOUSEMOVE
, false,
865 aMouseEvent
.mnX
, aMouseEvent
.mnY
,
866 aMouseEvent
.mnTime
, aMouseEvent
.mnCode
,
867 ImplGetMouseMoveMode(&aMouseEvent
),
868 pEvent
->GetClicks());
871 case VclEventId::WindowMouseButtonDown
:
872 aMouseEvent
.mnButton
= pEvent
->GetButtons();
873 bSuccess
= ImplLOKHandleMouseEvent(pWindow
, NotifyEventType::MOUSEBUTTONDOWN
, false,
874 aMouseEvent
.mnX
, aMouseEvent
.mnY
,
877 aMouseEvent
.mnButton
|
878 (aMouseEvent
.mnCode
& (KEY_SHIFT
| KEY_MOD1
| KEY_MOD2
| KEY_MOD3
)),
880 aMouseEvent
.mnButton
|
881 (aMouseEvent
.mnCode
& (KEY_SHIFT
| KEY_MOD1
| KEY_MOD2
)),
883 ImplGetMouseButtonMode(&aMouseEvent
),
884 pEvent
->GetClicks());
887 case VclEventId::WindowMouseButtonUp
:
888 aMouseEvent
.mnButton
= pEvent
->GetButtons();
889 bSuccess
= ImplLOKHandleMouseEvent(pWindow
, NotifyEventType::MOUSEBUTTONUP
, false,
890 aMouseEvent
.mnX
, aMouseEvent
.mnY
,
893 aMouseEvent
.mnButton
|
894 (aMouseEvent
.mnCode
& (KEY_SHIFT
| KEY_MOD1
| KEY_MOD2
| KEY_MOD3
)),
896 aMouseEvent
.mnButton
|
897 (aMouseEvent
.mnCode
& (KEY_SHIFT
| KEY_MOD1
| KEY_MOD2
)),
899 ImplGetMouseButtonMode(&aMouseEvent
),
900 pEvent
->GetClicks());
904 SAL_WARN( "vcl.layout", "Application::HandleMouseEvent unknown event (" << static_cast<int>(nEvent
) << ")" );
912 ImplSVEvent
* Application::PostMouseEvent( VclEventId nEvent
, vcl::Window
*pWin
, MouseEvent
const * pMouseEvent
)
914 const SolarMutexGuard aGuard
;
915 ImplSVEvent
* nEventId
= nullptr;
917 if( pWin
&& pMouseEvent
)
919 Point
aTransformedPos( pMouseEvent
->GetPosPixel() );
921 // LOK uses (0, 0) as the origin of all windows; don't offset.
922 if (!comphelper::LibreOfficeKit::isActive())
924 aTransformedPos
.AdjustX(pWin
->GetOutOffXPixel());
925 aTransformedPos
.AdjustY(pWin
->GetOutOffYPixel());
928 const MouseEvent
aTransformedEvent( aTransformedPos
, pMouseEvent
->GetClicks(), pMouseEvent
->GetMode(),
929 pMouseEvent
->GetButtons(), pMouseEvent
->GetModifier() );
931 std::unique_ptr
<ImplPostEventData
> pPostEventData(new ImplPostEventData( nEvent
, pWin
, aTransformedEvent
));
933 nEventId
= PostUserEvent(
934 LINK( nullptr, Application
, PostEventHandler
),
935 pPostEventData
.get() );
939 pPostEventData
->mnEventId
= nEventId
;
940 ImplGetSVData()->maAppData
.maPostedEventList
.emplace_back( pWin
, pPostEventData
.release() );
948 IMPL_STATIC_LINK( Application
, PostEventHandler
, void*, pCallData
, void )
950 const SolarMutexGuard aGuard
;
951 ImplPostEventData
* pData
= static_cast< ImplPostEventData
* >( pCallData
);
952 const void* pEventData
;
954 ImplSVEvent
* const nEventId
= pData
->mnEventId
;
956 switch( pData
->mnEvent
)
958 case VclEventId::WindowMouseMove
:
959 nEvent
= SalEvent::ExternalMouseMove
;
960 pEventData
= &pData
->maMouseEvent
;
963 case VclEventId::WindowMouseButtonDown
:
964 nEvent
= SalEvent::ExternalMouseButtonDown
;
965 pEventData
= &pData
->maMouseEvent
;
968 case VclEventId::WindowMouseButtonUp
:
969 nEvent
= SalEvent::ExternalMouseButtonUp
;
970 pEventData
= &pData
->maMouseEvent
;
973 case VclEventId::WindowKeyInput
:
974 nEvent
= SalEvent::ExternalKeyInput
;
975 pEventData
= &pData
->maKeyEvent
;
978 case VclEventId::WindowKeyUp
:
979 nEvent
= SalEvent::ExternalKeyUp
;
980 pEventData
= &pData
->maKeyEvent
;
983 case VclEventId::WindowGestureEvent
:
984 nEvent
= SalEvent::ExternalGesture
;
985 pEventData
= &pData
->maGestureEvent
;
989 nEvent
= SalEvent::NONE
;
990 pEventData
= nullptr;
994 if( pData
->mpWin
&& pData
->mpWin
->mpWindowImpl
->mpFrameWindow
&& pEventData
)
995 ImplWindowFrameProc( pData
->mpWin
->mpWindowImpl
->mpFrameWindow
.get(), nEvent
, pEventData
);
997 // remove this event from list of posted events, watch for destruction of internal data
998 auto svdata
= ImplGetSVData();
999 ::std::vector
< ImplPostEventPair
>::iterator
aIter( svdata
->maAppData
.maPostedEventList
.begin() );
1001 while( aIter
!= svdata
->maAppData
.maPostedEventList
.end() )
1003 if( nEventId
== (*aIter
).second
->mnEventId
)
1005 delete (*aIter
).second
;
1006 aIter
= svdata
->maAppData
.maPostedEventList
.erase( aIter
);
1013 void Application::RemoveMouseAndKeyEvents( vcl::Window
* pWin
)
1015 const SolarMutexGuard aGuard
;
1017 // remove all events for specific window, watch for destruction of internal data
1018 auto svdata
= ImplGetSVData();
1019 ::std::vector
< ImplPostEventPair
>::iterator
aIter( svdata
->maAppData
.maPostedEventList
.begin() );
1021 while( aIter
!= svdata
->maAppData
.maPostedEventList
.end() )
1023 if( pWin
== (*aIter
).first
)
1025 if( (*aIter
).second
->mnEventId
)
1026 RemoveUserEvent( (*aIter
).second
->mnEventId
);
1028 delete (*aIter
).second
;
1029 aIter
= svdata
->maAppData
.maPostedEventList
.erase( aIter
);
1036 ImplSVEvent
* Application::PostUserEvent( const Link
<void*,void>& rLink
, void* pCaller
,
1037 bool bReferenceLink
)
1039 vcl::Window
* pDefWindow
= ImplGetDefaultWindow();
1040 if ( pDefWindow
== nullptr )
1043 std::unique_ptr
<ImplSVEvent
> pSVEvent(new ImplSVEvent
);
1044 pSVEvent
->mpData
= pCaller
;
1045 pSVEvent
->maLink
= rLink
;
1046 pSVEvent
->mpWindow
= nullptr;
1047 pSVEvent
->mbCall
= true;
1050 SolarMutexGuard aGuard
;
1051 pSVEvent
->mpInstanceRef
= static_cast<vcl::Window
*>(rLink
.GetInstance());
1054 auto pTmpEvent
= pSVEvent
.get();
1055 if (!pDefWindow
->ImplGetFrame()->PostEvent( std::move(pSVEvent
) ))
1060 void Application::RemoveUserEvent( ImplSVEvent
* nUserEvent
)
1064 SAL_WARN_IF( nUserEvent
->mpWindow
, "vcl",
1065 "Application::RemoveUserEvent(): Event is send to a window" );
1066 SAL_WARN_IF( !nUserEvent
->mbCall
, "vcl",
1067 "Application::RemoveUserEvent(): Event is already removed" );
1069 nUserEvent
->mpWindow
.clear();
1070 nUserEvent
->mpInstanceRef
.clear();
1071 nUserEvent
->mbCall
= false;
1075 vcl::Window
* Application::GetFocusWindow()
1077 return ImplGetSVData()->mpWinData
->mpFocusWin
;
1080 OutputDevice
* Application::GetDefaultDevice()
1082 vcl::Window
* pWindow
= ImplGetDefaultWindow();
1083 if (pWindow
!= nullptr)
1085 return pWindow
->GetOutDev();
1093 basegfx::SystemDependentDataManager
& Application::GetSystemDependentDataManager()
1095 return ImplGetSystemDependentDataManager();
1098 vcl::Window
* Application::GetFirstTopLevelWindow()
1100 ImplSVData
* pSVData
= ImplGetSVData();
1101 return pSVData
->maFrameData
.mpFirstFrame
;
1104 vcl::Window
* Application::GetNextTopLevelWindow( vcl::Window
const * pWindow
)
1106 return pWindow
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1109 tools::Long
Application::GetTopWindowCount()
1111 tools::Long nRet
= 0;
1112 ImplSVData
* pSVData
= ImplGetSVData();
1113 vcl::Window
*pWin
= pSVData
? pSVData
->maFrameData
.mpFirstFrame
.get() : nullptr;
1116 if( pWin
->ImplGetWindow()->IsTopWindow() )
1118 pWin
= pWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1123 vcl::Window
* Application::GetTopWindow( tools::Long nIndex
)
1125 tools::Long nIdx
= 0;
1126 ImplSVData
* pSVData
= ImplGetSVData();
1127 vcl::Window
*pWin
= pSVData
? pSVData
->maFrameData
.mpFirstFrame
.get() : nullptr;
1130 if( pWin
->ImplGetWindow()->IsTopWindow() )
1132 if( nIdx
== nIndex
)
1133 return pWin
->ImplGetWindow();
1137 pWin
= pWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1142 vcl::Window
* Application::GetActiveTopWindow()
1144 vcl::Window
*pWin
= ImplGetSVData()->mpWinData
->mpFocusWin
;
1147 if( pWin
->IsTopWindow() )
1149 pWin
= pWin
->mpWindowImpl
->mpParent
;
1154 void Application::SetAppName( const OUString
& rUniqueName
)
1156 ImplSVData
* pSVData
= ImplGetSVData();
1157 pSVData
->maAppData
.mxAppName
= rUniqueName
;
1160 const OUString
& Application::GetAppName()
1162 ImplSVData
* pSVData
= ImplGetSVData();
1163 if ( pSVData
->maAppData
.mxAppName
)
1164 return *(pSVData
->maAppData
.mxAppName
);
1166 return EMPTY_OUSTRING
;
1169 enum {hwAll
=0, hwEnv
=1, hwUI
=2};
1171 static OUString
Localize(TranslateId aId
, const bool bLocalize
)
1174 return VclResId(aId
);
1176 return Translate::get(aId
, Translate::Create("vcl", LanguageTag(u
"en-US"_ustr
)));
1179 OUString
Application::GetOSVersion()
1181 ImplSVData
* pSVData
= ImplGetSVData();
1183 if (pSVData
&& pSVData
->mpDefInst
)
1184 aVersion
= pSVData
->mpDefInst
->getOSVersion();
1190 OUString
Application::GetHWOSConfInfo(const int bSelection
, const bool bLocalize
)
1192 OUStringBuffer aDetails
;
1194 const auto appendDetails
= [&aDetails
](std::u16string_view sep
, auto&& val
) {
1195 if (!aDetails
.isEmpty() && !sep
.empty())
1196 aDetails
.append(sep
);
1197 aDetails
.append(std::move(val
));
1200 if (bSelection
!= hwUI
) {
1201 appendDetails(u
"; ", Localize(SV_APP_CPUTHREADS
, bLocalize
)
1202 + OUString::number(std::thread::hardware_concurrency()));
1204 OUString aVersion
= GetOSVersion();
1206 appendDetails(u
"; ", Localize(SV_APP_OSVERSION
, bLocalize
) + aVersion
);
1209 if (bSelection
!= hwEnv
) {
1210 appendDetails(u
"; ", Localize(SV_APP_UIRENDER
, bLocalize
));
1211 #if HAVE_FEATURE_SKIA
1212 if ( SkiaHelper::isVCLSkiaEnabled() )
1214 switch(SkiaHelper::renderMethodToUse())
1216 case SkiaHelper::RenderVulkan
:
1217 appendDetails(u
"", Localize(SV_APP_SKIA_VULKAN
, bLocalize
));
1219 case SkiaHelper::RenderMetal
:
1220 appendDetails(u
"", Localize(SV_APP_SKIA_METAL
, bLocalize
));
1222 case SkiaHelper::RenderRaster
:
1223 appendDetails(u
"", Localize(SV_APP_SKIA_RASTER
, bLocalize
));
1229 appendDetails(u
"", Localize(SV_APP_DEFAULT
, bLocalize
));
1231 #if (defined LINUX || defined _WIN32 || defined MACOSX || defined __FreeBSD__ || defined EMSCRIPTEN)
1232 appendDetails(u
"; ", SV_APP_VCLBACKEND
+ GetToolkitName());
1236 return aDetails
.makeStringAndClear();
1239 void Application::SetDisplayName( const OUString
& rName
)
1241 ImplSVData
* pSVData
= ImplGetSVData();
1242 pSVData
->maAppData
.mxDisplayName
= rName
;
1245 OUString
Application::GetDisplayName()
1247 ImplSVData
* pSVData
= ImplGetSVData();
1248 if ( pSVData
->maAppData
.mxDisplayName
)
1249 return *(pSVData
->maAppData
.mxDisplayName
);
1250 else if (pSVData
->maFrameData
.mpAppWin
)
1251 return pSVData
->maFrameData
.mpAppWin
->GetText();
1256 unsigned int Application::GetScreenCount()
1258 SalSystem
* pSys
= ImplGetSalSystem();
1259 return pSys
? pSys
->GetDisplayScreenCount() : 0;
1262 unsigned int Application::GetDisplayBuiltInScreen()
1264 SalSystem
* pSys
= ImplGetSalSystem();
1265 return pSys
? pSys
->GetDisplayBuiltInScreen() : 0;
1268 unsigned int Application::GetDisplayExternalScreen()
1270 // This is really unpleasant, in theory we could have multiple
1271 // external displays etc.
1273 switch (GetDisplayBuiltInScreen())
1282 // When the built-in display is neither 0 nor 1
1283 // then place the full-screen presentation on the
1284 // first available screen.
1291 AbsoluteScreenPixelRectangle
Application::GetScreenPosSizePixel( unsigned int nScreen
)
1293 SalSystem
* pSys
= ImplGetSalSystem();
1296 SAL_WARN("vcl", "Requesting screen size/pos for screen #" << nScreen
<< " failed");
1298 return AbsoluteScreenPixelRectangle();
1300 AbsoluteScreenPixelRectangle aRect
= pSys
->GetDisplayScreenPosSizePixel(nScreen
);
1301 if (aRect
.GetHeight() == 0)
1302 SAL_WARN("vcl", "Requesting screen size/pos for screen #" << nScreen
<< " returned 0 height.");
1307 tools::Long
calcDistSquare( const AbsoluteScreenPixelPoint
& i_rPoint
, const AbsoluteScreenPixelRectangle
& i_rRect
)
1309 const AbsoluteScreenPixelPoint
aRectCenter( (i_rRect
.Left() + i_rRect
.Right())/2,
1310 (i_rRect
.Top() + i_rRect
.Bottom())/ 2 );
1311 const tools::Long nDX
= aRectCenter
.X() - i_rPoint
.X();
1312 const tools::Long nDY
= aRectCenter
.Y() - i_rPoint
.Y();
1313 return nDX
*nDX
+ nDY
*nDY
;
1317 unsigned int Application::GetBestScreen( const AbsoluteScreenPixelRectangle
& i_rRect
)
1319 const unsigned int nScreens
= GetScreenCount();
1320 unsigned int nBestMatchScreen
= 0;
1321 unsigned long nOverlap
= 0;
1322 for( unsigned int i
= 0; i
< nScreens
; i
++ )
1324 const AbsoluteScreenPixelRectangle
aCurScreenRect( GetScreenPosSizePixel( i
) );
1325 // if a screen contains the rectangle completely it is obviously the best screen
1326 if( aCurScreenRect
.Contains( i_rRect
) )
1328 // next the screen which contains most of the area of the rect is the best
1329 AbsoluteScreenPixelRectangle
aIntersection( aCurScreenRect
.GetIntersection( i_rRect
) );
1330 if( ! aIntersection
.IsEmpty() )
1332 const unsigned long nCurOverlap( aIntersection
.GetWidth() * aIntersection
.GetHeight() );
1333 if( nCurOverlap
> nOverlap
)
1335 nOverlap
= nCurOverlap
;
1336 nBestMatchScreen
= i
;
1341 return nBestMatchScreen
;
1343 // finally the screen which center is nearest to the rect is the best
1344 const AbsoluteScreenPixelPoint
aCenter( (i_rRect
.Left() + i_rRect
.Right())/2,
1345 (i_rRect
.Top() + i_rRect
.Bottom())/2 );
1346 tools::Long nDist
= std::numeric_limits
<tools::Long
>::max();
1347 for( unsigned int i
= 0; i
< nScreens
; i
++ )
1349 const AbsoluteScreenPixelRectangle
aCurScreenRect( GetScreenPosSizePixel( i
) );
1350 const tools::Long
nCurDist( calcDistSquare( aCenter
, aCurScreenRect
) );
1351 if( nCurDist
< nDist
)
1353 nBestMatchScreen
= i
;
1357 return nBestMatchScreen
;
1360 bool Application::InsertAccel( Accelerator
* pAccel
)
1362 ImplSVData
* pSVData
= ImplGetSVData();
1364 if ( !pSVData
->maAppData
.mpAccelMgr
)
1365 pSVData
->maAppData
.mpAccelMgr
= new ImplAccelManager();
1366 return pSVData
->maAppData
.mpAccelMgr
->InsertAccel( pAccel
);
1369 void Application::RemoveAccel( Accelerator
const * pAccel
)
1371 ImplSVData
* pSVData
= ImplGetSVData();
1373 if ( pSVData
->maAppData
.mpAccelMgr
)
1374 pSVData
->maAppData
.mpAccelMgr
->RemoveAccel( pAccel
);
1377 void Application::SetHelp( Help
* pHelp
)
1379 ImplGetSVData()->maAppData
.mpHelp
= pHelp
;
1382 void Application::UpdateMainThread()
1384 ImplSVData
* pSVData
= ImplGetSVData();
1385 if (pSVData
&& pSVData
->mpDefInst
)
1386 pSVData
->mpDefInst
->updateMainThread();
1389 Help
* Application::GetHelp()
1391 return ImplGetSVData()->maAppData
.mpHelp
;
1394 const OUString
& Application::GetToolkitName()
1396 ImplSVData
* pSVData
= ImplGetSVData();
1397 if ( pSVData
->maAppData
.mxToolkitName
)
1398 return *(pSVData
->maAppData
.mxToolkitName
);
1400 return EMPTY_OUSTRING
;
1403 vcl::Window
* Dialog::GetDefDialogParent()
1405 ImplSVData
* pSVData
= ImplGetSVData();
1406 // find some useful dialog parent
1408 // always use the topmost parent of the candidate
1409 // window to avoid using dialogs or floaters
1410 // as DefDialogParent
1412 // current focus frame
1413 vcl::Window
*pWin
= pSVData
->mpWinData
->mpFocusWin
;
1414 if (pWin
&& !pWin
->IsMenuFloatingWindow())
1416 while (pWin
->mpWindowImpl
&& pWin
->mpWindowImpl
->mpParent
)
1417 pWin
= pWin
->mpWindowImpl
->mpParent
;
1419 // check for corrupted window hierarchy, #122232#, may be we now crash somewhere else
1420 if (!pWin
->mpWindowImpl
)
1422 OSL_FAIL( "Window hierarchy corrupted!" );
1423 pSVData
->mpWinData
->mpFocusWin
= nullptr; // avoid further access
1427 if ((pWin
->mpWindowImpl
->mnStyle
& WB_INTROWIN
) == 0)
1429 return pWin
->mpWindowImpl
->mpFrameWindow
->ImplGetWindow();
1433 // last active application frame
1434 pWin
= pSVData
->maFrameData
.mpActiveApplicationFrame
;
1437 return pWin
->mpWindowImpl
->mpFrameWindow
->ImplGetWindow();
1440 // first visible top window (may be totally wrong...)
1441 pWin
= pSVData
->maFrameData
.mpFirstFrame
;
1444 if( pWin
->ImplGetWindow()->IsTopWindow() &&
1445 pWin
->mpWindowImpl
->mbReallyVisible
&&
1446 (pWin
->mpWindowImpl
->mnStyle
& WB_INTROWIN
) == 0
1449 while( pWin
->mpWindowImpl
->mpParent
)
1450 pWin
= pWin
->mpWindowImpl
->mpParent
;
1451 return pWin
->mpWindowImpl
->mpFrameWindow
->ImplGetWindow();
1453 pWin
= pWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1460 weld::Window
* Application::GetDefDialogParent()
1462 vcl::Window
* pWindow
= Dialog::GetDefDialogParent();
1463 return pWindow
? pWindow
->GetFrameWeld() : nullptr;
1466 DialogCancelMode
Application::GetDialogCancelMode()
1468 return ImplGetSVData()->maAppData
.meDialogCancel
;
1471 void Application::SetDialogCancelMode( DialogCancelMode mode
)
1473 ImplGetSVData()->maAppData
.meDialogCancel
= mode
;
1476 bool Application::IsDialogCancelEnabled()
1478 return ImplGetSVData()->maAppData
.meDialogCancel
!= DialogCancelMode::Off
;
1481 void Application::SetSystemWindowMode( SystemWindowFlags nMode
)
1483 ImplGetSVData()->maAppData
.mnSysWinMode
= nMode
;
1486 SystemWindowFlags
Application::GetSystemWindowMode()
1488 return ImplGetSVData()->maAppData
.mnSysWinMode
;
1491 css::uno::Reference
< css::awt::XToolkit
> Application::GetVCLToolkit()
1493 css::uno::Reference
< css::awt::XToolkit
> xT
;
1494 UnoWrapperBase
* pWrapper
= UnoWrapperBase::GetUnoWrapper();
1496 xT
= pWrapper
->GetVCLToolkit();
1500 #ifdef DISABLE_DYNLOADING
1502 extern "C" { UnoWrapperBase
* CreateUnoWrapper(); }
1506 extern "C" { static void thisModule() {} }
1510 UnoWrapperBase
* UnoWrapperBase::GetUnoWrapper( bool bCreateIfNotExist
)
1512 ImplSVData
* pSVData
= ImplGetSVData();
1513 static bool bAlreadyTriedToCreate
= false;
1514 if ( !pSVData
->mpUnoWrapper
&& bCreateIfNotExist
&& !bAlreadyTriedToCreate
)
1516 #ifndef DISABLE_DYNLOADING
1518 aTkLib
.loadRelative(&thisModule
, TK_DLL_NAME
);
1521 FN_TkCreateUnoWrapper fnCreateWrapper
= reinterpret_cast<FN_TkCreateUnoWrapper
>(aTkLib
.getFunctionSymbol("CreateUnoWrapper"));
1522 if ( fnCreateWrapper
)
1524 pSVData
->mpUnoWrapper
= fnCreateWrapper();
1528 SAL_WARN_IF( !pSVData
->mpUnoWrapper
, "vcl", "UnoWrapper could not be created!" );
1530 pSVData
->mpUnoWrapper
= CreateUnoWrapper();
1532 bAlreadyTriedToCreate
= true;
1534 return pSVData
->mpUnoWrapper
;
1537 void UnoWrapperBase::SetUnoWrapper( UnoWrapperBase
* pWrapper
)
1539 ImplSVData
* pSVData
= ImplGetSVData();
1540 SAL_WARN_IF( pSVData
->mpUnoWrapper
, "vcl", "SetUnoWrapper: Wrapper already exists" );
1541 pSVData
->mpUnoWrapper
= pWrapper
;
1544 css::uno::Reference
< css::awt::XDisplayConnection
> Application::GetDisplayConnection()
1546 ImplSVData
* pSVData
= ImplGetSVData();
1548 if( !pSVData
->mxDisplayConnection
.is() )
1550 pSVData
->mxDisplayConnection
.set( new vcl::DisplayConnectionDispatch
);
1551 pSVData
->mxDisplayConnection
->start();
1554 return pSVData
->mxDisplayConnection
;
1557 void Application::SetFilterHdl( const Link
<ConvertData
&,bool>& rLink
)
1559 ImplGetSVData()->maGDIData
.mxGrfConverter
->SetFilterHdl( rLink
);
1562 const LocaleDataWrapper
& Application::GetAppLocaleDataWrapper()
1564 return GetSettings().GetLocaleDataWrapper();
1567 void Application::EnableHeadlessMode( bool dialogsAreFatal
)
1569 DialogCancelMode eNewMode
= dialogsAreFatal
? DialogCancelMode::Fatal
: DialogCancelMode::Silent
;
1570 DialogCancelMode eOldMode
= GetDialogCancelMode();
1571 assert(eOldMode
== DialogCancelMode::Off
|| GetDialogCancelMode() == eNewMode
);
1572 if (eOldMode
!= eNewMode
)
1573 SetDialogCancelMode( eNewMode
);
1576 bool Application::IsHeadlessModeEnabled()
1578 return IsDialogCancelEnabled() || comphelper::LibreOfficeKit::isActive();
1581 void Application::EnableBitmapRendering()
1583 ImplGetSVData()->maAppData
.mbRenderToBitmaps
= true;
1586 bool Application::IsBitmapRendering()
1588 return ImplGetSVData()->maAppData
.mbRenderToBitmaps
;
1591 void Application::EnableConsoleOnly()
1593 EnableHeadlessMode(true);
1594 EnableBitmapRendering();
1597 static bool bSafeMode
= false;
1599 bool Application::IsSafeModeEnabled()
1604 void Application::EnableSafeMode()
1609 void Application::ShowNativeErrorBox(const OUString
& sTitle
,
1610 const OUString
& sMessage
)
1612 int btn
= ImplGetSalSystem()->ShowNativeMessageBox(
1615 if (btn
!= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
) {
1616 SAL_WARN( "vcl", "ShowNativeMessageBox returned " << btn
);
1620 const OUString
& Application::GetDesktopEnvironment()
1622 if (IsHeadlessModeEnabled())
1624 static constexpr OUString
aNone(u
"none"_ustr
);
1628 return SalGetDesktopEnvironment();
1631 void Application::AddToRecentDocumentList(const OUString
& rFileUrl
, const OUString
& rMimeType
, const OUString
& rDocumentService
)
1633 ImplSVData
* pSVData
= ImplGetSVData();
1634 pSVData
->mpDefInst
->AddToRecentDocumentList(rFileUrl
, rMimeType
, rDocumentService
);
1637 // MT: AppEvent was in oldsv.cxx, but is still needed...
1638 void Application::AppEvent( const ApplicationEvent
& /*rAppEvent*/ )
1642 bool Application::hasNativeFileSelection()
1644 ImplSVData
* pSVData
= ImplGetSVData();
1645 return pSVData
->mpDefInst
->hasNativeFileSelection();
1648 Reference
< ui::dialogs::XFilePicker2
>
1649 Application::createFilePicker( const Reference
< uno::XComponentContext
>& xSM
)
1651 ImplSVData
* pSVData
= ImplGetSVData();
1652 return pSVData
->mpDefInst
->createFilePicker( xSM
);
1655 Reference
< ui::dialogs::XFolderPicker2
>
1656 Application::createFolderPicker( const Reference
< uno::XComponentContext
>& xSM
)
1658 ImplSVData
* pSVData
= ImplGetSVData();
1659 return pSVData
->mpDefInst
->createFolderPicker( xSM
);
1662 void Application::setDeInitHook(Link
<LinkParamNone
*,void> const & hook
) {
1663 ImplSVData
* pSVData
= ImplGetSVData();
1664 assert(!pSVData
->maDeInitHook
.IsSet());
1665 pSVData
->maDeInitHook
= hook
;
1666 // Fake this for VCLXToolkit ctor instantiated from
1667 // postprocess/CppunitTest_services.mk:
1668 pSVData
->maAppData
.mbInAppMain
= true;
1671 namespace vcl::lok
{
1673 void registerPollCallbacks(
1674 LibreOfficeKitPollCallback pPollCallback
,
1675 LibreOfficeKitWakeCallback pWakeCallback
,
1678 ImplSVData
* pSVData
= ImplGetSVData();
1681 pSVData
->mpPollCallback
= pPollCallback
;
1682 pSVData
->mpWakeCallback
= pWakeCallback
;
1683 pSVData
->mpPollClosure
= pData
;
1687 void unregisterPollCallbacks()
1689 ImplSVData
* pSVData
= ImplGetSVData();
1693 // Not hyper-elegant - but in the case of Android & unipoll we need to detach
1694 // this thread from the JVM's clutches to avoid a crash closing document
1695 if (pSVData
->mpPollClosure
&& pSVData
->mpDefInst
)
1696 pSVData
->mpDefInst
->releaseMainThread();
1698 // Just set mpPollClosure to null as that is what calling this means, that the callback data
1699 // points to an object that no longer exists. In particular, don't set
1700 // pSVData->mpPollCallback to nullptr as that is used to detect whether Unipoll is in use in
1702 pSVData
->mpPollClosure
= nullptr;
1707 ImplSVData
* pSVData
= ImplGetSVData();
1708 return pSVData
&& pSVData
->mpPollCallback
!= nullptr;
1711 void numberOfViewsChanged(int count
)
1715 ImplSVData
* pSVData
= ImplGetSVData();
1716 auto& rCache
= pSVData
->maGDIData
.maScaleCache
;
1717 // Normally the cache size is set to 10, scale according to the number of users.
1718 rCache
.setMaxSize(count
* 10);
1721 void dumpState(rtl::OStringBuffer
&rState
)
1723 ImplSVData
* pSVData
= ImplGetSVData();
1728 // lo_dumpState deliberately doesn't take SolarMutexGuard
1729 // so disable these checks during dumpState
1730 DbgGUIDeInitSolarMutexCheck();
1733 rState
.append("\nWindows:\t");
1734 rState
.append(static_cast<sal_Int32
>(Application::GetTopWindowCount()));
1736 vcl::Window
*pWin
= Application::GetFirstTopLevelWindow();
1739 tools::JsonWriter aProps
;
1740 pWin
->DumpAsPropertyTree(aProps
);
1742 rState
.append("\n\tWindow: ");
1744 auto notifier
= pWin
->GetLOKNotifier();
1747 rState
.append(notifier
->dumpNotifyState());
1751 rState
.append("no notifier ");
1753 OString aPropStr
= aProps
.finishAndGetAsOString();
1754 if (aPropStr
.getLength() > 256)
1756 rState
.append(aPropStr
.subView(0, 256));
1757 rState
.append("...");
1759 rState
.append(aPropStr
);
1761 pWin
= Application::GetNextTopLevelWindow( pWin
);
1764 vcl::graphic::MemoryManager::get().dumpState(rState
);
1766 pSVData
->dumpState(rState
);
1769 DbgGUIInitSolarMutexCheck();
1773 void trimMemory(int nTarget
)
1775 if (nTarget
>= 1000)
1777 ImplSVData
* pSVData
= ImplGetSVData();
1778 if (!pSVData
) // shutting down
1780 pSVData
->dropCaches();
1781 vcl::graphic::MemoryManager::get().reduceAllAndNow();
1782 // TODO: ideally - free up any deeper dirtied thread stacks.
1783 // comphelper::ThreadPool::getSharedOptimalPool().shutdown();
1785 // else for now caches re-fill themselves as/when used.
1788 } // namespace lok, namespace vcl
1790 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */