JDK-4530925 : Regression b87/b86, you must let hover mouse over window to use Tab traversal
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • OS: linux,solaris_8
  • CPU: x86,sparc
  • Submitted: 2001-11-23
  • Updated: 2002-01-10
  • Resolved: 2001-12-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.0 rc1Fixed
Related Reports
Relates :  
Description
You must move (and let hover) mouse over the window, there you can to use Tab to traversing. This is regression against build 86 , there aren't needs to move mouse over window to be possible Tab traversing.

Steps to reproduce:
- create JFrame with two JButton1 and JButton2
- compile and run it
- > mouse isn't over showned window (JFrame)
- hit Tab or Ctrl+Tab
-> nothing happends
-> move mouse let hover window (JFrame)
- now try to hit Tab
-> focus transfered to JButton1 , hit Tab , focus transvered to  JButton2


================================================  

This is the test case in the attachments: 

import java.awt.*;
import javax.swing.*;

public class Test extends JComponent {
    public static void main(String[] args) {
        if (args.length > 0 && args[0].equals("-swing")) {
            System.out.println("SWING");
            JFrame frame = new JFrame("TEST");
            frame.getContentPane().setLayout(new FlowLayout());
            frame.getContentPane().add(new JButton("JButton 1"));
            frame.getContentPane().add(new JButton("JButton 2"));
            frame.pack();
            frame.show();
        }
        else {
            System.out.println("AWT");
            Frame frame = new Frame("TEST");
            frame.setLayout(new FlowLayout());
            frame.add(new Button("Button 1"));
            frame.add(new Button("Button 2"));
            frame.pack();
            frame.show();
        }
    }
}

###@###.### 2001-11-26

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-rc1 FIXED IN: merlin-rc1 INTEGRATED IN: merlin-rc1 VERIFIED IN: merlin-rc1
24-08-2004

WORK AROUND You must let hover mouse over window.
24-08-2004

SUGGESTED FIX Name: dmR10075 Date: 11/28/2001 ###@###.### *** /tmp/geta26784 Wed Nov 28 14:34:58 2001 --- awt_MToolkit.c Wed Nov 28 14:32:41 2001 *************** *** 560,565 **** --- 560,589 ---- return (findWidgetInfo(widget) != NULL); } + static Widget + getShellWidget(Widget part) { + int i; + for (i = 0; i < 3; i++) { + if (part == NULL) return NULL; + if (XtIsShell(part)) return part; + part = XtParent(part); + } + return NULL; + } + + static Boolean + isTheSameShellWidget(Widget shell, Widget w) { + Widget s1, s2; + if (shell == NULL || w == NULL) return False; + s1 = getShellWidget(shell); + s2 = getShellWidget(w); + if (s1 == s2 && s1 != NULL) { + return True; + } else { + return False; + } + } + static Boolean shouldDispatchToWidget(XEvent * xev) { *************** *** 631,647 **** } /* if focus owner is null, redirect key events to focused window */ ! if (focusWidget == NULL) { ! if (findWidgetInfo(widget) == NULL) { ! focusWidget = findTopLevelByShell(widget); ! } } /* If we are on a non-choice widget, process events in a normal way */ ! if ((focusWidget != NULL) && (focusWidget != widget) && ! (peer = findPeer(&focusWidget)) != NULL) { widget = focusWidget; ! win = xev->xkey.window = XtWindow(focusWidget); } } --- 655,674 ---- } /* if focus owner is null, redirect key events to focused window */ ! if (focusWidget == NULL && findWidgetInfo(widget) == NULL) { ! focusWidget = findTopLevelByShell(widget); } /* If we are on a non-choice widget, process events in a normal way */ ! if ((focusWidget != NULL) && (focusWidget != widget)) { ! if (isTheSameShellWidget(focusWidget, widget)) { ! focusWidget = findTopLevelByShell(widget); ! } ! peer = findPeer(&focusWidget); ! if (peer != NULL) { widget = focusWidget; ! win = xev->xkey.window = XtWindow(focusWidget); ! } } } ======================================================================
24-08-2004

PUBLIC COMMENTS Verified in merlin-rc1 : Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b89) Java HotSpot(TM) Client VM (build 1.4.0-rc-b89, mixed mode)
24-08-2004

EVALUATION I've attached a test case of this (Test.java). To run it with Swing use -swing as an arg, otherwise it will create awt widgets. This behavior only occurs with swing (likely with light weights). As submitter indicates as long as the mouse is over the frame tab traversal works, if the mouse isn't over the frame tab traversal does not work. This is on a solaris 8 machine with click to focus. Additionally it isn't just tab that doesn't work, no KeyEvents are dispatched unless the mouse is over the frame. I did a quick look and it would appear that when the mouse is not over the frame Component.dispatchEventImpl nor EventQueue.postEvent is invoked. Where as when the mouse is over the frame these methods are called and everyone is happy. Reassigning to awt for further investigation. ###@###.### 2001-11-26 Reproducible on Solaris 7. Reassigning to Russia. ###@###.### 2001-11-26 Name: dmR10075 Date: 11/28/2001 The problem is in native code. In fact, X window system dispatches key evens differently depending on where is the mouse - over the focused window or not. In native code we handle this by some heuristic, however starting from b87 it fails to correctly detect current focus situation. Top level constists of four widget - shell[form[outer_canvas[inner_canvas]]]. innver_canvas contains all child components of the top-level (like buttons). Shell is the upper widget in hierarchy and represents window for X system. inner_canvas is also responsible for events related to top-level as whole and of some interest for Java (like key events, mouse and such). The heuristic is in the awt_MToolkit.c:shouldDispatchToWidget(SDTW). For key events there are two widgets of some interest - current focused widget from Motif and the target widget of key event. Given these two widgets SDTW calculates some resulting widget which will receive key event: When mouse is over focused window(from the test) and we press any key: - Target of key event is inner_canvas, it is the canvas which holds all widgets for top-level - Current focused widget is outer_canvas which is parent of inner_canvas widget. After some heuristic is applied the resulting target widget is inner_canvas. When mouse is not over focused window and we press any key: - Target of key event is __shell widget__, the upper widget in the top-level's hierarchy - Current focused widget is outer_canvas. The resulting widget is shell. After we got the resulting widget we dispatch event to it. In case of inner_canvas it leads to call of key event's callback and generating events for Java. In case of shell it leads to loosing the event for Java. To fix the problem we need to change the logic of SDTW so it will produce inner_canvas as the resulting widget for second case. The possible idead is as following: if the key event is targeted to shell and current focus widget is one of the top-level widgets dispatch event to inner_canvas. ###@###.### 11-28-2001 ======================================================================
22-09-0018