From 448727e598ca0c35ee9cd6f2c25a847c8147943b Mon Sep 17 00:00:00 2001 From: Michael Meeks Date: Mon, 18 Nov 2013 15:41:26 +0000 Subject: uia: merge VCL pieces of IAccessible2 work. Original code from: Author: Steve Yin Date: Sat Nov 16 23:58:19 2013 +0100 Integrate branch of IAccessible2 With these improvements: Make IAccessible2 an experimental feature, with fallback to Java a11y. Move initial setup of windows into the bridge and clean, remove conditionals Check for presence of AT in the bridge as well to clean. Merge VCL events extensions and their handling. Clean and split WB_GETOBJECT handling out to it's own method. Add component prefix namespacing. Cleanup msaa service info, and implement XComponent to share mxAccessBridge. Add suitable debugging output, remove VCL dependency from UAccCOM causing registration issues. Change-Id: Ib19e38ddca71182018df438df27dcdb555d91402 --- include/sal/log-areas.dox | 4 + include/vcl/vclevent.hxx | 33 ++- vcl/source/app/svdata.cxx | 16 ++ vcl/source/window/window.cxx | 34 ++- vcl/win/source/window/salframe.cxx | 58 ++++- winaccessibility/Library_uacccom.mk | 2 - winaccessibility/inc/AccObject.hxx | 2 +- winaccessibility/inc/g_msacc.hxx | 4 + .../source/UAccCOM/CheckEnableAccessible.cxx | 34 --- .../source/UAccCOM/CheckEnableAccessible.h | 2 +- winaccessibility/source/UAccCOM/stdafx.h | 5 +- .../source/service/AccFrameEventListener.cxx | 13 - winaccessibility/source/service/AccObject.cxx | 13 +- .../source/service/AccTopWindowListener.cxx | 48 +--- .../source/service/msaaservice_impl.cxx | 285 +++++++++++++-------- .../source/service/winaccessibility.component | 2 +- 16 files changed, 332 insertions(+), 223 deletions(-) delete mode 100755 winaccessibility/source/UAccCOM/CheckEnableAccessible.cxx diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox index ca635c487f1e..a6ffef998215 100644 --- a/include/sal/log-areas.dox +++ b/include/sal/log-areas.dox @@ -346,6 +346,10 @@ certain functionality. @li @c vcl.virdev @li @c vcl.window +@section winaccessiblity + +@li @c iacc2 - IAccessible2 bridge debug + @section Writer @li @c sw diff --git a/include/vcl/vclevent.hxx b/include/vcl/vclevent.hxx index 1ce025f68b28..92ffca93b02f 100644 --- a/include/vcl/vclevent.hxx +++ b/include/vcl/vclevent.hxx @@ -151,6 +151,7 @@ namespace com { namespace sun { namespace star { #define VCLEVENT_ITEM_EXPANDED 1174 #define VCLEVENT_ITEM_COLLAPSED 1175 #define VCLEVENT_DROPDOWN_PRE_OPEN 1176 +#define VCLEVENT_LISTBOX_FOCUSITEMCHANGED 1180 // VclMenuEvent #define VCLEVENT_MENU_ACTIVATE 1200 @@ -169,23 +170,35 @@ namespace com { namespace sun { namespace star { #define VCLEVENT_MENU_ITEMCHECKED 1213 #define VCLEVENT_MENU_ITEMUNCHECKED 1214 #define VCLEVENT_MENU_ACCESSIBLENAMECHANGED 1215 +#define VCLEVENT_TOOLBOX_ITEMWINDOWCHANGED 1216 +#define VCLEVENT_TOOLBOX_ITEMUPDATED 1217 #define VCLEVENT_MENU_SHOW 1250 #define VCLEVENT_MENU_HIDE 1251 #define VCLEVENT_TOOLBOX_ITEMWINDOWCHANGED 1216 +#define VCLEVENT_LISTBOX_TREEEXPAND 1218 +#define VCLEVENT_LISTBOX_TREECOLLAPSE 1219 +#define VCLEVENT_LISTBOX_TREEFOCUS 1220 +#define VCLEVENT_LISTBOX_TREESELECT 1221 +#define VCLEVENT_EDIT_CARETCHANGED 1222 +#define VCLEVENT_COMBOBOX_UPDATEVALUE 1223 + +#define VCLEVENT_LISTBOX_FOCUS 1224 +#define VCLEVENT_LISTBOX_CLEAR 1225 // DockingWindow -#define VCLEVENT_WINDOW_STARTDOCKING 1217 // pData = DockingData -#define VCLEVENT_WINDOW_DOCKING 1218 -#define VCLEVENT_WINDOW_ENDDOCKING 1219 // pData = EndDockingData -#define VCLEVENT_WINDOW_PREPARETOGGLEFLOATING 1220 // pData = sal_Bool -#define VCLEVENT_WINDOW_TOGGLEFLOATING 1221 -#define VCLEVENT_WINDOW_ENDPOPUPMODE 1222 // pData = EndPopupModeData - -#define VCLEVENT_TOOLBOX_BUTTONSTATECHANGED 1223 // pData = itempos -#define VCLEVENT_TABLECELL_NAMECHANGED 1224 // pData = struct(Entry, Column, oldText) -#define VCLEVENT_TABLEROW_SELECT 1225 +#define VCLEVENT_WINDOW_STARTDOCKING 1227 // pData = DockingData +#define VCLEVENT_WINDOW_DOCKING 1228 +#define VCLEVENT_WINDOW_ENDDOCKING 1229 // pData = EndDockingData +#define VCLEVENT_WINDOW_PREPARETOGGLEFLOATING 1230 // pData = sal_Bool +#define VCLEVENT_WINDOW_TOGGLEFLOATING 1231 +#define VCLEVENT_WINDOW_ENDPOPUPMODE 1232 // pData = EndPopupModeData + +#define VCLEVENT_TOOLBOX_BUTTONSTATECHANGED 1233 // pData = itempos +#define VCLEVENT_TABLECELL_NAMECHANGED 1234 // pData = struct(Entry, Column, oldText) +#define VCLEVENT_TABLEROW_SELECT 1235 +#define VCLEVENT_LISTBOX_STATEUPDATE 1236 class VCL_DLLPUBLIC VclSimpleEvent { diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx index b42eeea45e45..cb24f027108f 100644 --- a/vcl/source/app/svdata.cxx +++ b/vcl/source/app/svdata.cxx @@ -52,6 +52,8 @@ #include "com/sun/star/java/MissingJavaRuntimeException.hpp" #include "com/sun/star/java/JavaDisabledException.hpp" +#include "officecfg/Office/Common.hxx" + #include using namespace com::sun::star::uno; @@ -321,6 +323,20 @@ bool ImplInitAccessBridge(bool bAllowCancel, bool &rCancelled) { css::uno::Reference< XComponentContext > xContext(comphelper::getProcessComponentContext()); + bool bTryIAcc2 = ( officecfg::Office::Common::Misc::ExperimentalMode::get( xContext ) && + !getenv ("SAL_DISABLE_IACCESSIBLE2") ); + + if ( bTryIAcc2 ) // Windows only really + { + // FIXME: convert to service ... pSVData->mxAccessBridge = css::accessibility::MSAAService::create( xContext ); + pSVData->mxAccessBridge = Reference< XComponent >( xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.accessibility.MSAAService", xContext ), UNO_QUERY ); + + SAL_INFO( "vcl", "IAccessible2 bridge is: " << (int)(pSVData->mxAccessBridge.is()) ); + return pSVData->mxAccessBridge.is(); + } + else + SAL_INFO( "vcl", "IAccessible2 disabled, falling back to java" ); + css::uno::Reference< XExtendedToolkit > xToolkit = css::uno::Reference< XExtendedToolkit >(Application::GetVCLToolkit(), UNO_QUERY); diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 64664b167c15..1ef62c1d36cb 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -8818,10 +8818,10 @@ sal_uInt16 Window::getDefaultAccessibleRole() const case WINDOW_CANCELBUTTON: case WINDOW_HELPBUTTON: case WINDOW_IMAGEBUTTON: - case WINDOW_MENUBUTTON: case WINDOW_MOREBUTTON: case WINDOW_SPINBUTTON: case WINDOW_BUTTON: nRole = accessibility::AccessibleRole::PUSH_BUTTON; break; + case WINDOW_MENUBUTTON: nRole = accessibility::AccessibleRole::BUTTON_MENU; break; case WINDOW_PATHDIALOG: nRole = accessibility::AccessibleRole::DIRECTORY_PANE; break; case WINDOW_FILEDIALOG: nRole = accessibility::AccessibleRole::FILE_CHOOSER; break; @@ -8835,10 +8835,6 @@ sal_uInt16 Window::getDefaultAccessibleRole() const case WINDOW_MULTILINEEDIT: nRole = accessibility::AccessibleRole::SCROLL_PANE; break; case WINDOW_PATTERNFIELD: - case WINDOW_NUMERICFIELD: - case WINDOW_METRICFIELD: - case WINDOW_CURRENCYFIELD: - case WINDOW_LONGCURRENCYFIELD: case WINDOW_CALCINPUTLINE: case WINDOW_EDIT: nRole = ( GetStyle() & WB_PASSWORD ) ? (accessibility::AccessibleRole::PASSWORD_TEXT) : (accessibility::AccessibleRole::TEXT); break; @@ -8855,7 +8851,13 @@ sal_uInt16 Window::getDefaultAccessibleRole() const case WINDOW_TREELISTBOX: nRole = accessibility::AccessibleRole::TREE; break; case WINDOW_FIXEDTEXT: nRole = accessibility::AccessibleRole::LABEL; break; - case WINDOW_FIXEDLINE: nRole = accessibility::AccessibleRole::SEPARATOR; break; + case WINDOW_FIXEDLINE: + if( !GetText().isEmpty() ) + nRole = accessibility::AccessibleRole::LABEL; + else + nRole = accessibility::AccessibleRole::SEPARATOR; + break; + case WINDOW_FIXEDBITMAP: case WINDOW_FIXEDIMAGE: nRole = accessibility::AccessibleRole::ICON; break; case WINDOW_GROUPBOX: nRole = accessibility::AccessibleRole::GROUP_BOX; break; @@ -8870,6 +8872,10 @@ sal_uInt16 Window::getDefaultAccessibleRole() const case WINDOW_DATEFIELD: case WINDOW_TIMEFIELD: nRole = accessibility::AccessibleRole::DATE_EDITOR; break; + case WINDOW_NUMERICFIELD: + case WINDOW_METRICFIELD: + case WINDOW_CURRENCYFIELD: + case WINDOW_LONGCURRENCYFIELD: case WINDOW_SPINFIELD: nRole = accessibility::AccessibleRole::SPIN_BOX; break; case WINDOW_TOOLBOX: nRole = accessibility::AccessibleRole::TOOL_BAR; break; @@ -8933,8 +8939,12 @@ void Window::SetAccessibleName( const OUString& rName ) if ( !mpWindowImpl->mpAccessibleInfos ) mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos; + OUString oldName = GetAccessibleName(); + delete mpWindowImpl->mpAccessibleInfos->pAccessibleName; mpWindowImpl->mpAccessibleInfos->pAccessibleName = new OUString( rName ); + + ImplCallEventListeners( VCLEVENT_WINDOW_FRAMETITLECHANGED, &oldName ); } OUString Window::GetAccessibleName() const @@ -8975,6 +8985,8 @@ OUString Window::getDefaultAccessibleName() const Window *pLabel = GetAccessibleRelationLabeledBy(); if ( pLabel && pLabel != this ) aAccessibleName = pLabel->GetText(); + if (aAccessibleName.isEmpty()) + aAccessibleName = GetQuickHelpText(); } break; @@ -8989,6 +9001,16 @@ OUString Window::getDefaultAccessibleName() const } break; + case WINDOW_TOOLBOX: + aAccessibleName = GetText(); + if( aAccessibleName.isEmpty() ) + aAccessibleName = "Tool Bar"; + break; + + case WINDOW_MOREBUTTON: + aAccessibleName = mpWindowImpl->maText; + break; + default: aAccessibleName = GetText(); break; diff --git a/vcl/win/source/window/salframe.cxx b/vcl/win/source/window/salframe.cxx index 87e5c1a2ec92..8ee2cae0a3c4 100644 --- a/vcl/win/source/window/salframe.cxx +++ b/vcl/win/source/window/salframe.cxx @@ -77,6 +77,12 @@ using ::std::max; #include +#include +#include +#ifndef WM_GETOBJECT // TESTME does this ever happen ? +# define WM_GETOBJECT 0x003D +#endif + #include #if defined ( __MINGW32__ ) @@ -5178,7 +5184,7 @@ static sal_Bool ImplHandleIMEStartComposition( HWND hWnd ) // ----------------------------------------------------------------------- static sal_Bool ImplHandleIMECompositionInput( WinSalFrame* pFrame, - HIMC hIMC, LPARAM lParam ) + HIMC hIMC, LPARAM lParam ) { sal_Bool bDef = TRUE; @@ -5478,6 +5484,46 @@ static void ImplHandleIMENotify( HWND hWnd, WPARAM wParam ) // ----------------------------------------------------------------------- +static bool ImplHandleGetObject( HWND hWnd, LPARAM lParam, WPARAM wParam, long &nRet ) +{ + // IA2 should be enabled automatically + AllSettings aSettings = Application::GetSettings(); + MiscSettings aMisc = aSettings.GetMiscSettings(); + aMisc.SetEnableATToolSupport( sal_True ); + aSettings.SetMiscSettings( aMisc ); + Application::SetSettings( aSettings ); + + if (!Application::GetSettings().GetMiscSettings().GetEnableATToolSupport()) + return false; // locked down somehow ? + + ImplSVData* pSVData = ImplGetSVData(); + + // Make sure to launch Accessibiliity only the following criterias are satisfied + // to avoid RFT interrupts regular accessibility processing + if ( !pSVData->mxAccessBridge.is() ) + { + bool bCancelled = false; + InitAccessBridge( false, bCancelled ); + if( bCancelled ) + return false; + } + + uno::Reference< accessibility::XMSAAService > xMSAA( pSVData->mxAccessBridge, uno::UNO_QUERY ); + if ( xMSAA.is() ) + { + // mhOnSetTitleWnd not set to reasonable value anywhere... + if ( lParam == OBJID_CLIENT ) + { + nRet = xMSAA->getAccObjectPtr( (long)hWnd, lParam, wParam ); + if( nRet != 0 ) + return true; + } + } + return false; +} + +// ----------------------------------------------------------------------- + static LRESULT ImplHandleIMEReconvertString( HWND hWnd, LPARAM lParam ) { WinSalFrame* pFrame = GetWindowPtr( hWnd ); @@ -6005,6 +6051,16 @@ LRESULT CALLBACK SalFrameWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP case WM_IME_NOTIFY: ImplHandleIMENotify( hWnd, wParam ); break; + + case WM_GETOBJECT: + long nRet; + if ( ImplHandleGetObject( hWnd, lParam, wParam, nRet ) ) + { + rDef = false; + return (HRESULT) nRet; + } + break; + case WM_APPCOMMAND: if( ImplHandleAppCommand( hWnd, lParam ) ) { diff --git a/winaccessibility/Library_uacccom.mk b/winaccessibility/Library_uacccom.mk index b3b91ce3c76c..f481b404fe51 100755 --- a/winaccessibility/Library_uacccom.mk +++ b/winaccessibility/Library_uacccom.mk @@ -41,7 +41,6 @@ $(eval $(call gb_Library_add_exception_objects,UAccCOM,\ winaccessibility/source/UAccCOM/AccText \ winaccessibility/source/UAccCOM/AccTextBase \ winaccessibility/source/UAccCOM/AccValue \ - winaccessibility/source/UAccCOM/CheckEnableAccessible \ winaccessibility/source/UAccCOM/EnumVariant \ winaccessibility/source/UAccCOM/MAccessible \ winaccessibility/source/UAccCOM/StdAfx \ @@ -58,7 +57,6 @@ $(eval $(call gb_Library_add_ldflags,UAccCOM,\ $(eval $(call gb_Library_use_libraries,UAccCOM,\ cppu \ - vcl \ sal \ )) diff --git a/winaccessibility/inc/AccObject.hxx b/winaccessibility/inc/AccObject.hxx index 1692064ded3d..ae63900187a1 100644 --- a/winaccessibility/inc/AccObject.hxx +++ b/winaccessibility/inc/AccObject.hxx @@ -58,7 +58,7 @@ private: ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleAction > m_xAccActionRef; ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessibleContext > m_xAccContextRef; - sal_Bool ImplInitilizeCreateObj();//create COM object + sal_Bool ImplInitializeCreateObj();//create COM object void UpdateActionDesc(); void UpdateRole(); diff --git a/winaccessibility/inc/g_msacc.hxx b/winaccessibility/inc/g_msacc.hxx index df6e4bd9bf0a..d700249a9bb3 100644 --- a/winaccessibility/inc/g_msacc.hxx +++ b/winaccessibility/inc/g_msacc.hxx @@ -20,6 +20,10 @@ #ifndef __G_MSACC_HXX #define __G_MSACC_HXX +extern void FreeTopWindowListener(); +extern void handleWindowOpened_impl( long pAcc ); +extern long GetMSComPtr( long hWnd, long lParam, long wParam ); + extern AccTopWindowListener* g_pTop; #endif diff --git a/winaccessibility/source/UAccCOM/CheckEnableAccessible.cxx b/winaccessibility/source/UAccCOM/CheckEnableAccessible.cxx deleted file mode 100755 index 128d2cb917d4..000000000000 --- a/winaccessibility/source/UAccCOM/CheckEnableAccessible.cxx +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#define _USE_NAMESPACE - -#ifndef _SV_SVAPP_HXX -#include -#endif - -#include "CheckEnableAccessible.h" - - -bool IsEnableAccessibleInterface() -{ - return Application::IsEnableAccessInterface(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/winaccessibility/source/UAccCOM/CheckEnableAccessible.h b/winaccessibility/source/UAccCOM/CheckEnableAccessible.h index 7170e9fea737..90099ace2138 100644 --- a/winaccessibility/source/UAccCOM/CheckEnableAccessible.h +++ b/winaccessibility/source/UAccCOM/CheckEnableAccessible.h @@ -20,7 +20,7 @@ #ifndef _CHECKENABLEACCESSIBLE_HXX #define _CHECKENABLEACCESSIBLE_HXX -bool IsEnableAccessibleInterface(); +inline bool IsEnableAccessibleInterface() { return true; } #define CHECK_ENABLE_INF if(!IsEnableAccessibleInterface()){ return S_FALSE; } #define CHECK_ENABLE_INF_ZERO if(!IsEnableAccessibleInterface()){ return 0; } diff --git a/winaccessibility/source/UAccCOM/stdafx.h b/winaccessibility/source/UAccCOM/stdafx.h index b933b12ee29c..6b2ccdd8c675 100644 --- a/winaccessibility/source/UAccCOM/stdafx.h +++ b/winaccessibility/source/UAccCOM/stdafx.h @@ -28,10 +28,6 @@ #pragma once #endif // _MSC_VER > 1000 -//#define STRICT -//#ifndef _WIN32_WINNT -//#define _WIN32_WINNT 0x0400 -//#endif //#define _ATL_APARTMENT_THREADED #include @@ -56,6 +52,7 @@ extern CComModule _Module; #include #undef OPAQUE #include "CheckEnableAccessible.h" + //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. diff --git a/winaccessibility/source/service/AccFrameEventListener.cxx b/winaccessibility/source/service/AccFrameEventListener.cxx index a57fc3c52ba8..81b81fff8291 100755 --- a/winaccessibility/source/service/AccFrameEventListener.cxx +++ b/winaccessibility/source/service/AccFrameEventListener.cxx @@ -32,20 +32,7 @@ using namespace com::sun::star::accessibility; #include #include - -//#ifndef _SV_SYSDATA_HXX -#if 0 -#if defined( WIN ) || defined( WNT ) || defined( OS2 ) -typedef sal_Int32 HWND; -typedef sal_Int32 HMENU; -typedef sal_Int32 HDC; -typedef void *PVOID; -typedef PVOID HANDLE; -typedef HANDLE HFONT; -#endif -#endif #include -//#endif AccFrameEventListener::AccFrameEventListener(com::sun::star::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent) :AccEventListener(pAcc, Agent) diff --git a/winaccessibility/source/service/AccObject.cxx b/winaccessibility/source/service/AccObject.cxx index 300ebce7355c..ad6b1811d190 100644 --- a/winaccessibility/source/service/AccObject.cxx +++ b/winaccessibility/source/service/AccObject.cxx @@ -53,7 +53,8 @@ using namespace com::sun::star::accessibility::AccessibleStateType; * @param listener listener that registers in UNO system. * @return. */ -AccObject::AccObject(XAccessible* pAcc,AccObjectManagerAgent* pAgent ,AccEventListener* listener) : +AccObject::AccObject(XAccessible* pAcc, AccObjectManagerAgent* pAgent, + AccEventListener* listener) : m_pIMAcc (NULL), m_resID (NULL), m_pParantID (NULL), @@ -62,7 +63,7 @@ AccObject::AccObject(XAccessible* pAcc,AccObjectManagerAgent* pAgent ,AccEventLi m_bShouldDestroy(sal_False), m_xAccRef( pAcc ) { - sal_Bool bRet = ImplInitilizeCreateObj(); + sal_Bool bRet = ImplInitializeCreateObj(); m_xAccContextRef = m_xAccRef->getAccessibleContext(); m_xAccActionRef = Reference< XAccessibleAction > (m_xAccContextRef,UNO_QUERY); @@ -150,12 +151,14 @@ void AccObject::UpdateValidWindow() * @param * @return If the method is correctly processed. */ -sal_Bool AccObject::ImplInitilizeCreateObj() +sal_Bool AccObject::ImplInitializeCreateObj() { ActivateActContext(); - HRESULT hr = CoCreateInstance( CLSID_MAccessible, NULL, CLSCTX_ALL , + HRESULT hr = CoCreateInstance( CLSID_MAccessible, NULL, CLSCTX_ALL, IID_IMAccessible, (void **)&m_pIMAcc); + if( !m_pIMAcc ) + SAL_WARN( "iacc2", "Failed to create IAccessible2 instance" ); DeactivateActContext(); if ( S_OK != hr ) @@ -312,7 +315,6 @@ void AccObject::SetValue( Any pAny ) m_pIMAcc->Put_XAccValue( val.getStr() ); break; case TREE_ITEM: - //IAccessibility2 Implementation 2009----- //case CHECK_BOX: //Commented by Li Xing to disable the value for general checkbox case COMBO_BOX: case TABLE_CELL: @@ -324,7 +326,6 @@ void AccObject::SetValue( Any pAny ) case CHECK_BOX: if( ( m_pParentObj !=NULL ) && (TREE == m_pParentObj->m_accRole || TREE_ITEM == m_pParentObj->m_accRole )) m_pIMAcc->Put_XAccValue( GetMAccessibleValueFromAny(pAny).getStr() ); - //-----IAccessibility2 Implementation 2009 break; default: break; diff --git a/winaccessibility/source/service/AccTopWindowListener.cxx b/winaccessibility/source/service/AccTopWindowListener.cxx index 28d2b7930ead..5c55cbd3b2a1 100755 --- a/winaccessibility/source/service/AccTopWindowListener.cxx +++ b/winaccessibility/source/service/AccTopWindowListener.cxx @@ -23,17 +23,6 @@ #include #include -//#ifndef _SV_SYSDATA_HXX -#if 0 -#if defined( WIN ) || defined( WNT ) || defined( OS2 ) -typedef sal_Int32 HWND; -typedef sal_Int32 HMENU; -typedef sal_Int32 HDC; -typedef void *PVOID; -typedef PVOID HANDLE; -typedef HANDLE HFONT; -#endif -#endif #include #include "AccTopWindowListener.hxx" @@ -53,11 +42,9 @@ using namespace com::sun::star::bridge; using namespace com::sun::star::awt; using namespace rtl; using namespace cppu; -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// AccTopWindowListener* g_pTop = NULL; + //when proccess exit, call FreeTopWindowListener() in svmain void FreeTopWindowListener() { @@ -73,7 +60,7 @@ void FreeTopWindowListener() */ void handleWindowOpened_impl(long pAcc) { - if( g_pTop && pAcc != NULL ) + if( g_pTop && pAcc != 0 ) g_pTop->handleWindowOpened( (com::sun::star::accessibility::XAccessible*)((void*)pAcc) ); } @@ -99,14 +86,13 @@ void AccTopWindowListener::handleWindowOpened( com::sun::star::accessibility::XA } Reference xContext(pAccessible->getAccessibleContext(),UNO_QUERY); if(!xContext.is()) - { return; - } + com::sun::star::accessibility::XAccessibleContext* pAccessibleContext = xContext.get(); //Only AccessibleContext exist, add all listeners if(pAccessibleContext != NULL && systemdata != NULL) { - accManagerAgent.SaveTopWindowHandle((long)(HWND)systemdata->hWnd, pAccessible); + accManagerAgent.SaveTopWindowHandle((long)(HWND)systemdata->hWnd, pAccessible); AddAllListeners(pAccessible,NULL,(HWND)systemdata->hWnd); @@ -115,7 +101,6 @@ void AccTopWindowListener::handleWindowOpened( com::sun::star::accessibility::XA short role = pAccessibleContext->getAccessibleRole(); - if (role == com::sun::star::accessibility::AccessibleRole::POPUP_MENU || role == com::sun::star::accessibility::AccessibleRole::MENU ) { @@ -147,20 +132,17 @@ AccTopWindowListener::~AccTopWindowListener() */ void AccTopWindowListener::windowOpened( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException) { + SAL_INFO( "iacc2", "windowOpened triggered" ); + if ( !e.Source.is()) - { return; - } Reference< com::sun::star::accessibility::XAccessible > xAccessible ( e.Source, UNO_QUERY ); com::sun::star::accessibility::XAccessible* pAccessible = xAccessible.get(); - if ( pAccessible == NULL) - { + if ( !pAccessible ) return; - } - - handleWindowOpened(pAccessible); + handleWindowOpened( pAccessible ); } /** @@ -213,16 +195,14 @@ void AccTopWindowListener::AddAllListeners(com::sun::star::accessibility::XAcces = mpAccessible->getAccessibleContext(); com::sun::star::accessibility::XAccessibleContext* mpContext = mxAccessibleContext.get(); if(mpContext != NULL) - { - //fprintf(output, "go on add child's children event listener\n"); - AddAllListeners(mpAccessible,pAccessible,pWND); - } + AddAllListeners( mpAccessible, pAccessible, pWND); } } } void AccTopWindowListener::windowClosing( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException) { + SAL_INFO( "iacc2", "windowClosing triggered" ); } /** @@ -232,17 +212,15 @@ void AccTopWindowListener::windowClosing( const ::com::sun::star::lang::EventObj */ void AccTopWindowListener::windowClosed( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException) { + SAL_INFO( "iacc2", "windowClosed triggered" ); + if ( !e.Source.is()) - { return; - } + Reference< com::sun::star::accessibility::XAccessible > xAccessible ( e.Source, UNO_QUERY ); com::sun::star::accessibility::XAccessible* pAccessible = xAccessible.get(); if ( pAccessible == NULL) - { return; - } - VCLXWindow* pvclwindow = (VCLXWindow*)pAccessible; Window* window = pvclwindow->GetWindow(); diff --git a/winaccessibility/source/service/msaaservice_impl.cxx b/winaccessibility/source/service/msaaservice_impl.cxx index ce720c37a64a..82a67b35d03a 100755 --- a/winaccessibility/source/service/msaaservice_impl.cxx +++ b/winaccessibility/source/service/msaaservice_impl.cxx @@ -17,7 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include +#include #include #include @@ -25,9 +25,13 @@ #include #include #include +#include #include #include +#include + +#include using namespace ::rtl; // for OUString using namespace ::com::sun::star; // for odk interfaces @@ -36,96 +40,53 @@ using namespace ::com::sun::star::accessibility; using namespace ::com::sun::star::awt; -typedef sal_Int32 HWND; - #include "AccTopWindowListener.hxx" #include "g_msacc.hxx" -extern void FreeTopWindowListener(); -extern long GetMSComPtr(long hWnd, long lParam, long wParam); -extern void handleWindowOpened_impl( long pAcc); - - namespace my_sc_impl { - //extern Sequence< OUString > SAL_CALL getSupportedServiceNames_MSAAServiceImpl(); - //static OUString SAL_CALL getImplementationName_MSAAServiceImpl(); - //static Reference< XInterface > SAL_CALL create_MSAAServiceImpl( - // Reference< XComponentContext > const & xContext ) - // SAL_THROW( () ); -/** - * Method that returns the service name. - * @param - * @return Name sequence. - */ static Sequence< OUString > getSupportedServiceNames_MSAAServiceImpl() { - static Sequence < OUString > *pNames = 0; - if( ! pNames ) - { - // MutexGuard guard( Mutex::getGlobalMutex() ); - if( !pNames ) - { - static Sequence< OUString > seqNames(1); - seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.MSAAService")); - pNames = &seqNames; - } - } - return *pNames; + Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = "com.sun.star.accessibility.MSAAService"; + return seqNames; } -/** - * Method that returns the service name. - * @param - * @return Name sequence. - */ static OUString getImplementationName_MSAAServiceImpl() { - static OUString *pImplName = 0; - if( ! pImplName ) - { - // MutexGuard guard( Mutex::getGlobalMutex() ); - if( ! pImplName ) - { - static OUString implName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.my_sc_implementation.MSAAService") ); - pImplName = &implName; - } - } - return *pImplName; + return OUString( "com.sun.star.accessibility.my_sc_implementation.MSAAService" ); } -class MSAAServiceImpl : public ::cppu::WeakImplHelper3< - XMSAAService, lang::XServiceInfo, lang::XInitialization > +class MSAAServiceImpl : public ::cppu::WeakImplHelper4< + XMSAAService, lang::XServiceInfo, + lang::XInitialization, lang::XComponent > { OUString m_arg; public: - // focus on three given interfaces, - // no need to implement XInterface, XTypeProvider, XWeak + // focus on four interfaces, + // no need to implement XInterface, XTypeProvider, XWeak etc. MSAAServiceImpl (); virtual ~MSAAServiceImpl( void ); + // XInitialization will be called upon createInstanceWithArguments[AndContext]() - virtual void SAL_CALL initialize( Sequence< Any > const & args ) - throw (Exception); + virtual void SAL_CALL initialize( Sequence< Any > const & args ) throw (Exception); + + // XComponent - as used by VCL to lifecycle manage this bridge. + virtual void SAL_CALL dispose(); + virtual void SAL_CALL addEventListener( const ::css::uno::Reference< ::css::lang::XEventListener >& ) { /* dummy */ } + virtual void SAL_CALL removeEventListener( const ::css::uno::Reference< ::css::lang::XEventListener >& ) { /* dummy */ } + // XMSAAService - virtual sal_Int32 SAL_CALL getAccObjectPtr (long hWnd, long lParam, long wParam) - throw (RuntimeException); - virtual void SAL_CALL handleWindowOpened(sal_Int32) - throw (RuntimeException); + virtual sal_Int32 SAL_CALL getAccObjectPtr (long hWnd, long lParam, long wParam); + virtual void SAL_CALL handleWindowOpened(sal_Int32); + // XServiceInfo - virtual OUString SAL_CALL getImplementationName() - throw (RuntimeException); - virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ) - throw (RuntimeException); - virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() - throw (RuntimeException); + virtual OUString SAL_CALL getImplementationName(); + virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(); }; -/** - * Implemention of XInitialization. - * @param - * @return. - */ void MSAAServiceImpl::initialize( Sequence< Any > const & args ) throw (Exception) { if (1 != args.getLength()) @@ -151,29 +112,24 @@ void MSAAServiceImpl::initialize( Sequence< Any > const & args ) throw (Exceptio */ sal_Int32 MSAAServiceImpl::getAccObjectPtr ( long hWnd, long lParam, long wParam) throw (RuntimeException) { - return GetMSComPtr(hWnd, lParam, wParam); + return GetMSComPtr( hWnd, lParam, wParam ); } /** - * Implemention of handleWindowOpened,the method will be invoked when a top window - * opened and AT starts up. + * Implemention of handleWindowOpened, the method will be invoked when a + * top window is opened and AT starts up. * @param * @return */ -void MSAAServiceImpl::handleWindowOpened( sal_Int32 pAcc) +void MSAAServiceImpl::handleWindowOpened( sal_Int32 nAcc) { - handleWindowOpened_impl(pAcc); + SAL_INFO( "iacc2", "Window opened " << nAcc ); + handleWindowOpened_impl( nAcc ); } -/** - * Implemention of XServiceInfo. - * @param - * @return Implementataion name. - */ OUString MSAAServiceImpl::getImplementationName() throw (RuntimeException) { - // unique implementation name - return OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.my_sc_impl.MSAAService") ); + return OUString( "com.sun.star.accessibility.my_sc_impl.MSAAService" ); } /** @@ -184,7 +140,7 @@ OUString MSAAServiceImpl::getImplementationName() throw (RuntimeException) sal_Bool MSAAServiceImpl::supportsService( OUString const & serviceName ) throw (RuntimeException) { // this object only supports one service, so the test is simple - return serviceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.accessibility.MSAAService") ); + return serviceName == "com.sun.star.accessibility.MSAAService"; } /** @@ -197,47 +153,159 @@ Sequence< OUString > MSAAServiceImpl::getSupportedServiceNames() throw (RuntimeE return getSupportedServiceNames_MSAAServiceImpl(); } +static void AccessBridgeHandleExistingWindow(const Reference< XMSAAService > &xAccMgr, + Window *pWindow, bool bShow) +{ + if ( pWindow ) + { + css::uno::Reference< css::accessibility::XAccessible > xAccessible; + + SAL_INFO( "iacc2", "Decide whether to register existing window with IAccessible2" ); + + // Test for combo box - drop down floating windows first + Window * pParentWindow = pWindow->GetParent(); + + if ( pParentWindow ) + { + try + { + // The parent window of a combo box floating window should have the role COMBO_BOX + css::uno::Reference< css::accessibility::XAccessible > xParentAccessible(pParentWindow->GetAccessible()); + if ( xParentAccessible.is() ) + { + css::uno::Reference< css::accessibility::XAccessibleContext > xParentAC( xParentAccessible->getAccessibleContext() ); + if ( xParentAC.is() && (css::accessibility::AccessibleRole::COMBO_BOX == xParentAC->getAccessibleRole()) ) + { + // O.k. - this is a combo box floating window corresponding to the child of role LIST of the parent. + // Let's not rely on a specific child order, just search for the child with the role LIST + sal_Int32 nCount = xParentAC->getAccessibleChildCount(); + for ( sal_Int32 n = 0; (n < nCount) && !xAccessible.is(); n++) + { + css::uno::Reference< css::accessibility::XAccessible > xChild = xParentAC->getAccessibleChild(n); + if ( xChild.is() ) + { + css::uno::Reference< css::accessibility::XAccessibleContext > xChildAC = xChild->getAccessibleContext(); + if ( xChildAC.is() && (css::accessibility::AccessibleRole::LIST == xChildAC->getAccessibleRole()) ) + { + xAccessible = xChild; + } + } + } + } + } + } + catch (::com::sun::star::uno::RuntimeException e) + { + // Ignore show events that throw DisposedExceptions in getAccessibleContext(), + // but keep revoking these windows in hide(s). + if (bShow) + return; + } + } + + // We have to rely on the fact that Window::GetAccessible()->getAccessibleContext() returns a valid XAccessibleContext + // also for other menus than menubar or toplevel popup window. Otherwise we had to traverse the hierarchy to find the + // context object to this menu floater. This makes the call to Window->IsMenuFloatingWindow() obsolete. + if ( ! xAccessible.is() ) + xAccessible = pWindow->GetAccessible(); + + assert( xAccMgr.is() ); + if ( xAccessible.is() ) + { + xAccMgr->handleWindowOpened( (long)xAccessible.get() ); + SAL_INFO( "iacc2", "Decide whether to register existing window with IAccessible2" ); + } + } +} + +/* + * Setup and notify the OS of Accessible peers for all existing windows. + */ +static void AccessBridgeUpdateOldTopWindows( const Reference< XMSAAService > &xAccMgr ) +{ + sal_uInt16 nTopWindowCount = (sal_uInt16)Application::GetTopWindowCount(); + + for ( sal_uInt16 i = 0; i < nTopWindowCount; i++ ) + { + Window* pTopWindow = Application::GetTopWindow( i ); + css::uno::Reference< css::accessibility::XAccessible > xAccessible = pTopWindow->GetAccessible(); + if ( xAccessible.is() ) + { + css::uno::Reference< css::accessibility::XAccessibleContext > xAC( xAccessible->getAccessibleContext() ); + if ( xAC.is()) + { + short role = xAC->getAccessibleRole(); + if ( !xAC->getAccessibleName().isEmpty() ) + AccessBridgeHandleExistingWindow( xAccMgr, pTopWindow, true ); + } + } + } +} + +static bool HasAtHook() +{ + sal_Int32 bIsRuning=0; + // BOOL WINAPI SystemParametersInfo( + // __in UINT uiAction, + // __in UINT uiParam, + // __inout PVOID pvParam, + // __in UINT fWinIni + // ); + // pvParam must be BOOL (defined in MFC as int) + // End + return SystemParametersInfo( SPI_GETSCREENREADER, 0, + &bIsRuning, 0) && bIsRuning; +} + /** - * Static method that can create an entity of our MSAA Service - * @param xContext No use here. - * @return The object interface. - */ + * Static method that can create an entity of our MSAA Service + * @param xContext No use here. + * @return The object interface. + */ Reference< XInterface > SAL_CALL create_MSAAServiceImpl( Reference< XComponentContext > const & /*xContext*/ ) SAL_THROW( () ) { - MSAAServiceImpl* xxx = new MSAAServiceImpl(); - //return static_cast< lang::XTypeProvider * >( xxx ); - Reference< XMSAAService > p( xxx ); - return p; + bool bRunWithoutAt = getenv("SAL_FORCE_IACCESSIBLE2"); + + if ( !HasAtHook() ) + { + if ( !bRunWithoutAt ) + { + SAL_INFO("iacc2", "Apparently no running AT -> not enabling IAccessible2 integration"); + return Reference< XMSAAService >(); + } + } + + Reference< XMSAAService > xAccMgr( new MSAAServiceImpl() ); + + AccessBridgeUpdateOldTopWindows( xAccMgr ); + + SAL_INFO("iacc2", "Created new IAccessible2 service impl."); + + return xAccMgr; } -/** - * Constructor. - * @param - * @return - */ MSAAServiceImpl::MSAAServiceImpl() { Reference< XExtendedToolkit > xToolkit = Reference< XExtendedToolkit >(Application::GetVCLToolkit(), UNO_QUERY); - if(xToolkit.is()) + if( xToolkit.is() ) { - AccTopWindowListener *accListener; - accListener = new AccTopWindowListener(); - g_pTop = accListener; - Reference< XTopWindowListener> x(accListener); - xToolkit->addTopWindowListener(x); + g_pTop = new AccTopWindowListener(); + Reference< XTopWindowListener> xRef( g_pTop ); + xToolkit->addTopWindowListener( xRef ); + SAL_INFO( "iacc2", "successfully connected to the toolkit event hose" ); } + else + SAL_WARN( "iacc2", "No VCL toolkit interface to listen to for events"); } -/** - * Static method that can create an entity of our MSAA Service - * @param Destructor - * @return - */ MSAAServiceImpl::~MSAAServiceImpl() { +} +void MSAAServiceImpl::dispose() +{ // As all folders and streams contain references to their parents, // we must remove these references so that they will be deleted when // the hash_map of the root folder is cleared, releasing all subfolders @@ -245,8 +313,6 @@ MSAAServiceImpl::~MSAAServiceImpl() // released when this destructor completes, the folder tree should be // deleted fully (and automagically). FreeTopWindowListener(); - - } } @@ -258,7 +324,8 @@ static struct ::cppu::ImplementationEntry s_component_entries [] = { { create_MSAAServiceImpl, getImplementationName_MSAAServiceImpl, - getSupportedServiceNames_MSAAServiceImpl, ::cppu::createSingleComponentFactory, + getSupportedServiceNames_MSAAServiceImpl, + ::cppu::createSingleComponentFactory, 0, 0 }, { 0, 0, 0, 0, 0, 0 } @@ -267,12 +334,12 @@ static struct ::cppu::ImplementationEntry s_component_entries [] = extern "C" { - SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + SAL_DLLPUBLIC_EXPORT void SAL_CALL iacc2_component_getImplementationEnvironment( sal_Char const ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) { *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; } - SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + SAL_DLLPUBLIC_EXPORT void * SAL_CALL iacc2_component_getFactory( sal_Char const * implName, lang::XMultiServiceFactory * xMgr, registry::XRegistryKey * xRegistry ) { diff --git a/winaccessibility/source/service/winaccessibility.component b/winaccessibility/source/service/winaccessibility.component index 3a73858f8062..71ea6de8bc87 100644 --- a/winaccessibility/source/service/winaccessibility.component +++ b/winaccessibility/source/service/winaccessibility.component @@ -16,7 +16,7 @@ * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . --> - -- cgit v1.2.3