Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/app/svapp.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include <config_features.h>
21
#include <config_version.h>
22
23
#include <i18nlangtag/languagetag.hxx>
24
#include <osl/diagnose.h>
25
#include <osl/file.hxx>
26
#include <osl/thread.hxx>
27
#include <osl/module.hxx>
28
#include <rtl/ustrbuf.hxx>
29
30
#include <sal/log.hxx>
31
32
#include <tools/debug.hxx>
33
#include <tools/time.hxx>
34
#include <tools/stream.hxx>
35
36
#include <comphelper/configuration.hxx>
37
#include <unotools/resmgr.hxx>
38
#include <unotools/syslocale.hxx>
39
#include <unotools/syslocaleoptions.hxx>
40
41
#include <vcl/DesktopType.hxx>
42
#include <vcl/toolkit/dialog.hxx>
43
#include <vcl/dialoghelper.hxx>
44
#include <vcl/exceptiontypes.hxx>
45
#include <vcl/toolkit/floatwin.hxx>
46
#include <vcl/settings.hxx>
47
#include <vcl/keycod.hxx>
48
#include <vcl/event.hxx>
49
#include <vcl/vclevent.hxx>
50
#include <vcl/virdev.hxx>
51
#include <vcl/wrkwin.hxx>
52
#include <vcl/svapp.hxx>
53
#include <vcl/cvtgrf.hxx>
54
#include <vcl/toolkit/unowrap.hxx>
55
#include <vcl/timer.hxx>
56
#include <vcl/scheduler.hxx>
57
#include <vcl/skia/SkiaHelper.hxx>
58
59
#include <dbggui.hxx>
60
#include <salinst.hxx>
61
#include <graphic/Manager.hxx>
62
#include <salframe.hxx>
63
#include <salsys.hxx>
64
#include <svdata.hxx>
65
#include <window.h>
66
#include <accmgr.hxx>
67
#include <strings.hrc>
68
#include <strings.hxx>
69
#if OSL_DEBUG_LEVEL > 0
70
#include <schedulerimpl.hxx>
71
#endif
72
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>
79
80
#ifdef DBG_UTIL
81
#include <svl/poolitem.hxx>
82
#include <svl/itemset.hxx>
83
#include <svl/itempool.hxx>
84
#endif
85
86
#include <cassert>
87
#include <limits>
88
#include <string_view>
89
#include <utility>
90
#include <thread>
91
92
using namespace ::com::sun::star;
93
using namespace ::com::sun::star::uno;
94
95
namespace {
96
void InitSettings(ImplSVData* pSVData);
97
}
98
99
// keycodes handled internally by VCL
100
vcl::KeyCode const ReservedKeys[]
101
{
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
111
};
112
113
extern "C" {
114
    typedef UnoWrapperBase* (*FN_TkCreateUnoWrapper)();
115
}
116
117
struct ImplPostEventData
118
{
119
    VclPtr<vcl::Window> mpWin;
120
    ImplSVEvent *   mnEventId;
121
    MouseEvent      maMouseEvent;
122
    VclEventId      mnEvent;
123
    KeyEvent        maKeyEvent;
124
    GestureEventPan maGestureEvent;
125
126
    ImplPostEventData(VclEventId nEvent, vcl::Window* pWin, const KeyEvent& rKeyEvent)
127
0
        : mpWin(pWin)
128
0
        , mnEventId(nullptr)
129
0
        , mnEvent(nEvent)
130
0
        , maKeyEvent(rKeyEvent)
131
0
    {}
132
    ImplPostEventData(VclEventId nEvent, vcl::Window* pWin, const MouseEvent& rMouseEvent)
133
0
        : mpWin(pWin)
134
0
        , mnEventId(nullptr)
135
0
        , maMouseEvent(rMouseEvent)
136
0
        , mnEvent(nEvent)
137
0
    {}
138
    ImplPostEventData(VclEventId nEvent, vcl::Window* pWin, const GestureEventPan& rGestureEvent)
139
0
        : mpWin(pWin)
140
0
        , mnEventId(nullptr)
141
0
        , mnEvent(nEvent)
142
0
        , maGestureEvent(rGestureEvent)
143
0
    {}
144
};
145
146
Application* GetpApp()
147
2
{
148
2
    ImplSVData* pSVData = ImplGetSVData();
149
2
    if ( !pSVData )
150
0
        return nullptr;
151
2
    return pSVData->mpApp;
152
2
}
153
154
Application::Application()
155
104
{
156
    // useful for themes at least, perhaps extensions too
157
104
    OUString aVar(u"LIBO_VERSION"_ustr), aValue(u"" LIBO_VERSION_DOTTED ""_ustr);
158
104
    osl_setEnvironment(aVar.pData, aValue.pData);
159
160
104
    ImplGetSVData()->mpApp = this;
161
104
    m_pCallbackData = nullptr;
162
104
    m_pCallback = nullptr;
163
104
}
164
165
Application::~Application()
166
0
{
167
0
    ImplDeInitSVData();
168
0
    ImplGetSVData()->mpApp = nullptr;
169
#ifdef DBG_UTIL
170
    // Due to
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");
183
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");
187
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");
191
192
    // Additional call to list still incarnated SfxPoolItems (under 'svl.items')
193
    listAllocatedSfxPoolItems();
194
195
    // List SfxPoolItems with highest RefCounts, these are the best
196
    // candidates to add a ItemInstanceManager mechanism
197
    listSfxPoolItemsWithHighestUsage(20);
198
    listSfxItemSetUsage();
199
#endif
200
0
}
201
202
int Application::Main()
203
0
{
204
0
    SAL_WARN("vcl", "Application is a base class and should be overridden.");
205
0
    return EXIT_SUCCESS;
206
0
}
207
208
bool Application::QueryExit()
209
0
{
210
0
    WorkWindow* pAppWin = ImplGetSVData()->maFrameData.mpAppWin;
211
212
    // call the close handler of the application window
213
0
    if ( pAppWin )
214
0
        return pAppWin->Close();
215
0
    else
216
0
        return true;
217
0
}
218
219
void Application::Shutdown()
220
0
{
221
0
}
222
223
void Application::Init()
224
104
{
225
104
}
226
227
void Application::InitFinished()
228
0
{
229
0
}
230
231
void Application::DeInit()
232
0
{
233
0
}
234
235
sal_uInt16 Application::GetCommandLineParamCount()
236
0
{
237
0
    return static_cast<sal_uInt16>(osl_getCommandArgCount());
238
0
}
239
240
OUString Application::GetCommandLineParam( sal_uInt16 nParam )
241
0
{
242
0
    OUString aParam;
243
0
    osl_getCommandArg( nParam, &aParam.pData );
244
0
    return aParam;
245
0
}
246
247
OUString Application::GetAppFileName()
248
0
{
249
0
    ImplSVData* pSVData = ImplGetSVData();
250
0
    SAL_WARN_IF( !pSVData->maAppData.mxAppFileName, "vcl", "AppFileName should be set to something after SVMain!" );
251
0
    if ( pSVData->maAppData.mxAppFileName )
252
0
        return *pSVData->maAppData.mxAppFileName;
253
254
    /*
255
     *  provide a fallback for people without initialized vcl here (like setup
256
     *  in responsefile mode)
257
     */
258
0
    OUString aAppFileName;
259
0
    OUString aExeFileName;
260
0
    osl_getExecutableFile(&aExeFileName.pData);
261
262
    // convert path to native file format
263
0
    osl::FileBase::getSystemPathFromFileURL(aExeFileName, aAppFileName);
264
265
0
    return aAppFileName;
266
0
}
267
268
void Application::Exception( ExceptionCategory nCategory )
269
0
{
270
0
    switch ( nCategory )
271
0
    {
272
        // System has precedence (so do nothing)
273
0
        case ExceptionCategory::System:
274
0
        case ExceptionCategory::UserInterface:
275
0
            break;
276
0
        default:
277
0
            Abort(u"Unknown Error"_ustr);
278
0
            break;
279
0
    }
280
0
}
281
282
void Application::Abort( const OUString& rErrorText )
283
0
{
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;
289
#else
290
0
    bool dumpCore = false;
291
0
    sal_uInt16 n = GetCommandLineParamCount();
292
0
    for (sal_uInt16 i = 0; i != n; ++i) {
293
0
        if (GetCommandLineParam(i) == "--norestore") {
294
0
            dumpCore = true;
295
0
            break;
296
0
        }
297
0
    }
298
0
#endif
299
300
0
    SalAbort( rErrorText, dumpCore );
301
0
}
302
303
size_t Application::GetReservedKeyCodeCount()
304
0
{
305
0
    return SAL_N_ELEMENTS(ReservedKeys);
306
0
}
307
308
const vcl::KeyCode* Application::GetReservedKeyCode( size_t i )
309
0
{
310
0
    if( i >= GetReservedKeyCodeCount() )
311
0
        return nullptr;
312
0
    else
313
0
        return &ReservedKeys[i];
314
0
}
315
316
void Application::notifyWindow(vcl::LOKWindowId /*nLOKWindowId*/,
317
                               const OUString& /*rAction*/,
318
                               const std::vector<vcl::LOKPayloadItem>& /*rPayload = std::vector<LOKPayloadItem>()*/) const
319
0
{
320
0
    SAL_WARN("vcl", "Invoked not implemented method: Application::notifyWindow");
321
0
}
322
323
OString Application::dumpNotifyState() const
324
0
{
325
0
    SAL_WARN("vcl", "Invoked not implemented method: Application::dumpNotifyState");
326
0
    return "notimpl"_ostr;
327
0
}
328
329
void Application::libreOfficeKitViewCallback(int nType, const OString& pPayload) const
330
0
{
331
0
    if (!comphelper::LibreOfficeKit::isActive())
332
0
        return;
333
334
0
    if (m_pCallback)
335
0
    {
336
0
        m_pCallback(nType, pPayload.getStr(), m_pCallbackData);
337
0
    }
338
0
}
339
340
void Application::notifyInvalidation(tools::Rectangle const* /*pRect*/) const
341
0
{
342
0
}
343
344
void Application::notifyCursorInvalidation(tools::Rectangle const* /*pRect*/, bool /*bControlEvent*/, int /*windowID*/) const
345
0
{
346
0
}
347
348
void Application::Execute()
349
0
{
350
0
    ImplSVData* pSVData = ImplGetSVData();
351
0
    pSVData->maAppData.mbInAppExecute = true;
352
0
    pSVData->maAppData.mbAppQuit = false;
353
354
0
    int nExitCode = 0;
355
0
    if (!pSVData->mpDefInst->DoExecute(nExitCode))
356
0
    {
357
0
        if (Application::IsUseSystemEventLoop())
358
0
        {
359
0
            SAL_WARN("vcl.schedule", "Can't omit DoExecute when running on system event loop!");
360
0
            std::abort();
361
0
        }
362
0
        while (!pSVData->maAppData.mbAppQuit)
363
0
        {
364
0
            Application::Yield();
365
0
            SolarMutexReleaser releaser; // Give a chance for the waiting threads to lock the mutex
366
0
            pSVData->m_inExecuteCondtion.set();
367
0
        }
368
0
    }
369
370
0
    pSVData->maAppData.mbInAppExecute = false;
371
372
0
    GetpApp()->Shutdown();
373
0
}
374
375
static bool InnerYield(bool i_bWait, bool i_bAllEvents)
376
53.9k
{
377
53.9k
    ImplSVData* pSVData = ImplGetSVData();
378
379
53.9k
    SAL_INFO("vcl.schedule", "Enter InnerYield: " << (i_bWait ? "wait" : "no wait") <<
380
53.9k
             ": " << (i_bAllEvents ? "all events" : "one event"));
381
382
    // there's a data race here on WNT only because InnerYield may be
383
    // called without SolarMutex; but the only remaining use of mnDispatchLevel
384
    // is in OSX specific code
385
53.9k
    pSVData->maAppData.mnDispatchLevel++;
386
387
    // do not wait for events if application was already quit; in that
388
    // case only dispatch events already available
389
53.9k
    bool bProcessedEvent = pSVData->mpDefInst->DoYield(
390
53.9k
            i_bWait && !pSVData->maAppData.mbAppQuit, i_bAllEvents );
391
392
53.9k
    pSVData->maAppData.mnDispatchLevel--;
393
394
53.9k
    DBG_TESTSOLARMUTEX(); // must be locked on return from Yield
395
396
53.9k
    SAL_INFO("vcl.schedule", "Leave InnerYield with return " << bProcessedEvent );
397
53.9k
    return bProcessedEvent;
398
53.9k
}
399
400
bool Application::Reschedule( bool i_bAllEvents )
401
10.7k
{
402
10.7k
    static const bool bAbort = Application::IsUseSystemEventLoop();
403
10.7k
    if (bAbort)
404
0
    {
405
0
        SAL_WARN("vcl.schedule", "Application::Reschedule(" << i_bAllEvents << ")");
406
0
        return false;
407
0
    }
408
10.7k
    int nOldView = -1;
409
10.7k
    ViewShellDocId nOldDocId(-1);
410
10.7k
    if (comphelper::LibreOfficeKit::isActive())
411
0
    {
412
0
        nOldView = comphelper::LibreOfficeKit::getView();
413
0
        nOldDocId = comphelper::LibreOfficeKit::getDocId();
414
0
    }
415
10.7k
    bool bRet = InnerYield(false, i_bAllEvents);
416
10.7k
    if (comphelper::LibreOfficeKit::isActive())
417
0
    {
418
        // Yield may have changed the current docId, restore the old value,
419
        // (which is cheap). If there is a view to restore this doesn't matter
420
        // much, but if there isn't yet, as in the case of loading a new
421
        // document, then this ensures that the next view to be created is
422
        // created with the expected document id.
423
0
        assert(nOldDocId.get() != -1 && "won't be unset");
424
0
        comphelper::LibreOfficeKit::setDocId(nOldDocId);
425
426
0
        int nNewView = comphelper::LibreOfficeKit::getView();
427
0
        if (nOldView != -1 && nNewView != -1 && nOldView != nNewView)
428
0
        {
429
            // Yield changed the current view, restore the old value.
430
0
            comphelper::LibreOfficeKit::setView(nOldView);
431
0
        }
432
0
    }
433
10.7k
    return bRet;
434
10.7k
}
435
436
bool Application::IsUseSystemEventLoop()
437
2
{
438
2
    return ImplGetSVData()->maAppData.m_bUseSystemLoop;
439
2
}
440
441
void Scheduler::ProcessEventsToIdle()
442
0
{
443
#if OSL_DEBUG_LEVEL > 0
444
    const ImplSVData* pSVData = ImplGetSVData();
445
    if (pSVData->mpDefInst->IsMainThread())
446
        assert(pSVData->maSchedCtx.mnIdlesLockCount == 0);
447
#endif
448
0
    int nSanity = 1;
449
0
    while (InnerYield(false, true))
450
0
    {
451
0
        if (0 == ++nSanity % 1000)
452
0
        {
453
0
            SAL_WARN("vcl.schedule", "ProcessEventsToIdle: " << nSanity);
454
0
        }
455
0
    }
456
#if OSL_DEBUG_LEVEL > 0
457
    // If we yield from a non-main thread we just can guarantee that all idle
458
    // events were processed at some point, but our check can't prevent further
459
    // processing in the main thread, which may add new events, so skip it.
460
    if ( !pSVData->mpDefInst->IsMainThread() )
461
        return;
462
    for (int nTaskPriority = 0; nTaskPriority < PRIO_COUNT; ++nTaskPriority)
463
    {
464
        const ImplSchedulerData* pSchedulerData = pSVData->maSchedCtx.mpFirstSchedulerData[nTaskPriority];
465
        while (pSchedulerData)
466
        {
467
            assert(!pSchedulerData->mbInScheduler);
468
            if (pSchedulerData->mpTask)
469
            {
470
                Idle *pIdle = dynamic_cast<Idle*>(pSchedulerData->mpTask);
471
                if (pIdle && pIdle->IsActive())
472
                {
473
                    SAL_WARN("vcl.schedule",
474
                             "Unprocessed Idle: "
475
                                 << pIdle << " "
476
                                 << (pIdle->GetDebugName() ? pIdle->GetDebugName() : "(nullptr)"));
477
                }
478
            }
479
            pSchedulerData = pSchedulerData->mpNext;
480
        }
481
    }
482
#endif
483
0
}
484
485
extern "C" {
486
/// used by unit tests that test only via the LOK API
487
SAL_DLLPUBLIC_EXPORT void unit_lok_process_events_to_idle()
488
0
{
489
0
    const SolarMutexGuard aGuard;
490
0
    Scheduler::ProcessEventsToIdle();
491
0
}
492
}
493
494
void Application::Yield()
495
43.1k
{
496
43.1k
    static const bool bAbort = Application::IsUseSystemEventLoop();
497
43.1k
    if (bAbort)
498
0
    {
499
0
        SAL_WARN("vcl.schedule", "Application::Yield()");
500
0
        std::abort();
501
0
    }
502
43.1k
    InnerYield(true, false);
503
43.1k
}
504
505
IMPL_STATIC_LINK_NOARG( ImplSVAppData, ImplQuitMsg, void*, void )
506
0
{
507
0
    assert(ImplGetSVData()->maAppData.mbAppQuit);
508
0
    GetSalInstance()->DoQuit();
509
0
}
510
511
void Application::Quit()
512
0
{
513
0
    ImplGetSVData()->maAppData.mbAppQuit = true;
514
0
    Application::PostUserEvent( LINK( nullptr, ImplSVAppData, ImplQuitMsg ) );
515
0
}
516
517
comphelper::SolarMutex& Application::GetSolarMutex()
518
202M
{
519
202M
    return *(GetSalInstance()->GetYieldMutex());
520
202M
}
521
522
bool Application::IsMainThread()
523
308k
{
524
308k
    return ImplGetSVData()->mnMainThreadId == osl::Thread::getCurrentIdentifier();
525
308k
}
526
527
sal_uInt32 Application::ReleaseSolarMutex()
528
42.5k
{
529
42.5k
    return GetSalInstance()->ReleaseYieldMutex(true);
530
42.5k
}
531
532
void Application::AcquireSolarMutex( sal_uInt32 nCount )
533
42.4k
{
534
42.4k
    GetSalInstance()->AcquireYieldMutex( nCount );
535
42.4k
}
536
537
bool Application::IsInMain()
538
6
{
539
6
    ImplSVData* pSVData = ImplGetSVData();
540
6
    return pSVData && pSVData->maAppData.mbInAppMain;
541
6
}
542
543
bool Application::IsInExecute()
544
0
{
545
0
    return ImplGetSVData()->maAppData.mbInAppExecute;
546
0
}
547
548
bool Application::IsQuit()
549
43.1k
{
550
43.1k
    return ImplGetSVData()->maAppData.mbAppQuit;
551
43.1k
}
552
553
bool Application::IsInModalMode()
554
0
{
555
0
    return (ImplGetSVData()->maAppData.mnModalMode != 0);
556
0
}
557
558
sal_uInt16 Application::GetDispatchLevel()
559
0
{
560
0
    return ImplGetSVData()->maAppData.mnDispatchLevel;
561
0
}
562
563
bool Application::AnyInput( VclInputFlags nType )
564
8.53k
{
565
8.53k
    return GetSalInstance()->AnyInput( nType );
566
8.53k
}
567
568
sal_uInt64 Application::GetLastInputInterval()
569
0
{
570
0
    return (tools::Time::GetSystemTicks()-ImplGetSVData()->maAppData.mnLastInputTime);
571
0
}
572
573
bool Application::IsUICaptured()
574
0
{
575
0
    ImplSVData* pSVData = ImplGetSVData();
576
577
    // If mouse was captured, or if in tracking- or in select-mode of a floatingwindow (e.g. menus
578
    // or pulldown toolboxes) another window should be created
579
    // D&D active !!!
580
0
    return pSVData->mpWinData->mpCaptureWin || pSVData->mpWinData->mpTrackWin
581
0
           || pSVData->mpWinData->mpFirstFloat || nImplSysDialog;
582
0
}
583
584
void Application::OverrideSystemSettings( AllSettings& /*rSettings*/ )
585
2
{
586
2
}
587
588
void Application::MergeSystemSettings( AllSettings& rSettings )
589
0
{
590
0
    vcl::Window* pWindow = ImplGetSVData()->maFrameData.mpFirstFrame;
591
0
    if( ! pWindow )
592
0
        pWindow = ImplGetDefaultWindow();
593
0
    if( pWindow )
594
0
    {
595
0
        ImplSVData* pSVData = ImplGetSVData();
596
0
        if ( !pSVData->maAppData.mbSettingsInit )
597
0
        {
598
            // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
599
0
            pWindow->ImplUpdateGlobalSettings( *pSVData->maAppData.mxSettings );
600
0
            pSVData->maAppData.mbSettingsInit = true;
601
0
        }
602
        // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
603
0
        pWindow->ImplUpdateGlobalSettings( rSettings, false );
604
0
    }
605
0
}
606
607
void Application::SetSettings(const AllSettings& rSettings, bool bTemporary)
608
556
{
609
556
    const SolarMutexGuard aGuard;
610
611
556
    ImplSVData* pSVData = ImplGetSVData();
612
556
    if ( !pSVData->maAppData.mxSettings )
613
0
    {
614
0
        InitSettings(pSVData);
615
0
        *pSVData->maAppData.mxSettings = rSettings;
616
0
    }
617
556
    else
618
556
    {
619
556
        AllSettings aOldSettings = *pSVData->maAppData.mxSettings;
620
556
        if (aOldSettings.GetUILanguageTag().getLanguageType() != rSettings.GetUILanguageTag().getLanguageType() &&
621
0
                pSVData->mbResLocaleSet)
622
0
        {
623
0
            pSVData->mbResLocaleSet = false;
624
0
        }
625
556
        *pSVData->maAppData.mxSettings = rSettings;
626
        // Don't broadcast temporary changes
627
556
        AllSettingsFlags nChangeFlags = bTemporary ? AllSettingsFlags::NONE
628
556
                                                   : aOldSettings.GetChangeFlags(*pSVData->maAppData.mxSettings);
629
556
        if (nChangeFlags != AllSettingsFlags::NONE)
630
0
        {
631
0
            DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, &aOldSettings, nChangeFlags );
632
633
            // notify data change handler
634
0
            ImplCallEventListenersApplicationDataChanged( &aDCEvt);
635
636
            // Update all windows
637
0
            vcl::Window* pFirstFrame = pSVData->maFrameData.mpFirstFrame;
638
            // Reset data that needs to be re-calculated
639
0
            tools::Long nOldDPIX = 0;
640
0
            tools::Long nOldDPIY = 0;
641
0
            if ( pFirstFrame )
642
0
            {
643
0
                nOldDPIX = pFirstFrame->GetOutDev()->GetDPIX();
644
0
                nOldDPIY = pFirstFrame->GetOutDev()->GetDPIY();
645
0
                vcl::Window::ImplInitAppFontData(pFirstFrame);
646
0
            }
647
0
            vcl::Window* pFrame = pFirstFrame;
648
0
            while ( pFrame )
649
0
            {
650
                // call UpdateSettings from ClientWindow in order to prevent updating data twice
651
0
                vcl::Window* pClientWin = pFrame;
652
0
                while ( pClientWin->ImplGetClientWindow() )
653
0
                    pClientWin = pClientWin->ImplGetClientWindow();
654
0
                pClientWin->UpdateSettings( rSettings, true );
655
656
0
                vcl::Window* pTempWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
657
0
                while ( pTempWin )
658
0
                {
659
                    // call UpdateSettings from ClientWindow in order to prevent updating data twice
660
0
                    pClientWin = pTempWin;
661
0
                    while ( pClientWin->ImplGetClientWindow() )
662
0
                        pClientWin = pClientWin->ImplGetClientWindow();
663
0
                    pClientWin->UpdateSettings( rSettings, true );
664
0
                    pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
665
0
                }
666
667
0
                pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
668
0
            }
669
670
            // if DPI resolution for screen output was changed set the new resolution for all
671
            // screen compatible VirDev's
672
0
            pFirstFrame = pSVData->maFrameData.mpFirstFrame;
673
0
            if ( pFirstFrame )
674
0
            {
675
0
                if ( (pFirstFrame->GetOutDev()->GetDPIX() != nOldDPIX) ||
676
0
                     (pFirstFrame->GetOutDev()->GetDPIY() != nOldDPIY) )
677
0
                {
678
0
                    VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
679
0
                    while ( pVirDev )
680
0
                    {
681
0
                        if ( pVirDev->mbScreenComp &&
682
0
                             (pVirDev->GetDPIX() == nOldDPIX) &&
683
0
                             (pVirDev->GetDPIY() == nOldDPIY) )
684
0
                        {
685
0
                            pVirDev->SetDPIX( pFirstFrame->GetOutDev()->GetDPIX() );
686
0
                            pVirDev->SetDPIY( pFirstFrame->GetOutDev()->GetDPIY() );
687
0
                            if ( pVirDev->IsMapModeEnabled() )
688
0
                            {
689
0
                                MapMode aMapMode = pVirDev->GetMapMode();
690
0
                                pVirDev->SetMapMode();
691
0
                                pVirDev->SetMapMode( aMapMode );
692
0
                            }
693
0
                        }
694
695
0
                        pVirDev = pVirDev->mpNext;
696
0
                    }
697
0
                }
698
0
            }
699
0
        }
700
556
    }
701
556
}
702
703
const AllSettings& Application::GetSettings()
704
7.02M
{
705
7.02M
    ImplSVData* pSVData = ImplGetSVData();
706
7.02M
    if ( !pSVData->maAppData.mxSettings )
707
82
    {
708
82
        InitSettings(pSVData);
709
82
    }
710
711
7.02M
    return *(pSVData->maAppData.mxSettings);
712
7.02M
}
713
714
namespace {
715
716
void InitSettings(ImplSVData* pSVData)
717
82
{
718
82
    assert(!pSVData->maAppData.mxSettings && "initialization should not happen twice!");
719
720
82
    pSVData->maAppData.mxSettings.emplace();
721
82
    if (!comphelper::IsFuzzing())
722
0
    {
723
0
        pSVData->maAppData.mpCfgListener = new LocaleConfigurationListener;
724
0
        pSVData->maAppData.mxSettings->GetSysLocale().GetOptions().AddListener( pSVData->maAppData.mpCfgListener );
725
0
    }
726
82
}
727
728
}
729
730
void Application::NotifyAllWindows( DataChangedEvent& rDCEvt )
731
0
{
732
0
    ImplSVData* pSVData = ImplGetSVData();
733
0
    vcl::Window* pFrame = pSVData->maFrameData.mpFirstFrame;
734
0
    while ( pFrame )
735
0
    {
736
0
        pFrame->NotifyAllChildren( rDCEvt );
737
738
0
        vcl::Window* pSysWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
739
0
        while ( pSysWin )
740
0
        {
741
0
            pSysWin->NotifyAllChildren( rDCEvt );
742
0
            pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
743
0
        }
744
745
0
        pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
746
0
    }
747
0
}
748
749
void Application::ImplCallEventListenersApplicationDataChanged( void* pData )
750
0
{
751
0
    ImplSVData* pSVData = ImplGetSVData();
752
0
    VclWindowEvent aEvent( nullptr, VclEventId::ApplicationDataChanged, pData );
753
754
0
    pSVData->maAppData.maEventListeners.Call( aEvent );
755
0
}
756
757
void Application::ImplCallEventListeners( VclSimpleEvent& rEvent )
758
198k
{
759
198k
    ImplSVData* pSVData = ImplGetSVData();
760
198k
    pSVData->maAppData.maEventListeners.Call( rEvent );
761
198k
}
762
763
void Application::AddEventListener( const Link<VclSimpleEvent&,void>& rEventListener )
764
0
{
765
0
    ImplSVData* pSVData = ImplGetSVData();
766
0
    pSVData->maAppData.maEventListeners.addListener( rEventListener );
767
0
}
768
769
void Application::RemoveEventListener( const Link<VclSimpleEvent&,void>& rEventListener )
770
0
{
771
0
    ImplSVData* pSVData = ImplGetSVData();
772
0
    pSVData->maAppData.maEventListeners.removeListener( rEventListener );
773
0
}
774
775
void Application::AddKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener )
776
0
{
777
0
    ImplSVData* pSVData = ImplGetSVData();
778
0
    pSVData->maAppData.maKeyListeners.push_back( rKeyListener );
779
0
}
780
781
void Application::RemoveKeyListener( const Link<VclWindowEvent&,bool>& rKeyListener )
782
0
{
783
0
    ImplSVData* pSVData = ImplGetSVData();
784
0
    auto & rVec = pSVData->maAppData.maKeyListeners;
785
0
    std::erase(rVec, rKeyListener);
786
0
}
787
788
bool Application::HandleKey( VclEventId nEvent, vcl::Window *pWin, KeyEvent* pKeyEvent )
789
0
{
790
    // let listeners process the key event
791
0
    VclWindowEvent aEvent( pWin, nEvent, static_cast<void *>(pKeyEvent) );
792
793
0
    ImplSVData* pSVData = ImplGetSVData();
794
795
0
    if ( pSVData->maAppData.maKeyListeners.empty() )
796
0
        return false;
797
798
0
    bool bProcessed = false;
799
    // Copy the list, because this can be destroyed when calling a Link...
800
0
    std::vector<Link<VclWindowEvent&,bool>> aCopy( pSVData->maAppData.maKeyListeners );
801
0
    for ( const Link<VclWindowEvent&,bool>& rLink : aCopy )
802
0
    {
803
0
        if( rLink.Call( aEvent ) )
804
0
        {
805
0
            bProcessed = true;
806
0
            break;
807
0
        }
808
0
    }
809
0
    return bProcessed;
810
0
}
811
812
ImplSVEvent * Application::PostKeyEvent( VclEventId nEvent, vcl::Window *pWin, KeyEvent const * pKeyEvent )
813
0
{
814
0
    const SolarMutexGuard aGuard;
815
0
    ImplSVEvent * nEventId = nullptr;
816
817
0
    if( pWin && pKeyEvent )
818
0
    {
819
0
        std::unique_ptr<ImplPostEventData> pPostEventData(new ImplPostEventData( nEvent, pWin, *pKeyEvent ));
820
821
0
        nEventId = PostUserEvent(
822
0
                       LINK( nullptr, Application, PostEventHandler ),
823
0
                       pPostEventData.get() );
824
825
0
        if( nEventId )
826
0
        {
827
0
            pPostEventData->mnEventId = nEventId;
828
0
            ImplGetSVData()->maAppData.maPostedEventList.emplace_back( pWin, pPostEventData.release() );
829
0
        }
830
0
    }
831
832
0
    return nEventId;
833
0
}
834
835
ImplSVEvent* Application::PostGestureEvent(VclEventId nEvent, vcl::Window* pWin,
836
                                           GestureEventPan const * pGestureEvent)
837
0
{
838
0
    const SolarMutexGuard aGuard;
839
0
    ImplSVEvent * nEventId = nullptr;
840
841
0
    if (pWin && pGestureEvent)
842
0
    {
843
0
        Point aTransformedPosition(pGestureEvent->mnX, pGestureEvent->mnY);
844
845
0
        aTransformedPosition.AdjustX(pWin->GetDeviceOriginX());
846
0
        aTransformedPosition.AdjustY(pWin->GetDeviceOriginY());
847
848
0
        const GestureEventPan aGestureEvent(
849
0
            sal_Int32(aTransformedPosition.X()),
850
0
            sal_Int32(aTransformedPosition.Y()),
851
0
            pGestureEvent->meEventType,
852
0
            pGestureEvent->mnOffset,
853
0
            pGestureEvent->meOrientation
854
0
        );
855
856
0
        std::unique_ptr<ImplPostEventData> pPostEventData(new ImplPostEventData(nEvent, pWin, aGestureEvent));
857
858
0
        nEventId = PostUserEvent(
859
0
                       LINK( nullptr, Application, PostEventHandler ),
860
0
                       pPostEventData.get());
861
862
0
        if (nEventId)
863
0
        {
864
0
            pPostEventData->mnEventId = nEventId;
865
0
            ImplGetSVData()->maAppData.maPostedEventList.emplace_back(pWin, pPostEventData.release());
866
0
        }
867
0
    }
868
869
0
    return nEventId;
870
0
}
871
872
bool Application::LOKHandleMouseEvent(VclEventId nEvent, vcl::Window* pWindow, const MouseEvent* pEvent)
873
0
{
874
0
    bool bSuccess = false;
875
0
    SalMouseEvent aMouseEvent;
876
877
0
    if (!pWindow)
878
0
        return false;
879
880
0
    if (!pEvent)
881
0
        return false;
882
883
0
    aMouseEvent.mnTime = tools::Time::GetSystemTicks();
884
0
    aMouseEvent.mnX = pEvent->GetPosPixel().X();
885
0
    aMouseEvent.mnY = pEvent->GetPosPixel().Y();
886
0
    aMouseEvent.mnCode = pEvent->GetButtons() | pEvent->GetModifier();
887
888
0
    switch (nEvent)
889
0
    {
890
0
        case VclEventId::WindowMouseMove:
891
0
            aMouseEvent.mnButton = 0;
892
0
            bSuccess = ImplLOKHandleMouseEvent(pWindow, NotifyEventType::MOUSEMOVE, false,
893
0
                                               aMouseEvent.mnX, aMouseEvent.mnY,
894
0
                                               aMouseEvent.mnTime, aMouseEvent.mnCode,
895
0
                                               ImplGetMouseMoveMode(&aMouseEvent),
896
0
                                               pEvent->GetClicks());
897
0
        break;
898
899
0
        case VclEventId::WindowMouseButtonDown:
900
0
            aMouseEvent.mnButton = pEvent->GetButtons();
901
0
            bSuccess = ImplLOKHandleMouseEvent(pWindow, NotifyEventType::MOUSEBUTTONDOWN, false,
902
0
                                               aMouseEvent.mnX, aMouseEvent.mnY,
903
0
                                               aMouseEvent.mnTime,
904
#ifdef MACOSX
905
                                               aMouseEvent.mnButton |
906
                                               (aMouseEvent.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
907
#else
908
0
                                               aMouseEvent.mnButton |
909
0
                                               (aMouseEvent.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
910
0
#endif
911
0
                                               ImplGetMouseButtonMode(&aMouseEvent),
912
0
                                               pEvent->GetClicks());
913
0
            break;
914
915
0
        case VclEventId::WindowMouseButtonUp:
916
0
            aMouseEvent.mnButton = pEvent->GetButtons();
917
0
            bSuccess = ImplLOKHandleMouseEvent(pWindow, NotifyEventType::MOUSEBUTTONUP, false,
918
0
                                               aMouseEvent.mnX, aMouseEvent.mnY,
919
0
                                               aMouseEvent.mnTime,
920
#ifdef MACOSX
921
                                               aMouseEvent.mnButton |
922
                                               (aMouseEvent.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
923
#else
924
0
                                               aMouseEvent.mnButton |
925
0
                                               (aMouseEvent.mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
926
0
#endif
927
0
                                               ImplGetMouseButtonMode(&aMouseEvent),
928
0
                                               pEvent->GetClicks());
929
0
            break;
930
931
0
        default:
932
0
            SAL_WARN( "vcl.layout", "Application::HandleMouseEvent unknown event (" << static_cast<int>(nEvent) << ")" );
933
0
            break;
934
0
    }
935
936
0
    return bSuccess;
937
0
}
938
939
940
ImplSVEvent* Application::PostMouseEvent( VclEventId nEvent, vcl::Window *pWin, MouseEvent const * pMouseEvent )
941
0
{
942
0
    const SolarMutexGuard aGuard;
943
0
    ImplSVEvent * nEventId = nullptr;
944
945
0
    if( pWin && pMouseEvent )
946
0
    {
947
0
        Point aTransformedPos( pMouseEvent->GetPosPixel() );
948
949
        // LOK uses (0, 0) as the origin of all windows; don't offset.
950
0
        if (!comphelper::LibreOfficeKit::isActive())
951
0
        {
952
0
            aTransformedPos.AdjustX(pWin->GetDeviceOriginX());
953
0
            aTransformedPos.AdjustY(pWin->GetDeviceOriginY());
954
0
        }
955
956
0
        const MouseEvent aTransformedEvent( aTransformedPos, pMouseEvent->GetClicks(), pMouseEvent->GetMode(),
957
0
                                            pMouseEvent->GetButtons(), pMouseEvent->GetModifier() );
958
959
0
        std::unique_ptr<ImplPostEventData> pPostEventData(new ImplPostEventData( nEvent, pWin, aTransformedEvent ));
960
961
0
        nEventId = PostUserEvent(
962
0
                       LINK( nullptr, Application, PostEventHandler ),
963
0
                       pPostEventData.get() );
964
965
0
        if( nEventId )
966
0
        {
967
0
            pPostEventData->mnEventId = nEventId;
968
0
            ImplGetSVData()->maAppData.maPostedEventList.emplace_back( pWin, pPostEventData.release() );
969
0
        }
970
0
    }
971
972
0
    return nEventId;
973
0
}
974
975
976
IMPL_STATIC_LINK( Application, PostEventHandler, void*, pCallData, void )
977
0
{
978
0
    const SolarMutexGuard aGuard;
979
0
    ImplPostEventData*  pData = static_cast< ImplPostEventData * >( pCallData );
980
0
    const void*         pEventData;
981
0
    SalEvent            nEvent;
982
0
    ImplSVEvent * const nEventId = pData->mnEventId;
983
984
0
    switch( pData->mnEvent )
985
0
    {
986
0
        case VclEventId::WindowMouseMove:
987
0
            nEvent = SalEvent::ExternalMouseMove;
988
0
            pEventData = &pData->maMouseEvent;
989
0
        break;
990
991
0
        case VclEventId::WindowMouseButtonDown:
992
0
            nEvent = SalEvent::ExternalMouseButtonDown;
993
0
            pEventData = &pData->maMouseEvent;
994
0
        break;
995
996
0
        case VclEventId::WindowMouseButtonUp:
997
0
            nEvent = SalEvent::ExternalMouseButtonUp;
998
0
            pEventData = &pData->maMouseEvent;
999
0
        break;
1000
1001
0
        case VclEventId::WindowKeyInput:
1002
0
            nEvent = SalEvent::ExternalKeyInput;
1003
0
            pEventData = &pData->maKeyEvent;
1004
0
        break;
1005
1006
0
        case VclEventId::WindowKeyUp:
1007
0
            nEvent = SalEvent::ExternalKeyUp;
1008
0
            pEventData = &pData->maKeyEvent;
1009
0
        break;
1010
1011
0
        case VclEventId::WindowGestureEvent:
1012
0
            nEvent = SalEvent::ExternalGesture;
1013
0
            pEventData = &pData->maGestureEvent;
1014
0
        break;
1015
1016
0
        default:
1017
0
            nEvent = SalEvent::NONE;
1018
0
            pEventData = nullptr;
1019
0
        break;
1020
0
    }
1021
1022
0
    if( pData->mpWin && pData->mpWin->mpWindowImpl->mpFrameWindow && pEventData )
1023
0
        ImplWindowFrameProc( pData->mpWin->mpWindowImpl->mpFrameWindow.get(), nEvent, pEventData );
1024
1025
    // remove this event from list of posted events, watch for destruction of internal data
1026
0
    auto svdata = ImplGetSVData();
1027
0
    ::std::vector< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() );
1028
1029
0
    while( aIter != svdata->maAppData.maPostedEventList.end() )
1030
0
    {
1031
0
        if( nEventId == (*aIter).second->mnEventId )
1032
0
        {
1033
0
            delete (*aIter).second;
1034
0
            aIter = svdata->maAppData.maPostedEventList.erase( aIter );
1035
0
        }
1036
0
        else
1037
0
            ++aIter;
1038
0
    }
1039
0
}
1040
1041
void Application::RemoveMouseAndKeyEvents( vcl::Window* pWin )
1042
103k
{
1043
103k
    const SolarMutexGuard aGuard;
1044
1045
    // remove all events for specific window, watch for destruction of internal data
1046
103k
    auto svdata = ImplGetSVData();
1047
103k
    ::std::vector< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() );
1048
1049
103k
    while( aIter != svdata->maAppData.maPostedEventList.end() )
1050
0
    {
1051
0
        if( pWin == (*aIter).first )
1052
0
        {
1053
0
            if( (*aIter).second->mnEventId )
1054
0
                RemoveUserEvent( (*aIter).second->mnEventId );
1055
1056
0
            delete (*aIter).second;
1057
0
            aIter = svdata->maAppData.maPostedEventList.erase( aIter );
1058
0
        }
1059
0
        else
1060
0
            ++aIter;
1061
0
    }
1062
103k
}
1063
1064
ImplSVEvent * Application::PostUserEvent( const Link<void*,void>& rLink, void* pCaller,
1065
                                          bool bReferenceLink )
1066
82.9k
{
1067
82.9k
    vcl::Window* pDefWindow = ImplGetDefaultWindow();
1068
82.9k
    if ( pDefWindow == nullptr )
1069
0
        return nullptr;
1070
1071
82.9k
    std::unique_ptr<ImplSVEvent> pSVEvent(new ImplSVEvent);
1072
82.9k
    pSVEvent->mpData    = pCaller;
1073
82.9k
    pSVEvent->maLink    = rLink;
1074
82.9k
    pSVEvent->mpWindow  = nullptr;
1075
82.9k
    pSVEvent->mbCall    = true;
1076
82.9k
    if (bReferenceLink)
1077
0
    {
1078
0
        SolarMutexGuard aGuard;
1079
0
        pSVEvent->mpInstanceRef = static_cast<vcl::Window *>(rLink.GetInstance());
1080
0
    }
1081
1082
82.9k
    auto pTmpEvent = pSVEvent.get();
1083
82.9k
    if (!pDefWindow->ImplGetFrame()->PostEvent( std::move(pSVEvent) ))
1084
0
        return nullptr;
1085
82.9k
    return pTmpEvent;
1086
82.9k
}
1087
1088
void Application::RemoveUserEvent( ImplSVEvent * nUserEvent )
1089
75.0k
{
1090
75.0k
    if(nUserEvent)
1091
75.0k
    {
1092
75.0k
        SAL_WARN_IF( nUserEvent->mpWindow, "vcl",
1093
75.0k
                    "Application::RemoveUserEvent(): Event is send to a window" );
1094
75.0k
        SAL_WARN_IF( !nUserEvent->mbCall, "vcl",
1095
75.0k
                    "Application::RemoveUserEvent(): Event is already removed" );
1096
1097
75.0k
        nUserEvent->mpWindow.reset();
1098
75.0k
        nUserEvent->mpInstanceRef.reset();
1099
75.0k
        nUserEvent->mbCall = false;
1100
75.0k
    }
1101
75.0k
}
1102
1103
vcl::Window* Application::GetFocusWindow()
1104
4.14k
{
1105
4.14k
    return ImplGetSVData()->mpWinData->mpFocusWin;
1106
4.14k
}
1107
1108
OutputDevice* Application::GetDefaultDevice()
1109
1.28M
{
1110
1.28M
    vcl::Window* pWindow = ImplGetDefaultWindow();
1111
1.28M
    if (pWindow != nullptr)
1112
1.28M
    {
1113
1.28M
        return pWindow->GetOutDev();
1114
1.28M
    }
1115
0
    else
1116
0
    {
1117
0
        return nullptr;
1118
0
    }
1119
1.28M
}
1120
1121
basegfx::SystemDependentDataManager& Application::GetSystemDependentDataManager()
1122
2.17M
{
1123
2.17M
    return ImplGetSystemDependentDataManager();
1124
2.17M
}
1125
1126
vcl::Window* Application::GetFirstTopLevelWindow()
1127
0
{
1128
0
    ImplSVData* pSVData = ImplGetSVData();
1129
0
    return pSVData->maFrameData.mpFirstFrame;
1130
0
}
1131
1132
vcl::Window* Application::GetNextTopLevelWindow( vcl::Window const * pWindow )
1133
0
{
1134
0
    return pWindow->mpWindowImpl->mpFrameData->mpNextFrame;
1135
0
}
1136
1137
tools::Long    Application::GetTopWindowCount()
1138
0
{
1139
0
    tools::Long nRet = 0;
1140
0
    ImplSVData* pSVData = ImplGetSVData();
1141
0
    vcl::Window *pWin = pSVData ? pSVData->maFrameData.mpFirstFrame.get() : nullptr;
1142
0
    while( pWin )
1143
0
    {
1144
0
        if( pWin->ImplGetWindow()->IsTopWindow() )
1145
0
            nRet++;
1146
0
        pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1147
0
    }
1148
0
    return nRet;
1149
0
}
1150
1151
vcl::Window* Application::GetTopWindow( tools::Long nIndex )
1152
0
{
1153
0
    tools::Long nIdx = 0;
1154
0
    ImplSVData* pSVData = ImplGetSVData();
1155
0
    vcl::Window *pWin = pSVData ? pSVData->maFrameData.mpFirstFrame.get() : nullptr;
1156
0
    while( pWin )
1157
0
    {
1158
0
        if( pWin->ImplGetWindow()->IsTopWindow() )
1159
0
        {
1160
0
            if( nIdx == nIndex )
1161
0
                return pWin->ImplGetWindow();
1162
0
            else
1163
0
                nIdx++;
1164
0
        }
1165
0
        pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1166
0
    }
1167
0
    return nullptr;
1168
0
}
1169
1170
vcl::Window* Application::GetActiveTopWindow()
1171
0
{
1172
0
    vcl::Window *pWin = ImplGetSVData()->mpWinData->mpFocusWin;
1173
0
    while( pWin )
1174
0
    {
1175
0
        if( pWin->IsTopWindow() )
1176
0
            return pWin;
1177
0
        pWin = pWin->mpWindowImpl->mpParent;
1178
0
    }
1179
0
    return nullptr;
1180
0
}
1181
1182
void Application::SetAppName( const OUString& rUniqueName )
1183
0
{
1184
0
    ImplSVData* pSVData = ImplGetSVData();
1185
0
    pSVData->maAppData.mxAppName = rUniqueName;
1186
0
}
1187
1188
const OUString & Application::GetAppName()
1189
0
{
1190
0
    ImplSVData* pSVData = ImplGetSVData();
1191
0
    if ( pSVData->maAppData.mxAppName )
1192
0
        return *(pSVData->maAppData.mxAppName);
1193
0
    else
1194
0
        return EMPTY_OUSTRING;
1195
0
}
1196
1197
enum {hwAll=0, hwEnv=1, hwUI=2};
1198
1199
static OUString Localize(TranslateId aId, const bool bLocalize)
1200
0
{
1201
0
    if (bLocalize)
1202
0
        return VclResId(aId);
1203
0
    else
1204
0
        return Translate::get(aId, Translate::Create("vcl", LanguageTag(u"en-US"_ustr)));
1205
0
}
1206
1207
OUString Application::GetOSVersion()
1208
0
{
1209
0
    if (SalInstance* pSalInstance = GetSalInstance())
1210
0
        return pSalInstance->getOSVersion();
1211
1212
0
    return u"-"_ustr;
1213
0
}
1214
1215
OUString Application::GetHWOSConfInfo(const int bSelection, const bool bLocalize)
1216
0
{
1217
0
    OUStringBuffer aDetails;
1218
1219
0
    const auto appendDetails = [&aDetails](std::u16string_view sep, auto&& val) {
1220
0
        if (!aDetails.isEmpty() && !sep.empty())
1221
0
            aDetails.append(sep);
1222
0
        aDetails.append(std::move(val));
1223
0
    };
Unexecuted instantiation: svapp.cxx:auto Application::GetHWOSConfInfo(int, bool)::$_0::operator()<rtl::StringConcat<char16_t, rtl::OUString, rtl::StringNumber<char16_t, 65ul>, 0> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, rtl::StringConcat<char16_t, rtl::OUString, rtl::StringNumber<char16_t, 65ul>, 0>&&) const
Unexecuted instantiation: svapp.cxx:auto Application::GetHWOSConfInfo(int, bool)::$_0::operator()<rtl::StringConcat<char16_t, rtl::OUString, rtl::OUString, 0> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, rtl::StringConcat<char16_t, rtl::OUString, rtl::OUString, 0>&&) const
Unexecuted instantiation: svapp.cxx:auto Application::GetHWOSConfInfo(int, bool)::$_0::operator()<rtl::OUString>(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, rtl::OUString&&) const
Unexecuted instantiation: svapp.cxx:auto Application::GetHWOSConfInfo(int, bool)::$_0::operator()<rtl::StringConcat<char16_t, char const [6], rtl::OUString, 0> >(std::__1::basic_string_view<char16_t, std::__1::char_traits<char16_t> >, rtl::StringConcat<char16_t, char const [6], rtl::OUString, 0>&&) const
1224
1225
0
    if (bSelection != hwUI) {
1226
0
        appendDetails(u"; ", Localize(SV_APP_CPUTHREADS, bLocalize)
1227
0
                                + OUString::number(std::thread::hardware_concurrency()));
1228
1229
0
        OUString aVersion = GetOSVersion();
1230
1231
0
        appendDetails(u"; ", Localize(SV_APP_OSVERSION, bLocalize) + aVersion);
1232
0
    }
1233
1234
0
    if (bSelection != hwEnv) {
1235
0
        appendDetails(u"; ", Localize(SV_APP_UIRENDER, bLocalize));
1236
#if HAVE_FEATURE_SKIA
1237
        if ( SkiaHelper::isVCLSkiaEnabled() )
1238
        {
1239
            switch(SkiaHelper::renderMethodToUse())
1240
            {
1241
                case SkiaHelper::RenderVulkan:
1242
                    appendDetails(u"", Localize(SV_APP_SKIA_VULKAN, bLocalize));
1243
                    break;
1244
                case SkiaHelper::RenderMetal:
1245
                    appendDetails(u"", Localize(SV_APP_SKIA_METAL, bLocalize));
1246
                    break;
1247
                case SkiaHelper::RenderRaster:
1248
                    appendDetails(u"", Localize(SV_APP_SKIA_RASTER, bLocalize));
1249
                    break;
1250
            }
1251
        }
1252
        else
1253
#endif
1254
0
            appendDetails(u"", Localize(SV_APP_DEFAULT, bLocalize));
1255
1256
0
#if (defined LINUX || defined _WIN32 || defined MACOSX || defined __FreeBSD__ || defined __EMSCRIPTEN__)
1257
0
        appendDetails(u"; ", SV_APP_VCLBACKEND + GetToolkitName());
1258
0
#endif
1259
0
    }
1260
1261
0
    return aDetails.makeStringAndClear();
1262
0
}
1263
1264
void Application::SetDisplayName( const OUString& rName )
1265
0
{
1266
0
    ImplSVData* pSVData = ImplGetSVData();
1267
0
    pSVData->maAppData.mxDisplayName = rName;
1268
0
}
1269
1270
OUString Application::GetDisplayName()
1271
0
{
1272
0
    ImplSVData* pSVData = ImplGetSVData();
1273
0
    if ( pSVData->maAppData.mxDisplayName )
1274
0
        return *(pSVData->maAppData.mxDisplayName);
1275
0
    else if (pSVData->maFrameData.mpAppWin)
1276
0
        return pSVData->maFrameData.mpAppWin->GetText();
1277
0
    else
1278
0
        return OUString();
1279
0
}
1280
1281
unsigned int Application::GetScreenCount()
1282
0
{
1283
0
    SalSystem* pSys = ImplGetSalSystem();
1284
0
    return pSys ? pSys->GetDisplayScreenCount() : 0;
1285
0
}
1286
1287
unsigned int Application::GetDisplayBuiltInScreen()
1288
0
{
1289
0
    SalSystem* pSys = ImplGetSalSystem();
1290
0
    return pSys ? pSys->GetDisplayBuiltInScreen() : 0;
1291
0
}
1292
1293
unsigned int Application::GetDisplayExternalScreen()
1294
0
{
1295
    // This is really unpleasant, in theory we could have multiple
1296
    // external displays etc.
1297
0
    int nExternal(0);
1298
0
    switch (GetDisplayBuiltInScreen())
1299
0
    {
1300
0
    case 0:
1301
0
        nExternal = 1;
1302
0
        break;
1303
0
    case 1:
1304
0
        nExternal = 0;
1305
0
        break;
1306
0
    default:
1307
        // When the built-in display is neither 0 nor 1
1308
        // then place the full-screen presentation on the
1309
        // first available screen.
1310
0
        nExternal = 0;
1311
0
        break;
1312
0
    }
1313
0
    return nExternal;
1314
0
}
1315
1316
AbsoluteScreenPixelRectangle Application::GetScreenPosSizePixel( unsigned int nScreen )
1317
0
{
1318
0
    SalSystem* pSys = ImplGetSalSystem();
1319
0
    if (!pSys)
1320
0
    {
1321
0
        SAL_WARN("vcl", "Requesting screen size/pos for screen #" << nScreen << " failed");
1322
0
        assert(false);
1323
0
        return AbsoluteScreenPixelRectangle();
1324
0
    }
1325
0
    AbsoluteScreenPixelRectangle aRect = pSys->GetDisplayScreenPosSizePixel(nScreen);
1326
0
    if (aRect.GetHeight() == 0)
1327
0
        SAL_WARN("vcl", "Requesting screen size/pos for screen #" << nScreen << " returned 0 height.");
1328
0
    return aRect;
1329
0
}
1330
1331
namespace {
1332
tools::Long calcDistSquare( const AbsoluteScreenPixelPoint& i_rPoint, const AbsoluteScreenPixelRectangle& i_rRect )
1333
0
{
1334
0
    const AbsoluteScreenPixelPoint aRectCenter( (i_rRect.Left() + i_rRect.Right())/2,
1335
0
                       (i_rRect.Top() + i_rRect.Bottom())/ 2 );
1336
0
    const tools::Long nDX = aRectCenter.X() - i_rPoint.X();
1337
0
    const tools::Long nDY = aRectCenter.Y() - i_rPoint.Y();
1338
0
    return nDX*nDX + nDY*nDY;
1339
0
}
1340
}
1341
1342
unsigned int Application::GetBestScreen( const AbsoluteScreenPixelRectangle& i_rRect )
1343
0
{
1344
0
    const unsigned int nScreens = GetScreenCount();
1345
0
    unsigned int nBestMatchScreen = 0;
1346
0
    unsigned long nOverlap = 0;
1347
0
    for( unsigned int i = 0; i < nScreens; i++ )
1348
0
    {
1349
0
        const AbsoluteScreenPixelRectangle aCurScreenRect( GetScreenPosSizePixel( i ) );
1350
        // if a screen contains the rectangle completely it is obviously the best screen
1351
0
        if( aCurScreenRect.Contains( i_rRect ) )
1352
0
            return i;
1353
        // next the screen which contains most of the area of the rect is the best
1354
0
        AbsoluteScreenPixelRectangle aIntersection( aCurScreenRect.GetIntersection( i_rRect ) );
1355
0
        if( ! aIntersection.IsEmpty() )
1356
0
        {
1357
0
            const unsigned long nCurOverlap( aIntersection.GetWidth() * aIntersection.GetHeight() );
1358
0
            if( nCurOverlap > nOverlap )
1359
0
            {
1360
0
                nOverlap = nCurOverlap;
1361
0
                nBestMatchScreen = i;
1362
0
            }
1363
0
        }
1364
0
    }
1365
0
    if( nOverlap > 0 )
1366
0
        return nBestMatchScreen;
1367
1368
    // finally the screen which center is nearest to the rect is the best
1369
0
    const AbsoluteScreenPixelPoint aCenter( (i_rRect.Left() + i_rRect.Right())/2,
1370
0
                         (i_rRect.Top() + i_rRect.Bottom())/2 );
1371
0
    tools::Long nDist = std::numeric_limits<tools::Long>::max();
1372
0
    for( unsigned int i = 0; i < nScreens; i++ )
1373
0
    {
1374
0
        const AbsoluteScreenPixelRectangle aCurScreenRect( GetScreenPosSizePixel( i ) );
1375
0
        const tools::Long nCurDist( calcDistSquare( aCenter, aCurScreenRect ) );
1376
0
        if( nCurDist < nDist )
1377
0
        {
1378
0
            nBestMatchScreen = i;
1379
0
            nDist = nCurDist;
1380
0
        }
1381
0
    }
1382
0
    return nBestMatchScreen;
1383
0
}
1384
1385
bool Application::InsertAccel( Accelerator* pAccel )
1386
0
{
1387
0
    ImplSVData* pSVData = ImplGetSVData();
1388
1389
0
    if ( !pSVData->maAppData.mpAccelMgr )
1390
0
        pSVData->maAppData.mpAccelMgr = new ImplAccelManager();
1391
0
    return pSVData->maAppData.mpAccelMgr->InsertAccel( pAccel );
1392
0
}
1393
1394
void Application::RemoveAccel( Accelerator const * pAccel )
1395
0
{
1396
0
    ImplSVData* pSVData = ImplGetSVData();
1397
1398
0
    if ( pSVData->maAppData.mpAccelMgr )
1399
0
        pSVData->maAppData.mpAccelMgr->RemoveAccel( pAccel );
1400
0
}
1401
1402
void Application::SetHelp( Help* pHelp )
1403
0
{
1404
0
    ImplGetSVData()->maAppData.mpHelp = pHelp;
1405
0
}
1406
1407
void Application::UpdateMainThread()
1408
0
{
1409
0
    ImplSVData* pSVData = ImplGetSVData();
1410
0
    if (pSVData && pSVData->mpDefInst)
1411
0
        pSVData->mpDefInst->updateMainThread();
1412
0
}
1413
1414
Help* Application::GetHelp()
1415
0
{
1416
0
    return ImplGetSVData()->maAppData.mpHelp;
1417
0
}
1418
1419
0
Platform Application::GetPlatform() { return GetSalInstance()->GetPlatform(); }
1420
1421
0
Toolkit Application::GetToolkit() { return GetSalInstance()->GetToolkit(); }
1422
1423
0
OUString Application::GetToolkitName() { return GetSalInstance()->GetToolkitName(); }
1424
1425
vcl::Window* Dialog::GetDefDialogParent()
1426
7.33k
{
1427
7.33k
    ImplSVData* pSVData = ImplGetSVData();
1428
    // find some useful dialog parent
1429
1430
    // always use the topmost parent of the candidate
1431
    // window to avoid using dialogs or floaters
1432
    // as DefDialogParent
1433
1434
    // current focus frame
1435
7.33k
    vcl::Window *pWin = pSVData->mpWinData->mpFocusWin;
1436
7.33k
    if (pWin && !pWin->IsMenuFloatingWindow())
1437
0
    {
1438
0
        while (pWin->mpWindowImpl && pWin->mpWindowImpl->mpParent)
1439
0
            pWin = pWin->mpWindowImpl->mpParent;
1440
1441
        // check for corrupted window hierarchy, #122232#, may be we now crash somewhere else
1442
0
        if (!pWin->mpWindowImpl)
1443
0
        {
1444
0
            OSL_FAIL( "Window hierarchy corrupted!" );
1445
0
            pSVData->mpWinData->mpFocusWin = nullptr;   // avoid further access
1446
0
            return nullptr;
1447
0
        }
1448
1449
0
        if ((pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0)
1450
0
        {
1451
0
            return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1452
0
        }
1453
0
    }
1454
1455
    // last active application frame
1456
7.33k
    pWin = pSVData->maFrameData.mpActiveApplicationFrame;
1457
7.33k
    if (pWin)
1458
0
    {
1459
0
        return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1460
0
    }
1461
1462
    // first visible top window (may be totally wrong...)
1463
7.33k
    pWin = pSVData->maFrameData.mpFirstFrame;
1464
14.6k
    while (pWin)
1465
7.33k
    {
1466
7.33k
        if( pWin->ImplGetWindow()->IsTopWindow() &&
1467
7.33k
            pWin->mpWindowImpl->mbReallyVisible &&
1468
0
            (pWin->mpWindowImpl->mnStyle & WB_INTROWIN) == 0
1469
7.33k
        )
1470
0
        {
1471
0
            while( pWin->mpWindowImpl->mpParent )
1472
0
                pWin = pWin->mpWindowImpl->mpParent;
1473
0
            return pWin->mpWindowImpl->mpFrameWindow->ImplGetWindow();
1474
0
        }
1475
7.33k
        pWin = pWin->mpWindowImpl->mpFrameData->mpNextFrame;
1476
7.33k
    }
1477
1478
    // use the desktop
1479
7.33k
    return nullptr;
1480
7.33k
}
1481
1482
weld::Window* Application::GetDefDialogParent()
1483
7.33k
{
1484
7.33k
    vcl::Window* pWindow = Dialog::GetDefDialogParent();
1485
7.33k
    return pWindow ? pWindow->GetFrameWeld() : nullptr;
1486
7.33k
}
1487
1488
DialogCancelMode Application::GetDialogCancelMode()
1489
4.24k
{
1490
4.24k
    return ImplGetSVData()->maAppData.meDialogCancel;
1491
4.24k
}
1492
1493
void Application::SetDialogCancelMode( DialogCancelMode mode )
1494
8.38k
{
1495
8.38k
    ImplGetSVData()->maAppData.meDialogCancel = mode;
1496
8.38k
}
1497
1498
bool Application::IsDialogCancelEnabled()
1499
91.4k
{
1500
91.4k
    return ImplGetSVData()->maAppData.meDialogCancel != DialogCancelMode::Off;
1501
91.4k
}
1502
1503
void Application::SetSystemWindowMode( SystemWindowFlags nMode )
1504
0
{
1505
0
    ImplGetSVData()->maAppData.mnSysWinMode = nMode;
1506
0
}
1507
1508
SystemWindowFlags Application::GetSystemWindowMode()
1509
0
{
1510
0
    return ImplGetSVData()->maAppData.mnSysWinMode;
1511
0
}
1512
1513
css::uno::Reference< css::awt::XToolkit > Application::GetVCLToolkit()
1514
0
{
1515
0
    css::uno::Reference< css::awt::XToolkit > xT;
1516
0
    UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
1517
0
    if ( pWrapper )
1518
0
        xT = pWrapper->GetVCLToolkit();
1519
0
    return xT;
1520
0
}
1521
1522
#ifdef DISABLE_DYNLOADING
1523
1524
extern "C" { UnoWrapperBase* CreateUnoWrapper(); }
1525
1526
#else
1527
1528
extern "C" { static void thisModule() {} }
1529
1530
#endif
1531
1532
UnoWrapperBase* UnoWrapperBase::GetUnoWrapper( bool bCreateIfNotExist )
1533
220k
{
1534
220k
    ImplSVData* pSVData = ImplGetSVData();
1535
220k
    static bool bAlreadyTriedToCreate = false;
1536
220k
    if ( !pSVData->mpUnoWrapper && bCreateIfNotExist && !bAlreadyTriedToCreate )
1537
30
    {
1538
#ifndef DISABLE_DYNLOADING
1539
        osl::Module aTkLib;
1540
        aTkLib.loadRelative(&thisModule, TK_DLL_NAME);
1541
        if (aTkLib.is())
1542
        {
1543
            FN_TkCreateUnoWrapper fnCreateWrapper = reinterpret_cast<FN_TkCreateUnoWrapper>(aTkLib.getFunctionSymbol("CreateUnoWrapper"));
1544
            if ( fnCreateWrapper )
1545
            {
1546
                pSVData->mpUnoWrapper = fnCreateWrapper();
1547
            }
1548
            aTkLib.release();
1549
        }
1550
        SAL_WARN_IF( !pSVData->mpUnoWrapper, "vcl", "UnoWrapper could not be created!" );
1551
#else
1552
30
        pSVData->mpUnoWrapper = CreateUnoWrapper();
1553
30
#endif
1554
30
        bAlreadyTriedToCreate = true;
1555
30
    }
1556
220k
    return pSVData->mpUnoWrapper;
1557
220k
}
1558
1559
void UnoWrapperBase::SetUnoWrapper( UnoWrapperBase* pWrapper )
1560
0
{
1561
0
    ImplSVData* pSVData = ImplGetSVData();
1562
0
    SAL_WARN_IF( pSVData->mpUnoWrapper, "vcl", "SetUnoWrapper: Wrapper already exists" );
1563
0
    pSVData->mpUnoWrapper = pWrapper;
1564
0
}
1565
1566
void Application::SetFilterHdl( const Link<ConvertData&,bool>& rLink )
1567
0
{
1568
0
    ImplGetSVData()->maGDIData.mxGrfConverter->SetFilterHdl( rLink );
1569
0
}
1570
1571
const LocaleDataWrapper& Application::GetAppLocaleDataWrapper()
1572
0
{
1573
0
    return GetSettings().GetLocaleDataWrapper();
1574
0
}
1575
1576
void Application::EnableHeadlessMode( bool dialogsAreFatal )
1577
104
{
1578
104
    DialogCancelMode eNewMode = dialogsAreFatal ? DialogCancelMode::Fatal : DialogCancelMode::Silent;
1579
104
    DialogCancelMode eOldMode = GetDialogCancelMode();
1580
104
    assert(eOldMode == DialogCancelMode::Off || GetDialogCancelMode() == eNewMode);
1581
104
    if (eOldMode != eNewMode)
1582
104
        SetDialogCancelMode( eNewMode );
1583
104
}
1584
1585
bool Application::IsHeadlessModeEnabled()
1586
91.4k
{
1587
91.4k
    return IsDialogCancelEnabled() || comphelper::LibreOfficeKit::isActive();
1588
91.4k
}
1589
1590
void Application::EnableBitmapRendering()
1591
104
{
1592
104
    ImplGetSVData()->maAppData.mbRenderToBitmaps = true;
1593
104
}
1594
1595
bool Application::IsBitmapRendering()
1596
104
{
1597
104
    return ImplGetSVData()->maAppData.mbRenderToBitmaps;
1598
104
}
1599
1600
void Application::EnableConsoleOnly()
1601
0
{
1602
0
    EnableHeadlessMode(true);
1603
0
    EnableBitmapRendering();
1604
0
}
1605
1606
static bool bSafeMode = false;
1607
1608
bool Application::IsSafeModeEnabled()
1609
12.4k
{
1610
12.4k
    return bSafeMode;
1611
12.4k
}
1612
1613
void Application::EnableSafeMode()
1614
0
{
1615
0
    bSafeMode = true;
1616
0
}
1617
1618
void Application::ShowNativeErrorBox(const OUString& sTitle  ,
1619
                                     const OUString& sMessage)
1620
0
{
1621
0
    ImplHideSplash();
1622
0
    ImplGetSalSystem()->ShowNativeMessageBox(sTitle, sMessage);
1623
0
}
1624
1625
DesktopType Application::GetDesktopEnvironment()
1626
0
{
1627
0
    if (IsHeadlessModeEnabled())
1628
0
        return DesktopType::Headless;
1629
1630
0
    return SalGetDesktopEnvironment();
1631
0
}
1632
1633
void Application::AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService)
1634
0
{
1635
0
    GetSalInstance()->AddToRecentDocumentList(rFileUrl, rMimeType, rDocumentService);
1636
0
}
1637
1638
// MT: AppEvent was in oldsv.cxx, but is still needed...
1639
void Application::AppEvent( const ApplicationEvent& /*rAppEvent*/ )
1640
0
{
1641
0
}
1642
1643
bool Application::hasNativeColorChooserDialog()
1644
0
{
1645
0
    return GetSalInstance()->hasNativeColorChooserDialog();
1646
0
}
1647
1648
bool Application::hasNativeFileSelection()
1649
0
{
1650
0
    return GetSalInstance()->hasNativeFileSelection();
1651
0
}
1652
1653
Reference< ui::dialogs::XFilePicker2 >
1654
Application::createFilePicker( const Reference< uno::XComponentContext >& xSM )
1655
0
{
1656
0
    return GetSalInstance()->createFilePicker( xSM );
1657
0
}
1658
1659
Reference< ui::dialogs::XFolderPicker2 >
1660
Application::createFolderPicker( const Reference< uno::XComponentContext >& xSM )
1661
0
{
1662
0
    return GetSalInstance()->createFolderPicker(xSM);
1663
0
}
1664
1665
0
void Application::setDeInitHook(Link<LinkParamNone*,void> const & hook) {
1666
0
    ImplSVData * pSVData = ImplGetSVData();
1667
0
    assert(!pSVData->maDeInitHook.IsSet());
1668
0
    pSVData->maDeInitHook = hook;
1669
    // Fake this for VCLXToolkit ctor instantiated from
1670
    // postprocess/CppunitTest_services.mk:
1671
0
    pSVData->maAppData.mbInAppMain = true;
1672
0
}
1673
1674
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */