1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "aqua/salinst.h"
25 #include "aqua/aqua11ylistener.hxx"
26 #include "aqua/aqua11yfactory.h"
27 #include "aqua/aqua11yfocustracker.hxx"
28 #include "aqua/aqua11ywrapper.h"
29 
30 #include "aqua11ytextwrapper.h"
31 
32 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
33 #include <com/sun/star/accessibility/AccessibleRole.hpp>
34 #include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
35 #include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
36 
37 using namespace ::com::sun::star::accessibility;
38 using namespace ::com::sun::star::awt;
39 using namespace ::com::sun::star::lang;
40 using namespace ::com::sun::star::uno;
41 
getTableNotification(const AccessibleEventObject & aEvent)42 NSString * getTableNotification( const AccessibleEventObject& aEvent )
43 {
44     AccessibleTableModelChange aChange;
45     NSString * notification = nil;
46 
47     if( (aEvent.NewValue >>= aChange) &&
48         ( AccessibleTableModelChangeType::INSERT == aChange.Type || AccessibleTableModelChangeType::DELETE == aChange.Type ) &&
49         aChange.FirstRow != aChange.LastRow )
50     {
51         notification = NSAccessibilityRowCountChangedNotification;
52     }
53 
54     return notification;
55 }
56 
57 //------------------------------------------------------------------------------
58 
AquaA11yEventListener(id wrapperObject,sal_Int16 role)59 AquaA11yEventListener::AquaA11yEventListener(id wrapperObject, sal_Int16 role) : m_wrapperObject(wrapperObject), m_role(role)
60 {
61     [ m_wrapperObject retain ];
62 }
63 
64 //------------------------------------------------------------------------------
65 
~AquaA11yEventListener()66 AquaA11yEventListener::~AquaA11yEventListener()
67 {
68     [ m_wrapperObject release ];
69 }
70 
71 //------------------------------------------------------------------------------
72 
73 void SAL_CALL
disposing(const EventObject &)74 AquaA11yEventListener::disposing( const EventObject& ) throw( RuntimeException )
75 {
76     [ AquaA11yFactory removeFromWrapperRepositoryFor: [ (AquaA11yWrapper *) m_wrapperObject accessibleContext ] ];
77 }
78 
79 //------------------------------------------------------------------------------
80 
81 void SAL_CALL
notifyEvent(const AccessibleEventObject & aEvent)82 AquaA11yEventListener::notifyEvent( const AccessibleEventObject& aEvent ) throw( RuntimeException )
83 {
84     NSString * notification = nil;
85     id element = m_wrapperObject;
86     Rectangle bounds;
87 
88     // TODO: NSAccessibilityValueChanged, NSAccessibilitySelectedRowsChangedNotification
89     switch( aEvent.EventId )
90     {
91         case AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
92             if( m_role != AccessibleRole::LIST ) {
93                 Reference< XAccessible > xAccessible;
94                 if( aEvent.NewValue >>= xAccessible )
95                     AquaA11yFocusTracker::get().setFocusedObject( xAccessible );
96             }
97             break;
98 
99         case AccessibleEventId::NAME_CHANGED:
100             notification = NSAccessibilityTitleChangedNotification;
101             break;
102 
103         case AccessibleEventId::CHILD:
104             // only needed for tooltips (says Apple)
105             if ( m_role == AccessibleRole::TOOL_TIP ) {
106                 if(aEvent.NewValue.hasValue()) {
107                     notification = NSAccessibilityCreatedNotification;
108                 } else if(aEvent.OldValue.hasValue()) {
109                     notification = NSAccessibilityUIElementDestroyedNotification;
110                 }
111             }
112             break;
113 
114         case AccessibleEventId::INVALIDATE_ALL_CHILDREN:
115             // TODO: depricate or remember all children
116             break;
117 
118         case AccessibleEventId::BOUNDRECT_CHANGED:
119             bounds = [ element accessibleComponent ] -> getBounds();
120             if ( m_oldBounds.X != 0 && ( bounds.X != m_oldBounds.X || bounds.Y != m_oldBounds.Y ) ) {
121                 NSAccessibilityPostNotification(element, NSAccessibilityMovedNotification); // post directly since both cases can happen simultaneously
122             }
123             if ( m_oldBounds.X != 0 && ( bounds.Width != m_oldBounds.Width || bounds.Height != m_oldBounds.Height ) ) {
124                 NSAccessibilityPostNotification(element, NSAccessibilityResizedNotification); // post directly since both cases can happen simultaneously
125             }
126             m_oldBounds = bounds;
127             break;
128 
129         case AccessibleEventId::SELECTION_CHANGED:
130             notification = NSAccessibilitySelectedChildrenChangedNotification;
131             break;
132 
133         case AccessibleEventId::TEXT_SELECTION_CHANGED:
134             notification = NSAccessibilitySelectedTextChangedNotification;
135             break;
136 
137         case AccessibleEventId::TABLE_MODEL_CHANGED:
138             notification = getTableNotification(aEvent);
139             break;
140 
141         case AccessibleEventId::CARET_CHANGED:
142             notification = NSAccessibilitySelectedTextChangedNotification;
143             break;
144 
145         case AccessibleEventId::TEXT_CHANGED:
146             notification = NSAccessibilityValueChangedNotification;
147             break;
148 
149         default:
150             break;
151     }
152 
153     if( nil != notification )
154         NSAccessibilityPostNotification(element, notification);
155 }
156