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 <string.h>
21
22 #include <comphelper/lok.hxx>
23 #include <comphelper/processfactory.hxx>
24 #include <tools/diagnose_ex.h>
25 #include <unotools/resmgr.hxx>
26 #include <sal/log.hxx>
27
28 #include <configsettings.hxx>
29 #include <vcl/QueueInfo.hxx>
30 #include <vcl/cvtgrf.hxx>
31 #include <vcl/dockwin.hxx>
32 #include <vcl/fieldvalues.hxx>
33 #include <vcl/menu.hxx>
34 #include <vcl/print.hxx>
35 #include <vcl/settings.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/virdev.hxx>
38 #include <vcl/wrkwin.hxx>
39 #include <vcl/uitest/logger.hxx>
40 #include <salframe.hxx>
41 #include <scrwnd.hxx>
42 #include <helpwin.hxx>
43 #include <vcl/toolkit/dialog.hxx>
44 #include <salinst.hxx>
45 #include <salgdi.hxx>
46 #include <svdata.hxx>
47 #include <salsys.hxx>
48 #include <windowdev.hxx>
49 #include <units.hrc>
50 #include <print.h>
51
52 #include <com/sun/star/accessibility/MSAAService.hpp>
53
54 #include <config_features.h>
55 #include <basegfx/utils/systemdependentdata.hxx>
56 #include <cppuhelper/basemutex.hxx>
57
58 using namespace com::sun::star::uno;
59 using namespace com::sun::star::lang;
60 using namespace com::sun::star::awt;
61
62 namespace
63 {
64 struct private_aImplSVData :
65 public rtl::Static<ImplSVData, private_aImplSVData> {};
66 /// Default instance ensures that ImplSVData::mpHelpData is never null.
67 struct private_aImplSVHelpData :
68 public rtl::Static<ImplSVHelpData, private_aImplSVHelpData> {};
69
70 /// Default instance ensures that ImplSVData::mpWinData is never null.
71 struct private_aImplSVWinData :
72 public rtl::Static<ImplSVWinData, private_aImplSVWinData> {};
73
74 }
75
ImplGetSVData()76 ImplSVData* ImplGetSVData() {
77 return &private_aImplSVData::get();
78 }
79
ImplGetSalSystem()80 SalSystem* ImplGetSalSystem()
81 {
82 ImplSVData* pSVData = ImplGetSVData();
83 if( ! pSVData->mpSalSystem )
84 pSVData->mpSalSystem.reset( pSVData->mpDefInst->CreateSalSystem() );
85 return pSVData->mpSalSystem.get();
86 }
87
ImplDeInitSVData()88 void ImplDeInitSVData()
89 {
90 ImplSVData* pSVData = ImplGetSVData();
91
92 // delete global instance data
93 pSVData->mpSettingsConfigItem.reset();
94
95 pSVData->mpDockingManager.reset();
96
97 pSVData->maCtrlData.maFieldUnitStrings.clear();
98 pSVData->maCtrlData.maCleanUnitStrings.clear();
99 pSVData->maPaperNames.clear();
100 }
101
102 namespace
103 {
104 typedef ::std::map< basegfx::SystemDependentData_SharedPtr, sal_uInt32 > EntryMap;
105
106 class SystemDependentDataBuffer final : public basegfx::SystemDependentDataManager, protected cppu::BaseMutex
107 {
108 private:
109 std::unique_ptr<AutoTimer> maTimer;
110 EntryMap maEntries;
111
112 DECL_LINK(implTimeoutHdl, Timer *, void);
113
114 public:
SystemDependentDataBuffer(const char * pDebugName)115 SystemDependentDataBuffer(const char* pDebugName)
116 : basegfx::SystemDependentDataManager(),
117 maTimer(std::make_unique<AutoTimer>(pDebugName))
118 {
119 maTimer->SetTimeout(1000);
120 maTimer->SetInvokeHandler(LINK(this, SystemDependentDataBuffer, implTimeoutHdl));
121 }
122
~SystemDependentDataBuffer()123 virtual ~SystemDependentDataBuffer() override
124 {
125 flushAll();
126 }
127
startUsage(basegfx::SystemDependentData_SharedPtr & rData)128 void startUsage(basegfx::SystemDependentData_SharedPtr& rData) override
129 {
130 ::osl::MutexGuard aGuard(m_aMutex);
131 EntryMap::iterator aFound(maEntries.find(rData));
132
133 if(aFound == maEntries.end())
134 {
135 if(maTimer && !maTimer->IsActive())
136 {
137 maTimer->Start();
138 }
139
140 maEntries[rData] = rData->calculateCombinedHoldCyclesInSeconds();
141 }
142 }
143
endUsage(basegfx::SystemDependentData_SharedPtr & rData)144 void endUsage(basegfx::SystemDependentData_SharedPtr& rData) override
145 {
146 ::osl::MutexGuard aGuard(m_aMutex);
147 EntryMap::iterator aFound(maEntries.find(rData));
148
149 if(aFound != maEntries.end())
150 {
151 maEntries.erase(aFound);
152 }
153 }
154
touchUsage(basegfx::SystemDependentData_SharedPtr & rData)155 void touchUsage(basegfx::SystemDependentData_SharedPtr& rData) override
156 {
157 ::osl::MutexGuard aGuard(m_aMutex);
158 EntryMap::iterator aFound(maEntries.find(rData));
159
160 if(aFound != maEntries.end())
161 {
162 aFound->second = rData->calculateCombinedHoldCyclesInSeconds();
163 }
164 }
165
flushAll()166 void flushAll() override
167 {
168 ::osl::MutexGuard aGuard(m_aMutex);
169
170 if(maTimer)
171 {
172 maTimer->Stop();
173 maTimer.reset();
174 }
175
176 maEntries.clear();
177 }
178 };
179
IMPL_LINK_NOARG(SystemDependentDataBuffer,implTimeoutHdl,Timer *,void)180 IMPL_LINK_NOARG(SystemDependentDataBuffer, implTimeoutHdl, Timer *, void)
181 {
182 ::osl::MutexGuard aGuard(m_aMutex);
183 EntryMap::iterator aIter(maEntries.begin());
184
185 while(aIter != maEntries.end())
186 {
187 if(aIter->second)
188 {
189 aIter->second--;
190 ++aIter;
191 }
192 else
193 {
194 aIter = maEntries.erase(aIter);
195 }
196 }
197
198 if (maEntries.empty())
199 maTimer->Stop();
200 }
201 }
202
ImplGetSystemDependentDataManager()203 basegfx::SystemDependentDataManager& ImplGetSystemDependentDataManager()
204 {
205 static SystemDependentDataBuffer aSystemDependentDataBuffer("vcl SystemDependentDataBuffer aSystemDependentDataBuffer");
206
207 return aSystemDependentDataBuffer;
208 }
209
210 /// Returns either the application window, or the default GL context window
ImplGetDefaultWindow()211 vcl::Window* ImplGetDefaultWindow()
212 {
213 ImplSVData* pSVData = ImplGetSVData();
214 if (pSVData->maFrameData.mpAppWin)
215 return pSVData->maFrameData.mpAppWin;
216 else
217 return ImplGetDefaultContextWindow();
218 }
219
220 /// returns the default window created to hold the persistent VCL GL context.
ImplGetDefaultContextWindow()221 vcl::Window *ImplGetDefaultContextWindow()
222 {
223 ImplSVData* pSVData = ImplGetSVData();
224
225 // Double check locking on mpDefaultWin.
226 if ( !pSVData->mpDefaultWin )
227 {
228 SolarMutexGuard aGuard;
229
230 if (!pSVData->mpDefaultWin && !pSVData->mbDeInit)
231 {
232 try
233 {
234 SAL_INFO( "vcl", "ImplGetDefaultWindow(): No AppWindow" );
235
236 pSVData->mpDefaultWin = VclPtr<WorkWindow>::Create(nullptr, WB_DEFAULTWIN);
237 pSVData->mpDefaultWin->SetText( "VCL ImplGetDefaultWindow" );
238 }
239 catch (const css::uno::Exception&)
240 {
241 TOOLS_WARN_EXCEPTION("vcl", "unable to create Default Window");
242 }
243 }
244 }
245
246 return pSVData->mpDefaultWin;
247 }
248
ImplGetResLocale()249 const std::locale& ImplGetResLocale()
250 {
251 ImplSVData* pSVData = ImplGetSVData();
252 if (!pSVData->mbResLocaleSet || comphelper::LibreOfficeKit::isActive())
253 {
254 pSVData->maResLocale = Translate::Create("vcl");
255 pSVData->mbResLocaleSet = true;
256 }
257 return pSVData->maResLocale;
258 }
259
VclResId(const char * pId)260 OUString VclResId(const char* pId)
261 {
262 return Translate::get(pId, ImplGetResLocale());
263 }
264
ImplGetFieldUnits()265 const FieldUnitStringList& ImplGetFieldUnits()
266 {
267 ImplSVData* pSVData = ImplGetSVData();
268 if( pSVData->maCtrlData.maFieldUnitStrings.empty() )
269 {
270 sal_uInt32 nUnits = SAL_N_ELEMENTS(SV_FUNIT_STRINGS);
271 pSVData->maCtrlData.maFieldUnitStrings.reserve( nUnits );
272 for (sal_uInt32 i = 0; i < nUnits; i++)
273 {
274 std::pair<OUString, FieldUnit> aElement(VclResId(SV_FUNIT_STRINGS[i].first), SV_FUNIT_STRINGS[i].second);
275 pSVData->maCtrlData.maFieldUnitStrings.push_back( aElement );
276 }
277 }
278 return pSVData->maCtrlData.maFieldUnitStrings;
279 }
280
281 namespace vcl
282 {
EnglishStringToMetric(const OUString & rEnglishMetricString)283 FieldUnit EnglishStringToMetric(const OUString& rEnglishMetricString)
284 {
285 sal_uInt32 nUnits = SAL_N_ELEMENTS(SV_FUNIT_STRINGS);
286 for (sal_uInt32 i = 0; i < nUnits; ++i)
287 {
288 const char *pId = strchr(SV_FUNIT_STRINGS[i].first, '\004');
289 assert(pId);
290 if (rEnglishMetricString.equalsAscii(pId+1))
291 return SV_FUNIT_STRINGS[i].second;
292 }
293 return FieldUnit::NONE;
294 }
295 }
296
ImplGetCleanedFieldUnits()297 const FieldUnitStringList& ImplGetCleanedFieldUnits()
298 {
299 ImplSVData* pSVData = ImplGetSVData();
300 if( pSVData->maCtrlData.maCleanUnitStrings.empty() )
301 {
302 const FieldUnitStringList& rUnits = ImplGetFieldUnits();
303 size_t nUnits = rUnits.size();
304 pSVData->maCtrlData.maCleanUnitStrings.reserve(nUnits);
305 for (size_t i = 0; i < nUnits; ++i)
306 {
307 OUString aUnit(rUnits[i].first);
308 aUnit = aUnit.replaceAll(" ", "");
309 aUnit = aUnit.toAsciiLowerCase();
310 std::pair<OUString, FieldUnit> aElement(aUnit, rUnits[i].second);
311 pSVData->maCtrlData.maCleanUnitStrings.push_back(aElement);
312 }
313 }
314 return pSVData->maCtrlData.maCleanUnitStrings;
315 }
316
ImplGetDockingManager()317 DockingManager* ImplGetDockingManager()
318 {
319 ImplSVData* pSVData = ImplGetSVData();
320 if ( !pSVData->mpDockingManager )
321 pSVData->mpDockingManager.reset(new DockingManager());
322
323 return pSVData->mpDockingManager.get();
324 }
325
ImplGetBlendFrameCache()326 BlendFrameCache* ImplGetBlendFrameCache()
327 {
328 ImplSVData* pSVData = ImplGetSVData();
329 if ( !pSVData->mpBlendFrameCache)
330 pSVData->mpBlendFrameCache.reset( new BlendFrameCache() );
331
332 return pSVData->mpBlendFrameCache.get();
333 }
334
335 #ifdef _WIN32
ImplInitAccessBridge()336 bool ImplInitAccessBridge()
337 {
338 ImplSVData* pSVData = ImplGetSVData();
339 if( ! pSVData->mxAccessBridge.is() )
340 {
341 css::uno::Reference< XComponentContext > xContext(comphelper::getProcessComponentContext());
342
343 if (!HasAtHook() && !getenv("SAL_FORCE_IACCESSIBLE2"))
344 {
345 SAL_INFO("vcl", "Apparently no running AT -> "
346 "not enabling IAccessible2 integration");
347 }
348 else
349 {
350 try {
351 pSVData->mxAccessBridge
352 = css::accessibility::MSAAService::create(xContext);
353 SAL_INFO("vcl", "got IAccessible2 bridge");
354 return true;
355 } catch (css::uno::DeploymentException &) {
356 TOOLS_WARN_EXCEPTION(
357 "vcl",
358 "got no IAccessible2 bridge");
359 return false;
360 }
361 }
362 }
363
364 return true;
365 }
366 #endif
367
ConfigurationChanged(utl::ConfigurationBroadcaster *,ConfigurationHints nHint)368 void LocaleConfigurationListener::ConfigurationChanged( utl::ConfigurationBroadcaster*, ConfigurationHints nHint )
369 {
370 AllSettings::LocaleSettingsChanged( nHint );
371 }
372
CreateSVWinData()373 ImplSVWinData* CreateSVWinData()
374 {
375 if (!comphelper::LibreOfficeKit::isActive())
376 return nullptr;
377
378 ImplSVWinData* p = new ImplSVWinData;
379
380 ImplSVData* pSVData = ImplGetSVData();
381 assert(pSVData && pSVData->mpWinData);
382
383 p->mpFocusWin = pSVData->mpWinData->mpFocusWin;
384 return p;
385 }
386
DestroySVWinData(ImplSVWinData * pData)387 void DestroySVWinData(ImplSVWinData* pData)
388 {
389 delete pData;
390 }
391
SetSVWinData(ImplSVWinData * pSVWinData)392 void SetSVWinData(ImplSVWinData* pSVWinData)
393 {
394 if (!comphelper::LibreOfficeKit::isActive())
395 return;
396
397 ImplSVData* pSVData = ImplGetSVData();
398 assert(pSVData != nullptr);
399
400 if (pSVData->mpWinData == pSVWinData)
401 return;
402
403 // If current one is the static, clean it up to avoid having lingering references.
404 if (pSVData->mpWinData == &private_aImplSVWinData::get())
405 {
406 pSVData->mpWinData->mpFocusWin.reset();
407 }
408
409 pSVData->mpWinData = pSVWinData;
410 if (pSVData->mpWinData == nullptr)
411 {
412 pSVData->mpWinData = &private_aImplSVWinData::get(); // Never leave it null.
413 }
414 }
415
ImplSVData()416 ImplSVData::ImplSVData()
417 {
418 mpHelpData = &private_aImplSVHelpData::get();
419 mpWinData = &private_aImplSVWinData::get();
420 }
421
CreateSVHelpData()422 ImplSVHelpData* CreateSVHelpData()
423 {
424 if (!comphelper::LibreOfficeKit::isActive())
425 return nullptr;
426
427 ImplSVHelpData* pNewData = new ImplSVHelpData;
428
429 // Set options set globally
430 ImplSVHelpData& aStaticHelpData = private_aImplSVHelpData::get();
431 pNewData->mbContextHelp = aStaticHelpData.mbContextHelp;
432 pNewData->mbExtHelp = aStaticHelpData.mbExtHelp;
433 pNewData->mbExtHelpMode = aStaticHelpData.mbExtHelpMode;
434 pNewData->mbOldBalloonMode = aStaticHelpData.mbOldBalloonMode;
435 pNewData->mbBalloonHelp = aStaticHelpData.mbBalloonHelp;
436 pNewData->mbQuickHelp = aStaticHelpData.mbQuickHelp;
437
438 return pNewData;
439 }
440
DestroySVHelpData(ImplSVHelpData * pSVHelpData)441 void DestroySVHelpData(ImplSVHelpData* pSVHelpData)
442 {
443 if (!comphelper::LibreOfficeKit::isActive())
444 return;
445
446 // Change the SVData's help date if necessary
447 if(ImplGetSVData()->mpHelpData == pSVHelpData)
448 {
449 ImplGetSVData()->mpHelpData = &private_aImplSVHelpData::get();
450 }
451
452 if(pSVHelpData)
453 {
454 ImplDestroyHelpWindow(*pSVHelpData, false);
455 delete pSVHelpData;
456 }
457 }
458
SetSVHelpData(ImplSVHelpData * pSVHelpData)459 void SetSVHelpData(ImplSVHelpData* pSVHelpData)
460 {
461 if (!comphelper::LibreOfficeKit::isActive())
462 return;
463
464 ImplSVData* pSVData = ImplGetSVData();
465 if (pSVData->mpHelpData == pSVHelpData)
466 return;
467
468 // If current one is the static, clean it up to avoid having lingering references.
469 if (pSVData->mpHelpData == &private_aImplSVHelpData::get())
470 {
471 pSVData->mpHelpData->mpHelpWin.reset();
472 }
473
474 pSVData->mpHelpData = pSVHelpData;
475 if (pSVData->mpHelpData == nullptr)
476 {
477 pSVData->mpHelpData = &private_aImplSVHelpData::get(); // Never leave it null.
478 }
479 }
480
ImplGetSVHelpData()481 ImplSVHelpData& ImplGetSVHelpData()
482 {
483 ImplSVData* pSVData = ImplGetSVData();
484 if(pSVData->mpHelpData)
485 {
486 return *pSVData->mpHelpData;
487 }
488 else
489 {
490 return private_aImplSVHelpData::get();
491 }
492 }
493
~ImplSVData()494 ImplSVData::~ImplSVData() {}
~ImplSVAppData()495 ImplSVAppData::~ImplSVAppData() {}
~ImplSVGDIData()496 ImplSVGDIData::~ImplSVGDIData() {}
~ImplSVFrameData()497 ImplSVFrameData::~ImplSVFrameData() {}
~ImplSVWinData()498 ImplSVWinData::~ImplSVWinData() {}
~ImplSVHelpData()499 ImplSVHelpData::~ImplSVHelpData() {}
500
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
502