JDK-4533002 : CURSOR DOES NOT CHANGE BACK TO AN HOURGLASS
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0,1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_nt,windows_xp
  • CPU: x86
  • Submitted: 2001-11-29
  • Updated: 2004-10-18
  • Resolved: 2004-10-01
Related Reports
Duplicate :  
Description
Name: pa48320			Date: 11/29/2001

(this bug has been created to track an issue for the JInitiator Replacement 
Project. please direct any questions to ###@###.###)

Happens only on Windows. And does not happen on solaris or
sunray client.

JDK version: JDK1.4.0 build 84

Steps to reproduce:
-------------------
Busy cursor is not restored  in an application when the
mouse re-enters the application. When there is a long query,
Oracle Forms set the cursor to busy cursor. At this time, if
the user goes out of the application form, and comes back
while it is still performing the query, the cursor is not
set busy.

The cursor remains as an arrow head or a two headed.
However this problem does not happen on Solaris.

A JDK only test case is provided below.

-----------------CursorTest.java----------------------------
import java.applet.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class CursorTest extends Applet
                      implements ActionListener,
                                 MouseMotionListener {
 public void init() {
   System.out.println("Inside init");
   createFrame();
 }
 public void start(){
   System.out.println("CursorTest started");
 }
 public void stop(){
   System.out.println("CursorTest Stopped");
 }
 private void createFrame() {
   theFrame =new JFrame();
   JButton b = new JButton("PushMe");
   theFrame.setBounds(getBounds());
   theFrame.getContentPane().add(b,BorderLayout.SOUTH);
   b.addActionListener(this);
   theFrame.setTitle("Hello World");
   theFrame.setVisible(true);
   theFrame.addMouseMotionListener(this);
 }
 private boolean _inAction = false ;
 private JFrame theFrame;
 public void actionPerformed(ActionEvent evt)
 {
   theFrame.setCursor(Cursor.WAIT_CURSOR);
   _inAction = true ;
   System.out.println("I am Pushed");
   for ( double i = 0.0 ; i < 99.0 ; i+=0.1 ){
     for ( double j = 0.0 ; j < 99.0 ; j+=0.1 ) {
          // just do something
          String HelloWorld = new String("HelloWorld") ;
          byte[] HelloWorldByteArray = HelloWorld.getBytes() ;
     }
    }
    _inAction = false ;
    theFrame.setCursor(Cursor.DEFAULT_CURSOR);
  }
  public void mouseDragged(MouseEvent evt)
  {
  }
  public void mouseMoved(MouseEvent evt)
  {
   if ( theFrame != null )
   {
     if ( _inAction )
        theFrame.setCursor(Cursor.WAIT_CURSOR);
     else
        theFrame.setCursor(Cursor.DEFAULT_CURSOR);
   }
   else
     System.out.println("The Frame is null");
  }
 public static void main(String [] args)
 {
  CursorTest ct = new CursorTest();
  ct.init();
  ct.theFrame.setSize(400,400);
  ct.theFrame.validate();
 }
}
-----------------CursorTest.java----------------------------
(Review ID: 134857) 
======================================================================
I can reproduce this bug when running awt manual test.

JDK            : JDK1.4.1 b21, JDK1.4.2 b25
Platform[s]    : Windows 2003 (32/64), Windows XPpro
switch/Mode    : -cleint -Xmixed
test harness   : tonga 1.2 (52)
testbase       : /net/cady/export/dtf/unified/knight-ws/suites/awt/testbase
testcase       : AWT_Hopper_WS/CursorManagement/src/Interactive/4650763/BusyCursorTest.html

The cursor becomes ResizeCursor instead of BusyCursor.
###@###.### 2003-06-03

Given a Tonga test (AWT_Hopper_WS/CursorManagement/src/Interactive/4650763/BusyCursorTest.html) I could reproduce the bug with 1.4.2, but couldn't with 1.5

###@###.### 2004-08-24

Comments
EVALUATION I spoke with an Oracle engineer about this. Apparently, Oracle needs to do lengthy processing on the EDT. This prevents the cursor from updating when it re-enters the Frame. I wonder if we can do something on the Toolkit thread? I guess race conditions should be considered with this type of solution. This bug blocks Oracle certification on Sun systems. Commit to fix in Hopper (Oracle showstopper). ###@###.### 2001-11-30 This is a duplicate of 4372119. This is not a bug. ###@###.### 2001-12-04 The Suggested Fix for this bug causes deadlocks. We backed it out of the workspace soon after it was introduced. ###@###.### 2003-01-13 This is a duplicate of 4372119, and it has been fixed already (though the fix caused 5097531). Closing as a duplicate. ###@###.### 2004-10-01
13-01-2003

SUGGESTED FIX echawkes@jano:/java/jdk/ws/AWT/AWT-Hopper/src/win32/native/sun/windows( 103 )% scdiffs 1.150 1.151 awt_Component.h *** /tmp/geta23835 Sun Feb 24 17:37:50 2002 --- /tmp/getb23835 Sun Feb 24 17:37:50 2002 *************** *** 88,93 **** --- 88,94 ---- static jmethodID resetGCMID; static jmethodID replaceSurfaceDataMID; static jmethodID replaceSurfaceDataLaterMID; + static jmethodID updateCursorImmediatelyMID; static const UINT WmAwtIsComponent; *************** *** 437,442 **** --- 438,444 ---- virtual MsgRouting WmPaint(HDC hDC); virtual MsgRouting WmGetMinMaxInfo(LPMINMAXINFO lpmmi); virtual MsgRouting WmMove(int x, int y); + virtual MsgRouting WmSetCursor(WORD hitTest); virtual MsgRouting WmSize(int type, int w, int h); virtual MsgRouting WmSizing(); virtual MsgRouting WmShowWindow(int show, long status); echawkes@jano:/java/jdk/ws/AWT/AWT-Hopper/src/win32/native/sun/windows( 105 )% scdiffs 1.310 1.311 awt_Component.cpp *** /tmp/geta26248 Sun Feb 24 17:38:40 2002 --- /tmp/getb26248 Sun Feb 24 17:38:41 2002 *************** *** 106,111 **** --- 106,112 ---- jmethodID AwtComponent::resetGCMID; jmethodID AwtComponent::replaceSurfaceDataMID; jmethodID AwtComponent::replaceSurfaceDataLaterMID; + jmethodID AwtComponent::updateCursorImmediatelyMID; HKL AwtComponent::m_hkl = ::GetKeyboardLayout(0); LANGID AwtComponent::m_idLang = LOWORD(::GetKeyboardLayout(0)); *************** *** 1145,1152 **** break; case WM_SETCURSOR: ! mr = (LOWORD(lParam) == HTCLIENT) ? mrConsume : mrDoDefault; ! break; case WM_KEYDOWN: MSG msg; --- 1146,1153 ---- break; case WM_SETCURSOR: ! mr = WmSetCursor(LOWORD(lParam)); ! break; case WM_KEYDOWN: MSG msg; *************** *** 1979,1984 **** --- 1980,1997 ---- return mrConsume; } + MsgRouting AwtComponent::WmSetCursor(WORD hitTest) + { + // Update the cursor immediately if over the client area + if (hitTest == HTCLIENT) { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm,JNI_VERSION_1_2); + env->CallObjectMethod(GetTarget(env), AwtComponent::updateCursorImmediatelyMID); + return(mrConsume); + } else { + return(mrDoDefault); + } + } + jint AwtComponent::GetKeyLocation(UINT wkey, UINT flags) { // Rector+Newcomer page 413 // The extended keys are the Alt and Control on the right of *************** *** 5524,5531 **** env->GetMethodID(peerCls, "replaceSurfaceData", "()V"); AwtComponent::replaceSurfaceDataLaterMID = env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V"); - DASSERT(AwtComponent::xID); DASSERT(AwtComponent::yID); DASSERT(AwtComponent::heightID); --- 5537,5545 ---- env->GetMethodID(peerCls, "replaceSurfaceData", "()V"); AwtComponent::replaceSurfaceDataLaterMID = env->GetMethodID(peerCls, "replaceSurfaceDataLater", "()V"); + AwtComponent::updateCursorImmediatelyMID = + env->GetMethodID(cls, "updateCursorImmediately", "()V"); DASSERT(AwtComponent::xID); DASSERT(AwtComponent::yID); DASSERT(AwtComponent::heightID); *************** *** 5544,5550 **** DASSERT(AwtComponent::resetGCMID); DASSERT(AwtComponent::replaceSurfaceDataMID); DASSERT(AwtComponent::replaceSurfaceDataLaterMID); ! CATCH_BAD_ALLOC; } --- 5558,5565 ---- DASSERT(AwtComponent::resetGCMID); DASSERT(AwtComponent::replaceSurfaceDataMID); DASSERT(AwtComponent::replaceSurfaceDataLaterMID); ! DASSERT(AwtComponent::updateCursorImmediatelyMID); ! CATCH_BAD_ALLOC; } echawkes@jano:/net/jano/export/disk03/awt/echawkes/jdk141-1/src/share/classes/java/awt( 109 )% scdiffs 1.332 1.333 Component.java *** /tmp/geta6084 Sun Feb 24 17:41:14 2002 --- /tmp/getb6084 Sun Feb 24 17:41:15 2002 *************** *** 2210,2215 **** --- 2210,2219 ---- updateCursorImmediately(); } + /** + * Updates the cursor. Could be invoked from the native + * message pump. + */ final void updateCursorImmediately() { if (peer instanceof LightweightPeer) { Container nativeContainer = getNativeContainer(); ###@###.### 2002-02-24
24-02-2002