mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			256 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			256 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* Copyright (C) 2000, 2001  Free Software Foundation
 | |
| 
 | |
|    This file is part of libgcj.
 | |
| 
 | |
| This software is copyrighted work licensed under the terms of the
 | |
| Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 | |
| details.  */
 | |
| 
 | |
| package java.awt;
 | |
| 
 | |
| import java.awt.event.*;
 | |
| import java.util.EmptyStackException;
 | |
| import java.lang.reflect.InvocationTargetException;
 | |
| 
 | |
| /* Written using on-line Java 2 Platform Standard Edition v1.3 API 
 | |
|  * Specification, as well as "The Java Class Libraries", 2nd edition 
 | |
|  * (Addison-Wesley, 1998).
 | |
|  * Status:  Believed complete, but untested. Check FIXME's.
 | |
|  */
 | |
| 
 | |
| /** @author Bryce McKinlay */
 | |
| 
 | |
| public class EventQueue
 | |
| {
 | |
|   private static final int INITIAL_QUEUE_DEPTH = 8;
 | |
|   private AWTEvent[] queue = new AWTEvent[INITIAL_QUEUE_DEPTH];
 | |
|   
 | |
|   private int next_in = 0; // Index where next event will be added to queue
 | |
|   private int next_out = 0; // Index of next event to be removed from queue
 | |
| 
 | |
|   private EventQueue next;
 | |
|   private EventQueue prev;
 | |
| 
 | |
|   private EventDispatchThread dispatchThread = new EventDispatchThread(this);
 | |
| 
 | |
|   public EventQueue()
 | |
|   {
 | |
|   }
 | |
|   
 | |
|   public synchronized AWTEvent getNextEvent()
 | |
|     throws InterruptedException
 | |
|   {
 | |
|     if (next != null)
 | |
|       return next.getNextEvent();
 | |
|       
 | |
|     while (next_in == next_out)
 | |
|       wait();
 | |
|     
 | |
|     AWTEvent res = queue[next_out];
 | |
|     
 | |
|     if (++next_out == queue.length)
 | |
|       next_out = 0;
 | |
|     return res;
 | |
|   }
 | |
|   
 | |
|   /** @specnote Does not block. Returns null if there are no events on the 
 | |
|    *            queue. 
 | |
|    */ 
 | |
|   public synchronized AWTEvent peekEvent()
 | |
|   {
 | |
|     if (next != null)
 | |
|       return next.peekEvent();
 | |
|       
 | |
|     if (next_in != next_out)
 | |
|       return queue[next_out];
 | |
|     else return null;
 | |
|   }
 | |
|   
 | |
|   /** @specnote Does not block. Returns null if there are no matching events 
 | |
|    *            on the queue. 
 | |
|    */ 
 | |
|   public synchronized AWTEvent peekEvent(int id)
 | |
|   {
 | |
|     if (next != null)
 | |
|       return next.peekEvent(id);
 | |
| 
 | |
|     int i = next_out;
 | |
|     while (i != next_in)
 | |
|       {
 | |
|         AWTEvent qevt = queue[i];
 | |
|         if (qevt.id == id)
 | |
| 	  return qevt;
 | |
|       }
 | |
|     return null;
 | |
|   }
 | |
|   
 | |
|   public synchronized void postEvent(AWTEvent evt)
 | |
|   {
 | |
|     if (next != null)
 | |
|       {
 | |
|         next.postEvent(evt);
 | |
| 	return;
 | |
|       }
 | |
|     // FIXME: Security checks?
 | |
|     
 | |
|     /* Check for any events already on the queue with the same source 
 | |
|        and ID. */	
 | |
|     int i = next_out;
 | |
|     while (i != next_in)
 | |
|       {
 | |
|         AWTEvent qevt = queue[i];
 | |
| 	Object src;
 | |
| 	if (qevt.id == evt.id
 | |
| 	    && (src = qevt.getSource()) == evt.getSource()
 | |
| 	    && src instanceof Component)
 | |
| 	  {
 | |
| 	    /* If there are, call coalesceEvents on the source component 
 | |
| 	       to see if they can be combined. */
 | |
| 	    Component srccmp = (Component) src;
 | |
| 	    AWTEvent coalesced_evt = srccmp.coalesceEvents(qevt, evt);
 | |
| 	    if (coalesced_evt != null)
 | |
| 	      {
 | |
| 	        /* Yes. Replace the existing event with the combined event. */
 | |
| 	        queue[i] = coalesced_evt;
 | |
| 		return;
 | |
| 	      }
 | |
|             break;
 | |
| 	  }
 | |
| 	if (++i == queue.length)
 | |
| 	  i = 0;
 | |
|       }
 | |
| 
 | |
|     queue[next_in] = evt;    
 | |
|     if (++next_in == queue.length)
 | |
|       next_in = 0;
 | |
|       
 | |
|     if (next_in == next_out)
 | |
|       {
 | |
|         /* Queue is full. Extend it. */
 | |
|         AWTEvent[] oldQueue = queue;
 | |
| 	queue = new AWTEvent[queue.length * 2];
 | |
| 	
 | |
| 	int len = oldQueue.length - next_out;
 | |
| 	System.arraycopy(oldQueue, next_out, queue, 0, len);
 | |
| 	if (next_out != 0)
 | |
| 	  System.arraycopy(oldQueue, 0, queue, len, next_out);
 | |
| 	  
 | |
| 	next_out = 0;
 | |
| 	next_in = oldQueue.length;
 | |
|       }
 | |
|     notify();
 | |
|   }
 | |
|   
 | |
|   /** @since JDK1.2 */
 | |
|   public static void invokeAndWait(Runnable runnable)
 | |
|     throws InterruptedException, InvocationTargetException
 | |
|   {
 | |
|     EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); 
 | |
|     Thread current = Thread.currentThread();
 | |
|     if (current == eq.dispatchThread)
 | |
|       throw new Error("Can't call invokeAndWait from event dispatch thread");
 | |
|   
 | |
|     InvocationEvent ie = 
 | |
|       new InvocationEvent(eq, runnable, current, true);
 | |
| 
 | |
|     synchronized (current)
 | |
|       {
 | |
| 	eq.postEvent(ie);
 | |
| 	current.wait();
 | |
|       }
 | |
| 
 | |
|     Exception exception;
 | |
|     
 | |
|     if ((exception = ie.getException()) != null)
 | |
|       throw new InvocationTargetException(exception);
 | |
|   }
 | |
|   
 | |
|   /** @since JDK1.2 */
 | |
|   public static void invokeLater(Runnable runnable)
 | |
|   {
 | |
|     EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); 
 | |
| 
 | |
|     InvocationEvent ie = 
 | |
|       new InvocationEvent(eq, runnable, null, false);
 | |
| 
 | |
|     eq.postEvent(ie);
 | |
|   }
 | |
|   
 | |
|   public static boolean isDispatchThread()
 | |
|   {
 | |
|     EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue(); 
 | |
|     return (Thread.currentThread() == eq.dispatchThread);
 | |
|   }
 | |
|   
 | |
|   /** Allows a custom EventQueue implementation to replace this one. 
 | |
|     * All pending events are transferred to the new queue. Calls to postEvent,
 | |
|     * getNextEvent, and peekEvent are forwarded to the pushed queue until it
 | |
|     * is removed with a pop().
 | |
|     */
 | |
|   public synchronized void push(EventQueue newEventQueue)
 | |
|   {
 | |
|     int i = next_out;
 | |
|     while (i != next_in)
 | |
|       {
 | |
|         newEventQueue.postEvent(queue[i]);
 | |
| 	next_out = i;
 | |
| 	if (++i == queue.length)
 | |
| 	  i = 0;
 | |
|       }
 | |
| 
 | |
|     next = newEventQueue;
 | |
|     newEventQueue.prev = this;    
 | |
|   }
 | |
|   
 | |
|   /** Transfer any pending events from this queue back to the parent queue that
 | |
|     * was previously push()ed. Event dispatch from this queue is suspended. */
 | |
|   protected void pop() throws EmptyStackException
 | |
|   {
 | |
|     if (prev == null)
 | |
|       throw new EmptyStackException();
 | |
|     
 | |
|     // Don't synchronize both this and prev at the same time, or deadlock could
 | |
|     // occur.
 | |
|     synchronized (prev)
 | |
|       {
 | |
| 	prev.next = null;
 | |
|       }
 | |
|       
 | |
|     synchronized (this)
 | |
|       {
 | |
| 	int i = next_out;
 | |
| 	while (i != next_in)
 | |
| 	  {
 | |
|             prev.postEvent(queue[i]);
 | |
| 	    next_out = i;
 | |
| 	    if (++i == queue.length)
 | |
| 	      i = 0;
 | |
| 	  }
 | |
|       }
 | |
|   }
 | |
|   
 | |
|   protected void dispatchEvent(AWTEvent evt)
 | |
|   {
 | |
|     if (evt instanceof ActiveEvent)
 | |
|       {
 | |
|         ActiveEvent active_evt = (ActiveEvent) evt;
 | |
| 	active_evt.dispatch();
 | |
|       }
 | |
|     else
 | |
|       {
 | |
| 	Object source = evt.getSource();
 | |
| 
 | |
| 	if (source instanceof Component)
 | |
| 	  {
 | |
|             Component srccmp = (Component) source;
 | |
| 	    srccmp.dispatchEvent(evt);
 | |
| 	  }
 | |
| 	else if (source instanceof MenuComponent)
 | |
| 	  {
 | |
| 	    MenuComponent srccmp = (MenuComponent) source;
 | |
| 	    srccmp.dispatchEvent(evt);
 | |
| 	  }
 | |
|       }
 | |
|   }
 | |
| }
 |