--- old/jdk/src/windows/classes/com/sun/java/accessibility/util/EventQueueMonitor.java 2015-05-20 23:54:07.792822600 -0500 +++ /dev/null 2015-05-20 23:54:08.000000000 -0500 @@ -1,619 +0,0 @@ -/* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.java.accessibility.util; - -import java.util.*; -import java.awt.*; -import java.awt.event.*; -import javax.accessibility.*; -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * The {@code EventQueueMonitor} class provides key core functionality for Assistive - * Technologies (and other system-level technologies that need some of the same - * things that Assistive Technology needs). - * - * @see AWTEventMonitor - * @see SwingEventMonitor - */ -@jdk.Exported -public class EventQueueMonitor - implements AWTEventListener { - - // NOTE: All of the following properties are static. The reason - // for this is that there may be multiple EventQueue instances - // in use in the same VM. By making these properties static, - // we can guarantee we get the information from all of the - // EventQueue instances. - - // The stuff that is cached. - // - static Vector topLevelWindows = new Vector(); - static Window topLevelWindowWithFocus = null; - static Point currentMousePosition = null; - static Component currentMouseComponent = null; - - // Low-level listener interfaces - // - static GUIInitializedListener guiInitializedListener = null; - static TopLevelWindowListener topLevelWindowListener = null; - static MouseMotionListener mouseMotionListener = null; - - /** - * Class variable stating whether the assistive technologies have - * been loaded yet or not. The assistive technologies won't be - * loaded until the first event is posted to the EventQueue. This - * gives the toolkit a chance to do all the necessary initialization - * it needs to do. - */ - - /** - * Class variable stating whether the GUI subsystem has been initialized - * or not. - * - * @see #isGUIInitialized - */ - static boolean guiInitialized = false; - - /** - * Queue that holds events for later processing. - */ - static EventQueueMonitorItem componentEventQueue = null; - - /** - * Class that tells us what the component event dispatch thread is. - */ - static private ComponentEvtDispatchThread cedt = null; - - /** - * Handle the synchronization between the thing that populates the - * component event dispatch thread ({@link #queueComponentEvent}) - * and the thing that processes the events ({@link ComponentEvtDispatchThread}). - */ - static Object componentEventQueueLock = new Object(); - - /** - * Create a new {@code EventQueueMonitor} instance. Normally, this will - * be called only by the AWT Toolkit during initialization time. - * Assistive technologies should not create instances of - * EventQueueMonitor by themselves. Instead, they should either - * refer to it directly via the static methods in this class, e.g., - * {@link #getCurrentMousePosition} or obtain the instance by asking the - * Toolkit, e.g., {@link java.awt.Toolkit#getSystemEventQueue}. - */ - public EventQueueMonitor() { - if (cedt == null) { - cedt = new ComponentEvtDispatchThread("EventQueueMonitor-ComponentEvtDispatch"); - - cedt.setDaemon(true); - cedt.start(); - } - } - - /** - * Queue up a {@link java.awt.event.ComponentEvent ComponentEvent} for later - * processing by the {@link ComponentEvtDispatch} thread. - * - * @param e a {@code ComponentEvent} - */ - static void queueComponentEvent(ComponentEvent e) { - synchronized(componentEventQueueLock) { - EventQueueMonitorItem eqi = new EventQueueMonitorItem(e); - if (componentEventQueue == null) { - componentEventQueue = eqi; - } else { - EventQueueMonitorItem q = componentEventQueue; - while (true) { - if (q.next != null) { - q = q.next; - } else { - break; - } - } - q.next = eqi; - } - componentEventQueueLock.notifyAll(); - } - } - - /** - * Tell the {@code EventQueueMonitor} to start listening for events. - */ - public static void maybeInitialize() { - if (cedt == null) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - try { - long eventMask = AWTEvent.WINDOW_EVENT_MASK | - AWTEvent.FOCUS_EVENT_MASK | - AWTEvent.MOUSE_MOTION_EVENT_MASK; - - Toolkit.getDefaultToolkit().addAWTEventListener(new EventQueueMonitor(), eventMask); - } catch (Exception e) { - } - return null; - } - } - ); - } - } - - /** - * Handle events as a result of registering a listener - * on the {@link java.awt.EventQueue EventQueue} in {@link #maybeInitialize}. - */ - public void eventDispatched(AWTEvent theEvent) { - processEvent(theEvent); - } - - /** - * Assisitive technologies that have - * registered a {@link GUIInitializedListener} will be notified. - * - * @see #addGUIInitializedListener - */ - static void maybeNotifyAssistiveTechnologies() { - - if (!guiInitialized) { - guiInitialized = true; - if (guiInitializedListener != null) { - guiInitializedListener.guiInitialized(); - } - } - - } - - /********************************************************************/ - /* */ - /* Package Private Methods */ - /* */ - /********************************************************************/ - - /** - * Add a Container to the list of top-level containers - * in the cache. This follows the object's hierarchy up the - * tree until it finds the top most parent. If the parent is - * not already in the list of Containers, it adds it to the list. - * - * @param c the Container - */ - static void addTopLevelWindow(Component c) { - Container parent; - - if (c == null) { - return; - } - - if (!(c instanceof Window)) { - addTopLevelWindow(c.getParent()); - return; - } - - if ((c instanceof Dialog) || (c instanceof Window)) { - parent = (Container) c; - } else { - parent = c.getParent(); - if (parent != null) { - addTopLevelWindow(parent); - return; - } - } - - if (parent == null) { - parent = (Container) c; - } - - // Because this method is static, do not make it synchronized because - // it can lock the whole class. Instead, just lock what needs to be - // locked. - // - synchronized (topLevelWindows) { - if ((parent != null) && !topLevelWindows.contains(parent)) { - topLevelWindows.addElement(parent); - if (topLevelWindowListener != null) { - topLevelWindowListener.topLevelWindowCreated((Window) parent); - } - } - } - } - - /** - * Removes a container from the list of top level containers in the cache. - * - * @param c the top level container to remove - */ - static void removeTopLevelWindow(Window w) { - - // Because this method is static, do not make it synchronized because - // it can lock the whole class. Instead, just lock what needs to be - // locked. - // - synchronized (topLevelWindows) { - if (topLevelWindows.contains(w)) { - topLevelWindows.removeElement(w); - if (topLevelWindowListener != null) { - topLevelWindowListener.topLevelWindowDestroyed(w); - } - } - } - } - - /** - * Update current mouse position. - * - * @param mouseEvent the MouseEvent that holds the new mouse position. - */ - static void updateCurrentMousePosition(MouseEvent mouseEvent) { - Point oldMousePos = currentMousePosition; - // Be careful here. The component in the event might be - // hidden by the time we process the event. - try { - Point eventPoint = mouseEvent.getPoint(); - currentMouseComponent = (Component) (mouseEvent.getSource()); - currentMousePosition = currentMouseComponent.getLocationOnScreen(); - currentMousePosition.translate(eventPoint.x,eventPoint.y); - } catch (Exception e) { - currentMousePosition = oldMousePos; - } - } - - /** - * Process the event. This maintains the event cache in addition - * to calling all the registered listeners. NOTE: The events that - * come through here are from peered Components. - * - * @param theEvent the AWTEvent - */ - static void processEvent(AWTEvent theEvent) { - switch (theEvent.getID()) { - case MouseEvent.MOUSE_MOVED: - case MouseEvent.MOUSE_DRAGGED: - case FocusEvent.FOCUS_GAINED: - case WindowEvent.WINDOW_DEACTIVATED: - queueComponentEvent((ComponentEvent) theEvent); - break; - - case WindowEvent.WINDOW_ACTIVATED: - // Dialogs fire WINDOW_ACTIVATED and FOCUS_GAINED events - // before WINDOW_OPENED so we need to add topLevelListeners - // for the dialog when it is first activated to get a - // focus gained event for the focus component in the dialog. - if (theEvent instanceof ComponentEvent) { - ComponentEvent ce = (ComponentEvent)theEvent; - if (ce.getComponent() instanceof Window) { - EventQueueMonitor.addTopLevelWindow(ce.getComponent()); - EventQueueMonitor.maybeNotifyAssistiveTechnologies(); - } else { - EventQueueMonitor.maybeNotifyAssistiveTechnologies(); - EventQueueMonitor.addTopLevelWindow(ce.getComponent()); - } - } - queueComponentEvent((ComponentEvent) theEvent); - break; - - // handle WINDOW_OPENED and WINDOW_CLOSED events synchronously - case WindowEvent.WINDOW_OPENED: - if (theEvent instanceof ComponentEvent) { - ComponentEvent ce = (ComponentEvent)theEvent; - if (ce.getComponent() instanceof Window) { - EventQueueMonitor.addTopLevelWindow(ce.getComponent()); - EventQueueMonitor.maybeNotifyAssistiveTechnologies(); - } else { - EventQueueMonitor.maybeNotifyAssistiveTechnologies(); - EventQueueMonitor.addTopLevelWindow(ce.getComponent()); - } - } - break; - case WindowEvent.WINDOW_CLOSED: - if (theEvent instanceof ComponentEvent) { - ComponentEvent ce = (ComponentEvent)theEvent; - EventQueueMonitor.removeTopLevelWindow((Window) (ce.getComponent())); - } - break; - - default: - break; - } - } - - /** - * Internal test - */ - static synchronized Component getShowingComponentAt(Container c, int x, int y) { - if (!c.contains(x, y)) { - return null; - } - int ncomponents = c.getComponentCount(); - for (int i = 0 ; i < ncomponents ; i++) { - Component comp = c.getComponent(i); - if (comp != null && comp.isShowing()) { - Point location = comp.getLocation(); - if (comp.contains(x - location.x, y - location.y)) { - return comp; - } - } - } - return c; - } - - /** - * Return the Component at the given Point on the screen in the - * given Container. - * - * @param c the Container to search - * @param p the Point in screen coordinates - * @return the Component at the given Point on the screen in the - * given Container -- can be null if no Component is at that Point - */ - static synchronized Component getComponentAt(Container c, Point p) { - if (!c.isShowing()) { - return null; - } - - Component comp; - Point containerLoc = c.getLocationOnScreen(); - Point containerPoint = new Point(p.x - containerLoc.x, - p.y - containerLoc.y); - - comp = getShowingComponentAt(c, containerPoint.x, containerPoint.y); - - if ((comp != c) && (comp instanceof Container)) { - return getComponentAt((Container)comp,p); - } else { - return comp; - } - } - - /** - * Obtain the {@link javax.accessibility.Accessible Accessible} object at the given point on the Screen. - * The return value may be null if an {@code Accessible} object cannot be - * found at the particular point. - * - * @param p the point to be accessed - * @return the {@code Accessible} at the specified point - */ - static public Accessible getAccessibleAt(Point p) { - Window w = getTopLevelWindowWithFocus(); - Window[] wins = getTopLevelWindows(); - Component c = null; - - // See if the point we're being asked about is the - // currentMousePosition. If so, start with the component - // that we know the currentMousePostion is over - // - if (currentMousePosition == null) { - return null; - } - if (currentMousePosition.equals(p)) { - if (currentMouseComponent instanceof Container) { - c = getComponentAt((Container) currentMouseComponent, p); - } - } - - // Try the window with focus next - // - if (c == null && w != null) { - c = getComponentAt(w,p); - } - - // Try the other windows next. [[[WDW: Stacking order???]]] - if (c == null) { - for (int i = 0; i < wins.length; i++) { - c = getComponentAt(wins[i],p); - if (c != null) { - break; - } - } - } - - if (c instanceof Accessible) { - AccessibleContext ac = ((Accessible) c).getAccessibleContext(); - if (ac != null) { - AccessibleComponent acmp = ac.getAccessibleComponent(); - if ((acmp != null) && (ac.getAccessibleChildrenCount() != 0)) { - Point location = acmp.getLocationOnScreen(); - location.move(p.x - location.x, p.y - location.y); - return acmp.getAccessibleAt(location); - } - } - return (Accessible) c; - } else { - return Translator.getAccessible(c); - } - } - - /********************************************************************/ - /* */ - /* Public Methods */ - /* */ - /********************************************************************/ - - /** - * Says whether the GUI subsystem has been initialized or not. - * If this returns true, the assistive technology can freely - * create GUI component instances. If the return value is false, - * the assistive technology should register a {@link GUIInitializedListener} - * and wait to create GUI component instances until the listener is - * called. - * - * @return true if the GUI subsystem has been initialized - * @see #addGUIInitializedListener - */ - static public boolean isGUIInitialized() { - maybeInitialize(); - return guiInitialized; - } - - /** - * Adds the specified listener to be notified when the GUI subsystem - * is initialized. Assistive technologies should get the results of - * {@link #isGUIInitialized} before calling this method. - * - * @param l the listener to add - * @see #isGUIInitialized - * @see #removeTopLevelWindowListener - */ - static public void addGUIInitializedListener(GUIInitializedListener l) { - maybeInitialize(); - guiInitializedListener = - GUIInitializedMulticaster.add(guiInitializedListener,l); - } - - /** - * Removes the specified listener to be notified when the GUI subsystem - * is initialized. - * - * @param l the listener to remove - * @see #addGUIInitializedListener - */ - static public void removeGUIInitializedListener(GUIInitializedListener l) { - guiInitializedListener = - GUIInitializedMulticaster.remove(guiInitializedListener,l); - } - - /** - * Adds the specified listener to be notified when a top level window - * is created or destroyed. - * - * @param l the listener to add - * @see #removeTopLevelWindowListener - */ - static public void addTopLevelWindowListener(TopLevelWindowListener l) { - topLevelWindowListener = - TopLevelWindowMulticaster.add(topLevelWindowListener,l); - } - - /** - * Removes the specified listener to be notified when a top level window - * is created or destroyed. - * - * @param l the listener to remove - * @see #addTopLevelWindowListener - */ - static public void removeTopLevelWindowListener(TopLevelWindowListener l) { - topLevelWindowListener = - TopLevelWindowMulticaster.remove(topLevelWindowListener,l); - } - - /** - * Return the last recorded position of the mouse in screen coordinates. - * - * @return the last recorded position of the mouse in screen coordinates - */ - static public Point getCurrentMousePosition() { - return currentMousePosition; - } - - /** - * Return the list of top level Windows in use in the Java Virtual Machine. - * - * @return an array of top level {@code Window}s in use in the Java Virtual Machine - */ - static public Window[] getTopLevelWindows() { - - // Because this method is static, do not make it synchronized because - // it can lock the whole class. Instead, just lock what needs to be - // locked. - // - synchronized (topLevelWindows) { - int count = topLevelWindows.size(); - if (count > 0) { - Window[] w = new Window[count]; - for (int i = 0; i < count; i++) { - w[i] = (Window)topLevelWindows.elementAt(i); - } - return w; - } else { - return new Window[0]; - } - } - } - - /** - * Return the top level {@code Window} that currently has keyboard focus. - * - * @return the top level {@code Window} that currently has keyboard focus - */ - static public Window getTopLevelWindowWithFocus() { - return topLevelWindowWithFocus; - } -} - -/** - * Handle all Component events in a separate thread. The reason for this is - * that WindowEvents tend to be used to do lots of processing on the Window - * hierarchy. As a result, it can frequently result in deadlock situations. - */ -class ComponentEvtDispatchThread extends Thread { - public ComponentEvtDispatchThread(String name) { - super(name); - } - public void run() { - ComponentEvent ce = null; - while (true) { - synchronized(EventQueueMonitor.componentEventQueueLock) { - while (EventQueueMonitor.componentEventQueue == null) { - try { - EventQueueMonitor.componentEventQueueLock.wait(); - } catch (InterruptedException e) { - } - } - ce = (ComponentEvent)EventQueueMonitor.componentEventQueue.event; - EventQueueMonitor.componentEventQueue = - EventQueueMonitor.componentEventQueue.next; - } - switch (ce.getID()) { - case MouseEvent.MOUSE_MOVED: - case MouseEvent.MOUSE_DRAGGED: - EventQueueMonitor.updateCurrentMousePosition((MouseEvent) ce); - break; - case WindowEvent.WINDOW_ACTIVATED: - EventQueueMonitor.maybeNotifyAssistiveTechnologies(); - EventQueueMonitor.topLevelWindowWithFocus = ((WindowEvent) ce).getWindow(); - break; - - default: - break; - } - } - } -} - -/** - * EventQueueMonitorItem is the basic type that handles the - * queue for queueComponentEvent and the ComponentEvtDispatchThread. - */ -class EventQueueMonitorItem { - AWTEvent event; - EventQueueMonitorItem next; - - EventQueueMonitorItem(AWTEvent evt) { - event = evt; - next = null; - } -}