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 <osl/file.hxx>
23 #include <osl/thread.hxx>
24 #include <osl/module.hxx>
25 #include <rtl/ustrbuf.hxx>
27 #include <sal/log.hxx>
29 #include <tools/debug.hxx>
30 #include <tools/time.hxx>
31 #include <tools/stream.hxx>
32 #include <tools/json_writer.hxx>
34 #include <unotools/configmgr.hxx>
35 #include <unotools/resmgr.hxx>
36 #include <unotools/syslocale.hxx>
37 #include <unotools/syslocaleoptions.hxx>
39 #include <vcl/toolkit/dialog.hxx>
40 #include <vcl/dialoghelper.hxx>
41 #include <vcl/lok.hxx>
42 #include <vcl/toolkit/floatwin.hxx>
43 #include <vcl/settings.hxx>
44 #include <vcl/keycod.hxx>
45 #include <vcl/event.hxx>
46 #include <vcl/vclevent.hxx>
47 #include <vcl/virdev.hxx>
48 #include <vcl/wrkwin.hxx>
49 #include <vcl/svapp.hxx>
50 #include <vcl/cvtgrf.hxx>
51 #include <vcl/toolkit/unowrap.hxx>
52 #include <vcl/timer.hxx>
53 #include <vcl/scheduler.hxx>
54 #include <vcl/skia/SkiaHelper.hxx>
56 #include <salinst.hxx>
57 #include <graphic/Manager.hxx>
58 #include <salframe.hxx>
61 #include <displayconnectiondispatch.hxx>
64 #include <strings.hrc>
65 #include <strings.hxx>
66 #if OSL_DEBUG_LEVEL > 0
67 #include <schedulerimpl.hxx>
70 #include <com/sun/star/uno/Reference.h>
71 #include <com/sun/star/awt/XToolkit.hpp>
72 #include <comphelper/lok.hxx>
73 #include <comphelper/threadpool.hxx>
74 #include <comphelper/solarmutex.hxx>
75 #include <osl/process.h>
79 #include <string_view>
83 using namespace ::com::sun::star
;
84 using namespace ::com::sun::star::uno
;
87 void InitSettings(ImplSVData
* pSVData
);
90 // keycodes handled internally by VCL
91 vcl::KeyCode
const ReservedKeys
[]
93 vcl::KeyCode(KEY_F1
,0) ,
94 vcl::KeyCode(KEY_F1
,KEY_SHIFT
) ,
95 vcl::KeyCode(KEY_F1
,KEY_MOD1
) ,
96 vcl::KeyCode(KEY_F2
,KEY_SHIFT
) ,
97 vcl::KeyCode(KEY_F4
,KEY_MOD1
) ,
98 vcl::KeyCode(KEY_F4
,KEY_MOD2
) ,
99 vcl::KeyCode(KEY_F4
,KEY_MOD1
|KEY_MOD2
) ,
100 vcl::KeyCode(KEY_F6
,0) ,
101 vcl::KeyCode(KEY_F6
,KEY_MOD1
) ,
102 vcl::KeyCode(KEY_F6
,KEY_SHIFT
) ,
103 vcl::KeyCode(KEY_F6
,KEY_MOD1
|KEY_SHIFT
) ,
104 vcl::KeyCode(KEY_F10
,0)
107 vcl::KeyCode(KEY_1
,KEY_SHIFT
|KEY_MOD1
),
108 vcl::KeyCode(KEY_2
,KEY_SHIFT
|KEY_MOD1
),
109 vcl::KeyCode(KEY_3
,KEY_SHIFT
|KEY_MOD1
),
110 vcl::KeyCode(KEY_4
,KEY_SHIFT
|KEY_MOD1
),
111 vcl::KeyCode(KEY_5
,KEY_SHIFT
|KEY_MOD1
),
112 vcl::KeyCode(KEY_6
,KEY_SHIFT
|KEY_MOD1
),
113 vcl::KeyCode(KEY_7
,KEY_SHIFT
|KEY_MOD1
),
114 vcl::KeyCode(KEY_8
,KEY_SHIFT
|KEY_MOD1
),
115 vcl::KeyCode(KEY_9
,KEY_SHIFT
|KEY_MOD1
),
116 vcl::KeyCode(KEY_0
,KEY_SHIFT
|KEY_MOD1
),
117 vcl::KeyCode(KEY_ADD
,KEY_SHIFT
|KEY_MOD1
)
122 typedef UnoWrapperBase
* (*FN_TkCreateUnoWrapper
)();
125 struct ImplPostEventData
127 VclPtr
<vcl::Window
> mpWin
;
128 ImplSVEvent
* mnEventId
;
129 MouseEvent maMouseEvent
;
132 GestureEventPan maGestureEvent
;
134 ImplPostEventData(VclEventId nEvent
, vcl::Window
* pWin
, const KeyEvent
& rKeyEvent
)
138 , maKeyEvent(rKeyEvent
)
140 ImplPostEventData(VclEventId nEvent
, vcl::Window
* pWin
, const MouseEvent
& rMouseEvent
)
143 , maMouseEvent(rMouseEvent
)
146 ImplPostEventData(VclEventId nEvent
, vcl::Window
* pWin
, const GestureEventPan
& rGestureEvent
)
150 , maGestureEvent(rGestureEvent
)
154 Application
* GetpApp()
156 ImplSVData
* pSVData
= ImplGetSVData();
159 return pSVData
->mpApp
;
162 Application::Application()
164 // useful for themes at least, perhaps extensions too
165 OUString
aVar("LIBO_VERSION"), aValue(LIBO_VERSION_DOTTED
);
166 osl_setEnvironment(aVar
.pData
, aValue
.pData
);
168 ImplGetSVData()->mpApp
= this;
169 m_pCallbackData
= nullptr;
170 m_pCallback
= nullptr;
173 Application::~Application()
176 ImplGetSVData()->mpApp
= nullptr;
179 int Application::Main()
181 SAL_WARN("vcl", "Application is a base class and should be overridden.");
185 bool Application::QueryExit()
187 WorkWindow
* pAppWin
= ImplGetSVData()->maFrameData
.mpAppWin
;
189 // call the close handler of the application window
191 return pAppWin
->Close();
196 void Application::Shutdown()
200 void Application::Init()
204 void Application::InitFinished()
208 void Application::DeInit()
212 sal_uInt16
Application::GetCommandLineParamCount()
214 return static_cast<sal_uInt16
>(osl_getCommandArgCount());
217 OUString
Application::GetCommandLineParam( sal_uInt16 nParam
)
220 osl_getCommandArg( nParam
, &aParam
.pData
);
224 OUString
Application::GetAppFileName()
226 ImplSVData
* pSVData
= ImplGetSVData();
227 SAL_WARN_IF( !pSVData
->maAppData
.mxAppFileName
, "vcl", "AppFileName should be set to something after SVMain!" );
228 if ( pSVData
->maAppData
.mxAppFileName
)
229 return *pSVData
->maAppData
.mxAppFileName
;
232 * provide a fallback for people without initialized vcl here (like setup
233 * in responsefile mode)
235 OUString aAppFileName
;
236 OUString aExeFileName
;
237 osl_getExecutableFile(&aExeFileName
.pData
);
239 // convert path to native file format
240 osl::FileBase::getSystemPathFromFileURL(aExeFileName
, aAppFileName
);
245 void Application::Exception( ExceptionCategory nCategory
)
249 // System has precedence (so do nothing)
250 case ExceptionCategory::System
:
251 case ExceptionCategory::UserInterface
:
254 Abort("Unknown Error");
259 void Application::Abort( const OUString
& rErrorText
)
261 //HACK: Dump core iff --norestore command line argument is given (assuming
262 // this process is run by developers who are interested in cores, vs. end
263 // users who are not):
264 #if OSL_DEBUG_LEVEL > 0
265 bool dumpCore
= true;
267 bool dumpCore
= false;
268 sal_uInt16 n
= GetCommandLineParamCount();
269 for (sal_uInt16 i
= 0; i
!= n
; ++i
) {
270 if (GetCommandLineParam(i
) == "--norestore") {
277 SalAbort( rErrorText
, dumpCore
);
280 size_t Application::GetReservedKeyCodeCount()
282 return SAL_N_ELEMENTS(ReservedKeys
);
285 const vcl::KeyCode
* Application::GetReservedKeyCode( size_t i
)
287 if( i
>= GetReservedKeyCodeCount() )
290 return &ReservedKeys
[i
];
293 IMPL_STATIC_LINK_NOARG( ImplSVAppData
, ImplEndAllPopupsMsg
, void*, void )
295 ImplSVData
* pSVData
= ImplGetSVData();
296 while (pSVData
->mpWinData
->mpFirstFloat
)
297 pSVData
->mpWinData
->mpFirstFloat
->EndPopupMode(FloatWinPopupEndFlags::Cancel
);
300 IMPL_STATIC_LINK_NOARG( ImplSVAppData
, ImplEndAllDialogsMsg
, void*, void )
302 vcl::Window
* pAppWindow
= Application::GetFirstTopLevelWindow();
305 vcl::EndAllDialogs(pAppWindow
);
306 pAppWindow
= Application::GetNextTopLevelWindow(pAppWindow
);
310 void Application::EndAllDialogs()
312 Application::PostUserEvent( LINK( nullptr, ImplSVAppData
, ImplEndAllDialogsMsg
) );
315 void Application::EndAllPopups()
317 Application::PostUserEvent( LINK( nullptr, ImplSVAppData
, ImplEndAllPopupsMsg
) );
320 void Application::notifyWindow(vcl::LOKWindowId
/*nLOKWindowId*/,
321 const OUString
& /*rAction*/,
322 const std::vector
<vcl::LOKPayloadItem
>& /*rPayload = std::vector<LOKPayloadItem>()*/) const
324 SAL_WARN("vcl", "Invoked not implemented method: Application::notifyWindow");
327 void Application::libreOfficeKitViewCallback(int nType
, const OString
& pPayload
) const
329 if (!comphelper::LibreOfficeKit::isActive())
334 m_pCallback(nType
, pPayload
.getStr(), m_pCallbackData
);
338 void Application::notifyInvalidation(tools::Rectangle
const* /*pRect*/) const
342 void Application::Execute()
344 ImplSVData
* pSVData
= ImplGetSVData();
345 pSVData
->maAppData
.mbInAppExecute
= true;
346 pSVData
->maAppData
.mbAppQuit
= false;
349 if (!pSVData
->mpDefInst
->DoExecute(nExitCode
))
351 if (Application::IsOnSystemEventLoop())
353 SAL_WARN("vcl.schedule", "Can't omit DoExecute when running on system event loop!");
356 while (!pSVData
->maAppData
.mbAppQuit
)
357 Application::Yield();
360 pSVData
->maAppData
.mbInAppExecute
= false;
362 GetpApp()->Shutdown();
365 static bool ImplYield(bool i_bWait
, bool i_bAllEvents
)
367 ImplSVData
* pSVData
= ImplGetSVData();
369 SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait
? "wait" : "no wait") <<
370 ": " << (i_bAllEvents
? "all events" : "one event"));
372 // there's a data race here on WNT only because ImplYield may be
373 // called without SolarMutex; but the only remaining use of mnDispatchLevel
374 // is in OSX specific code
375 pSVData
->maAppData
.mnDispatchLevel
++;
377 // do not wait for events if application was already quit; in that
378 // case only dispatch events already available
379 bool bProcessedEvent
= pSVData
->mpDefInst
->DoYield(
380 i_bWait
&& !pSVData
->maAppData
.mbAppQuit
, i_bAllEvents
);
382 pSVData
->maAppData
.mnDispatchLevel
--;
384 DBG_TESTSOLARMUTEX(); // must be locked on return from Yield
386 SAL_INFO("vcl.schedule", "Leave ImplYield with return " << bProcessedEvent
);
387 return bProcessedEvent
;
390 bool Application::Reschedule( bool i_bAllEvents
)
392 static const bool bAbort
= Application::IsOnSystemEventLoop();
395 SAL_WARN("vcl.schedule", "Application::Reschedule(" << i_bAllEvents
<< ")");
398 return ImplYield(false, i_bAllEvents
);
401 bool Application::IsOnSystemEventLoop()
403 return ImplGetSVData()->maAppData
.m_bUseSystemLoop
;
406 void Scheduler::ProcessEventsToIdle()
409 while (ImplYield(false, true))
411 if (0 == ++nSanity
% 1000)
413 SAL_WARN("vcl.schedule", "ProcessEventsToIdle: " << nSanity
);
416 #if OSL_DEBUG_LEVEL > 0
417 // If we yield from a non-main thread we just can guarantee that all idle
418 // events were processed at some point, but our check can't prevent further
419 // processing in the main thread, which may add new events, so skip it.
420 const ImplSVData
* pSVData
= ImplGetSVData();
421 if ( !pSVData
->mpDefInst
->IsMainThread() )
423 for (int nTaskPriority
= 0; nTaskPriority
< PRIO_COUNT
; ++nTaskPriority
)
425 const ImplSchedulerData
* pSchedulerData
= pSVData
->maSchedCtx
.mpFirstSchedulerData
[nTaskPriority
];
426 while (pSchedulerData
)
428 assert(!pSchedulerData
->mbInScheduler
);
429 if (pSchedulerData
->mpTask
)
431 Idle
*pIdle
= dynamic_cast<Idle
*>(pSchedulerData
->mpTask
);
432 if (pIdle
&& pIdle
->IsActive())
434 SAL_WARN("vcl.schedule",
437 << (pIdle
->GetDebugName() ? pIdle
->GetDebugName() : "(nullptr)"));
440 pSchedulerData
= pSchedulerData
->mpNext
;
447 /// used by unit tests that test only via the LOK API
448 SAL_DLLPUBLIC_EXPORT
void unit_lok_process_events_to_idle()
450 const SolarMutexGuard aGuard
;
451 Scheduler::ProcessEventsToIdle();
455 void Application::Yield()
457 static const bool bAbort
= Application::IsOnSystemEventLoop();
460 SAL_WARN("vcl.schedule", "Application::Yield()");
463 ImplYield(true, false);
466 IMPL_STATIC_LINK_NOARG( ImplSVAppData
, ImplQuitMsg
, void*, void )
468 assert(ImplGetSVData()->maAppData
.mbAppQuit
);
469 ImplGetSVData()->mpDefInst
->DoQuit();
472 void Application::Quit()
474 ImplGetSVData()->maAppData
.mbAppQuit
= true;
475 Application::PostUserEvent( LINK( nullptr, ImplSVAppData
, ImplQuitMsg
) );
478 comphelper::SolarMutex
& Application::GetSolarMutex()
480 ImplSVData
* pSVData
= ImplGetSVData();
481 return *(pSVData
->mpDefInst
->GetYieldMutex());
484 bool Application::IsMainThread()
486 return ImplGetSVData()->mnMainThreadId
== osl::Thread::getCurrentIdentifier();
489 sal_uInt32
Application::ReleaseSolarMutex()
491 ImplSVData
* pSVData
= ImplGetSVData();
492 return pSVData
->mpDefInst
->ReleaseYieldMutexAll();
495 void Application::AcquireSolarMutex( sal_uInt32 nCount
)
497 ImplSVData
* pSVData
= ImplGetSVData();
498 pSVData
->mpDefInst
->AcquireYieldMutex( nCount
);
501 bool Application::IsInMain()
503 ImplSVData
* pSVData
= ImplGetSVData();
504 return pSVData
&& pSVData
->maAppData
.mbInAppMain
;
507 bool Application::IsInExecute()
509 return ImplGetSVData()->maAppData
.mbInAppExecute
;
512 bool Application::IsQuit()
514 return ImplGetSVData()->maAppData
.mbAppQuit
;
517 bool Application::IsInModalMode()
519 return (ImplGetSVData()->maAppData
.mnModalMode
!= 0);
522 sal_uInt16
Application::GetDispatchLevel()
524 return ImplGetSVData()->maAppData
.mnDispatchLevel
;
527 bool Application::AnyInput( VclInputFlags nType
)
529 return ImplGetSVData()->mpDefInst
->AnyInput( nType
);
532 sal_uInt64
Application::GetLastInputInterval()
534 return (tools::Time::GetSystemTicks()-ImplGetSVData()->maAppData
.mnLastInputTime
);
537 bool Application::IsUICaptured()
539 ImplSVData
* pSVData
= ImplGetSVData();
541 // If mouse was captured, or if in tracking- or in select-mode of a floatingwindow (e.g. menus
542 // or pulldown toolboxes) another window should be created
544 return pSVData
->mpWinData
->mpCaptureWin
|| pSVData
->mpWinData
->mpTrackWin
545 || pSVData
->mpWinData
->mpFirstFloat
|| nImplSysDialog
;
548 void Application::OverrideSystemSettings( AllSettings
& /*rSettings*/ )
552 void Application::MergeSystemSettings( AllSettings
& rSettings
)
554 vcl::Window
* pWindow
= ImplGetSVData()->maFrameData
.mpFirstFrame
;
556 pWindow
= ImplGetDefaultWindow();
559 ImplSVData
* pSVData
= ImplGetSVData();
560 if ( !pSVData
->maAppData
.mbSettingsInit
)
562 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
563 pWindow
->ImplUpdateGlobalSettings( *pSVData
->maAppData
.mxSettings
);
564 pSVData
->maAppData
.mbSettingsInit
= true;
566 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
567 pWindow
->ImplUpdateGlobalSettings( rSettings
, false );
571 void Application::SetSettings( const AllSettings
& rSettings
)
573 const SolarMutexGuard aGuard
;
575 ImplSVData
* pSVData
= ImplGetSVData();
576 if ( !pSVData
->maAppData
.mxSettings
)
578 InitSettings(pSVData
);
579 *pSVData
->maAppData
.mxSettings
= rSettings
;
583 AllSettings aOldSettings
= *pSVData
->maAppData
.mxSettings
;
584 if (aOldSettings
.GetUILanguageTag().getLanguageType() != rSettings
.GetUILanguageTag().getLanguageType() &&
585 pSVData
->mbResLocaleSet
)
587 pSVData
->mbResLocaleSet
= false;
589 *pSVData
->maAppData
.mxSettings
= rSettings
;
590 AllSettingsFlags nChangeFlags
= aOldSettings
.GetChangeFlags( *pSVData
->maAppData
.mxSettings
);
591 if ( bool(nChangeFlags
) )
593 DataChangedEvent
aDCEvt( DataChangedEventType::SETTINGS
, &aOldSettings
, nChangeFlags
);
595 // notify data change handler
596 ImplCallEventListenersApplicationDataChanged( &aDCEvt
);
598 // Update all windows
599 vcl::Window
* pFirstFrame
= pSVData
->maFrameData
.mpFirstFrame
;
600 // Reset data that needs to be re-calculated
601 tools::Long nOldDPIX
= 0;
602 tools::Long nOldDPIY
= 0;
605 nOldDPIX
= pFirstFrame
->GetOutDev()->GetDPIX();
606 nOldDPIY
= pFirstFrame
->GetOutDev()->GetDPIY();
607 vcl::Window::ImplInitAppFontData(pFirstFrame
);
609 vcl::Window
* pFrame
= pFirstFrame
;
612 // call UpdateSettings from ClientWindow in order to prevent updating data twice
613 vcl::Window
* pClientWin
= pFrame
;
614 while ( pClientWin
->ImplGetClientWindow() )
615 pClientWin
= pClientWin
->ImplGetClientWindow();
616 pClientWin
->UpdateSettings( rSettings
, true );
618 vcl::Window
* pTempWin
= pFrame
->mpWindowImpl
->mpFrameData
->mpFirstOverlap
;
621 // call UpdateSettings from ClientWindow in order to prevent updating data twice
622 pClientWin
= pTempWin
;
623 while ( pClientWin
->ImplGetClientWindow() )
624 pClientWin
= pClientWin
->ImplGetClientWindow();
625 pClientWin
->UpdateSettings( rSettings
, true );
626 pTempWin
= pTempWin
->mpWindowImpl
->mpNextOverlap
;
629 pFrame
= pFrame
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
632 // if DPI resolution for screen output was changed set the new resolution for all
633 // screen compatible VirDev's
634 pFirstFrame
= pSVData
->maFrameData
.mpFirstFrame
;
637 if ( (pFirstFrame
->GetOutDev()->GetDPIX() != nOldDPIX
) ||
638 (pFirstFrame
->GetOutDev()->GetDPIY() != nOldDPIY
) )
640 VirtualDevice
* pVirDev
= pSVData
->maGDIData
.mpFirstVirDev
;
643 if ( pVirDev
->mbScreenComp
&&
644 (pVirDev
->GetDPIX() == nOldDPIX
) &&
645 (pVirDev
->GetDPIY() == nOldDPIY
) )
647 pVirDev
->SetDPIX( pFirstFrame
->GetOutDev()->GetDPIX() );
648 pVirDev
->SetDPIY( pFirstFrame
->GetOutDev()->GetDPIY() );
649 if ( pVirDev
->IsMapModeEnabled() )
651 MapMode aMapMode
= pVirDev
->GetMapMode();
652 pVirDev
->SetMapMode();
653 pVirDev
->SetMapMode( aMapMode
);
657 pVirDev
= pVirDev
->mpNext
;
665 const AllSettings
& Application::GetSettings()
667 ImplSVData
* pSVData
= ImplGetSVData();
668 if ( !pSVData
->maAppData
.mxSettings
)
670 InitSettings(pSVData
);
673 return *(pSVData
->maAppData
.mxSettings
);
678 void InitSettings(ImplSVData
* pSVData
)
680 assert(!pSVData
->maAppData
.mxSettings
&& "initialization should not happen twice!");
682 pSVData
->maAppData
.mxSettings
.emplace();
683 if (!utl::ConfigManager::IsFuzzing())
685 pSVData
->maAppData
.mpCfgListener
= new LocaleConfigurationListener
;
686 pSVData
->maAppData
.mxSettings
->GetSysLocale().GetOptions().AddListener( pSVData
->maAppData
.mpCfgListener
);
692 void Application::NotifyAllWindows( DataChangedEvent
& rDCEvt
)
694 ImplSVData
* pSVData
= ImplGetSVData();
695 vcl::Window
* pFrame
= pSVData
->maFrameData
.mpFirstFrame
;
698 pFrame
->NotifyAllChildren( rDCEvt
);
700 vcl::Window
* pSysWin
= pFrame
->mpWindowImpl
->mpFrameData
->mpFirstOverlap
;
703 pSysWin
->NotifyAllChildren( rDCEvt
);
704 pSysWin
= pSysWin
->mpWindowImpl
->mpNextOverlap
;
707 pFrame
= pFrame
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
711 void Application::ImplCallEventListenersApplicationDataChanged( void* pData
)
713 ImplSVData
* pSVData
= ImplGetSVData();
714 VclWindowEvent
aEvent( nullptr, VclEventId::ApplicationDataChanged
, pData
);
716 pSVData
->maAppData
.maEventListeners
.Call( aEvent
);
719 void Application::ImplCallEventListeners( VclSimpleEvent
& rEvent
)
721 ImplSVData
* pSVData
= ImplGetSVData();
722 pSVData
->maAppData
.maEventListeners
.Call( rEvent
);
725 void Application::AddEventListener( const Link
<VclSimpleEvent
&,void>& rEventListener
)
727 ImplSVData
* pSVData
= ImplGetSVData();
728 pSVData
->maAppData
.maEventListeners
.addListener( rEventListener
);
731 void Application::RemoveEventListener( const Link
<VclSimpleEvent
&,void>& rEventListener
)
733 ImplSVData
* pSVData
= ImplGetSVData();
734 pSVData
->maAppData
.maEventListeners
.removeListener( rEventListener
);
737 void Application::AddKeyListener( const Link
<VclWindowEvent
&,bool>& rKeyListener
)
739 ImplSVData
* pSVData
= ImplGetSVData();
740 pSVData
->maAppData
.maKeyListeners
.push_back( rKeyListener
);
743 void Application::RemoveKeyListener( const Link
<VclWindowEvent
&,bool>& rKeyListener
)
745 ImplSVData
* pSVData
= ImplGetSVData();
746 auto & rVec
= pSVData
->maAppData
.maKeyListeners
;
747 rVec
.erase( std::remove(rVec
.begin(), rVec
.end(), rKeyListener
), rVec
.end() );
750 bool Application::HandleKey( VclEventId nEvent
, vcl::Window
*pWin
, KeyEvent
* pKeyEvent
)
752 // let listeners process the key event
753 VclWindowEvent
aEvent( pWin
, nEvent
, static_cast<void *>(pKeyEvent
) );
755 ImplSVData
* pSVData
= ImplGetSVData();
757 if ( pSVData
->maAppData
.maKeyListeners
.empty() )
760 bool bProcessed
= false;
761 // Copy the list, because this can be destroyed when calling a Link...
762 std::vector
<Link
<VclWindowEvent
&,bool>> aCopy( pSVData
->maAppData
.maKeyListeners
);
763 for ( const Link
<VclWindowEvent
&,bool>& rLink
: aCopy
)
765 if( rLink
.Call( aEvent
) )
774 ImplSVEvent
* Application::PostKeyEvent( VclEventId nEvent
, vcl::Window
*pWin
, KeyEvent
const * pKeyEvent
)
776 const SolarMutexGuard aGuard
;
777 ImplSVEvent
* nEventId
= nullptr;
779 if( pWin
&& pKeyEvent
)
781 std::unique_ptr
<ImplPostEventData
> pPostEventData(new ImplPostEventData( nEvent
, pWin
, *pKeyEvent
));
783 nEventId
= PostUserEvent(
784 LINK( nullptr, Application
, PostEventHandler
),
785 pPostEventData
.get() );
789 pPostEventData
->mnEventId
= nEventId
;
790 ImplGetSVData()->maAppData
.maPostedEventList
.emplace_back( pWin
, pPostEventData
.release() );
797 ImplSVEvent
* Application::PostGestureEvent(VclEventId nEvent
, vcl::Window
* pWin
,
798 GestureEventPan
const * pGestureEvent
)
800 const SolarMutexGuard aGuard
;
801 ImplSVEvent
* nEventId
= nullptr;
803 if (pWin
&& pGestureEvent
)
805 Point
aTransformedPosition(pGestureEvent
->mnX
, pGestureEvent
->mnY
);
807 aTransformedPosition
.AdjustX(pWin
->GetOutOffXPixel());
808 aTransformedPosition
.AdjustY(pWin
->GetOutOffYPixel());
810 const GestureEventPan
aGestureEvent(
811 sal_Int32(aTransformedPosition
.X()),
812 sal_Int32(aTransformedPosition
.Y()),
813 pGestureEvent
->meEventType
,
814 pGestureEvent
->mnOffset
,
815 pGestureEvent
->meOrientation
818 std::unique_ptr
<ImplPostEventData
> pPostEventData(new ImplPostEventData(nEvent
, pWin
, aGestureEvent
));
820 nEventId
= PostUserEvent(
821 LINK( nullptr, Application
, PostEventHandler
),
822 pPostEventData
.get());
826 pPostEventData
->mnEventId
= nEventId
;
827 ImplGetSVData()->maAppData
.maPostedEventList
.emplace_back(pWin
, pPostEventData
.release());
834 bool Application::LOKHandleMouseEvent(VclEventId nEvent
, vcl::Window
* pWindow
, const MouseEvent
* pEvent
)
836 bool bSuccess
= false;
837 SalMouseEvent aMouseEvent
;
845 aMouseEvent
.mnTime
= tools::Time::GetSystemTicks();
846 aMouseEvent
.mnX
= pEvent
->GetPosPixel().X();
847 aMouseEvent
.mnY
= pEvent
->GetPosPixel().Y();
848 aMouseEvent
.mnCode
= pEvent
->GetButtons() | pEvent
->GetModifier();
852 case VclEventId::WindowMouseMove
:
853 aMouseEvent
.mnButton
= 0;
854 bSuccess
= ImplLOKHandleMouseEvent(pWindow
, NotifyEventType::MOUSEMOVE
, false,
855 aMouseEvent
.mnX
, aMouseEvent
.mnY
,
856 aMouseEvent
.mnTime
, aMouseEvent
.mnCode
,
857 ImplGetMouseMoveMode(&aMouseEvent
),
858 pEvent
->GetClicks());
861 case VclEventId::WindowMouseButtonDown
:
862 aMouseEvent
.mnButton
= pEvent
->GetButtons();
863 bSuccess
= ImplLOKHandleMouseEvent(pWindow
, NotifyEventType::MOUSEBUTTONDOWN
, false,
864 aMouseEvent
.mnX
, aMouseEvent
.mnY
,
867 aMouseEvent
.mnButton
|
868 (aMouseEvent
.mnCode
& (KEY_SHIFT
| KEY_MOD1
| KEY_MOD2
| KEY_MOD3
)),
870 aMouseEvent
.mnButton
|
871 (aMouseEvent
.mnCode
& (KEY_SHIFT
| KEY_MOD1
| KEY_MOD2
)),
873 ImplGetMouseButtonMode(&aMouseEvent
),
874 pEvent
->GetClicks());
877 case VclEventId::WindowMouseButtonUp
:
878 aMouseEvent
.mnButton
= pEvent
->GetButtons();
879 bSuccess
= ImplLOKHandleMouseEvent(pWindow
, NotifyEventType::MOUSEBUTTONUP
, false,
880 aMouseEvent
.mnX
, aMouseEvent
.mnY
,
883 aMouseEvent
.mnButton
|
884 (aMouseEvent
.mnCode
& (KEY_SHIFT
| KEY_MOD1
| KEY_MOD2
| KEY_MOD3
)),
886 aMouseEvent
.mnButton
|
887 (aMouseEvent
.mnCode
& (KEY_SHIFT
| KEY_MOD1
| KEY_MOD2
)),
889 ImplGetMouseButtonMode(&aMouseEvent
),
890 pEvent
->GetClicks());
894 SAL_WARN( "vcl.layout", "Application::HandleMouseEvent unknown event (" << static_cast<int>(nEvent
) << ")" );
902 ImplSVEvent
* Application::PostMouseEvent( VclEventId nEvent
, vcl::Window
*pWin
, MouseEvent
const * pMouseEvent
)
904 const SolarMutexGuard aGuard
;
905 ImplSVEvent
* nEventId
= nullptr;
907 if( pWin
&& pMouseEvent
)
909 Point
aTransformedPos( pMouseEvent
->GetPosPixel() );
911 // LOK uses (0, 0) as the origin of all windows; don't offset.
912 if (!comphelper::LibreOfficeKit::isActive())
914 aTransformedPos
.AdjustX(pWin
->GetOutOffXPixel());
915 aTransformedPos
.AdjustY(pWin
->GetOutOffYPixel());
918 const MouseEvent
aTransformedEvent( aTransformedPos
, pMouseEvent
->GetClicks(), pMouseEvent
->GetMode(),
919 pMouseEvent
->GetButtons(), pMouseEvent
->GetModifier() );
921 std::unique_ptr
<ImplPostEventData
> pPostEventData(new ImplPostEventData( nEvent
, pWin
, aTransformedEvent
));
923 nEventId
= PostUserEvent(
924 LINK( nullptr, Application
, PostEventHandler
),
925 pPostEventData
.get() );
929 pPostEventData
->mnEventId
= nEventId
;
930 ImplGetSVData()->maAppData
.maPostedEventList
.emplace_back( pWin
, pPostEventData
.release() );
938 IMPL_STATIC_LINK( Application
, PostEventHandler
, void*, pCallData
, void )
940 const SolarMutexGuard aGuard
;
941 ImplPostEventData
* pData
= static_cast< ImplPostEventData
* >( pCallData
);
942 const void* pEventData
;
944 ImplSVEvent
* const nEventId
= pData
->mnEventId
;
946 switch( pData
->mnEvent
)
948 case VclEventId::WindowMouseMove
:
949 nEvent
= SalEvent::ExternalMouseMove
;
950 pEventData
= &pData
->maMouseEvent
;
953 case VclEventId::WindowMouseButtonDown
:
954 nEvent
= SalEvent::ExternalMouseButtonDown
;
955 pEventData
= &pData
->maMouseEvent
;
958 case VclEventId::WindowMouseButtonUp
:
959 nEvent
= SalEvent::ExternalMouseButtonUp
;
960 pEventData
= &pData
->maMouseEvent
;
963 case VclEventId::WindowKeyInput
:
964 nEvent
= SalEvent::ExternalKeyInput
;
965 pEventData
= &pData
->maKeyEvent
;
968 case VclEventId::WindowKeyUp
:
969 nEvent
= SalEvent::ExternalKeyUp
;
970 pEventData
= &pData
->maKeyEvent
;
973 case VclEventId::WindowGestureEvent
:
974 nEvent
= SalEvent::ExternalGesture
;
975 pEventData
= &pData
->maGestureEvent
;
979 nEvent
= SalEvent::NONE
;
980 pEventData
= nullptr;
984 if( pData
->mpWin
&& pData
->mpWin
->mpWindowImpl
->mpFrameWindow
&& pEventData
)
985 ImplWindowFrameProc( pData
->mpWin
->mpWindowImpl
->mpFrameWindow
.get(), nEvent
, pEventData
);
987 // remove this event from list of posted events, watch for destruction of internal data
988 auto svdata
= ImplGetSVData();
989 ::std::vector
< ImplPostEventPair
>::iterator
aIter( svdata
->maAppData
.maPostedEventList
.begin() );
991 while( aIter
!= svdata
->maAppData
.maPostedEventList
.end() )
993 if( nEventId
== (*aIter
).second
->mnEventId
)
995 delete (*aIter
).second
;
996 aIter
= svdata
->maAppData
.maPostedEventList
.erase( aIter
);
1003 void Application::RemoveMouseAndKeyEvents( vcl::Window
* pWin
)
1005 const SolarMutexGuard aGuard
;
1007 // remove all events for specific window, watch for destruction of internal data
1008 auto svdata
= ImplGetSVData();
1009 ::std::vector
< ImplPostEventPair
>::iterator
aIter( svdata
->maAppData
.maPostedEventList
.begin() );
1011 while( aIter
!= svdata
->maAppData
.maPostedEventList
.end() )
1013 if( pWin
== (*aIter
).first
)
1015 if( (*aIter
).second
->mnEventId
)
1016 RemoveUserEvent( (*aIter
).second
->mnEventId
);
1018 delete (*aIter
).second
;
1019 aIter
= svdata
->maAppData
.maPostedEventList
.erase( aIter
);
1026 ImplSVEvent
* Application::PostUserEvent( const Link
<void*,void>& rLink
, void* pCaller
,
1027 bool bReferenceLink
)
1029 vcl::Window
* pDefWindow
= ImplGetDefaultWindow();
1030 if ( pDefWindow
== nullptr )
1033 std::unique_ptr
<ImplSVEvent
> pSVEvent(new ImplSVEvent
);
1034 pSVEvent
->mpData
= pCaller
;
1035 pSVEvent
->maLink
= rLink
;
1036 pSVEvent
->mpWindow
= nullptr;
1037 pSVEvent
->mbCall
= true;
1040 SolarMutexGuard aGuard
;
1041 pSVEvent
->mpInstanceRef
= static_cast<vcl::Window
*>(rLink
.GetInstance());
1044 auto pTmpEvent
= pSVEvent
.get();
1045 if (!pDefWindow
->ImplGetFrame()->PostEvent( std::move(pSVEvent
) ))
1050 void Application::RemoveUserEvent( ImplSVEvent
* nUserEvent
)
1054 SAL_WARN_IF( nUserEvent
->mpWindow
, "vcl",
1055 "Application::RemoveUserEvent(): Event is send to a window" );
1056 SAL_WARN_IF( !nUserEvent
->mbCall
, "vcl",
1057 "Application::RemoveUserEvent(): Event is already removed" );
1059 nUserEvent
->mpWindow
.clear();
1060 nUserEvent
->mpInstanceRef
.clear();
1061 nUserEvent
->mbCall
= false;
1065 vcl::Window
* Application::GetFocusWindow()
1067 return ImplGetSVData()->mpWinData
->mpFocusWin
;
1070 OutputDevice
* Application::GetDefaultDevice()
1072 vcl::Window
* pWindow
= ImplGetDefaultWindow();
1073 if (pWindow
!= nullptr)
1075 return pWindow
->GetOutDev();
1083 basegfx::SystemDependentDataManager
& Application::GetSystemDependentDataManager()
1085 return ImplGetSystemDependentDataManager();
1088 vcl::Window
* Application::GetFirstTopLevelWindow()
1090 ImplSVData
* pSVData
= ImplGetSVData();
1091 return pSVData
->maFrameData
.mpFirstFrame
;
1094 vcl::Window
* Application::GetNextTopLevelWindow( vcl::Window
const * pWindow
)
1096 return pWindow
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1099 tools::Long
Application::GetTopWindowCount()
1101 tools::Long nRet
= 0;
1102 ImplSVData
* pSVData
= ImplGetSVData();
1103 vcl::Window
*pWin
= pSVData
? pSVData
->maFrameData
.mpFirstFrame
.get() : nullptr;
1106 if( pWin
->ImplGetWindow()->IsTopWindow() )
1108 pWin
= pWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1113 vcl::Window
* Application::GetTopWindow( tools::Long nIndex
)
1115 tools::Long nIdx
= 0;
1116 ImplSVData
* pSVData
= ImplGetSVData();
1117 vcl::Window
*pWin
= pSVData
? pSVData
->maFrameData
.mpFirstFrame
.get() : nullptr;
1120 if( pWin
->ImplGetWindow()->IsTopWindow() )
1122 if( nIdx
== nIndex
)
1123 return pWin
->ImplGetWindow();
1127 pWin
= pWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1132 vcl::Window
* Application::GetActiveTopWindow()
1134 vcl::Window
*pWin
= ImplGetSVData()->mpWinData
->mpFocusWin
;
1137 if( pWin
->IsTopWindow() )
1139 pWin
= pWin
->mpWindowImpl
->mpParent
;
1144 void Application::SetAppName( const OUString
& rUniqueName
)
1146 ImplSVData
* pSVData
= ImplGetSVData();
1147 pSVData
->maAppData
.mxAppName
= rUniqueName
;
1150 OUString
Application::GetAppName()
1152 ImplSVData
* pSVData
= ImplGetSVData();
1153 if ( pSVData
->maAppData
.mxAppName
)
1154 return *(pSVData
->maAppData
.mxAppName
);
1159 enum {hwAll
=0, hwEnv
=1, hwUI
=2};
1161 static OUString
Localize(TranslateId aId
, const bool bLocalize
)
1164 return VclResId(aId
);
1166 return Translate::get(aId
, Translate::Create("vcl", LanguageTag("en-US")));
1169 OUString
Application::GetOSVersion()
1171 ImplSVData
* pSVData
= ImplGetSVData();
1173 if (pSVData
&& pSVData
->mpDefInst
)
1174 aVersion
= pSVData
->mpDefInst
->getOSVersion();
1180 OUString
Application::GetHWOSConfInfo(const int bSelection
, const bool bLocalize
)
1182 OUStringBuffer aDetails
;
1184 const auto appendDetails
= [&aDetails
](std::u16string_view sep
, auto&& val
) {
1185 if (!aDetails
.isEmpty() && !sep
.empty())
1186 aDetails
.append(sep
);
1187 aDetails
.append(std::move(val
));
1190 if (bSelection
!= hwUI
) {
1191 appendDetails(u
"; ", Localize(SV_APP_CPUTHREADS
, bLocalize
)
1192 + OUString::number(std::thread::hardware_concurrency()));
1194 OUString aVersion
= GetOSVersion();
1196 appendDetails(u
"; ", Localize(SV_APP_OSVERSION
, bLocalize
) + aVersion
);
1199 if (bSelection
!= hwEnv
) {
1200 appendDetails(u
"; ", Localize(SV_APP_UIRENDER
, bLocalize
));
1201 #if HAVE_FEATURE_SKIA
1202 if ( SkiaHelper::isVCLSkiaEnabled() )
1204 switch(SkiaHelper::renderMethodToUse())
1206 case SkiaHelper::RenderVulkan
:
1207 appendDetails(u
"", Localize(SV_APP_SKIA_VULKAN
, bLocalize
));
1209 case SkiaHelper::RenderMetal
:
1210 appendDetails(u
"", Localize(SV_APP_SKIA_METAL
, bLocalize
));
1212 case SkiaHelper::RenderRaster
:
1213 appendDetails(u
"", Localize(SV_APP_SKIA_RASTER
, bLocalize
));
1219 appendDetails(u
"", Localize(SV_APP_DEFAULT
, bLocalize
));
1221 #if (defined LINUX || defined _WIN32 || defined MACOSX || defined __FreeBSD__ || defined EMSCRIPTEN)
1222 appendDetails(u
"; ", SV_APP_VCLBACKEND
+ GetToolkitName());
1226 return aDetails
.makeStringAndClear();
1229 void Application::SetDisplayName( const OUString
& rName
)
1231 ImplSVData
* pSVData
= ImplGetSVData();
1232 pSVData
->maAppData
.mxDisplayName
= rName
;
1235 OUString
Application::GetDisplayName()
1237 ImplSVData
* pSVData
= ImplGetSVData();
1238 if ( pSVData
->maAppData
.mxDisplayName
)
1239 return *(pSVData
->maAppData
.mxDisplayName
);
1240 else if (pSVData
->maFrameData
.mpAppWin
)
1241 return pSVData
->maFrameData
.mpAppWin
->GetText();
1246 unsigned int Application::GetScreenCount()
1248 SalSystem
* pSys
= ImplGetSalSystem();
1249 return pSys
? pSys
->GetDisplayScreenCount() : 0;
1252 bool Application::IsUnifiedDisplay()
1254 SalSystem
* pSys
= ImplGetSalSystem();
1255 return pSys
== nullptr || pSys
->IsUnifiedDisplay();
1258 unsigned int Application::GetDisplayBuiltInScreen()
1260 SalSystem
* pSys
= ImplGetSalSystem();
1261 return pSys
? pSys
->GetDisplayBuiltInScreen() : 0;
1264 unsigned int Application::GetDisplayExternalScreen()
1266 // This is really unpleasant, in theory we could have multiple
1267 // external displays etc.
1269 switch (GetDisplayBuiltInScreen())
1278 // When the built-in display is neither 0 nor 1
1279 // then place the full-screen presentation on the
1280 // first available screen.
1287 tools::Rectangle
Application::GetScreenPosSizePixel( unsigned int nScreen
)
1289 SalSystem
* pSys
= ImplGetSalSystem();
1292 SAL_WARN("vcl", "Requesting screen size/pos for screen #" << nScreen
<< " failed");
1294 return tools::Rectangle();
1296 tools::Rectangle aRect
= pSys
->GetDisplayScreenPosSizePixel(nScreen
);
1297 if (aRect
.GetHeight() == 0)
1298 SAL_WARN("vcl", "Requesting screen size/pos for screen #" << nScreen
<< " returned 0 height.");
1303 tools::Long
calcDistSquare( const Point
& i_rPoint
, const tools::Rectangle
& i_rRect
)
1305 const Point
aRectCenter( (i_rRect
.Left() + i_rRect
.Right())/2,
1306 (i_rRect
.Top() + i_rRect
.Bottom())/ 2 );
1307 const tools::Long nDX
= aRectCenter
.X() - i_rPoint
.X();
1308 const tools::Long nDY
= aRectCenter
.Y() - i_rPoint
.Y();
1309 return nDX
*nDX
+ nDY
*nDY
;
1313 unsigned int Application::GetBestScreen( const tools::Rectangle
& i_rRect
)
1315 if( !IsUnifiedDisplay() )
1316 return GetDisplayBuiltInScreen();
1318 const unsigned int nScreens
= GetScreenCount();
1319 unsigned int nBestMatchScreen
= 0;
1320 unsigned long nOverlap
= 0;
1321 for( unsigned int i
= 0; i
< nScreens
; i
++ )
1323 const tools::Rectangle
aCurScreenRect( GetScreenPosSizePixel( i
) );
1324 // if a screen contains the rectangle completely it is obviously the best screen
1325 if( aCurScreenRect
.Contains( i_rRect
) )
1327 // next the screen which contains most of the area of the rect is the best
1328 tools::Rectangle
aIntersection( aCurScreenRect
.GetIntersection( i_rRect
) );
1329 if( ! aIntersection
.IsEmpty() )
1331 const unsigned long nCurOverlap( aIntersection
.GetWidth() * aIntersection
.GetHeight() );
1332 if( nCurOverlap
> nOverlap
)
1334 nOverlap
= nCurOverlap
;
1335 nBestMatchScreen
= i
;
1340 return nBestMatchScreen
;
1342 // finally the screen which center is nearest to the rect is the best
1343 const Point
aCenter( (i_rRect
.Left() + i_rRect
.Right())/2,
1344 (i_rRect
.Top() + i_rRect
.Bottom())/2 );
1345 tools::Long nDist
= std::numeric_limits
<tools::Long
>::max();
1346 for( unsigned int i
= 0; i
< nScreens
; i
++ )
1348 const tools::Rectangle
aCurScreenRect( GetScreenPosSizePixel( i
) );
1349 const tools::Long
nCurDist( calcDistSquare( aCenter
, aCurScreenRect
) );
1350 if( nCurDist
< nDist
)
1352 nBestMatchScreen
= i
;
1356 return nBestMatchScreen
;
1359 bool Application::InsertAccel( Accelerator
* pAccel
)
1361 ImplSVData
* pSVData
= ImplGetSVData();
1363 if ( !pSVData
->maAppData
.mpAccelMgr
)
1364 pSVData
->maAppData
.mpAccelMgr
= new ImplAccelManager();
1365 return pSVData
->maAppData
.mpAccelMgr
->InsertAccel( pAccel
);
1368 void Application::RemoveAccel( Accelerator
const * pAccel
)
1370 ImplSVData
* pSVData
= ImplGetSVData();
1372 if ( pSVData
->maAppData
.mpAccelMgr
)
1373 pSVData
->maAppData
.mpAccelMgr
->RemoveAccel( pAccel
);
1376 void Application::SetHelp( Help
* pHelp
)
1378 ImplGetSVData()->maAppData
.mpHelp
= pHelp
;
1381 void Application::UpdateMainThread()
1383 ImplSVData
* pSVData
= ImplGetSVData();
1384 if (pSVData
&& pSVData
->mpDefInst
)
1385 pSVData
->mpDefInst
->updateMainThread();
1388 Help
* Application::GetHelp()
1390 return ImplGetSVData()->maAppData
.mpHelp
;
1393 OUString
Application::GetToolkitName()
1395 ImplSVData
* pSVData
= ImplGetSVData();
1396 if ( pSVData
->maAppData
.mxToolkitName
)
1397 return *(pSVData
->maAppData
.mxToolkitName
);
1402 vcl::Window
* Dialog::GetDefDialogParent()
1404 ImplSVData
* pSVData
= ImplGetSVData();
1405 // find some useful dialog parent
1407 // always use the topmost parent of the candidate
1408 // window to avoid using dialogs or floaters
1409 // as DefDialogParent
1411 // current focus frame
1412 vcl::Window
*pWin
= pSVData
->mpWinData
->mpFocusWin
;
1413 if (pWin
&& !pWin
->IsMenuFloatingWindow())
1415 while (pWin
->mpWindowImpl
&& pWin
->mpWindowImpl
->mpParent
)
1416 pWin
= pWin
->mpWindowImpl
->mpParent
;
1418 // check for corrupted window hierarchy, #122232#, may be we now crash somewhere else
1419 if (!pWin
->mpWindowImpl
)
1421 OSL_FAIL( "Window hierarchy corrupted!" );
1422 pSVData
->mpWinData
->mpFocusWin
= nullptr; // avoid further access
1426 if ((pWin
->mpWindowImpl
->mnStyle
& WB_INTROWIN
) == 0)
1428 return pWin
->mpWindowImpl
->mpFrameWindow
->ImplGetWindow();
1432 // last active application frame
1433 pWin
= pSVData
->maFrameData
.mpActiveApplicationFrame
;
1436 return pWin
->mpWindowImpl
->mpFrameWindow
->ImplGetWindow();
1439 // first visible top window (may be totally wrong...)
1440 pWin
= pSVData
->maFrameData
.mpFirstFrame
;
1443 if( pWin
->ImplGetWindow()->IsTopWindow() &&
1444 pWin
->mpWindowImpl
->mbReallyVisible
&&
1445 (pWin
->mpWindowImpl
->mnStyle
& WB_INTROWIN
) == 0
1448 while( pWin
->mpWindowImpl
->mpParent
)
1449 pWin
= pWin
->mpWindowImpl
->mpParent
;
1450 return pWin
->mpWindowImpl
->mpFrameWindow
->ImplGetWindow();
1452 pWin
= pWin
->mpWindowImpl
->mpFrameData
->mpNextFrame
;
1459 weld::Window
* Application::GetDefDialogParent()
1461 vcl::Window
* pWindow
= Dialog::GetDefDialogParent();
1462 return pWindow
? pWindow
->GetFrameWeld() : nullptr;
1465 DialogCancelMode
Application::GetDialogCancelMode()
1467 return ImplGetSVData()->maAppData
.meDialogCancel
;
1470 void Application::SetDialogCancelMode( DialogCancelMode mode
)
1472 ImplGetSVData()->maAppData
.meDialogCancel
= mode
;
1475 bool Application::IsDialogCancelEnabled()
1477 return ImplGetSVData()->maAppData
.meDialogCancel
!= DialogCancelMode::Off
;
1480 void Application::SetSystemWindowMode( SystemWindowFlags nMode
)
1482 ImplGetSVData()->maAppData
.mnSysWinMode
= nMode
;
1485 SystemWindowFlags
Application::GetSystemWindowMode()
1487 return ImplGetSVData()->maAppData
.mnSysWinMode
;
1490 css::uno::Reference
< css::awt::XToolkit
> Application::GetVCLToolkit()
1492 css::uno::Reference
< css::awt::XToolkit
> xT
;
1493 UnoWrapperBase
* pWrapper
= UnoWrapperBase::GetUnoWrapper();
1495 xT
= pWrapper
->GetVCLToolkit();
1499 #ifdef DISABLE_DYNLOADING
1501 extern "C" { UnoWrapperBase
* CreateUnoWrapper(); }
1505 extern "C" { static void thisModule() {} }
1509 UnoWrapperBase
* UnoWrapperBase::GetUnoWrapper( bool bCreateIfNotExist
)
1511 ImplSVData
* pSVData
= ImplGetSVData();
1512 static bool bAlreadyTriedToCreate
= false;
1513 if ( !pSVData
->mpUnoWrapper
&& bCreateIfNotExist
&& !bAlreadyTriedToCreate
)
1515 #ifndef DISABLE_DYNLOADING
1517 aTkLib
.loadRelative(&thisModule
, TK_DLL_NAME
);
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 UnoWrapperBase::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
;
1556 void Application::SetFilterHdl( const Link
<ConvertData
&,bool>& rLink
)
1558 ImplGetSVData()->maGDIData
.mxGrfConverter
->SetFilterHdl( rLink
);
1561 const LocaleDataWrapper
& Application::GetAppLocaleDataWrapper()
1563 return GetSettings().GetLocaleDataWrapper();
1566 void Application::EnableHeadlessMode( bool dialogsAreFatal
)
1568 DialogCancelMode eNewMode
= dialogsAreFatal
? DialogCancelMode::Fatal
: DialogCancelMode::Silent
;
1569 DialogCancelMode eOldMode
= GetDialogCancelMode();
1570 assert(eOldMode
== DialogCancelMode::Off
|| GetDialogCancelMode() == eNewMode
);
1571 if (eOldMode
!= eNewMode
)
1572 SetDialogCancelMode( eNewMode
);
1575 bool Application::IsHeadlessModeEnabled()
1577 return IsDialogCancelEnabled() || comphelper::LibreOfficeKit::isActive();
1580 void Application::EnableBitmapRendering()
1582 ImplGetSVData()->maAppData
.mbRenderToBitmaps
= true;
1585 bool Application::IsBitmapRendering()
1587 return ImplGetSVData()->maAppData
.mbRenderToBitmaps
;
1590 void Application::EnableConsoleOnly()
1592 EnableHeadlessMode(true);
1593 EnableBitmapRendering();
1596 static bool bSafeMode
= false;
1598 bool Application::IsSafeModeEnabled()
1603 void Application::EnableSafeMode()
1608 void Application::ShowNativeErrorBox(const OUString
& sTitle
,
1609 const OUString
& sMessage
)
1611 int btn
= ImplGetSalSystem()->ShowNativeMessageBox(
1614 if (btn
!= SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
) {
1615 SAL_WARN( "vcl", "ShowNativeMessageBox returned " << btn
);
1619 const OUString
& Application::GetDesktopEnvironment()
1621 if (IsHeadlessModeEnabled())
1623 static const OUString
aNone("none");
1627 return SalGetDesktopEnvironment();
1630 void Application::AddToRecentDocumentList(const OUString
& rFileUrl
, const OUString
& rMimeType
, const OUString
& rDocumentService
)
1632 ImplSVData
* pSVData
= ImplGetSVData();
1633 pSVData
->mpDefInst
->AddToRecentDocumentList(rFileUrl
, rMimeType
, rDocumentService
);
1636 bool InitAccessBridge()
1638 // Disable MSAA bridge on UNIX
1642 bool bRet
= ImplInitAccessBridge();
1646 // disable accessibility if the user chooses to continue
1647 AllSettings aSettings
= Application::GetSettings();
1648 MiscSettings aMisc
= aSettings
.GetMiscSettings();
1649 aMisc
.SetEnableATToolSupport( false );
1650 aSettings
.SetMiscSettings( aMisc
);
1651 Application::SetSettings( aSettings
);
1657 // MT: AppEvent was in oldsv.cxx, but is still needed...
1658 void Application::AppEvent( const ApplicationEvent
& /*rAppEvent*/ )
1662 bool Application::hasNativeFileSelection()
1664 ImplSVData
* pSVData
= ImplGetSVData();
1665 return pSVData
->mpDefInst
->hasNativeFileSelection();
1668 Reference
< ui::dialogs::XFilePicker2
>
1669 Application::createFilePicker( const Reference
< uno::XComponentContext
>& xSM
)
1671 ImplSVData
* pSVData
= ImplGetSVData();
1672 return pSVData
->mpDefInst
->createFilePicker( xSM
);
1675 Reference
< ui::dialogs::XFolderPicker2
>
1676 Application::createFolderPicker( const Reference
< uno::XComponentContext
>& xSM
)
1678 ImplSVData
* pSVData
= ImplGetSVData();
1679 return pSVData
->mpDefInst
->createFolderPicker( xSM
);
1682 void Application::setDeInitHook(Link
<LinkParamNone
*,void> const & hook
) {
1683 ImplSVData
* pSVData
= ImplGetSVData();
1684 assert(!pSVData
->maDeInitHook
.IsSet());
1685 pSVData
->maDeInitHook
= hook
;
1686 // Fake this for VCLXToolkit ctor instantiated from
1687 // postprocess/CppunitTest_services.mk:
1688 pSVData
->maAppData
.mbInAppMain
= true;
1691 namespace vcl::lok
{
1693 void registerPollCallbacks(
1694 LibreOfficeKitPollCallback pPollCallback
,
1695 LibreOfficeKitWakeCallback pWakeCallback
,
1698 ImplSVData
* pSVData
= ImplGetSVData();
1701 pSVData
->mpPollCallback
= pPollCallback
;
1702 pSVData
->mpWakeCallback
= pWakeCallback
;
1703 pSVData
->mpPollClosure
= pData
;
1707 void unregisterPollCallbacks()
1709 ImplSVData
* pSVData
= ImplGetSVData();
1713 // Not hyper-elegant - but in the case of Android & unipoll we need to detach
1714 // this thread from the JVM's clutches to avoid a crash closing document
1715 if (pSVData
->mpPollClosure
&& pSVData
->mpDefInst
)
1716 pSVData
->mpDefInst
->releaseMainThread();
1718 // Just set mpPollClosure to null as that is what calling this means, that the callback data
1719 // points to an object that no longer exists. In particular, don't set
1720 // pSVData->mpPollCallback to nullptr as that is used to detect whether Unipoll is in use in
1722 pSVData
->mpPollClosure
= nullptr;
1727 ImplSVData
* pSVData
= ImplGetSVData();
1728 return pSVData
&& pSVData
->mpPollCallback
!= nullptr;
1731 void numberOfViewsChanged(int count
)
1735 ImplSVData
* pSVData
= ImplGetSVData();
1736 auto& rCache
= pSVData
->maGDIData
.maScaleCache
;
1737 // Normally the cache size is set to 10, scale according to the number of users.
1738 rCache
.setMaxSize(count
* 10);
1741 void dumpState(rtl::OStringBuffer
&rState
)
1743 ImplSVData
* pSVData
= ImplGetSVData();
1747 rState
.append("\nWindows:\t");
1748 rState
.append(static_cast<sal_Int32
>(Application::GetTopWindowCount()));
1750 vcl::Window
*pWin
= Application::GetFirstTopLevelWindow();
1753 tools::JsonWriter props
;
1754 pWin
->DumpAsPropertyTree(props
);
1756 rState
.append("\n\tWindow: ");
1757 rState
.append(props
.finishAndGetAsOString());
1759 pWin
= Application::GetNextTopLevelWindow( pWin
);
1762 vcl::graphic::Manager::get().dumpState(rState
);
1764 pSVData
->dumpState(rState
);
1767 void trimMemory(int nTarget
)
1769 if (nTarget
>= 1000)
1771 ImplSVData
* pSVData
= ImplGetSVData();
1772 if (!pSVData
) // shutting down
1774 pSVData
->dropCaches();
1775 vcl::graphic::Manager::get().dropCache();
1776 // TODO: ideally - free up any deeper dirtied thread stacks.
1777 // comphelper::ThreadPool::getSharedOptimalPool().shutdown();
1779 // else for now caches re-fill themselves as/when used.
1782 } // namespace lok, namespace vcl
1784 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */