1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <boost/ptr_container/ptr_vector.hpp>
23 #include <comphelper/processfactory.hxx>
24 #include <comphelper/string.hxx>
25 #include <osl/mutex.hxx>
26 #include <rtl/process.h>
27 #include <tools/debug.hxx>
28 #include <tools/resary.hxx>
29 #include <tools/gen.hxx>
30 #include <unotools/fontcfg.hxx>
31 #include <cppuhelper/implbase1.hxx>
32 #include <uno/current_context.hxx>
34 #include "vcl/configsettings.hxx"
35 #include "vcl/svapp.hxx"
36 #include "vcl/wrkwin.hxx"
37 #include "vcl/msgbox.hxx"
38 #include "vcl/button.hxx"
39 #include "vcl/dockwin.hxx"
40 #include "salinst.hxx"
41 #include "salframe.hxx"
44 #include "salimestatus.hxx"
48 #include "com/sun/star/accessibility/AccessBridge.hpp"
49 #include "com/sun/star/accessibility/MSAAService.hpp"
50 #include "com/sun/star/awt/XExtendedToolkit.hpp"
51 #include "com/sun/star/java/JavaNotConfiguredException.hpp"
52 #include "com/sun/star/java/JavaVMCreationFailureException.hpp"
53 #include "com/sun/star/java/MissingJavaRuntimeException.hpp"
54 #include "com/sun/star/java/JavaDisabledException.hpp"
56 #include "officecfg/Office/Common.hxx"
60 using namespace com::sun::star::uno
;
61 using namespace com::sun::star::lang
;
62 using namespace com::sun::star::awt
;
64 // =======================================================================
68 struct private_aImplSVData
:
69 public rtl::Static
<ImplSVData
, private_aImplSVData
> {};
73 ImplSVData
* pImplSVData
= NULL
;
75 SalSystem
* ImplGetSalSystem()
77 ImplSVData
* pSVData
= ImplGetSVData();
78 if( ! pSVData
->mpSalSystem
)
79 pSVData
->mpSalSystem
= pSVData
->mpDefInst
->CreateSalSystem();
80 return pSVData
->mpSalSystem
;
84 static OUString
ReplaceJavaErrorMessages( const OUString
& rString
)
86 return rString
.replaceAll("%OK", Button::GetStandardText(BUTTON_OK
)).
87 replaceAll("%IGNORE", Button::GetStandardText(BUTTON_IGNORE
)).
88 replaceAll("%CANCEL", Button::GetStandardText(BUTTON_CANCEL
));
91 // =======================================================================
95 pImplSVData
= &private_aImplSVData::get();
97 // init global instance data
98 memset( pImplSVData
, 0, sizeof( ImplSVData
) );
99 pImplSVData
->maHelpData
.mbAutoHelpId
= sal_True
;
100 pImplSVData
->maNWFData
.maMenuBarHighlightTextColor
= Color( COL_TRANSPARENT
);
102 // mark default layout border as unitialized
103 pImplSVData
->maAppData
.mnDefaultLayoutBorder
= -1;
106 // -----------------------------------------------------------------------
108 void ImplDeInitSVData()
110 ImplSVData
* pSVData
= ImplGetSVData();
112 // delete global instance data
113 if( pSVData
->mpSettingsConfigItem
)
114 delete pSVData
->mpSettingsConfigItem
;
116 if( pSVData
->mpDockingManager
)
117 delete pSVData
->mpDockingManager
;
119 if( pSVData
->maGDIData
.mpDefaultFontConfiguration
)
120 delete pSVData
->maGDIData
.mpDefaultFontConfiguration
;
121 if( pSVData
->maGDIData
.mpFontSubstConfiguration
)
122 delete pSVData
->maGDIData
.mpFontSubstConfiguration
;
124 if( pSVData
->maCtrlData
.mpFieldUnitStrings
)
125 delete pSVData
->maCtrlData
.mpFieldUnitStrings
, pSVData
->maCtrlData
.mpFieldUnitStrings
= NULL
;
126 if( pSVData
->maCtrlData
.mpCleanUnitStrings
)
127 delete pSVData
->maCtrlData
.mpCleanUnitStrings
, pSVData
->maCtrlData
.mpCleanUnitStrings
= NULL
;
128 if( pSVData
->mpPaperNames
)
129 delete pSVData
->mpPaperNames
, pSVData
->mpPaperNames
= NULL
;
132 // -----------------------------------------------------------------------
134 void ImplDestroySVData()
139 // -----------------------------------------------------------------------
141 Window
* ImplGetDefaultWindow()
143 ImplSVData
* pSVData
= ImplGetSVData();
144 if ( pSVData
->maWinData
.mpAppWin
)
145 return pSVData
->maWinData
.mpAppWin
;
147 // First test if we already have a default window.
148 // Don't only place a single if..else inside solar mutex lockframe
149 // because then we might have to wait for the solar mutex what is not necessary
150 // if we already have a default window.
152 if ( !pSVData
->mpDefaultWin
)
154 Application::GetSolarMutex().acquire();
156 // Test again because the thread who released the solar mutex could have called
159 if ( !pSVData
->mpDefaultWin
&& !pSVData
->mbDeInit
)
161 DBG_WARNING( "ImplGetDefaultWindow(): No AppWindow" );
162 pSVData
->mpDefaultWin
= new WorkWindow( 0, WB_DEFAULTWIN
);
163 pSVData
->mpDefaultWin
->SetText( OUString( "VCL ImplGetDefaultWindow" ) );
165 Application::GetSolarMutex().release();
168 return pSVData
->mpDefaultWin
;
171 // -----------------------------------------------------------------------
173 ResMgr
* ImplGetResMgr()
175 ImplSVData
* pSVData
= ImplGetSVData();
176 if ( !pSVData
->mpResMgr
)
178 LanguageTag
aLocale( Application::GetSettings().GetUILanguageTag());
179 pSVData
->mpResMgr
= ResMgr::SearchCreateResMgr( "vcl", aLocale
);
181 static bool bMessageOnce
= false;
182 if( !pSVData
->mpResMgr
&& ! bMessageOnce
)
186 "Missing vcl resource. This indicates that files vital to localization are missing. "
187 "You might have a corrupt installation.";
188 fprintf( stderr
, "%s\n", pMsg
);
189 ErrorBox
aBox( NULL
, WB_OK
| WB_DEF_OK
, OUString( pMsg
, strlen( pMsg
), RTL_TEXTENCODING_ASCII_US
) );
193 return pSVData
->mpResMgr
;
196 ResId
VclResId( sal_Int32 nId
)
198 ResMgr
* pMgr
= ImplGetResMgr();
200 throw std::bad_alloc();
202 return ResId( nId
, *pMgr
);
205 FieldUnitStringList
* ImplGetFieldUnits()
207 ImplSVData
* pSVData
= ImplGetSVData();
208 if( ! pSVData
->maCtrlData
.mpFieldUnitStrings
)
210 ResMgr
* pResMgr
= ImplGetResMgr();
213 ResStringArray
aUnits( ResId (SV_FUNIT_STRINGS
, *pResMgr
) );
214 sal_uInt32 nUnits
= aUnits
.Count();
215 pSVData
->maCtrlData
.mpFieldUnitStrings
= new FieldUnitStringList();
216 pSVData
->maCtrlData
.mpFieldUnitStrings
->reserve( nUnits
);
217 for( sal_uInt32 i
= 0; i
< nUnits
; i
++ )
219 std::pair
< OUString
, FieldUnit
> aElement( aUnits
.GetString(i
), static_cast<FieldUnit
>(aUnits
.GetValue(i
)) );
220 pSVData
->maCtrlData
.mpFieldUnitStrings
->push_back( aElement
);
224 return pSVData
->maCtrlData
.mpFieldUnitStrings
;
227 FieldUnitStringList
* ImplGetCleanedFieldUnits()
229 ImplSVData
* pSVData
= ImplGetSVData();
230 if( ! pSVData
->maCtrlData
.mpCleanUnitStrings
)
232 FieldUnitStringList
* pUnits
= ImplGetFieldUnits();
235 size_t nUnits
= pUnits
->size();
236 pSVData
->maCtrlData
.mpCleanUnitStrings
= new FieldUnitStringList();
237 pSVData
->maCtrlData
.mpCleanUnitStrings
->reserve( nUnits
);
238 for( size_t i
= 0; i
< nUnits
; ++i
)
240 OUString
aUnit( (*pUnits
)[i
].first
);
241 aUnit
= comphelper::string::remove(aUnit
, ' ');
242 aUnit
= aUnit
.toAsciiLowerCase();
243 std::pair
< OUString
, FieldUnit
> aElement( aUnit
, (*pUnits
)[i
].second
);
244 pSVData
->maCtrlData
.mpCleanUnitStrings
->push_back( aElement
);
248 return pSVData
->maCtrlData
.mpCleanUnitStrings
;
251 DockingManager
* ImplGetDockingManager()
253 ImplSVData
* pSVData
= ImplGetSVData();
254 if ( !pSVData
->mpDockingManager
)
255 pSVData
->mpDockingManager
= new DockingManager();
257 return pSVData
->mpDockingManager
;
260 BlendFrameCache
* ImplGetBlendFrameCache()
262 ImplSVData
* pSVData
= ImplGetSVData();
263 if ( !pSVData
->mpBlendFrameCache
)
264 pSVData
->mpBlendFrameCache
= new BlendFrameCache();
266 return pSVData
->mpBlendFrameCache
;
269 class AccessBridgeCurrentContext
: public cppu::WeakImplHelper1
< com::sun::star::uno::XCurrentContext
>
272 AccessBridgeCurrentContext(
273 const com::sun::star::uno::Reference
< com::sun::star::uno::XCurrentContext
> &context
) :
274 m_prevContext( context
) {}
277 virtual com::sun::star::uno::Any SAL_CALL
getValueByName( const OUString
& Name
)
278 throw (com::sun::star::uno::RuntimeException
);
280 com::sun::star::uno::Reference
< com::sun::star::uno::XCurrentContext
> m_prevContext
;
283 com::sun::star::uno::Any
AccessBridgeCurrentContext::getValueByName( const OUString
& Name
)
284 throw (com::sun::star::uno::RuntimeException
)
286 com::sun::star::uno::Any ret
;
287 if ( Name
== "java-vm.interaction-handler" )
289 // Currently, for accessbility no interaction handler shall be offered.
290 // There may be introduced later on a handler using native toolkits
291 // jbu->obr: Instantiate here your interaction handler
293 else if( m_prevContext
.is() )
295 ret
= m_prevContext
->getValueByName( Name
);
304 bool ImplInitAccessBridge(bool bAllowCancel
, bool &rCancelled
)
308 bool bErrorMessage
= true;
311 // if bAllowCancel is sal_True we were called from application startup
312 // where we will disable any Java errorboxes and show our own accessibility dialog if Java throws an exception
313 // if bAllowCancel is sal_False we were called from Tools->Options
314 // where we will see Java errorboxes, se we do not show our dialogs in addition to Java's
318 // No error messages when env var is set ..
319 static const char* pEnv
= getenv("SAL_ACCESSIBILITY_ENABLED" );
322 bErrorMessage
= false;
325 ImplSVData
* pSVData
= ImplGetSVData();
326 if( ! pSVData
->mxAccessBridge
.is() )
328 css::uno::Reference
< XComponentContext
> xContext(comphelper::getProcessComponentContext());
331 bool bTryIAcc2
= ( officecfg::Office::Common::Misc::ExperimentalMode::get( xContext
) &&
332 !getenv ("SAL_DISABLE_IACCESSIBLE2") );
334 if ( bTryIAcc2
) // Windows only really
336 if (!HasAtHook() && !getenv("SAL_FORCE_IACCESSIBLE2"))
338 SAL_INFO("vcl", "Apparently no running AT -> "
339 "not enabling IAccessible2 integration");
344 pSVData
->mxAccessBridge
345 = css::accessibility::MSAAService::create(xContext
);
346 SAL_INFO("vcl", "got IAccessible2 bridge");
348 } catch (css::uno::DeploymentException
& e
) {
351 "got no IAccessible2 bridge, \"" << e
.Message
352 << "\", falling back to java");
357 SAL_INFO( "vcl", "IAccessible2 disabled, falling back to java" );
360 css::uno::Reference
< XExtendedToolkit
> xToolkit
=
361 css::uno::Reference
< XExtendedToolkit
>(Application::GetVCLToolkit(), UNO_QUERY
);
363 // Disable default java error messages on startup, because they were probably unreadable
364 // for a disabled user. Use native message boxes which are accessible without java support.
365 // No need to do this when activated by Tools-Options dialog ..
368 // customize the java-not-available-interaction-handler entry within the
369 // current context when called at startup.
370 com::sun::star::uno::ContextLayer
layer(
371 new AccessBridgeCurrentContext( com::sun::star::uno::getCurrentContext() ) );
373 pSVData
->mxAccessBridge
374 = css::accessibility::AccessBridge::createWithToolkit(
379 pSVData
->mxAccessBridge
380 = css::accessibility::AccessBridge::createWithToolkit(
387 catch (const ::com::sun::star::java::JavaNotConfiguredException
&)
389 ResMgr
*pResMgr
= ImplGetResMgr();
390 if( bErrorMessage
&& bAllowCancel
&& pResMgr
)
392 OUString
aTitle(ResId(SV_ACCESSERROR_JAVA_NOT_CONFIGURED
, *pResMgr
).toString());
393 OUStringBuffer
aMessage((ResId(SV_ACCESSERROR_JAVA_MSG
, *pResMgr
)).toString());
395 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
397 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
399 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
400 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
401 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
403 // Do not change the setting in case the user chooses to cancel
404 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
410 catch (const ::com::sun::star::java::JavaVMCreationFailureException
&)
412 ResMgr
*pResMgr
= ImplGetResMgr();
413 if( bErrorMessage
&& bAllowCancel
&& pResMgr
)
415 OUString
aTitle(ResId(SV_ACCESSERROR_FAULTY_JAVA
, *pResMgr
).toString());
416 OUStringBuffer
aMessage(ResId(SV_ACCESSERROR_JAVA_MSG
, *pResMgr
).toString());
418 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
420 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
422 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
423 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
424 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
426 // Do not change the setting in case the user chooses to cancel
427 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
433 catch (const ::com::sun::star::java::MissingJavaRuntimeException
&)
435 ResMgr
*pResMgr
= ImplGetResMgr();
436 if( bErrorMessage
&& bAllowCancel
&& pResMgr
)
438 OUString
aTitle(ResId(SV_ACCESSERROR_MISSING_JAVA
, *pResMgr
).toString());
439 OUStringBuffer
aMessage(ResId(SV_ACCESSERROR_JAVA_MSG
, *pResMgr
).toString());
441 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
443 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
445 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
446 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
447 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
449 // Do not change the setting in case the user chooses to cancel
450 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
456 catch (const ::com::sun::star::java::JavaDisabledException
&)
458 ResMgr
*pResMgr
= ImplGetResMgr();
459 if( bErrorMessage
&& bAllowCancel
&& pResMgr
)
461 OUString
aTitle(ResId(SV_ACCESSERROR_JAVA_DISABLED
, *pResMgr
).toString());
462 OUStringBuffer
aMessage(ResId(SV_ACCESSERROR_JAVA_MSG
, *pResMgr
).toString());
464 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
466 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
468 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
469 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
470 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
472 // Do not change the setting in case the user chooses to cancel
473 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
479 catch (const ::com::sun::star::uno::RuntimeException
& e
)
481 ResMgr
*pResMgr
= ImplGetResMgr();
482 if( bErrorMessage
&& pResMgr
)
485 OUStringBuffer
aMessage(ResId(SV_ACCESSERROR_BRIDGE_MSG
, *pResMgr
).toString());
487 if( e
.Message
.startsWith("ClassNotFound") )
489 aTitle
= ResId(SV_ACCESSERROR_MISSING_BRIDGE
, *pResMgr
).toString();
491 else if( e
.Message
.startsWith("NoSuchMethod") )
493 aTitle
= ResId(SV_ACCESSERROR_WRONG_VERSION
, *pResMgr
).toString();
496 if (!aTitle
.isEmpty())
500 // Something went wrong initializing the Java AccessBridge (on Windows) during the
501 // startup. Since the office will be probably unusable for a disabled user, we offer
502 // to terminate directly.
503 aMessage
.append(' ').append(ResId(SV_ACCESSERROR_OK_CANCEL_MSG
, *pResMgr
).toString());
505 int ret
= ImplGetSalSystem()->ShowNativeMessageBox(
507 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
508 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK_CANCEL
,
509 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
, true);
511 // Do not change the setting in case the user chooses to cancel
512 if( SALSYSTEM_SHOWNATIVEMSGBOX_BTN_CANCEL
== ret
)
513 rCancelled
= sal_True
;
517 // The user tried to activate accessibility support using Tools-Options dialog,
518 // so we don't offer to terminate here !
519 ImplGetSalSystem()->ShowNativeMessageBox(
521 ReplaceJavaErrorMessages(aMessage
.makeStringAndClear()),
522 SALSYSTEM_SHOWNATIVEMSGBOX_BTNCOMBI_OK
,
523 SALSYSTEM_SHOWNATIVEMSGBOX_BTN_OK
, true);
536 // -----------------------------------------------------------------------
538 Window
* ImplFindWindow( const SalFrame
* pFrame
, ::Point
& rSalFramePos
)
540 ImplSVData
* pSVData
= ImplGetSVData();
541 Window
* pFrameWindow
= pSVData
->maWinData
.mpFirstFrame
;
542 while ( pFrameWindow
)
544 if ( pFrameWindow
->ImplGetFrame() == pFrame
)
546 Window
* pWindow
= pFrameWindow
->ImplFindWindow( rSalFramePos
);
548 pWindow
= pFrameWindow
->ImplGetWindow();
549 rSalFramePos
= pWindow
->ImplFrameToOutput( rSalFramePos
);
552 pFrameWindow
= pFrameWindow
->ImplGetFrameData()->mpNextFrame
;
558 void LocaleConfigurationListener::ConfigurationChanged( utl::ConfigurationBroadcaster
*, sal_uInt32 nHint
)
560 AllSettings::LocaleSettingsChanged( nHint
);
563 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */