/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: */ |