1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: aqua11yfocustracker.cxx,v $
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
) );
72 case VCLEVENT_WINDOW_GETFOCUS
:
73 pFocusTracker
->window_got_focus( getWindow(pEvent
) );
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
) );
81 case VCLEVENT_TOOLBOX_HIGHLIGHT
:
82 pFocusTracker
->toolbox_highlight_on( getWindow(pEvent
) );
84 case VCLEVENT_TABPAGE_ACTIVATE
:
85 pFocusTracker
->tabpage_activated( getWindow(pEvent
) );
87 case VCLEVENT_MENU_HIGHLIGHT
:
88 pFocusTracker
->menu_highlighted( static_cast < const VclMenuEvent
* > (pEvent
) );
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());
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() ) {
160 Reference
< XAccessibleContext
> rxContext
= rxAccessible
-> getAccessibleContext();
161 if ( ! rxContext
.is() ) {
164 if ( rxContext
-> getAccessibleChildCount() > 0 ) {
165 Reference
< XAccessible
> rxAccessibleChild
= rxContext
-> getAccessibleChild( 0 );
166 if ( ! rxAccessibleChild
.is() ) {
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() )
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();
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
)
238 // ToolBoxes are handled through VCLEVENT_TOOLBOX_HIGHLIGHT
239 if( pWindow
->GetType() == WINDOW_TOOLBOX
)
242 if( pWindow
->GetType() == WINDOW_TABCONTROL
)
244 tabpage_activated( pWindow
);
248 Reference
< XAccessible
> xAccessible(pWindow
->GetAccessible());
250 if( ! xAccessible
.is() )
253 Reference
< XAccessibleContext
> xContext
= xAccessible
->getAccessibleContext();
255 if( ! xContext
.is() )
258 Reference
< XAccessibleStateSet
> xStateSet
= xContext
->getAccessibleStateSet();
260 if( ! xStateSet
.is() )
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
);
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
279 fprintf(stderr
, "Window %p already in the list\n", pWindow
);