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