United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6518753 REGRESSION:Modal Internal Frames are broken in 1.6
JDK-6518753 : REGRESSION:Modal Internal Frames are broken in 1.6

Details
Type:
Bug
Submit Date:
2007-01-29
Status:
Closed
Updated Date:
2011-03-07
Project Name:
JDK
Resolved Date:
2011-03-07
Component:
client-libs
OS:
windows_xp
Sub-Component:
java.awt
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:

Related Reports
Backport:
Relates:

Sub Tasks

Description
J2SE Version (please include all output from java -version flag):
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

Does this problem occur on J2SE 1.4.x or 5.0.x ?  Yes / No (pick one)
No

Operating System Configuration Information (be specific):
Microsoft Windows 2000 [Version 5.00.2195]

Modal Internal Frames are broken in 1.6

Opening a Modal Internal Frame from a Modal Internal Frame into a different Window than the original is causing Mouse Events not to be dispatched.

1) Run Code
(Two Frames with just buttons at the bottom should appear)

2) On the left Frame click on the 'Show Message in this Frame' button
(A dialog should appear in the left Frame and the right Frame should remain empty)
 
3) On the left Frame click on the 'Show Message in other Frame' button
(Now a dialog should appear in the right Frame with the text 'Test' and the other dialog should remain in the left Frame)

4) Observe that clicking OK with the Mouse no longer works (using the enter key still works)

import static java.awt.BorderLayout.*;
import static javax.swing.JFrame.*;
import static javax.swing.JOptionPane.*;
import java.awt.event.*;
import javax.swing.*;

public class Test {
 public static void main(String[] args) {
   final JDesktopPane desktop1 = new JDesktopPane();
   final JDesktopPane desktop2 = new JDesktopPane();
     JFrame frame1 = new JFrame("Frame 1");
   frame1.add(desktop1);
   frame1.add(new JButton(new AbstractAction("Show Message in this Frame") {
     public void actionPerformed(ActionEvent anEvent) {
       showInternalMessageDialog(desktop1, new JButton(new AbstractAction(
           "Show Message in other Frame") {
         public void actionPerformed(ActionEvent anEvent) {
           showInternalMessageDialog(desktop2, "Test");
         }
       }));
     }
   }), SOUTH);
   frame1.setDefaultCloseOperation(EXIT_ON_CLOSE);
   frame1.setBounds(50, 50, 300, 300);
   frame1.setVisible(true);
     JFrame frame2 = new JFrame("Frame 2");
   frame2.add(desktop2);
   frame2.add(new JButton(new AbstractAction("Show Message in this Frame") {
     public void actionPerformed(ActionEvent anEvent) {
       showInternalMessageDialog(desktop2, new JButton(new AbstractAction(
           "Show Message in other Frame") {
         public void actionPerformed(ActionEvent anEvent) {
           showInternalMessageDialog(desktop1, "Test");
         }
       }));
     }
   }), SOUTH);
   frame2.setDefaultCloseOperation(EXIT_ON_CLOSE);
   frame2.setBounds(400, 50, 300, 300);
   frame2.setVisible(true);
 }
}

                                    

Comments
EVALUATION

This bug is introduced with the fix for 4080029 (AWT modality improvement). Among many other things, this fix contains events filters which are used to filter some kinds of events for blocked windows.

Event filters work the following way. Any event, to be accepted for dispatching, must be accepted by all filters. Prior to the fix only the last modal component was required to accept event. This is why when two internal frames are shown, they block each other's events.

While working with this bug I have also found, that some additional events filtering is performed in LightweightDispatcher. This piece of code was introduced right for modal internal frames (bad design :( ), so I have decided to reuse it instead of totally refactoring modal internal frames code. So the fix is: don't filter events for modal internal frames in event filters, leave LightweightDispatcher filter only. See suggested fix for details.
                                     
2007-01-30
SUGGESTED FIX

*** /tmp/geta28989	2007-01-30 16:08:50.000000000 +0300
--- EventDispatchThread.java	2007-01-30 15:56:30.000000000 +0300
***************
*** 414,427 ****
                   * KeyEvent is handled by using enqueueKeyEvent
                   * in Dialog.show
                   */
                  int eventID = event.getID();
!                 if (((eventID >= MouseEvent.MOUSE_FIRST &&
!                       eventID <= MouseEvent.MOUSE_LAST) &&
!                      !(checkMouseEventForModalJInternalFrame((MouseEvent)event, modalComponent))) || 
!                     (eventID >= ActionEvent.ACTION_FIRST &&
!                      eventID <= ActionEvent.ACTION_LAST) ||
!                     eventID == WindowEvent.WINDOW_CLOSING)
!                 {
                      Object o = event.getSource();
                      if (o instanceof sun.awt.ModalExclude) {
                          // Exclude this object from modality and
--- 399,420 ----
                   * KeyEvent is handled by using enqueueKeyEvent
                   * in Dialog.show
                   */
+                 if (Component.isInstanceOf(modalComponent, "javax.swing.JInternalFrame")) {
+                     /*
+                      * Modal internal frames are handled separately. If event is
+                      * for some component from another heavyweight than modalComp,
+                      * it is accepted. If heavyweight is the same - we still accept
+                      * event and perform further filtering in LightweightDispatcher
+                      */
+                     return FilterAction.ACCEPT;
+                 }
                  int eventID = event.getID();
!                 boolean mouseEvent = (eventID >= MouseEvent.MOUSE_FIRST) &&
!                                      (eventID <= MouseEvent.MOUSE_LAST);
!                 boolean actionEvent = (eventID >= ActionEvent.ACTION_FIRST) &&
!                                       (eventID <= ActionEvent.ACTION_LAST);
!                 boolean windowClosingEvent = (eventID == WindowEvent.WINDOW_CLOSING);
!                 if (mouseEvent || actionEvent || windowClosingEvent) {
                      Object o = event.getSource();
                      if (o instanceof sun.awt.ModalExclude) {
                          // Exclude this object from modality and
                                     
2007-01-30



Hardware and Software, Engineered to Work Together