1*9f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*9f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*9f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*9f62ea84SAndrew Rist * distributed with this work for additional information
6*9f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*9f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*9f62ea84SAndrew Rist * "License"); you may not use this file except in compliance
9*9f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11*9f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13*9f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*9f62ea84SAndrew Rist * software distributed under the License is distributed on an
15*9f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f62ea84SAndrew Rist * KIND, either express or implied. See the License for the
17*9f62ea84SAndrew Rist * specific language governing permissions and limitations
18*9f62ea84SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20*9f62ea84SAndrew Rist *************************************************************/
21*9f62ea84SAndrew Rist
22*9f62ea84SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include "vcl/svapp.hxx"
28cdf0e10cSrcweir #include "vcl/window.hxx"
29cdf0e10cSrcweir #include "vcl/toolbox.hxx"
30cdf0e10cSrcweir #include "vcl/menu.hxx"
31cdf0e10cSrcweir
32cdf0e10cSrcweir #include "aqua/aqua11yfocustracker.hxx"
33cdf0e10cSrcweir
34cdf0e10cSrcweir #include "documentfocuslistener.hxx"
35cdf0e10cSrcweir
36cdf0e10cSrcweir #include <com/sun/star/accessibility/XAccessibleContext.hpp>
37cdf0e10cSrcweir #include <com/sun/star/accessibility/XAccessibleSelection.hpp>
38cdf0e10cSrcweir #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
39cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleRole.hpp>
41cdf0e10cSrcweir
42cdf0e10cSrcweir using namespace ::com::sun::star::accessibility;
43cdf0e10cSrcweir using namespace ::com::sun::star::uno;
44cdf0e10cSrcweir
45cdf0e10cSrcweir //------------------------------------------------------------------------------
46cdf0e10cSrcweir
47cdf0e10cSrcweir static inline Window *
getWindow(const::VclSimpleEvent * pEvent)48cdf0e10cSrcweir getWindow(const ::VclSimpleEvent *pEvent)
49cdf0e10cSrcweir {
50cdf0e10cSrcweir return static_cast< const ::VclWindowEvent *> (pEvent)->GetWindow();
51cdf0e10cSrcweir }
52cdf0e10cSrcweir
53cdf0e10cSrcweir
54cdf0e10cSrcweir //------------------------------------------------------------------------------
55cdf0e10cSrcweir
56cdf0e10cSrcweir // callback function for Application::addEventListener
57cdf0e10cSrcweir
WindowEventHandler(AquaA11yFocusTracker * pFocusTracker,::VclSimpleEvent const * pEvent)58cdf0e10cSrcweir long AquaA11yFocusTracker::WindowEventHandler(AquaA11yFocusTracker *pFocusTracker, ::VclSimpleEvent const *pEvent)
59cdf0e10cSrcweir {
60cdf0e10cSrcweir switch (pEvent->GetId())
61cdf0e10cSrcweir {
62cdf0e10cSrcweir case VCLEVENT_WINDOW_PAINT:
63cdf0e10cSrcweir pFocusTracker-> toolbox_open_floater( getWindow(pEvent) );
64cdf0e10cSrcweir break;
65cdf0e10cSrcweir case VCLEVENT_WINDOW_GETFOCUS:
66cdf0e10cSrcweir pFocusTracker->window_got_focus( getWindow(pEvent) );
67cdf0e10cSrcweir break;
68cdf0e10cSrcweir case VCLEVENT_OBJECT_DYING:
69cdf0e10cSrcweir pFocusTracker->m_aDocumentWindowList.erase( getWindow(pEvent) );
70cdf0e10cSrcweir // intentional pass through ..
71cdf0e10cSrcweir case VCLEVENT_TOOLBOX_HIGHLIGHTOFF:
72cdf0e10cSrcweir pFocusTracker->toolbox_highlight_off( getWindow(pEvent) );
73cdf0e10cSrcweir break;
74cdf0e10cSrcweir case VCLEVENT_TOOLBOX_HIGHLIGHT:
75cdf0e10cSrcweir pFocusTracker->toolbox_highlight_on( getWindow(pEvent) );
76cdf0e10cSrcweir break;
77cdf0e10cSrcweir case VCLEVENT_TABPAGE_ACTIVATE:
78cdf0e10cSrcweir pFocusTracker->tabpage_activated( getWindow(pEvent) );
79cdf0e10cSrcweir break;
80cdf0e10cSrcweir case VCLEVENT_MENU_HIGHLIGHT:
81cdf0e10cSrcweir pFocusTracker->menu_highlighted( static_cast < const VclMenuEvent * > (pEvent) );
82cdf0e10cSrcweir break;
83cdf0e10cSrcweir default:
84cdf0e10cSrcweir break;
85cdf0e10cSrcweir };
86cdf0e10cSrcweir
87cdf0e10cSrcweir return 0;
88cdf0e10cSrcweir }
89cdf0e10cSrcweir
90cdf0e10cSrcweir //------------------------------------------------------------------------------
91cdf0e10cSrcweir
AquaA11yFocusTracker()92cdf0e10cSrcweir AquaA11yFocusTracker::AquaA11yFocusTracker() :
93cdf0e10cSrcweir m_aWindowEventLink(this, (PSTUB) WindowEventHandler),
94cdf0e10cSrcweir m_xDocumentFocusListener(new DocumentFocusListener(*this))
95cdf0e10cSrcweir {
96cdf0e10cSrcweir Application::AddEventListener(m_aWindowEventLink);
97cdf0e10cSrcweir window_got_focus(Application::GetFocusWindow());
98cdf0e10cSrcweir }
99cdf0e10cSrcweir
100cdf0e10cSrcweir //------------------------------------------------------------------------------
101cdf0e10cSrcweir
setFocusedObject(const Reference<XAccessible> & xAccessible)102cdf0e10cSrcweir void AquaA11yFocusTracker::setFocusedObject(const Reference< XAccessible >& xAccessible)
103cdf0e10cSrcweir {
104cdf0e10cSrcweir if( xAccessible != m_xFocusedObject )
105cdf0e10cSrcweir {
106cdf0e10cSrcweir m_xFocusedObject = xAccessible;
107cdf0e10cSrcweir
108cdf0e10cSrcweir if( m_aFocusListener.is() )
109cdf0e10cSrcweir m_aFocusListener->focusedObjectChanged(xAccessible);
110cdf0e10cSrcweir }
111cdf0e10cSrcweir }
112cdf0e10cSrcweir
113cdf0e10cSrcweir //------------------------------------------------------------------------------
114cdf0e10cSrcweir
notify_toolbox_item_focus(ToolBox * pToolBox)115cdf0e10cSrcweir void AquaA11yFocusTracker::notify_toolbox_item_focus(ToolBox *pToolBox)
116cdf0e10cSrcweir {
117cdf0e10cSrcweir Reference< XAccessible > xAccessible( pToolBox->GetAccessible() );
118cdf0e10cSrcweir
119cdf0e10cSrcweir if( xAccessible.is() )
120cdf0e10cSrcweir {
121cdf0e10cSrcweir Reference< XAccessibleContext > xContext(xAccessible->getAccessibleContext());
122cdf0e10cSrcweir
123cdf0e10cSrcweir if( xContext.is() )
124cdf0e10cSrcweir {
125cdf0e10cSrcweir sal_Int32 nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() );
126cdf0e10cSrcweir if( nPos != TOOLBOX_ITEM_NOTFOUND )
127cdf0e10cSrcweir setFocusedObject( xContext->getAccessibleChild( nPos ) );
128cdf0e10cSrcweir }
129cdf0e10cSrcweir }
130cdf0e10cSrcweir }
131cdf0e10cSrcweir
132cdf0e10cSrcweir //------------------------------------------------------------------------------
133cdf0e10cSrcweir
toolbox_open_floater(Window * pWindow)134cdf0e10cSrcweir void AquaA11yFocusTracker::toolbox_open_floater(Window *pWindow)
135cdf0e10cSrcweir {
136cdf0e10cSrcweir bool bToolboxFound = false;
137cdf0e10cSrcweir bool bFloatingWindowFound = false;
138cdf0e10cSrcweir Window * pFloatingWindow = NULL;
139cdf0e10cSrcweir while ( pWindow != NULL ) {
140cdf0e10cSrcweir if ( pWindow->GetType() == WINDOW_TOOLBOX ) {
141cdf0e10cSrcweir bToolboxFound = true;
142cdf0e10cSrcweir } else if ( pWindow->GetType() == WINDOW_FLOATINGWINDOW ) {
143cdf0e10cSrcweir bFloatingWindowFound = true;
144cdf0e10cSrcweir pFloatingWindow = pWindow;
145cdf0e10cSrcweir }
146cdf0e10cSrcweir pWindow = pWindow->GetParent();
147cdf0e10cSrcweir }
148cdf0e10cSrcweir if ( bToolboxFound && bFloatingWindowFound ) {
149cdf0e10cSrcweir Reference < XAccessible > rxAccessible = pFloatingWindow -> GetAccessible();
150cdf0e10cSrcweir if ( ! rxAccessible.is() ) {
151cdf0e10cSrcweir return;
152cdf0e10cSrcweir }
153cdf0e10cSrcweir Reference < XAccessibleContext > rxContext = rxAccessible -> getAccessibleContext();
154cdf0e10cSrcweir if ( ! rxContext.is() ) {
155cdf0e10cSrcweir return;
156cdf0e10cSrcweir }
157cdf0e10cSrcweir if ( rxContext -> getAccessibleChildCount() > 0 ) {
158cdf0e10cSrcweir Reference < XAccessible > rxAccessibleChild = rxContext -> getAccessibleChild( 0 );
159cdf0e10cSrcweir if ( ! rxAccessibleChild.is() ) {
160cdf0e10cSrcweir return;
161cdf0e10cSrcweir }
162cdf0e10cSrcweir setFocusedObject ( rxAccessibleChild );
163cdf0e10cSrcweir }
164cdf0e10cSrcweir }
165cdf0e10cSrcweir }
166cdf0e10cSrcweir
167cdf0e10cSrcweir //------------------------------------------------------------------------------
168cdf0e10cSrcweir
toolbox_highlight_on(Window * pWindow)169cdf0e10cSrcweir void AquaA11yFocusTracker::toolbox_highlight_on(Window *pWindow)
170cdf0e10cSrcweir {
171cdf0e10cSrcweir // Make sure either the toolbox or its parent toolbox has the focus
172cdf0e10cSrcweir if ( ! pWindow->HasFocus() )
173cdf0e10cSrcweir {
174cdf0e10cSrcweir ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() );
175cdf0e10cSrcweir if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() )
176cdf0e10cSrcweir return;
177cdf0e10cSrcweir }
178cdf0e10cSrcweir
179cdf0e10cSrcweir notify_toolbox_item_focus(static_cast <ToolBox *> (pWindow));
180cdf0e10cSrcweir }
181cdf0e10cSrcweir
182cdf0e10cSrcweir //------------------------------------------------------------------------------
183cdf0e10cSrcweir
toolbox_highlight_off(Window * pWindow)184cdf0e10cSrcweir void AquaA11yFocusTracker::toolbox_highlight_off(Window *pWindow)
185cdf0e10cSrcweir {
186cdf0e10cSrcweir ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() );
187cdf0e10cSrcweir
188cdf0e10cSrcweir // Notify when leaving sub toolboxes
189cdf0e10cSrcweir if( pToolBoxParent && pToolBoxParent->HasFocus() )
190cdf0e10cSrcweir notify_toolbox_item_focus( pToolBoxParent );
191cdf0e10cSrcweir }
192cdf0e10cSrcweir
193cdf0e10cSrcweir //------------------------------------------------------------------------------
194cdf0e10cSrcweir
tabpage_activated(Window * pWindow)195cdf0e10cSrcweir void AquaA11yFocusTracker::tabpage_activated(Window *pWindow)
196cdf0e10cSrcweir {
197cdf0e10cSrcweir Reference< XAccessible > xAccessible( pWindow->GetAccessible() );
198cdf0e10cSrcweir
199cdf0e10cSrcweir if( xAccessible.is() )
200cdf0e10cSrcweir {
201cdf0e10cSrcweir Reference< XAccessibleSelection > xSelection(xAccessible->getAccessibleContext(), UNO_QUERY);
202cdf0e10cSrcweir
203cdf0e10cSrcweir if( xSelection.is() )
204cdf0e10cSrcweir setFocusedObject( xSelection->getSelectedAccessibleChild(0) );
205cdf0e10cSrcweir }
206cdf0e10cSrcweir }
207cdf0e10cSrcweir
208cdf0e10cSrcweir //------------------------------------------------------------------------------
209cdf0e10cSrcweir
menu_highlighted(const VclMenuEvent * pEvent)210cdf0e10cSrcweir void AquaA11yFocusTracker::menu_highlighted(const VclMenuEvent *pEvent)
211cdf0e10cSrcweir {
212cdf0e10cSrcweir Menu * pMenu = pEvent->GetMenu();
213cdf0e10cSrcweir
214cdf0e10cSrcweir if( pMenu )
215cdf0e10cSrcweir {
216cdf0e10cSrcweir Reference< XAccessible > xAccessible( pMenu->GetAccessible() );
217cdf0e10cSrcweir
218cdf0e10cSrcweir if( xAccessible.is() )
219cdf0e10cSrcweir setFocusedObject( xAccessible );
220cdf0e10cSrcweir }
221cdf0e10cSrcweir }
222cdf0e10cSrcweir
223cdf0e10cSrcweir //------------------------------------------------------------------------------
224cdf0e10cSrcweir
window_got_focus(Window * pWindow)225cdf0e10cSrcweir void AquaA11yFocusTracker::window_got_focus(Window *pWindow)
226cdf0e10cSrcweir {
227cdf0e10cSrcweir // The menu bar is handled through VCLEVENT_MENU_HIGHLIGHTED
228cdf0e10cSrcweir if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WINDOW_MENUBARWINDOW )
229cdf0e10cSrcweir return;
230cdf0e10cSrcweir
231cdf0e10cSrcweir // ToolBoxes are handled through VCLEVENT_TOOLBOX_HIGHLIGHT
232cdf0e10cSrcweir if( pWindow->GetType() == WINDOW_TOOLBOX )
233cdf0e10cSrcweir return;
234cdf0e10cSrcweir
235cdf0e10cSrcweir if( pWindow->GetType() == WINDOW_TABCONTROL )
236cdf0e10cSrcweir {
237cdf0e10cSrcweir tabpage_activated( pWindow );
238cdf0e10cSrcweir return;
239cdf0e10cSrcweir }
240cdf0e10cSrcweir
241cdf0e10cSrcweir Reference< XAccessible > xAccessible(pWindow->GetAccessible());
242cdf0e10cSrcweir
243cdf0e10cSrcweir if( ! xAccessible.is() )
244cdf0e10cSrcweir return;
245cdf0e10cSrcweir
246cdf0e10cSrcweir Reference< XAccessibleContext > xContext = xAccessible->getAccessibleContext();
247cdf0e10cSrcweir
248cdf0e10cSrcweir if( ! xContext.is() )
249cdf0e10cSrcweir return;
250cdf0e10cSrcweir
251cdf0e10cSrcweir Reference< XAccessibleStateSet > xStateSet = xContext->getAccessibleStateSet();
252cdf0e10cSrcweir
253cdf0e10cSrcweir if( ! xStateSet.is() )
254cdf0e10cSrcweir return;
255cdf0e10cSrcweir
256cdf0e10cSrcweir /* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we
257cdf0e10cSrcweir * need to add listeners to the children instead of re-using the tabpage stuff
258cdf0e10cSrcweir */
259cdf0e10cSrcweir if( xStateSet->contains(AccessibleStateType::FOCUSED) && (pWindow->GetType() != WINDOW_TREELISTBOX) )
260cdf0e10cSrcweir {
261cdf0e10cSrcweir setFocusedObject( xAccessible );
262cdf0e10cSrcweir }
263cdf0e10cSrcweir else
264cdf0e10cSrcweir {
265cdf0e10cSrcweir if( m_aDocumentWindowList.find(pWindow) == m_aDocumentWindowList.end() )
266cdf0e10cSrcweir {
267cdf0e10cSrcweir m_aDocumentWindowList.insert(pWindow);
268cdf0e10cSrcweir m_xDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet);
269cdf0e10cSrcweir }
270cdf0e10cSrcweir #ifdef ENABLE_TRACING
271cdf0e10cSrcweir else
272cdf0e10cSrcweir fprintf(stderr, "Window %p already in the list\n", pWindow );
273cdf0e10cSrcweir #endif
274cdf0e10cSrcweir }
275cdf0e10cSrcweir }
276