merge the formfield patch from ooo-build
[ooovba.git] / accessibility / bridge / source / java / WindowsAccessBridgeAdapter.cxx
blob0816a3a2a2db23685ac6724a7f1c5c72903a61eb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: WindowsAccessBridgeAdapter.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_accessibility.hxx"
34 //------------------------------------------------------------------------
35 // includes
36 //------------------------------------------------------------------------
38 #include <WindowsAccessBridgeAdapter.h>
40 #include <tools/prewin.h>
41 #include <wtypes.h>
42 #include <tools/postwin.h>
43 #include <rtl/process.h>
44 #include <tools/link.hxx>
46 #ifndef _SVAPP_HXX
47 #include <vcl/svapp.hxx>
48 #endif
49 #include <vcl/window.hxx>
50 #include <vcl/sysdata.hxx>
51 #include <uno/current_context.hxx>
52 #include <uno/environment.h>
53 #include <uno/mapping.hxx>
54 #include <com/sun/star/accessibility/AccessibleRole.hpp>
55 #include <com/sun/star/accessibility/XAccessible.hpp>
57 #ifndef _JVMACCESS_UNOVIRTUALMACHINE_HXX_
58 #include "jvmaccess/unovirtualmachine.hxx"
59 #endif
61 #ifndef _JVMACCESS_VIRTUALMACHINE_HXX_
62 #include "jvmaccess/virtualmachine.hxx"
63 #endif
65 #include <osl/diagnose.h>
67 using ::rtl::OUString;
68 using ::com::sun::star::uno::Mapping;
69 using ::com::sun::star::uno::Reference;
70 using ::com::sun::star::uno::RuntimeException;
71 using namespace ::com::sun::star::accessibility;
73 long VCLEventListenerLinkFunc(void * pInst, void * pData);
75 //------------------------------------------------------------------------
76 // global vatiables
77 //------------------------------------------------------------------------
79 Link g_aEventListenerLink(NULL, VCLEventListenerLinkFunc);
81 rtl::Reference< jvmaccess::UnoVirtualMachine > g_xUnoVirtualMachine;
82 typelib_InterfaceTypeDescription * g_pTypeDescription = NULL;
83 Mapping g_unoMapping;
85 jclass g_jcWindowsAccessBridgeAdapter = NULL;
86 jmethodID g_jmRegisterTopWindow = 0;
87 jmethodID g_jmRevokeTopWindow = 0;
89 //------------------------------------------------------------------------
90 // functions
91 //------------------------------------------------------------------------
93 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *, void *)
95 return JNI_VERSION_1_2;
98 JNIEXPORT jbyteArray JNICALL
99 Java_org_openoffice_accessibility_WindowsAccessBridgeAdapter_getProcessID(JNIEnv *pJNIEnv, jclass clazz)
101 // Initialize global class and method references
102 g_jcWindowsAccessBridgeAdapter =
103 static_cast< jclass > (pJNIEnv->NewGlobalRef(clazz));
104 if (NULL == g_jcWindowsAccessBridgeAdapter) {
105 return 0; /* jni error occured */
107 g_jmRegisterTopWindow =
108 pJNIEnv->GetStaticMethodID(clazz, "registerTopWindow", "(ILcom/sun/star/accessibility/XAccessible;)V");
109 if (0 == g_jmRegisterTopWindow) {
110 return 0; /* jni error occured */
112 g_jmRevokeTopWindow =
113 pJNIEnv->GetStaticMethodID(clazz, "revokeTopWindow", "(ILcom/sun/star/accessibility/XAccessible;)V");
114 if (0 == g_jmRevokeTopWindow) {
115 return 0; /* jni error occured */
118 // Use the special protocol of XJavaVM.getJavaVM: If the passed in
119 // process ID has an extra 17th byte of value one, the returned any
120 // contains a pointer to a jvmaccess::UnoVirtualMachine, instead of
121 // the underlying JavaVM pointer:
122 jbyte processID[17];
123 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8 *> (processID));
124 // #i51265# we need a jvmaccess::UnoVirtualMachine pointer for the
125 // uno_getEnvironment() call later.
126 processID[16] = 1;
128 // Copy the result into a java byte[] and return.
129 jbyteArray jbaProcessID = pJNIEnv->NewByteArray(17);
130 pJNIEnv->SetByteArrayRegion(jbaProcessID, 0, 17, processID);
131 return jbaProcessID;
134 JNIEXPORT jboolean JNICALL
135 Java_org_openoffice_accessibility_WindowsAccessBridgeAdapter_createMapping(JNIEnv *, jclass, jlong pointer)
137 uno_Environment * pJava_environment = NULL;
138 uno_Environment * pUno_environment = NULL;
140 try {
141 // We get a non-refcounted pointer to a jvmaccess::VirtualMachine
142 // from the XJavaVM service (the pointer is guaranteed to be valid
143 // as long as our reference to the XJavaVM service lasts), and
144 // convert the non-refcounted pointer into a refcounted one
145 // immediately:
146 g_xUnoVirtualMachine = reinterpret_cast< jvmaccess::UnoVirtualMachine * >(pointer);
148 if ( g_xUnoVirtualMachine.is() )
150 OUString sJava(RTL_CONSTASCII_USTRINGPARAM("java"));
151 uno_getEnvironment(&pJava_environment, sJava.pData, g_xUnoVirtualMachine.get());
153 OUString sCppu_current_lb_name(RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME));
154 uno_getEnvironment(&pUno_environment, sCppu_current_lb_name.pData, NULL);
156 if ( pJava_environment && pUno_environment )
158 g_unoMapping = Mapping(pUno_environment, pJava_environment);
159 getCppuType((::com::sun::star::uno::Reference< XAccessible > *) 0).getDescription((typelib_TypeDescription **) & g_pTypeDescription);
162 if ( pJava_environment )
164 // release java environment
165 pJava_environment->release(pJava_environment);
166 pJava_environment = NULL;
169 if ( pUno_environment )
171 // release uno environment
172 pUno_environment->release(pUno_environment);
173 pUno_environment = NULL;
178 catch ( RuntimeException e)
180 OSL_TRACE("RuntimeException caught while initializing the mapping");
183 if ( (0 != g_jmRegisterTopWindow) && (0 != g_jmRevokeTopWindow) )
185 ::Application::AddEventListener(g_aEventListenerLink);
187 return JNI_TRUE;
190 JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *)
192 ::Application::RemoveEventListener(g_aEventListenerLink);
194 if ( NULL != g_jcWindowsAccessBridgeAdapter )
196 JNIEnv * pJNIEnv;
197 if ( ! jvm->GetEnv((void **) &pJNIEnv, JNI_VERSION_1_2) )
199 pJNIEnv->DeleteGlobalRef(g_jcWindowsAccessBridgeAdapter);
200 g_jcWindowsAccessBridgeAdapter = NULL;
204 if ( NULL != g_pTypeDescription )
206 typelib_typedescription_release( reinterpret_cast< typelib_TypeDescription * > (g_pTypeDescription) );
207 g_pTypeDescription = NULL;
210 g_unoMapping.clear();
211 g_xUnoVirtualMachine.clear();
214 HWND GetHWND(Window * pWindow)
216 const SystemEnvData * pEnvData = pWindow->GetSystemData();
217 if (pEnvData != NULL)
219 return pEnvData->hWnd;
221 return (HWND) -1;
224 void handleWindowEvent(Window * pWindow, bool bShow)
226 if ( pWindow && pWindow->IsTopWindow() )
228 ::com::sun::star::uno::Reference< XAccessible > xAccessible;
230 // Test for combo box - drop down floating windows first
231 Window * pParentWindow = pWindow->GetParent();
233 if ( pParentWindow )
235 try
237 // The parent window of a combo box floating window should have the role COMBO_BOX
238 ::com::sun::star::uno::Reference< XAccessible > xParentAccessible(pParentWindow->GetAccessible());
239 if ( xParentAccessible.is() )
241 ::com::sun::star::uno::Reference< XAccessibleContext > xParentAC(xParentAccessible->getAccessibleContext());
242 if ( xParentAC.is() && (AccessibleRole::COMBO_BOX == xParentAC->getAccessibleRole()) )
244 // O.k. - this is a combo box floating window corresponding to the child of role LIST of the parent.
245 // Let's not rely on a specific child order, just search for the child with the role LIST
246 sal_Int32 nCount = xParentAC->getAccessibleChildCount();
247 for ( sal_Int32 n = 0; (n < nCount) && !xAccessible.is(); n++)
249 ::com::sun::star::uno::Reference< XAccessible > xChild = xParentAC->getAccessibleChild(n);
250 if ( xChild.is() )
252 ::com::sun::star::uno::Reference< XAccessibleContext > xChildAC = xChild->getAccessibleContext();
253 if ( xChildAC.is() && (AccessibleRole::LIST == xChildAC->getAccessibleRole()) )
255 xAccessible = xChild;
262 catch (::com::sun::star::uno::RuntimeException e)
264 // Ignore show events that throw DisposedExceptions in getAccessibleContext(),
265 // but keep revoking these windows in hide(s).
266 if (bShow)
267 return;
271 // We have to rely on the fact that Window::GetAccessible()->getAccessibleContext() returns a valid XAccessibleContext
272 // also for other menus than menubar or toplevel popup window. Otherwise we had to traverse the hierarchy to find the
273 // context object to this menu floater. This makes the call to Window->IsMenuFloatingWindow() obsolete.
274 if ( ! xAccessible.is() )
275 xAccessible = pWindow->GetAccessible();
277 if ( xAccessible.is() && g_unoMapping.is() )
279 jobject * joXAccessible = reinterpret_cast < jobject * > (g_unoMapping.mapInterface(
280 xAccessible.get(), g_pTypeDescription));
282 if ( NULL != joXAccessible )
284 jvmaccess::VirtualMachine::AttachGuard aGuard(g_xUnoVirtualMachine->getVirtualMachine());
285 JNIEnv * pJNIEnv = aGuard.getEnvironment();
287 if ( NULL != pJNIEnv )
289 // g_jmRegisterTopWindow and g_jmRevokeTopWindow are ensured to be != 0 - otherwise
290 // the event listener would not have been attached.
291 pJNIEnv->CallStaticVoidMethod(g_jcWindowsAccessBridgeAdapter,
292 (bShow) ? g_jmRegisterTopWindow : g_jmRevokeTopWindow,
293 (jint) GetHWND(pWindow), joXAccessible );
295 // Clear any exception that might have been occured.
296 if (pJNIEnv->ExceptionCheck()) {
297 pJNIEnv->ExceptionClear();
305 long VCLEventListenerLinkFunc(void *, void * pData)
307 ::VclSimpleEvent const * pEvent = (::VclSimpleEvent const *) pData;
309 switch (pEvent->GetId())
311 case VCLEVENT_WINDOW_SHOW:
312 handleWindowEvent(((::VclWindowEvent const *) pEvent)->GetWindow(), true);
313 break;
314 case VCLEVENT_WINDOW_HIDE:
315 handleWindowEvent(((::VclWindowEvent const *) pEvent)->GetWindow(), false);
316 break;
319 return 0;