blob: 2d47a2d48c676fb047c9597c85032c58b3010c14 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include <cppuhelper/bootstrap.hxx>
#include <com/sun/star/bridge/XUnoUrlResolver.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <vcl/window.hxx>
#include <toolkit/awt/Vclxwindow.hxx>
#ifndef _SV_SYSDATA_HXX
#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
#include <vcl/sysdata.hxx>
#endif
#include "AccTopWindowListener.hxx"
#include "unomsaaevent.hxx"
#include <com/sun/star/awt/XExtendedToolkit.hpp>
#include <com/sun/star/uno/XInterface.hpp>
#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
#include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
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()
{
if( g_pTop )
{
g_pTop->release();
g_pTop = NULL;
}
}
/**
* As a global method to invoke the handleWindowOpened() method
*/
void handleWindowOpened_impl(long pAcc)
{
if( g_pTop && pAcc != NULL )
g_pTop->handleWindowOpened( (com::sun::star::accessibility::XAccessible*)((void*)pAcc) );
}
/**
* For the new opened window, generate all the UNO accessible's object, COM object and add
* accessible listener to monitor all these objects.
* @param pAccessible the accessible of the new opened window
*/
void AccTopWindowListener::handleWindowOpened( com::sun::star::accessibility::XAccessible* pAccessible )
{
//get SystemData from window
VCLXWindow* pvclwindow = (VCLXWindow*)pAccessible;
Window* window = pvclwindow->GetWindow();
// The SalFrame of window may be destructed at this time
const SystemEnvData* systemdata = NULL;
try
{
systemdata = window->GetSystemData();
}
catch(...)
{
systemdata = NULL;
}
Reference<com::sun::star::accessibility::XAccessibleContext> 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((HWND)systemdata->hWnd, pAccessible);
AddAllListeners(pAccessible,NULL,(HWND)systemdata->hWnd);
if( window->GetStyle() & WB_MOVEABLE )
accManagerAgent.IncreaseState( pAccessible, -1 /* U_MOVEBLE */ );
short role = pAccessibleContext->getAccessibleRole();
if (role == com::sun::star::accessibility::AccessibleRole::POPUP_MENU ||
role == com::sun::star::accessibility::AccessibleRole::MENU )
{
accManagerAgent.NotifyAccEvent(UM_EVENT_MENUPOPUPSTART, pAccessible);
}
if (role == com::sun::star::accessibility::AccessibleRole::FRAME ||
role == com::sun::star::accessibility::AccessibleRole::DIALOG ||
role == com::sun::star::accessibility::AccessibleRole::WINDOW ||
role == com::sun::star::accessibility::AccessibleRole::ALERT)
{
accManagerAgent.NotifyAccEvent(UM_EVENT_SHOW, pAccessible);
}
}
}
AccTopWindowListener::AccTopWindowListener():
accManagerAgent(),
m_refcount(1)
{
}
AccTopWindowListener::~AccTopWindowListener()
{
}
/**
* It is invoked when a new window is opened, the source of this EventObject is the window
*/
void AccTopWindowListener::windowOpened( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException)
{
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;
}
handleWindowOpened(pAccessible);
}
/**
* Add the accessible event listener to object and all its children objects.
* @param pAccessible the accessible object
* @param pParentXAcc the parent of current accessible object
* @param pWND the handle of top window which current object resides
*/
void AccTopWindowListener::AddAllListeners(com::sun::star::accessibility::XAccessible* pAccessible, com::sun::star::accessibility::XAccessible* pParentXAcc, HWND pWND)
{
Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
if(!xContext.is())
{
return;
}
com::sun::star::accessibility::XAccessibleContext* pAccessibleContext = xContext.get();
if(pAccessibleContext == NULL)
{
return;
}
accManagerAgent.InsertAccObj( pAccessible, pParentXAcc,pWND );
if (!accManagerAgent.IsContainer(pAccessible))
{
return;
}
short role = pAccessibleContext->getAccessibleRole();
if(com::sun::star::accessibility::AccessibleRole::DOCUMENT == role )
{
if(accManagerAgent.IsStateManageDescendant(pAccessible))
{
return ;
}
}
int count = pAccessibleContext->getAccessibleChildCount();
for (int i=0;i<count;i++)
{
Reference<com::sun::star::accessibility::XAccessible> mxAccessible
= pAccessibleContext->getAccessibleChild(i);
com::sun::star::accessibility::XAccessible* mpAccessible = mxAccessible.get();
if(mpAccessible != NULL)
{
Reference<com::sun::star::accessibility::XAccessibleContext> mxAccessibleContext
= 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);
}
}
}
}
void AccTopWindowListener::windowClosing( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException)
{
}
/**
* Invoke this method when the top window is closed, remove all the objects and its children
* from current manager's cache, and remove the COM object and the accessible event listener
* assigned to the accessible objects.
*/
void AccTopWindowListener::windowClosed( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException)
{
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();
const SystemEnvData* systemdata=window->GetSystemData();
Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
if(!xContext.is())
{
return;
}
com::sun::star::accessibility::XAccessibleContext* pAccessibleContext = xContext.get();
short role = -1;
if(pAccessibleContext != NULL)
{
role = pAccessibleContext->getAccessibleRole();
if (role == com::sun::star::accessibility::AccessibleRole::POPUP_MENU ||
role == com::sun::star::accessibility::AccessibleRole::MENU)
{
accManagerAgent.NotifyAccEvent(UM_EVENT_MENUPOPUPEND, pAccessible);
}
}
accManagerAgent.DeleteChildrenAccObj( pAccessible );
if( role != com::sun::star::accessibility::AccessibleRole::POPUP_MENU )
accManagerAgent.DeleteAccObj( pAccessible );
}
void AccTopWindowListener::windowMinimized( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
{
}
void AccTopWindowListener::windowNormalized( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
{
}
void AccTopWindowListener::windowActivated( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
{
}
void AccTopWindowListener::windowDeactivated( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
{
}
void AccTopWindowListener::disposing( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
{
}
//need to investigate further
::com::sun::star::uno::Any SAL_CALL AccTopWindowListener::queryInterface( const ::com::sun::star::uno::Type& aType ) throw (::com::sun::star::uno::RuntimeException)
{
if (aType.equals( ::getCppuType( (Reference< com::sun::star::awt::XTopWindowListener> const *)0 ) ))
{
Reference< com::sun::star::awt::XTopWindowListener> xTopListener( static_cast< com::sun::star::awt::XTopWindowListener* >(this));
return makeAny(xTopListener);
}
return Any();
}
void AccTopWindowListener::acquire( ) throw ()
{
::osl_incrementInterlockedCount( &m_refcount );
}
void AccTopWindowListener::release() throw ()
{
// thread-safe decrementation of reference count
if (0 == ::osl_decrementInterlockedCount( &m_refcount ))
{
delete this; // shutdown this object
}
}