489 PostEventQueue postEventQueue = 490 (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); 491 if (postEventQueue != null) { 492 postEventQueue.postEvent(event); 493 } 494 } 495 496 /* 497 * Post AWTEvent of high priority. 498 */ 499 public static void postPriorityEvent(final AWTEvent e) { 500 PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() { 501 public void run() { 502 AWTAccessor.getAWTEventAccessor().setPosted(e); 503 ((Component)e.getSource()).dispatchEvent(e); 504 } 505 }, PeerEvent.ULTIMATE_PRIORITY_EVENT); 506 postEvent(targetToAppContext(e.getSource()), pe); 507 } 508 509 protected static final Lock flushLock = new ReentrantLock(); 510 private static boolean isFlushingPendingEvents = false; 511 512 /* 513 * Flush any pending events which haven't been posted to the AWT 514 * EventQueue yet. 515 */ 516 public static void flushPendingEvents() { 517 flushLock.lock(); 518 try { 519 // Don't call flushPendingEvents() recursively 520 if (!isFlushingPendingEvents) { 521 isFlushingPendingEvents = true; 522 AppContext appContext = AppContext.getAppContext(); 523 PostEventQueue postEventQueue = 524 (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); 525 if (postEventQueue != null) { 526 postEventQueue.flush(); 527 } 528 } 529 } finally { 530 isFlushingPendingEvents = false; 531 flushLock.unlock(); 532 } 533 } 534 535 public static boolean isPostEventQueueEmpty() { 536 AppContext appContext = AppContext.getAppContext(); 537 PostEventQueue postEventQueue = 538 (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); 539 if (postEventQueue != null) { 540 return postEventQueue.noEvents(); 541 } else { 542 return true; 543 } 544 } 545 546 /* 547 * Execute a chunk of code on the Java event handler thread for the 548 * given target. Does not wait for the execution to occur before 549 * returning to the caller. 550 */ 551 public static void executeOnEventHandlerThread(Object target, 552 Runnable runnable) { 553 executeOnEventHandlerThread(new PeerEvent(target, runnable, PeerEvent.PRIORITY_EVENT)); 554 } 555 556 /* 557 * Fixed 5064013: the InvocationEvent time should be equals 558 * the time of the ActionEvent 559 */ 560 @SuppressWarnings("serial") 561 public static void executeOnEventHandlerThread(Object target, 562 Runnable runnable, 2028 return AWTAccessor.getAWTEventAccessor().isSystemGenerated(e); 2029 } 2030 2031 } // class SunToolkit 2032 2033 2034 /* 2035 * PostEventQueue is a Thread that runs in the same AppContext as the 2036 * Java EventQueue. It is a queue of AWTEvents to be posted to the 2037 * Java EventQueue. The toolkit Thread (AWT-Windows/AWT-Motif) posts 2038 * events to this queue, which then calls EventQueue.postEvent(). 2039 * 2040 * We do this because EventQueue.postEvent() may be overridden by client 2041 * code, and we mustn't ever call client code from the toolkit thread. 2042 */ 2043 class PostEventQueue { 2044 private EventQueueItem queueHead = null; 2045 private EventQueueItem queueTail = null; 2046 private final EventQueue eventQueue; 2047 2048 // For the case when queue is cleared but events are not posted 2049 private volatile boolean isFlushing = false; 2050 2051 PostEventQueue(EventQueue eq) { 2052 eventQueue = eq; 2053 } 2054 2055 public synchronized boolean noEvents() { 2056 return queueHead == null && !isFlushing; 2057 } 2058 2059 /* 2060 * Continually post pending AWTEvents to the Java EventQueue. The method 2061 * is synchronized to ensure the flush is completed before a new event 2062 * can be posted to this queue. 2063 * 2064 * 7177040: The method couldn't be wholly synchronized because of calls 2065 * of EventQueue.postEvent() that uses pushPopLock, otherwise it could 2066 * potentially lead to deadlock 2067 */ 2068 public void flush() { 2069 EventQueueItem tempQueue; 2070 synchronized (this) { 2071 tempQueue = queueHead; 2072 queueHead = queueTail = null; 2073 isFlushing = true; 2074 } 2075 try { 2076 while (tempQueue != null) { 2077 eventQueue.postEvent(tempQueue.event); 2078 tempQueue = tempQueue.next; 2079 } 2080 } 2081 finally { 2082 isFlushing = false; 2083 } 2084 } 2085 2086 /* 2087 * Enqueue an AWTEvent to be posted to the Java EventQueue. 2088 */ 2089 void postEvent(AWTEvent event) { 2090 EventQueueItem item = new EventQueueItem(event); 2091 2092 synchronized (this) { 2093 if (queueHead == null) { 2094 queueHead = queueTail = item; 2095 } else { 2096 queueTail.next = item; 2097 queueTail = item; 2098 } 2099 } 2100 SunToolkit.wakeupEventQueue(eventQueue, event.getSource() == AWTAutoShutdown.getInstance()); 2101 } 2102 } // class PostEventQueue | 489 PostEventQueue postEventQueue = 490 (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); 491 if (postEventQueue != null) { 492 postEventQueue.postEvent(event); 493 } 494 } 495 496 /* 497 * Post AWTEvent of high priority. 498 */ 499 public static void postPriorityEvent(final AWTEvent e) { 500 PeerEvent pe = new PeerEvent(Toolkit.getDefaultToolkit(), new Runnable() { 501 public void run() { 502 AWTAccessor.getAWTEventAccessor().setPosted(e); 503 ((Component)e.getSource()).dispatchEvent(e); 504 } 505 }, PeerEvent.ULTIMATE_PRIORITY_EVENT); 506 postEvent(targetToAppContext(e.getSource()), pe); 507 } 508 509 /* 510 * Flush any pending events which haven't been posted to the AWT 511 * EventQueue yet. 512 */ 513 public static void flushPendingEvents() { 514 AppContext appContext = AppContext.getAppContext(); 515 flushPendingEvents(appContext); 516 } 517 518 /* 519 * Flush the PostEventQueue for the right AppContext. 520 * The default flushPendingEvents only flushes the thread-local context, 521 * which is not always correct, c.f. 3746956 522 */ 523 public static void flushPendingEvents(AppContext appContext) { 524 PostEventQueue postEventQueue = 525 (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); 526 if (postEventQueue != null) { 527 postEventQueue.flush(); 528 } 529 } 530 531 /* 532 * Execute a chunk of code on the Java event handler thread for the 533 * given target. Does not wait for the execution to occur before 534 * returning to the caller. 535 */ 536 public static void executeOnEventHandlerThread(Object target, 537 Runnable runnable) { 538 executeOnEventHandlerThread(new PeerEvent(target, runnable, PeerEvent.PRIORITY_EVENT)); 539 } 540 541 /* 542 * Fixed 5064013: the InvocationEvent time should be equals 543 * the time of the ActionEvent 544 */ 545 @SuppressWarnings("serial") 546 public static void executeOnEventHandlerThread(Object target, 547 Runnable runnable, 2013 return AWTAccessor.getAWTEventAccessor().isSystemGenerated(e); 2014 } 2015 2016 } // class SunToolkit 2017 2018 2019 /* 2020 * PostEventQueue is a Thread that runs in the same AppContext as the 2021 * Java EventQueue. It is a queue of AWTEvents to be posted to the 2022 * Java EventQueue. The toolkit Thread (AWT-Windows/AWT-Motif) posts 2023 * events to this queue, which then calls EventQueue.postEvent(). 2024 * 2025 * We do this because EventQueue.postEvent() may be overridden by client 2026 * code, and we mustn't ever call client code from the toolkit thread. 2027 */ 2028 class PostEventQueue { 2029 private EventQueueItem queueHead = null; 2030 private EventQueueItem queueTail = null; 2031 private final EventQueue eventQueue; 2032 2033 private Thread flushThread = null; 2034 2035 PostEventQueue(EventQueue eq) { 2036 eventQueue = eq; 2037 } 2038 2039 /* 2040 * Continually post pending AWTEvents to the Java EventQueue. The method 2041 * is synchronized to ensure the flush is completed before a new event 2042 * can be posted to this queue. 2043 * 2044 * 7177040: The method couldn't be wholly synchronized because of calls 2045 * of EventQueue.postEvent() that uses pushPopLock, otherwise it could 2046 * potentially lead to deadlock 2047 */ 2048 public void flush() { 2049 2050 Thread newThread = Thread.currentThread(); 2051 2052 try { 2053 EventQueueItem tempQueue; 2054 synchronized (this) { 2055 // Avoid method recursion 2056 if (newThread == flushThread) { 2057 newThread = null; 2058 return; 2059 } 2060 // Wait for other threads' flushing 2061 while (flushThread != null) { 2062 wait(); 2063 } 2064 // Skip everything if queue is empty 2065 if (queueHead == null) { 2066 notifyAll(); 2067 return; 2068 } 2069 // Remember flushing thread 2070 flushThread = newThread; 2071 2072 tempQueue = queueHead; 2073 queueHead = queueTail = null; 2074 } 2075 while (tempQueue != null) { 2076 eventQueue.postEvent(tempQueue.event); 2077 tempQueue = tempQueue.next; 2078 } 2079 } 2080 catch (InterruptedException e) { 2081 // Couldn't allow exception go up, so at least recover the flag 2082 newThread.interrupt(); 2083 } 2084 finally { 2085 synchronized (this) { 2086 // Forget flushing thread, inform other pending threads 2087 if (newThread == flushThread) { 2088 flushThread = null; 2089 notifyAll(); 2090 } 2091 } 2092 } 2093 } 2094 2095 /* 2096 * Enqueue an AWTEvent to be posted to the Java EventQueue. 2097 */ 2098 void postEvent(AWTEvent event) { 2099 EventQueueItem item = new EventQueueItem(event); 2100 2101 synchronized (this) { 2102 if (queueHead == null) { 2103 queueHead = queueTail = item; 2104 } else { 2105 queueTail.next = item; 2106 queueTail = item; 2107 } 2108 } 2109 SunToolkit.wakeupEventQueue(eventQueue, event.getSource() == AWTAutoShutdown.getInstance()); 2110 } 2111 } // class PostEventQueue |