I fixed the JOptionPane showInternal*** method. These have been totally
broken. I did the following to fix it:

- Added an event dispatch loop for the case when the call to
startModal() blocks the event dispatch thread. We still need to dispatch
events, but may not return from the method, so we must dispatch them
explicitly here. The alternative would have been to start a new thread
for that, but that seemed overhead, especially since the old event
thread would have to wait() anyway.
- Added a glasspane-like interceptor panel, that catches all mouse
events that are not targetted at the internal frame. This is not allowed
in a modal dialog.

2006-05-16  Roman Kennke <[EMAIL PROTECTED]>

        PR 24031
        * javax/swing/JOptionPane.java
        (startModal): Rewritten. The events are now dispatched, even
        when the event dispatch thread gets blocked by the call
        to this method. Also, mouse events get intercepted outside the
        internal frame.

/Roman

-- 
“Improvement makes straight roads, but the crooked roads, without
Improvement, are roads of Genius.” - William Blake
Index: javax/swing/JOptionPane.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JOptionPane.java,v
retrieving revision 1.29
diff -u -1 -0 -r1.29 JOptionPane.java
--- javax/swing/JOptionPane.java	5 May 2006 02:56:17 -0000	1.29
+++ javax/swing/JOptionPane.java	16 May 2006 11:47:16 -0000
@@ -31,28 +31,34 @@
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
 
 package javax.swing;
 
+import java.awt.AWTEvent;
+import java.awt.ActiveEvent;
 import java.awt.Component;
+import java.awt.Container;
+import java.awt.EventQueue;
 import java.awt.Frame;
+import java.awt.MenuComponent;
+import java.awt.Toolkit;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseMotionAdapter;
 
 import javax.accessibility.Accessible;
 import javax.accessibility.AccessibleContext;
 import javax.accessibility.AccessibleRole;
-import javax.swing.event.InternalFrameAdapter;
-import javax.swing.event.InternalFrameEvent;
 import javax.swing.plaf.OptionPaneUI;
 
 /**
  * This class creates different types of JDialogs and JInternalFrames that can
  * ask users for input or pass on information. JOptionPane can be used by
  * calling one of the show static methods or  by creating an instance of
  * JOptionPane and calling createDialog or createInternalFrame.
  */
 public class JOptionPane extends JComponent implements Accessible
 {
@@ -1521,38 +1527,71 @@
   /**
    * This helper method makes the JInternalFrame wait until it is notified by
    * an InternalFrameClosing event. This method also adds the given
    * JOptionPane to the JInternalFrame and sizes it according to the
    * JInternalFrame's preferred size.
    *
    * @param f The JInternalFrame to make modal.
    */
   private static void startModal(JInternalFrame f)
   {
-    synchronized (f)
-    {
-      final JInternalFrame tmp = f;
-      tmp.toFront();
+    // We need to add an additional glasspane-like component directly
+    // below the frame, which intercepts all mouse events that are not
+    // directed at the frame itself.
+    JPanel modalInterceptor = new JPanel();
+    modalInterceptor.setOpaque(false);
+    JLayeredPane lp = JLayeredPane.getLayeredPaneAbove(f);
+    lp.setLayer(modalInterceptor, JLayeredPane.MODAL_LAYER.intValue());
+    modalInterceptor.setBounds(0, 0, lp.getWidth(), lp.getHeight());
+    modalInterceptor.addMouseListener(new MouseAdapter(){});
+    modalInterceptor.addMouseMotionListener(new MouseMotionAdapter(){});
+    lp.add(modalInterceptor);
+    f.toFront();
+
+    // We need to explicitly dispatch events when we are blocking the event
+    // dispatch thread.
+    EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue();
+    try
+      {
+        while (! f.isClosed())
+          {
+            if (EventQueue.isDispatchThread())
+              {
+                // The getNextEventMethod() issues wait() when no
+                // event is available, so we don't need do explicitly wait().
+                AWTEvent ev = queue.getNextEvent();
+                // This mimics EventQueue.dispatchEvent(). We can't use
+                // EventQueue.dispatchEvent() directly, because it is
+                // protected, unfortunately.
+                if (ev instanceof ActiveEvent)
+                  ((ActiveEvent) ev).dispatch();
+                else if (ev.getSource() instanceof Component)
+                  ((Component) ev.getSource()).dispatchEvent(ev);
+                else if (ev.getSource() instanceof MenuComponent)
+                  ((MenuComponent) ev.getSource()).dispatchEvent(ev);
+                // Other events are ignored as per spec in
+                // EventQueue.dispatchEvent
+              }
+            else
+              {
+                // Give other threads a chance to become active.
+                Thread.yield();
+              }
+          }
+      }
+    catch (InterruptedException ex)
+      {
+        // If we get interrupted, then leave the modal state.
+      }
+    finally
+      {
+        // Clean up the modal interceptor.
+        lp.remove(modalInterceptor);
 
-      f.addInternalFrameListener(new InternalFrameAdapter()
-                                 {
-                                   public void internalFrameClosed(InternalFrameEvent e)
-                                   {
-                                     synchronized (tmp)
-                                     {
-                                       tmp.removeInternalFrameListener(this);
-                                       tmp.notifyAll();
-                                     }
-                                   }
-                                 });
-      try
-        {
-          while (! f.isClosed())
-            f.wait();
-        }
-      catch (InterruptedException ignored)
-        {
-          // Ignore this Exception.
-        }
-    }
+        // Remove the internal frame from its parent, so it is no longer
+        // lurking around and clogging memory.
+        Container parent = f.getParent();
+        if (parent != null)
+          parent.remove(f);
+      }
   }
 }

Attachment: signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil

Reply via email to