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