Bump for 4.0-11
[LibreOffice.git] / accessibility / bridge / source / java / WindowsAccessBridgeAdapter.cxx
blob5b66b22106d3e82d30653ca181e45b3b3162bed1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #ifdef WNT
21 #include <prewin.h>
22 #include <postwin.h>
23 #endif
25 #include <WindowsAccessBridgeAdapter.h>
27 #include <wtypes.h>
28 #include <rtl/process.h>
29 #include <tools/link.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/window.hxx>
33 #include <vcl/sysdata.hxx>
34 #include <uno/current_context.hxx>
35 #include <uno/environment.h>
36 #include <uno/mapping.hxx>
37 #include <com/sun/star/accessibility/AccessibleRole.hpp>
38 #include <com/sun/star/accessibility/XAccessible.hpp>
40 #include "jvmaccess/unovirtualmachine.hxx"
42 #include "jvmaccess/virtualmachine.hxx"
44 #include <osl/diagnose.h>
46 using ::com::sun::star::uno::Mapping;
47 using ::com::sun::star::uno::Reference;
48 using ::com::sun::star::uno::RuntimeException;
49 using namespace ::com::sun::star::accessibility;
51 long VCLEventListenerLinkFunc(void * pInst, void * pData);
53 //------------------------------------------------------------------------
54 // global vatiables
55 //------------------------------------------------------------------------
57 Link g_aEventListenerLink(NULL, VCLEventListenerLinkFunc);
59 rtl::Reference< jvmaccess::UnoVirtualMachine > g_xUnoVirtualMachine;
60 typelib_InterfaceTypeDescription * g_pTypeDescription = NULL;
61 Mapping g_unoMapping;
63 jclass g_jcWindowsAccessBridgeAdapter = NULL;
64 jmethodID g_jmRegisterTopWindow = 0;
65 jmethodID g_jmRevokeTopWindow = 0;
67 //------------------------------------------------------------------------
68 // functions
69 //------------------------------------------------------------------------
71 SAL_DLLPUBLIC_EXPORT jint JNICALL JNI_OnLoad(JavaVM *, void *)
73 return JNI_VERSION_1_2;
76 SAL_DLLPUBLIC_EXPORT jbyteArray JNICALL
77 Java_org_openoffice_accessibility_WindowsAccessBridgeAdapter_getProcessID(JNIEnv *pJNIEnv, jclass clazz)
79 // Initialize global class and method references
80 g_jcWindowsAccessBridgeAdapter =
81 static_cast< jclass > (pJNIEnv->NewGlobalRef(clazz));
82 if (NULL == g_jcWindowsAccessBridgeAdapter) {
83 return 0; /* jni error occurred */
85 g_jmRegisterTopWindow =
86 pJNIEnv->GetStaticMethodID(clazz, "registerTopWindow", "(ILcom/sun/star/accessibility/XAccessible;)V");
87 if (0 == g_jmRegisterTopWindow) {
88 return 0; /* jni error occurred */
90 g_jmRevokeTopWindow =
91 pJNIEnv->GetStaticMethodID(clazz, "revokeTopWindow", "(ILcom/sun/star/accessibility/XAccessible;)V");
92 if (0 == g_jmRevokeTopWindow) {
93 return 0; /* jni error occurred */
96 // Use the special protocol of XJavaVM.getJavaVM: If the passed in
97 // process ID has an extra 17th byte of value one, the returned any
98 // contains a pointer to a jvmaccess::UnoVirtualMachine, instead of
99 // the underlying JavaVM pointer:
100 jbyte processID[17];
101 rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8 *> (processID));
102 // #i51265# we need a jvmaccess::UnoVirtualMachine pointer for the
103 // uno_getEnvironment() call later.
104 processID[16] = 1;
106 // Copy the result into a java byte[] and return.
107 jbyteArray jbaProcessID = pJNIEnv->NewByteArray(17);
108 pJNIEnv->SetByteArrayRegion(jbaProcessID, 0, 17, processID);
109 return jbaProcessID;
112 SAL_DLLPUBLIC_EXPORT jboolean JNICALL
113 Java_org_openoffice_accessibility_WindowsAccessBridgeAdapter_createMapping(JNIEnv *, jclass, jlong pointer)
115 uno_Environment * pJava_environment = NULL;
116 uno_Environment * pUno_environment = NULL;
118 try {
119 // We get a non-refcounted pointer to a jvmaccess::VirtualMachine
120 // from the XJavaVM service (the pointer is guaranteed to be valid
121 // as long as our reference to the XJavaVM service lasts), and
122 // convert the non-refcounted pointer into a refcounted one
123 // immediately:
124 g_xUnoVirtualMachine = reinterpret_cast< jvmaccess::UnoVirtualMachine * >(pointer);
126 if ( g_xUnoVirtualMachine.is() )
128 OUString sJava(RTL_CONSTASCII_USTRINGPARAM("java"));
129 uno_getEnvironment(&pJava_environment, sJava.pData, g_xUnoVirtualMachine.get());
131 OUString sCppu_current_lb_name(RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME));
132 uno_getEnvironment(&pUno_environment, sCppu_current_lb_name.pData, NULL);
134 if ( pJava_environment && pUno_environment )
136 g_unoMapping = Mapping(pUno_environment, pJava_environment);
137 getCppuType((::com::sun::star::uno::Reference< XAccessible > *) 0).getDescription((typelib_TypeDescription **) & g_pTypeDescription);
140 if ( pJava_environment )
142 // release java environment
143 pJava_environment->release(pJava_environment);
144 pJava_environment = NULL;
147 if ( pUno_environment )
149 // release uno environment
150 pUno_environment->release(pUno_environment);
151 pUno_environment = NULL;
156 catch (const RuntimeException &)
158 OSL_TRACE("RuntimeException caught while initializing the mapping");
161 if ( (0 != g_jmRegisterTopWindow) && (0 != g_jmRevokeTopWindow) )
163 ::Application::AddEventListener(g_aEventListenerLink);
165 return JNI_TRUE;
168 SAL_DLLPUBLIC_EXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *)
170 ::Application::RemoveEventListener(g_aEventListenerLink);
172 if ( NULL != g_jcWindowsAccessBridgeAdapter )
174 JNIEnv * pJNIEnv;
175 if ( ! jvm->GetEnv((void **) &pJNIEnv, JNI_VERSION_1_2) )
177 pJNIEnv->DeleteGlobalRef(g_jcWindowsAccessBridgeAdapter);
178 g_jcWindowsAccessBridgeAdapter = NULL;
182 if ( NULL != g_pTypeDescription )
184 typelib_typedescription_release( reinterpret_cast< typelib_TypeDescription * > (g_pTypeDescription) );
185 g_pTypeDescription = NULL;
188 g_unoMapping.clear();
189 g_xUnoVirtualMachine.clear();
192 HWND GetHWND(Window * pWindow)
194 const SystemEnvData * pEnvData = pWindow->GetSystemData();
195 if (pEnvData != NULL)
197 return pEnvData->hWnd;
199 return (HWND) -1;
202 void handleWindowEvent(Window * pWindow, bool bShow)
204 if ( pWindow && pWindow->IsTopWindow() )
206 ::com::sun::star::uno::Reference< XAccessible > xAccessible;
208 // Test for combo box - drop down floating windows first
209 Window * pParentWindow = pWindow->GetParent();
211 if ( pParentWindow )
215 // The parent window of a combo box floating window should have the role COMBO_BOX
216 ::com::sun::star::uno::Reference< XAccessible > xParentAccessible(pParentWindow->GetAccessible());
217 if ( xParentAccessible.is() )
219 ::com::sun::star::uno::Reference< XAccessibleContext > xParentAC(xParentAccessible->getAccessibleContext());
220 if ( xParentAC.is() && (AccessibleRole::COMBO_BOX == xParentAC->getAccessibleRole()) )
222 // O.k. - this is a combo box floating window corresponding to the child of role LIST of the parent.
223 // Let's not rely on a specific child order, just search for the child with the role LIST
224 sal_Int32 nCount = xParentAC->getAccessibleChildCount();
225 for ( sal_Int32 n = 0; (n < nCount) && !xAccessible.is(); n++)
227 ::com::sun::star::uno::Reference< XAccessible > xChild = xParentAC->getAccessibleChild(n);
228 if ( xChild.is() )
230 ::com::sun::star::uno::Reference< XAccessibleContext > xChildAC = xChild->getAccessibleContext();
231 if ( xChildAC.is() && (AccessibleRole::LIST == xChildAC->getAccessibleRole()) )
233 xAccessible = xChild;
240 catch (const ::com::sun::star::uno::RuntimeException &)
242 // Ignore show events that throw DisposedExceptions in getAccessibleContext(),
243 // but keep revoking these windows in hide(s).
244 if (bShow)
245 return;
249 // We have to rely on the fact that Window::GetAccessible()->getAccessibleContext() returns a valid XAccessibleContext
250 // also for other menus than menubar or toplevel popup window. Otherwise we had to traverse the hierarchy to find the
251 // context object to this menu floater. This makes the call to Window->IsMenuFloatingWindow() obsolete.
252 if ( ! xAccessible.is() )
253 xAccessible = pWindow->GetAccessible();
255 if ( xAccessible.is() && g_unoMapping.is() )
257 jobject * joXAccessible = reinterpret_cast < jobject * > (g_unoMapping.mapInterface(
258 xAccessible.get(), g_pTypeDescription));
260 if ( NULL != joXAccessible )
262 jvmaccess::VirtualMachine::AttachGuard aGuard(g_xUnoVirtualMachine->getVirtualMachine());
263 JNIEnv * pJNIEnv = aGuard.getEnvironment();
265 if ( NULL != pJNIEnv )
267 // g_jmRegisterTopWindow and g_jmRevokeTopWindow are ensured to be != 0 - otherwise
268 // the event listener would not have been attached.
269 pJNIEnv->CallStaticVoidMethod(g_jcWindowsAccessBridgeAdapter,
270 (bShow) ? g_jmRegisterTopWindow : g_jmRevokeTopWindow,
271 (jint) GetHWND(pWindow), joXAccessible );
273 // Clear any exception that might have been occurred.
274 if (pJNIEnv->ExceptionCheck()) {
275 pJNIEnv->ExceptionClear();
283 long VCLEventListenerLinkFunc(void *, void * pData)
285 ::VclSimpleEvent const * pEvent = (::VclSimpleEvent const *) pData;
287 switch (pEvent->GetId())
289 case VCLEVENT_WINDOW_SHOW:
290 handleWindowEvent(((::VclWindowEvent const *) pEvent)->GetWindow(), true);
291 break;
292 case VCLEVENT_WINDOW_HIDE:
293 handleWindowEvent(((::VclWindowEvent const *) pEvent)->GetWindow(), false);
294 break;
297 return 0;
300 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */