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