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 import com.sun.star.accessibility.XAccessible; 25 import com.sun.star.accessibility.XAccessibleEventListener; 26 import com.sun.star.accessibility.AccessibleEventObject; 27 import com.sun.star.lang.EventObject; 28 import com.sun.star.awt.XTopWindowListener; 29 import com.sun.star.uno.UnoRuntime; 30 31 import java.util.LinkedList; 32 33 /** This class acts as a proxy for the simple screen reader. It waits for 34 two types of events: 35 1. Accessibility events signal modifications concerning accessibility 36 objects. 37 2. Top window events inform the listener about new or removed windows. 38 39 This class exists because events had to be handled in a separate thread 40 to avoid dead locks: The thread that receives an event must no call back 41 to the Office directly. 42 43 Soon this should not be necessary anymore. There is now a flag which 44 switches between synchronous and asynchronous callbacks. 45 46 All reveived events are eventually forwarded to the actual listener. In 47 this way it decouples the Office from the listener. 48 */ 49 class EventListenerProxy 50 implements Runnable, XAccessibleEventListener, XTopWindowListener 51 { EventListenerProxy(EventHandler aListener)52 public EventListenerProxy (EventHandler aListener) 53 { 54 maListener = aListener; 55 mbAsynchron = true; 56 if (mbAsynchron) 57 { 58 maEventQueue = new LinkedList(); 59 new Thread (this, "EventListenerProxy").start(); 60 } 61 } 62 addEvent(Runnable aEventObject)63 private void addEvent (Runnable aEventObject) 64 { 65 if (mbAsynchron) 66 synchronized (maEventQueue) 67 { 68 maEventQueue.addLast (aEventObject); 69 // Tell the queue that there is a new event in the queue. 70 maEventQueue.notify(); 71 } 72 else 73 { 74 System.out.println ("running " + aEventObject); 75 aEventObject.run(); 76 System.out.println (" done"); 77 } 78 } 79 80 81 82 83 /** In an infinite loop, check for events to deliver, then wait on lock 84 (which will be notified when new events arrive) 85 */ run()86 public void run () 87 { 88 while (true) 89 { 90 // Process all events that are currently in the queue. 91 Runnable aEvent; 92 do 93 { 94 synchronized (maEventQueue) 95 { 96 if (maEventQueue.size() > 0) 97 aEvent = (Runnable)maEventQueue.removeFirst(); 98 else 99 aEvent = null; 100 } 101 102 if (aEvent != null) 103 { 104 try 105 { 106 aEvent.run(); 107 } 108 catch (Throwable aException) 109 { 110 MessageArea.println( 111 "Exception during event delivery: " + aException); 112 aException.printStackTrace(); 113 } 114 } 115 } 116 while (aEvent != null); 117 118 // Now that the queue is empty go to sleep again. 119 try 120 { 121 synchronized (maEventQueue) 122 { 123 maEventQueue.wait(); 124 } 125 } 126 catch (Exception aException) 127 { 128 // Ignore this exception since there is not much 129 // that we can do about it. 130 } 131 } 132 } 133 134 disposing( final EventObject aEvent)135 public void disposing( final EventObject aEvent) 136 { 137 addEvent (new Runnable() 138 { 139 public void run() 140 { 141 maListener.disposing (aEvent); 142 } 143 } ); 144 } 145 notifyEvent(final AccessibleEventObject aEvent)146 public void notifyEvent (final AccessibleEventObject aEvent) 147 { 148 addEvent ( 149 new Runnable() 150 { 151 public void run() 152 { 153 maListener.notifyEvent (aEvent); 154 } 155 } ); 156 } 157 windowOpened(final com.sun.star.lang.EventObject aEvent)158 public void windowOpened (final com.sun.star.lang.EventObject aEvent) 159 { 160 addEvent ( 161 new Runnable() 162 { 163 public void run() 164 { 165 maListener.windowOpened ( 166 (XAccessible) UnoRuntime.queryInterface( 167 XAccessible.class, 168 aEvent.Source)); 169 } 170 } ); 171 } windowClosing(final com.sun.star.lang.EventObject aEvent)172 public void windowClosing (final com.sun.star.lang.EventObject aEvent) 173 { 174 // Ignored. 175 } windowClosed(final com.sun.star.lang.EventObject aEvent)176 public void windowClosed (final com.sun.star.lang.EventObject aEvent) 177 { 178 addEvent ( 179 new Runnable() 180 { 181 public void run() 182 { 183 maListener.windowClosed ( 184 (XAccessible) UnoRuntime.queryInterface( 185 XAccessible.class, 186 aEvent.Source)); 187 } 188 } ); 189 } windowMinimized(com.sun.star.lang.EventObject aEvent)190 public void windowMinimized (com.sun.star.lang.EventObject aEvent) 191 { 192 // Ignored. 193 } windowNormalized(com.sun.star.lang.EventObject aEvent)194 public void windowNormalized (com.sun.star.lang.EventObject aEvent) 195 { 196 // Ignored. 197 } windowActivated(com.sun.star.lang.EventObject aEvent)198 public void windowActivated (com.sun.star.lang.EventObject aEvent) 199 { 200 // Ignored. 201 } windowDeactivated(com.sun.star.lang.EventObject aEvent)202 public void windowDeactivated (com.sun.star.lang.EventObject aEvent) 203 { 204 // Ignored. 205 } 206 207 /** The queue of event objects, LinkedList<Runnable>. 208 The queue object will also serve as lock for the consumer/producer type 209 synchronization. 210 */ 211 private LinkedList maEventQueue; 212 213 /** This is the actual listener that the events will eventually forwarded to. 214 */ 215 private EventHandler maListener; 216 217 /** This flag determines whether event forwarding is done asynchroniously 218 or synchroniously. 219 */ 220 private boolean mbAsynchron; 221 } 222