blob: 91e3d0e6f2ed0980f3e1d5a6c6c7a0d52519acd8 [file] [log] [blame]
/**************************************************************
*
* 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.
*
*************************************************************/
import com.sun.star.accessibility.XAccessible;
import com.sun.star.accessibility.XAccessibleEventListener;
import com.sun.star.accessibility.AccessibleEventObject;
import com.sun.star.lang.EventObject;
import com.sun.star.awt.XTopWindowListener;
import com.sun.star.uno.UnoRuntime;
import java.util.LinkedList;
/** This class acts as a proxy for the simple screen reader. It waits for
two types of events:
1. Accessibility events signal modifications concerning accessibility
objects.
2. Top window events inform the listener about new or removed windows.
This class exists because events had to be handled in a seperate thread
to avoid dead locks: The thread that receives an event must no call back
to the Office directly.
Soon this should not be necessary anymore. There is now a flag which
switches between synchronous and asynchronous callbacks.
All reveived events are eventually forwarded to the actual listener. In
this way it decouples the Office from the listener.
*/
class EventListenerProxy
implements Runnable, XAccessibleEventListener, XTopWindowListener
{
public EventListenerProxy (EventHandler aListener)
{
maListener = aListener;
mbAsynchron = true;
if (mbAsynchron)
{
maEventQueue = new LinkedList();
new Thread (this, "EventListenerProxy").start();
}
}
private void addEvent (Runnable aEventObject)
{
if (mbAsynchron)
synchronized (maEventQueue)
{
maEventQueue.addLast (aEventObject);
// Tell the queue that there is a new event in the queue.
maEventQueue.notify();
}
else
{
System.out.println ("running " + aEventObject);
aEventObject.run();
System.out.println (" done");
}
}
/** In an infinite loop, check for events to deliver, then wait on lock
(which will be notified when new events arrive)
*/
public void run ()
{
while (true)
{
// Process all events that are currently in the queue.
Runnable aEvent;
do
{
synchronized (maEventQueue)
{
if (maEventQueue.size() > 0)
aEvent = (Runnable)maEventQueue.removeFirst();
else
aEvent = null;
}
if (aEvent != null)
{
try
{
aEvent.run();
}
catch (Throwable aException)
{
MessageArea.println(
"Exception during event delivery: " + aException);
aException.printStackTrace();
}
}
}
while (aEvent != null);
// Now that the queue is empty go to sleep again.
try
{
synchronized (maEventQueue)
{
maEventQueue.wait();
}
}
catch (Exception aException)
{
// Ignore this exception since there is not much
// that we can do about it.
}
}
}
public void disposing( final EventObject aEvent)
{
addEvent (new Runnable()
{
public void run()
{
maListener.disposing (aEvent);
}
} );
}
public void notifyEvent (final AccessibleEventObject aEvent)
{
addEvent (
new Runnable()
{
public void run()
{
maListener.notifyEvent (aEvent);
}
} );
}
public void windowOpened (final com.sun.star.lang.EventObject aEvent)
{
addEvent (
new Runnable()
{
public void run()
{
maListener.windowOpened (
(XAccessible) UnoRuntime.queryInterface(
XAccessible.class,
aEvent.Source));
}
} );
}
public void windowClosing (final com.sun.star.lang.EventObject aEvent)
{
// Ignored.
}
public void windowClosed (final com.sun.star.lang.EventObject aEvent)
{
addEvent (
new Runnable()
{
public void run()
{
maListener.windowClosed (
(XAccessible) UnoRuntime.queryInterface(
XAccessible.class,
aEvent.Source));
}
} );
}
public void windowMinimized (com.sun.star.lang.EventObject aEvent)
{
// Ignored.
}
public void windowNormalized (com.sun.star.lang.EventObject aEvent)
{
// Ignored.
}
public void windowActivated (com.sun.star.lang.EventObject aEvent)
{
// Ignored.
}
public void windowDeactivated (com.sun.star.lang.EventObject aEvent)
{
// Ignored.
}
/** The queue of event objects, LinkedList<Runnable>.
The queue object will also serve as lock for the consumer/producer type
syncronization.
*/
private LinkedList maEventQueue;
/** This is the actual listener that the events will eventually forwarded to.
*/
private EventHandler maListener;
/** This flag determines whether event forwarding is done asynchroniously
or synchroniously.
*/
private boolean mbAsynchron;
}