1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #include <cppuhelper/bootstrap.hxx>
23 #include <com/sun/star/bridge/XUnoUrlResolver.hpp>
24 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
25 #include <vcl/window.hxx>
26 #include <toolkit/awt/Vclxwindow.hxx>
27 
28 #ifndef _SV_SYSDATA_HXX
29 #if defined( WIN ) || defined( WNT ) || defined( OS2 )
30 typedef sal_Int32 HWND;
31 typedef sal_Int32 HMENU;
32 typedef sal_Int32 HDC;
33 typedef void *PVOID;
34 typedef PVOID HANDLE;
35 typedef HANDLE HFONT;
36 #endif
37 #include <vcl/sysdata.hxx>
38 #endif
39 
40 #include "AccTopWindowListener.hxx"
41 #include "unomsaaevent.hxx"
42 
43 #include <com/sun/star/awt/XExtendedToolkit.hpp>
44 #include <com/sun/star/uno/XInterface.hpp>
45 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
46 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
47 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
48 #include <com/sun/star/accessibility/AccessibleRole.hpp>
49 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
50 
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::bridge;
54 using namespace com::sun::star::awt;
55 using namespace rtl;
56 using namespace cppu;
57 //////////////////////////////////////////////////////////////////////
58 // Construction/Destruction
59 //////////////////////////////////////////////////////////////////////
60 
61 AccTopWindowListener* g_pTop = NULL;
62 //when proccess exit, call FreeTopWindowListener() in svmain
FreeTopWindowListener()63 void FreeTopWindowListener()
64 {
65     if( g_pTop )
66     {
67         g_pTop->release();
68         g_pTop = NULL;
69     }
70 }
71 
72 /**
73  *	As a global method to invoke the handleWindowOpened() method
74  */
handleWindowOpened_impl(long pAcc)75 void handleWindowOpened_impl(long pAcc)
76 {
77     if( g_pTop && pAcc != NULL )
78         g_pTop->handleWindowOpened( (com::sun::star::accessibility::XAccessible*)((void*)pAcc) );
79 }
80 
81 /**
82  *	For the new opened window, generate all the UNO accessible's object, COM object and add
83  *	accessible listener to monitor all these objects.
84  *	@param pAccessible		the accessible of the new opened window
85  */
handleWindowOpened(com::sun::star::accessibility::XAccessible * pAccessible)86 void AccTopWindowListener::handleWindowOpened( com::sun::star::accessibility::XAccessible* pAccessible )
87 {
88     //get SystemData from window
89     VCLXWindow* pvclwindow = (VCLXWindow*)pAccessible;
90     Window* window = pvclwindow->GetWindow();
91 	// The SalFrame of window may be destructed at this time
92     const SystemEnvData* systemdata = NULL;
93 	try
94 	{
95 		systemdata = window->GetSystemData();
96 	}
97 	catch(...)
98 	{
99 		systemdata = NULL;
100 	}
101     Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
102     if(!xContext.is())
103     {
104         return;
105     }
106     com::sun::star::accessibility::XAccessibleContext* pAccessibleContext = xContext.get();
107     //Only AccessibleContext exist, add all listeners
108     if(pAccessibleContext != NULL && systemdata != NULL)
109     {
110         accManagerAgent.SaveTopWindowHandle((HWND)systemdata->hWnd,  pAccessible);
111 
112         AddAllListeners(pAccessible,NULL,(HWND)systemdata->hWnd);
113 
114         if( window->GetStyle() & WB_MOVEABLE )
115             accManagerAgent.IncreaseState( pAccessible, -1 /* U_MOVEBLE */ );
116 
117         short role = pAccessibleContext->getAccessibleRole();
118 
119 
120         if (role == com::sun::star::accessibility::AccessibleRole::POPUP_MENU ||
121                 role == com::sun::star::accessibility::AccessibleRole::MENU )
122         {
123             accManagerAgent.NotifyAccEvent(UM_EVENT_MENUPOPUPSTART, pAccessible);
124         }
125 
126         if (role == com::sun::star::accessibility::AccessibleRole::FRAME ||
127                 role == com::sun::star::accessibility::AccessibleRole::DIALOG ||
128                 role == com::sun::star::accessibility::AccessibleRole::WINDOW ||
129 				role == com::sun::star::accessibility::AccessibleRole::ALERT)
130         {
131             accManagerAgent.NotifyAccEvent(UM_EVENT_SHOW, pAccessible);
132         }
133     }
134 }
135 
AccTopWindowListener()136 AccTopWindowListener::AccTopWindowListener():
137         accManagerAgent(),
138         m_refcount(1)
139 {
140 }
141 
~AccTopWindowListener()142 AccTopWindowListener::~AccTopWindowListener()
143 {
144 }
145 
146 /**
147  *	It is invoked when a new window is opened, the source of this EventObject is the window
148  */
windowOpened(const::com::sun::star::lang::EventObject & e)149 void AccTopWindowListener::windowOpened( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException)
150 {
151     if ( !e.Source.is())
152     {
153         return;
154     }
155 
156     Reference< com::sun::star::accessibility::XAccessible > xAccessible ( e.Source, UNO_QUERY );
157     com::sun::star::accessibility::XAccessible* pAccessible = xAccessible.get();
158     if ( pAccessible == NULL)
159     {
160         return;
161     }
162 
163     handleWindowOpened(pAccessible);
164 
165 }
166 
167 /**
168  *	Add the accessible event listener to object and all its children objects.
169  *	@param	pAccessible		the accessible object
170  *	@param	pParentXAcc		the parent of current accessible object
171  *	@param	pWND			the handle of top window which current object resides
172  */
AddAllListeners(com::sun::star::accessibility::XAccessible * pAccessible,com::sun::star::accessibility::XAccessible * pParentXAcc,HWND pWND)173 void AccTopWindowListener::AddAllListeners(com::sun::star::accessibility::XAccessible* pAccessible, com::sun::star::accessibility::XAccessible* pParentXAcc, HWND pWND)
174 {
175     Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
176     if(!xContext.is())
177     {
178         return;
179     }
180     com::sun::star::accessibility::XAccessibleContext* pAccessibleContext = xContext.get();
181     if(pAccessibleContext == NULL)
182     {
183         return;
184     }
185 
186     accManagerAgent.InsertAccObj( pAccessible, pParentXAcc,pWND );
187 
188     if (!accManagerAgent.IsContainer(pAccessible))
189     {
190         return;
191     }
192 
193 
194     short role = pAccessibleContext->getAccessibleRole();
195     if(com::sun::star::accessibility::AccessibleRole::DOCUMENT == role )
196     {
197         if(accManagerAgent.IsStateManageDescendant(pAccessible))
198         {
199             return ;
200         }
201     }
202 
203 
204     int count = pAccessibleContext->getAccessibleChildCount();
205     for (int i=0;i<count;i++)
206     {
207         Reference<com::sun::star::accessibility::XAccessible> mxAccessible
208         = pAccessibleContext->getAccessibleChild(i);
209 
210         com::sun::star::accessibility::XAccessible* mpAccessible = mxAccessible.get();
211         if(mpAccessible != NULL)
212         {
213             Reference<com::sun::star::accessibility::XAccessibleContext> mxAccessibleContext
214             = mpAccessible->getAccessibleContext();
215             com::sun::star::accessibility::XAccessibleContext* mpContext = mxAccessibleContext.get();
216             if(mpContext != NULL)
217             {
218                 //fprintf(output, "go on add child's children event listener\n");
219                 AddAllListeners(mpAccessible,pAccessible,pWND);
220             }
221         }
222     }
223 }
224 
windowClosing(const::com::sun::star::lang::EventObject & e)225 void AccTopWindowListener::windowClosing( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException)
226 {
227 }
228 
229 /**
230  *	Invoke this method when the top window is closed, remove all the objects and its children
231  *	from current manager's cache, and remove the COM object and the accessible event listener
232  *	assigned to the accessible objects.
233  */
windowClosed(const::com::sun::star::lang::EventObject & e)234 void AccTopWindowListener::windowClosed( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException)
235 {
236     if ( !e.Source.is())
237     {
238         return;
239     }
240     Reference< com::sun::star::accessibility::XAccessible > xAccessible ( e.Source, UNO_QUERY );
241     com::sun::star::accessibility::XAccessible* pAccessible = xAccessible.get();
242     if ( pAccessible == NULL)
243     {
244         return;
245     }
246 
247 
248     VCLXWindow* pvclwindow = (VCLXWindow*)pAccessible;
249     Window* window = pvclwindow->GetWindow();
250     const SystemEnvData* systemdata=window->GetSystemData();
251 
252     Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
253     if(!xContext.is())
254     {
255         return;
256     }
257     com::sun::star::accessibility::XAccessibleContext* pAccessibleContext = xContext.get();
258 
259     short role = -1;
260     if(pAccessibleContext != NULL)
261     {
262         role = pAccessibleContext->getAccessibleRole();
263 
264         if (role == com::sun::star::accessibility::AccessibleRole::POPUP_MENU ||
265                 role == com::sun::star::accessibility::AccessibleRole::MENU)
266         {
267             accManagerAgent.NotifyAccEvent(UM_EVENT_MENUPOPUPEND, pAccessible);
268         }
269     }
270 
271 
272     accManagerAgent.DeleteChildrenAccObj( pAccessible );
273     if( role != com::sun::star::accessibility::AccessibleRole::POPUP_MENU )
274         accManagerAgent.DeleteAccObj( pAccessible );
275 
276 }
277 
windowMinimized(const::com::sun::star::lang::EventObject &)278 void AccTopWindowListener::windowMinimized( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
279 {
280 }
281 
windowNormalized(const::com::sun::star::lang::EventObject &)282 void AccTopWindowListener::windowNormalized( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
283 {
284 }
285 
windowActivated(const::com::sun::star::lang::EventObject &)286 void AccTopWindowListener::windowActivated( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
287 {
288 }
289 
windowDeactivated(const::com::sun::star::lang::EventObject &)290 void AccTopWindowListener::windowDeactivated( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
291 {
292 }
293 
disposing(const::com::sun::star::lang::EventObject &)294 void AccTopWindowListener::disposing( const ::com::sun::star::lang::EventObject&  ) throw (::com::sun::star::uno::RuntimeException)
295 {
296 }
297 
298 //need to investigate further
queryInterface(const::com::sun::star::uno::Type & aType)299 ::com::sun::star::uno::Any SAL_CALL AccTopWindowListener::queryInterface( const ::com::sun::star::uno::Type& aType ) throw (::com::sun::star::uno::RuntimeException)
300 {
301     if (aType.equals( ::getCppuType( (Reference< com::sun::star::awt::XTopWindowListener> const *)0 ) ))
302     {
303         Reference< com::sun::star::awt::XTopWindowListener> xTopListener( static_cast< com::sun::star::awt::XTopWindowListener* >(this));
304         return makeAny(xTopListener);
305     }
306     return Any();
307 }
308 
acquire()309 void AccTopWindowListener::acquire( ) throw ()
310 {
311     ::osl_incrementInterlockedCount( &m_refcount );
312 }
313 
release()314 void AccTopWindowListener::release() throw ()
315 {
316     // thread-safe decrementation of reference count
317     if (0 == ::osl_decrementInterlockedCount( &m_refcount ))
318     {
319         delete this; // shutdown this object
320     }
321 }
322