JDK-6412812 : Regression. XToolkit: Cursor shown on components on a blocked window changes when clicked
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2006-04-13
  • Updated: 2011-01-19
  • Resolved: 2006-06-03
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.
JDK 6
6 b87Fixed
Related Reports
Relates :  
Relates :  
Description
This behavior occurs with the latest mustang build, b79. It does not occur with b66. This occurs on Linux and Solaris platforms.

Clicking on swing components present in a blocked JFrame changes the cursor shown. I've a JFrame on which I have a JButton and JTextField. The frame is blocked by a modal dialog. When I move the mouse over the JTextField, default cursor is shown. When I click on the text field, the cursor changes to text cursor. Even when I move the mouse over the button, the cursor shown is the same. Now, if I click anywhere on the frame outside the text field, the cursor changes to default cursor.

This behavior is not reproducible with awt components.

To reproduce, run the code below:

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

public class TestCursor {
    public static void main(String[] args) {
        JFrame f = new JFrame("Frame");
        JDialog d = new JDialog(new JFrame(), "Dialog");
        d.setModal(true);
        d.setSize(100, 100);
        d.setLocation(200, 200);
        f.setSize(200, 200);
        f.getContentPane().setLayout(new FlowLayout());
        f.getContentPane().add(new JButton("Button"));
        f.getContentPane().add(new JTextField(15));
        f.getContentPane().add(new JTextArea(5, 10));
        f.setVisible(true);
        d.setVisible(true);
    }
}

Comments
EVALUATION The final idea of the fix is as follows. It contains two parts. 1) filter crossing events causing cursor change while window is blocked. It's in XWindow.handleXCrossingEvent(): XWindowPeer toplevel = getToplevelXWindow(); if (toplevel != null && !toplevel.isModalBlocked()){ //CHANGE CURSOR HERE } So far if the window is blocked then we wouldn't change cursor withing it. This also covering popup menus - this IF statement doesn't work because popup doesn't have a toplevel parent. 2) if cursor explicitly set on a window: window.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); then 1) part wouldn't work. We should override that cursor to default after last cursor change: if (toplevel != null && toplevel.isModalBlocked()){ ((XComponentPeer)target.getPeer()).pSetCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } The test should verify that installed cursor is restoring after modal dialog had disappear.
06-05-2006

EVALUATION Found an issue while testing this fix. It's in adding a check if (toplevel != null && !toplevel.isModalBlocked()){ into XWindow.handleXCrossingEvent() before XGlobalCursorManger is about to change the cursor. This only works for components with it's own cursor. If I create a window and write: window.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); then this fix wouldn't work. JDK is able to change it only by setting correct properties to the window by XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),getWindow(),valuemask,xwa.pData); For this purpose we use XComponentPeer.pSetCursor()
05-05-2006

EVALUATION XWindow shouldn't process Enter/LeaveNotify events on cursor changes if happens on a blocked window.
04-05-2006

SUGGESTED FIX *** m 75 2006-05-05 19:15:19.000000000 +0400 --- XWindow.java 2006-05-05 19:07:48.000000000 +0400 *************** *** 757,773 **** // current component. Second one notifies that it has entered into the same component. // This looks like the window under the mouse has actually changed and Java handle these events // accordingly. This leads to impossibility to make a double click on Component (6404708) ! if (xce.get_mode() != NotifyNormal) { ! // 6404708 : need update cursor in accordance with skipping Leave/EnterNotify event ! // whereas it doesn't need to handled further. ! if (xce.get_type() == EnterNotify) { ! XAwtState.setComponentMouseEntered(getEventSource()); ! XGlobalCursorManager.nativeUpdateCursor(getEventSource()); ! } else { // LeaveNotify: ! XAwtState.setComponentMouseEntered(null); } ! return; ! } // X sends XCrossing to all hierarchy so if the edge of child equals to // ancestor and mouse enters child, the ancestor will get an event too. // From java point the event is bogus as ancestor is obscured, so if --- 757,776 ---- // current component. Second one notifies that it has entered into the same component. // This looks like the window under the mouse has actually changed and Java handle these events // accordingly. This leads to impossibility to make a double click on Component (6404708) ! XWindowPeer toplevel = getToplevelXWindow(); ! if (toplevel != null && !toplevel.isModalBlocked()){ ! if (xce.get_mode() != NotifyNormal) { ! // 6404708 : need update cursor in accordance with skipping Leave/EnterNotify event ! // whereas it doesn't need to handled further. ! if (xce.get_type() == EnterNotify) { ! XAwtState.setComponentMouseEntered(getEventSource()); ! XGlobalCursorManager.nativeUpdateCursor(getEventSource()); ! } else { // LeaveNotify: ! XAwtState.setComponentMouseEntered(null); ! } ! return; } ! } // X sends XCrossing to all hierarchy so if the edge of child equals to // ancestor and mouse enters child, the ancestor will get an event too. // From java point the event is bogus as ancestor is obscured, so if *************** *** 784,798 **** // Remember old component with mouse to have the opportunity to send it MOUSE_EXITED. final Component compWithMouse = XAwtState.getComponentMouseEntered(); ! ! if (xce.get_type() == EnterNotify) { ! // Change XAwtState's component mouse entered to the up-to-date one before requesting ! // to update the cursor since XAwtState.getComponentMouseEntered() is used when the ! // cursor is updated (in XGlobalCursorManager.findHeavyweightUnderCursor()). ! XAwtState.setComponentMouseEntered(getEventSource()); ! XGlobalCursorManager.nativeUpdateCursor(getEventSource()); ! } else { // LeaveNotify: ! XAwtState.setComponentMouseEntered(null); } if (isEventDisabled(xce)) { --- 787,806 ---- // Remember old component with mouse to have the opportunity to send it MOUSE_EXITED. final Component compWithMouse = XAwtState.getComponentMouseEntered(); ! if (toplevel != null && !toplevel.isModalBlocked()){ ! if (xce.get_type() == EnterNotify) { ! // Change XAwtState's component mouse entered to the up-to-date one before requesting ! // to update the cursor since XAwtState.getComponentMouseEntered() is used when the ! // cursor is updated (in XGlobalCursorManager.findHeavyweightUnderCursor()). ! XAwtState.setComponentMouseEntered(getEventSource()); ! XGlobalCursorManager.nativeUpdateCursor(getEventSource()); ! } else { // LeaveNotify: ! XAwtState.setComponentMouseEntered(null); ! } ! } ! // note there is no "!" before isModalBlocked ! if (toplevel != null && toplevel.isModalBlocked()){ ! ((XComponentPeer)target.getPeer()).pSetCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } if (isEventDisabled(xce)) {
04-05-2006

EVALUATION This shouldn't happen without a blocked in window hierarchy. This somehow relate to activation mechanism: once the mouse being pressed over blocked Frame Java recieves: 1) LeaveNotify from Dialog 2) EnterNotify on Frame 3) LeaveNotify from Frame 4) EnterNotify on Dialog although mouse wasn't moved at all. Interestingly that also happens with MToolkit on the same desktop but I'm observing the Dialog does lose focus and Frame becomes highighted. This only happens on a components with a different then default cursor over them such as TextComponents or if they are explicitly defined. On Windows cursor changes for every TextComponent and restores once the mouse left them. This is a desirable behavior for every platform.
13-04-2006

EVALUATION This is a regression of 6242833 and it still there even with the fix for 6404708. In some cases we shouldn't update the cursor. The same is also observing on MToolkit. It doesn't depend on the focus transfer model (point-to-focus/click-to-focus)
13-04-2006