merge the formfield patch from ooo-build
[ooovba.git] / vcl / aqua / source / a11y / aqua11yfocustracker.cxx
blob91514db0ac5ea7dbd2a35716b89c01ccafc2d738
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: aqua11yfocustracker.cxx,v $
11 * $Revision: 1.3 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_vcl.hxx"
35 #include "aqua11yfocustracker.hxx"
36 #include "documentfocuslistener.hxx"
38 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
39 #include <com/sun/star/accessibility/XAccessibleSelection.hpp>
40 #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
41 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
42 #include <com/sun/star/accessibility/AccessibleRole.hpp>
44 #include "vcl/svapp.hxx"
45 #include "vcl/window.hxx"
46 #include "vcl/toolbox.hxx"
47 #include "vcl/menu.hxx"
49 using namespace ::com::sun::star::accessibility;
50 using namespace ::com::sun::star::uno;
52 //------------------------------------------------------------------------------
54 static inline Window *
55 getWindow(const ::VclSimpleEvent *pEvent)
57 return static_cast< const ::VclWindowEvent *> (pEvent)->GetWindow();
61 //------------------------------------------------------------------------------
63 // callback function for Application::addEventListener
65 long AquaA11yFocusTracker::WindowEventHandler(AquaA11yFocusTracker *pFocusTracker, ::VclSimpleEvent const *pEvent)
67 switch (pEvent->GetId())
69 case VCLEVENT_WINDOW_PAINT:
70 pFocusTracker-> toolbox_open_floater( getWindow(pEvent) );
71 break;
72 case VCLEVENT_WINDOW_GETFOCUS:
73 pFocusTracker->window_got_focus( getWindow(pEvent) );
74 break;
75 case VCLEVENT_OBJECT_DYING:
76 pFocusTracker->m_aDocumentWindowList.erase( getWindow(pEvent) );
77 // intentional pass through ..
78 case VCLEVENT_TOOLBOX_HIGHLIGHTOFF:
79 pFocusTracker->toolbox_highlight_off( getWindow(pEvent) );
80 break;
81 case VCLEVENT_TOOLBOX_HIGHLIGHT:
82 pFocusTracker->toolbox_highlight_on( getWindow(pEvent) );
83 break;
84 case VCLEVENT_TABPAGE_ACTIVATE:
85 pFocusTracker->tabpage_activated( getWindow(pEvent) );
86 break;
87 case VCLEVENT_MENU_HIGHLIGHT:
88 pFocusTracker->menu_highlighted( static_cast < const VclMenuEvent * > (pEvent) );
89 break;
90 default:
91 break;
94 return 0;
97 //------------------------------------------------------------------------------
99 AquaA11yFocusTracker::AquaA11yFocusTracker() :
100 m_aWindowEventLink(this, (PSTUB) WindowEventHandler),
101 m_xDocumentFocusListener(new DocumentFocusListener(*this))
103 Application::AddEventListener(m_aWindowEventLink);
104 window_got_focus(Application::GetFocusWindow());
107 //------------------------------------------------------------------------------
109 void AquaA11yFocusTracker::setFocusedObject(const Reference< XAccessible >& xAccessible)
111 if( xAccessible != m_xFocusedObject )
113 m_xFocusedObject = xAccessible;
115 if( m_aFocusListener.is() )
116 m_aFocusListener->focusedObjectChanged(xAccessible);
120 //------------------------------------------------------------------------------
122 void AquaA11yFocusTracker::notify_toolbox_item_focus(ToolBox *pToolBox)
124 Reference< XAccessible > xAccessible( pToolBox->GetAccessible() );
126 if( xAccessible.is() )
128 Reference< XAccessibleContext > xContext(xAccessible->getAccessibleContext());
130 if( xContext.is() )
132 sal_Int32 nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() );
133 if( nPos != TOOLBOX_ITEM_NOTFOUND )
134 setFocusedObject( xContext->getAccessibleChild( nPos ) );
139 //------------------------------------------------------------------------------
141 void AquaA11yFocusTracker::toolbox_open_floater(Window *pWindow)
143 bool bToolboxFound = false;
144 bool bFloatingWindowFound = false;
145 Window * pFloatingWindow = NULL;
146 while ( pWindow != NULL ) {
147 if ( pWindow->GetType() == WINDOW_TOOLBOX ) {
148 bToolboxFound = true;
149 } else if ( pWindow->GetType() == WINDOW_FLOATINGWINDOW ) {
150 bFloatingWindowFound = true;
151 pFloatingWindow = pWindow;
153 pWindow = pWindow->GetParent();
155 if ( bToolboxFound && bFloatingWindowFound ) {
156 Reference < XAccessible > rxAccessible = pFloatingWindow -> GetAccessible();
157 if ( ! rxAccessible.is() ) {
158 return;
160 Reference < XAccessibleContext > rxContext = rxAccessible -> getAccessibleContext();
161 if ( ! rxContext.is() ) {
162 return;
164 if ( rxContext -> getAccessibleChildCount() > 0 ) {
165 Reference < XAccessible > rxAccessibleChild = rxContext -> getAccessibleChild( 0 );
166 if ( ! rxAccessibleChild.is() ) {
167 return;
169 setFocusedObject ( rxAccessibleChild );
174 //------------------------------------------------------------------------------
176 void AquaA11yFocusTracker::toolbox_highlight_on(Window *pWindow)
178 // Make sure either the toolbox or its parent toolbox has the focus
179 if ( ! pWindow->HasFocus() )
181 ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() );
182 if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() )
183 return;
186 notify_toolbox_item_focus(static_cast <ToolBox *> (pWindow));
189 //------------------------------------------------------------------------------
191 void AquaA11yFocusTracker::toolbox_highlight_off(Window *pWindow)
193 ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() );
195 // Notify when leaving sub toolboxes
196 if( pToolBoxParent && pToolBoxParent->HasFocus() )
197 notify_toolbox_item_focus( pToolBoxParent );
200 //------------------------------------------------------------------------------
202 void AquaA11yFocusTracker::tabpage_activated(Window *pWindow)
204 Reference< XAccessible > xAccessible( pWindow->GetAccessible() );
206 if( xAccessible.is() )
208 Reference< XAccessibleSelection > xSelection(xAccessible->getAccessibleContext(), UNO_QUERY);
210 if( xSelection.is() )
211 setFocusedObject( xSelection->getSelectedAccessibleChild(0) );
215 //------------------------------------------------------------------------------
217 void AquaA11yFocusTracker::menu_highlighted(const VclMenuEvent *pEvent)
219 Menu * pMenu = pEvent->GetMenu();
221 if( pMenu )
223 Reference< XAccessible > xAccessible( pMenu->GetAccessible() );
225 if( xAccessible.is() )
226 setFocusedObject( xAccessible );
230 //------------------------------------------------------------------------------
232 void AquaA11yFocusTracker::window_got_focus(Window *pWindow)
234 // The menu bar is handled through VCLEVENT_MENU_HIGHLIGHTED
235 if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WINDOW_MENUBARWINDOW )
236 return;
238 // ToolBoxes are handled through VCLEVENT_TOOLBOX_HIGHLIGHT
239 if( pWindow->GetType() == WINDOW_TOOLBOX )
240 return;
242 if( pWindow->GetType() == WINDOW_TABCONTROL )
244 tabpage_activated( pWindow );
245 return;
248 Reference< XAccessible > xAccessible(pWindow->GetAccessible());
250 if( ! xAccessible.is() )
251 return;
253 Reference< XAccessibleContext > xContext = xAccessible->getAccessibleContext();
255 if( ! xContext.is() )
256 return;
258 Reference< XAccessibleStateSet > xStateSet = xContext->getAccessibleStateSet();
260 if( ! xStateSet.is() )
261 return;
263 /* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we
264 * need to add listeners to the children instead of re-using the tabpage stuff
266 if( xStateSet->contains(AccessibleStateType::FOCUSED) && (pWindow->GetType() != WINDOW_TREELISTBOX) )
268 setFocusedObject( xAccessible );
270 else
272 if( m_aDocumentWindowList.find(pWindow) == m_aDocumentWindowList.end() )
274 m_aDocumentWindowList.insert(pWindow);
275 m_xDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet);
277 #ifdef ENABLE_TRACING
278 else
279 fprintf(stderr, "Window %p already in the list\n", pWindow );
280 #endif