xref: /AOO41X/main/vcl/aqua/source/a11y/aqua11yfocustracker.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
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