| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_vcl.hxx" |
| |
| #include "vcl/svapp.hxx" |
| #include "vcl/window.hxx" |
| #include "vcl/toolbox.hxx" |
| #include "vcl/menu.hxx" |
| |
| #include "aqua/aqua11yfocustracker.hxx" |
| |
| #include "documentfocuslistener.hxx" |
| |
| #include <com/sun/star/accessibility/XAccessibleContext.hpp> |
| #include <com/sun/star/accessibility/XAccessibleSelection.hpp> |
| #include <com/sun/star/accessibility/XAccessibleStateSet.hpp> |
| #include <com/sun/star/accessibility/AccessibleStateType.hpp> |
| #include <com/sun/star/accessibility/AccessibleRole.hpp> |
| |
| using namespace ::com::sun::star::accessibility; |
| using namespace ::com::sun::star::uno; |
| |
| //------------------------------------------------------------------------------ |
| |
| static inline Window * |
| getWindow(const ::VclSimpleEvent *pEvent) |
| { |
| return static_cast< const ::VclWindowEvent *> (pEvent)->GetWindow(); |
| } |
| |
| |
| //------------------------------------------------------------------------------ |
| |
| // callback function for Application::addEventListener |
| |
| long AquaA11yFocusTracker::WindowEventHandler(AquaA11yFocusTracker *pFocusTracker, ::VclSimpleEvent const *pEvent) |
| { |
| switch (pEvent->GetId()) |
| { |
| case VCLEVENT_WINDOW_PAINT: |
| pFocusTracker-> toolbox_open_floater( getWindow(pEvent) ); |
| break; |
| case VCLEVENT_WINDOW_GETFOCUS: |
| pFocusTracker->window_got_focus( getWindow(pEvent) ); |
| break; |
| case VCLEVENT_OBJECT_DYING: |
| pFocusTracker->m_aDocumentWindowList.erase( getWindow(pEvent) ); |
| // intentional pass through .. |
| case VCLEVENT_TOOLBOX_HIGHLIGHTOFF: |
| pFocusTracker->toolbox_highlight_off( getWindow(pEvent) ); |
| break; |
| case VCLEVENT_TOOLBOX_HIGHLIGHT: |
| pFocusTracker->toolbox_highlight_on( getWindow(pEvent) ); |
| break; |
| case VCLEVENT_TABPAGE_ACTIVATE: |
| pFocusTracker->tabpage_activated( getWindow(pEvent) ); |
| break; |
| case VCLEVENT_MENU_HIGHLIGHT: |
| pFocusTracker->menu_highlighted( static_cast < const VclMenuEvent * > (pEvent) ); |
| break; |
| default: |
| break; |
| }; |
| |
| return 0; |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| AquaA11yFocusTracker::AquaA11yFocusTracker() : |
| m_aWindowEventLink(this, (PSTUB) WindowEventHandler), |
| m_xDocumentFocusListener(new DocumentFocusListener(*this)) |
| { |
| Application::AddEventListener(m_aWindowEventLink); |
| window_got_focus(Application::GetFocusWindow()); |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| void AquaA11yFocusTracker::setFocusedObject(const Reference< XAccessible >& xAccessible) |
| { |
| if( xAccessible != m_xFocusedObject ) |
| { |
| m_xFocusedObject = xAccessible; |
| |
| if( m_aFocusListener.is() ) |
| m_aFocusListener->focusedObjectChanged(xAccessible); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| void AquaA11yFocusTracker::notify_toolbox_item_focus(ToolBox *pToolBox) |
| { |
| Reference< XAccessible > xAccessible( pToolBox->GetAccessible() ); |
| |
| if( xAccessible.is() ) |
| { |
| Reference< XAccessibleContext > xContext(xAccessible->getAccessibleContext()); |
| |
| if( xContext.is() ) |
| { |
| sal_Int32 nPos = pToolBox->GetItemPos( pToolBox->GetHighlightItemId() ); |
| if( nPos != TOOLBOX_ITEM_NOTFOUND ) |
| setFocusedObject( xContext->getAccessibleChild( nPos ) ); |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| void AquaA11yFocusTracker::toolbox_open_floater(Window *pWindow) |
| { |
| bool bToolboxFound = false; |
| bool bFloatingWindowFound = false; |
| Window * pFloatingWindow = NULL; |
| while ( pWindow != NULL ) { |
| if ( pWindow->GetType() == WINDOW_TOOLBOX ) { |
| bToolboxFound = true; |
| } else if ( pWindow->GetType() == WINDOW_FLOATINGWINDOW ) { |
| bFloatingWindowFound = true; |
| pFloatingWindow = pWindow; |
| } |
| pWindow = pWindow->GetParent(); |
| } |
| if ( bToolboxFound && bFloatingWindowFound ) { |
| Reference < XAccessible > rxAccessible = pFloatingWindow -> GetAccessible(); |
| if ( ! rxAccessible.is() ) { |
| return; |
| } |
| Reference < XAccessibleContext > rxContext = rxAccessible -> getAccessibleContext(); |
| if ( ! rxContext.is() ) { |
| return; |
| } |
| if ( rxContext -> getAccessibleChildCount() > 0 ) { |
| Reference < XAccessible > rxAccessibleChild = rxContext -> getAccessibleChild( 0 ); |
| if ( ! rxAccessibleChild.is() ) { |
| return; |
| } |
| setFocusedObject ( rxAccessibleChild ); |
| } |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| void AquaA11yFocusTracker::toolbox_highlight_on(Window *pWindow) |
| { |
| // Make sure either the toolbox or its parent toolbox has the focus |
| if ( ! pWindow->HasFocus() ) |
| { |
| ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() ); |
| if ( ! pToolBoxParent || ! pToolBoxParent->HasFocus() ) |
| return; |
| } |
| |
| notify_toolbox_item_focus(static_cast <ToolBox *> (pWindow)); |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| void AquaA11yFocusTracker::toolbox_highlight_off(Window *pWindow) |
| { |
| ToolBox* pToolBoxParent = dynamic_cast< ToolBox * >( pWindow->GetParent() ); |
| |
| // Notify when leaving sub toolboxes |
| if( pToolBoxParent && pToolBoxParent->HasFocus() ) |
| notify_toolbox_item_focus( pToolBoxParent ); |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| void AquaA11yFocusTracker::tabpage_activated(Window *pWindow) |
| { |
| Reference< XAccessible > xAccessible( pWindow->GetAccessible() ); |
| |
| if( xAccessible.is() ) |
| { |
| Reference< XAccessibleSelection > xSelection(xAccessible->getAccessibleContext(), UNO_QUERY); |
| |
| if( xSelection.is() ) |
| setFocusedObject( xSelection->getSelectedAccessibleChild(0) ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| void AquaA11yFocusTracker::menu_highlighted(const VclMenuEvent *pEvent) |
| { |
| Menu * pMenu = pEvent->GetMenu(); |
| |
| if( pMenu ) |
| { |
| Reference< XAccessible > xAccessible( pMenu->GetAccessible() ); |
| |
| if( xAccessible.is() ) |
| setFocusedObject( xAccessible ); |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| |
| void AquaA11yFocusTracker::window_got_focus(Window *pWindow) |
| { |
| // The menu bar is handled through VCLEVENT_MENU_HIGHLIGHTED |
| if( ! pWindow || !pWindow->IsReallyVisible() || pWindow->GetType() == WINDOW_MENUBARWINDOW ) |
| return; |
| |
| // ToolBoxes are handled through VCLEVENT_TOOLBOX_HIGHLIGHT |
| if( pWindow->GetType() == WINDOW_TOOLBOX ) |
| return; |
| |
| if( pWindow->GetType() == WINDOW_TABCONTROL ) |
| { |
| tabpage_activated( pWindow ); |
| return; |
| } |
| |
| Reference< XAccessible > xAccessible(pWindow->GetAccessible()); |
| |
| if( ! xAccessible.is() ) |
| return; |
| |
| Reference< XAccessibleContext > xContext = xAccessible->getAccessibleContext(); |
| |
| if( ! xContext.is() ) |
| return; |
| |
| Reference< XAccessibleStateSet > xStateSet = xContext->getAccessibleStateSet(); |
| |
| if( ! xStateSet.is() ) |
| return; |
| |
| /* the UNO ToolBox wrapper does not (yet?) support XAccessibleSelection, so we |
| * need to add listeners to the children instead of re-using the tabpage stuff |
| */ |
| if( xStateSet->contains(AccessibleStateType::FOCUSED) && (pWindow->GetType() != WINDOW_TREELISTBOX) ) |
| { |
| setFocusedObject( xAccessible ); |
| } |
| else |
| { |
| if( m_aDocumentWindowList.find(pWindow) == m_aDocumentWindowList.end() ) |
| { |
| m_aDocumentWindowList.insert(pWindow); |
| m_xDocumentFocusListener->attachRecursive(xAccessible, xContext, xStateSet); |
| } |
| #ifdef ENABLE_TRACING |
| else |
| fprintf(stderr, "Window %p already in the list\n", pWindow ); |
| #endif |
| } |
| } |