Found and solved a bug on Cursor Management on Windows platforms

Morvan Le Mescam morvan.lemescam at gmail.com
Wed Apr 17 17:01:51 UTC 2013


Dear all,

When developping a Swing client, I face the following problem :
When setting the hand cursor on Windows, I noticed that the default system
cursor was not used.

I analysed the problem and found the rrot cause.
I also made a correction and tested it on Windows 7.

This is my analyse :

When reading Java source code, it is obvious that on Windows, Java does not
use System resources.

In the code (from *jdk\src\windows\native\sun\windows\awt_Cursor.cpp* )
bellow :

AwtCursor * AwtCursor::*CreateSystemCursor*(jobject jCursor)

{

    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);



    jint type = env->GetIntField(jCursor, AwtCursor::typeID);

    DASSERT(type != java_awt_Cursor_CUSTOM_CURSOR);



    LPCTSTR winCursor;

    switch (type) {

      case java_awt_Cursor_DEFAULT_CURSOR:

      default:

        winCursor = IDC_ARROW;

        break;

      case java_awt_Cursor_CROSSHAIR_CURSOR:

        winCursor = IDC_CROSS;

        break;

*[…]*

*      case java_awt_Cursor_HAND_CURSOR:*

*        winCursor = TEXT("HAND_CURSOR");*

*        break;*

      case java_awt_Cursor_MOVE_CURSOR:

        winCursor = IDC_SIZEALL;

        break;

    }

*    HCURSOR hCursor = ::LoadCursor(NULL, winCursor);*

    if (*hCursor == NULL*) {

        /* Not a system cursor, check for resource. */

        *hCursor = ::LoadCursor(AwtToolkit::GetInstance().GetModuleHandle(),
*

*                               winCursor);*

    }

    if (hCursor == NULL) {

        hCursor = ::LoadCursor(NULL, IDC_ARROW);

        DASSERT(hCursor != NULL);

    }



    AwtCursor *awtCursor = new AwtCursor(env, hCursor, jCursor);

    setPData(jCursor, ptr_to_jlong(awtCursor));



    return awtCursor;

}



In the case of the HAND_CURSOR (*in red*),  Java will try to load the
cursor from the system (*in blue*).

If it fails (*hCursor == NULL*) then it will try to load the cursor from
its own resource (*in orange*) :

*hCursor = ::LoadCursor(AwtToolkit::GetInstance().GetModuleHandle(),*

*                               winCursor);*



In our case, if we check in the AWTToolkit module resources, in *
jdk\src\windows\native\sun\windows\awr.rc*, we find the following content :

#include "windows.h"



// Need 2 defines so macro argument to XSTR will get expanded before
quoting.

#define XSTR(x) STR(x)

#define STR(x)  #x



LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL



*HAND_CURSOR  CURSOR  DISCARDABLE "hand.cur"*

AWT_ICON     ICON    DISCARDABLE "awt.ico"

CHECK_BITMAP BITMAP  DISCARDABLE "check.bmp"



And we find that java.exe embed its own hand cursor, in *
jdk\src\windows\native\sun\windows\hand.cur* : The “famous” hand that it is
displayed instead of our system cursor.


This is the correction :

, I made the correction into the JRE source code :

      case java_awt_Cursor_HAND_CURSOR:

        /* MLM change winCursor = TEXT("HAND_CURSOR"); */

        winCursor = IDC_HAND;

        break;

I could compile and regenerate a JRE with this change :

D:\Work\Current\openjdk\build\windows-amd64\bin>java -version

openjdk version "1.7.0-u6-unofficial"

OpenJDK Runtime Environment (build 1.7.0-u6-unofficial-b24)

OpenJDK 64-Bit Server VM (build 21.0-b17, mixed mode)





And this works !

If I change the hand cursor at System level, Java takes it into account.
Last but not least question:

Why did a Sun developper, one day :  winCursor = TEXT("HAND_CURSOR");

This seems so not consistent with other part of the code... So there is
probably a good reason. Perhaps the hand cursor was not existant on Windows
platform when this was done ?


Regards


Morvan



More information about the build-dev mailing list