| /* |
| * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #include "jlong.h" |
| #include "awt_Cursor.h" |
| #include "awt_Component.h" |
| #include "awt_Container.h" |
| #include "awt_IconCursor.h" |
| #include "awt_Toolkit.h" |
| #include "awt_Window.h" |
| #include <java_awt_Cursor.h> |
| #include <sun_awt_windows_WCustomCursor.h> |
| #include <sun_awt_windows_WGlobalCursorManager.h> |
| |
| |
| /************************************************************************ |
| * AwtCursor fields |
| */ |
| jmethodID AwtCursor::mSetPDataID; |
| jfieldID AwtCursor::pDataID; |
| jfieldID AwtCursor::typeID; |
| |
| jfieldID AwtCursor::pointXID; |
| jfieldID AwtCursor::pointYID; |
| |
| jclass AwtCursor::globalCursorManagerClass; |
| jmethodID AwtCursor::updateCursorID; |
| |
| AwtObjectList AwtCursor::customCursors; |
| |
| |
| AwtCursor::AwtCursor(JNIEnv *env, HCURSOR hCur, jobject jCur) |
| { |
| hCursor = hCur; |
| jCursor = env->NewWeakGlobalRef(jCur); |
| |
| xHotSpot = yHotSpot = nWidth = nHeight = nSS = 0; |
| cols = NULL; |
| mask = NULL; |
| |
| custom = dirty = FALSE; |
| } |
| |
| AwtCursor::AwtCursor(JNIEnv *env, HCURSOR hCur, jobject jCur, int xH, int yH, |
| int nWid, int nHgt, int nS, int *col, BYTE *hM) |
| { |
| hCursor = hCur; |
| jCursor = env->NewWeakGlobalRef(jCur); |
| |
| xHotSpot = xH; |
| yHotSpot = yH; |
| nWidth = nWid; |
| nHeight = nHgt; |
| nSS = nS; |
| cols = col; |
| mask = hM; |
| |
| custom = TRUE; |
| dirty = FALSE; |
| } |
| |
| AwtCursor::~AwtCursor() |
| { |
| } |
| |
| void AwtCursor::Dispose() |
| { |
| delete[] mask; |
| delete[] cols; |
| |
| if (custom) { |
| ::DestroyIcon(hCursor); |
| } |
| |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| jobject localObj = env->NewLocalRef(jCursor); |
| if (localObj != NULL) { |
| setPData(localObj, ptr_to_jlong(NULL)); |
| env->DeleteLocalRef(localObj); |
| } |
| env->DeleteWeakGlobalRef(jCursor); |
| |
| AwtObject::Dispose(); |
| } |
| |
| 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_TEXT_CURSOR: |
| winCursor = IDC_IBEAM; |
| break; |
| case java_awt_Cursor_WAIT_CURSOR: |
| winCursor = IDC_WAIT; |
| break; |
| case java_awt_Cursor_NE_RESIZE_CURSOR: |
| case java_awt_Cursor_SW_RESIZE_CURSOR: |
| winCursor = IDC_SIZENESW; |
| break; |
| case java_awt_Cursor_SE_RESIZE_CURSOR: |
| case java_awt_Cursor_NW_RESIZE_CURSOR: |
| winCursor = IDC_SIZENWSE; |
| break; |
| case java_awt_Cursor_N_RESIZE_CURSOR: |
| case java_awt_Cursor_S_RESIZE_CURSOR: |
| winCursor = IDC_SIZENS; |
| break; |
| case java_awt_Cursor_W_RESIZE_CURSOR: |
| case java_awt_Cursor_E_RESIZE_CURSOR: |
| winCursor = IDC_SIZEWE; |
| break; |
| case java_awt_Cursor_HAND_CURSOR: |
| winCursor = IDC_HAND; |
| 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; |
| } |
| |
| HCURSOR AwtCursor::GetCursor(JNIEnv *env, AwtComponent *comp) { |
| jlong pData ; |
| |
| if (comp == NULL) { |
| return NULL; |
| } |
| if (env->EnsureLocalCapacity(2) < 0) { |
| return NULL; |
| } |
| jobject jcomp = comp->GetTarget(env); |
| if (jcomp == NULL) |
| return NULL; |
| jobject jcurs = env->GetObjectField (jcomp, AwtComponent::cursorID); |
| |
| if (jcurs != NULL) { |
| pData = env->GetLongField(jcurs, AwtCursor::pDataID); |
| AwtCursor *awtCursor = (AwtCursor *)jlong_to_ptr(pData); |
| |
| env->DeleteLocalRef(jcomp); |
| env->DeleteLocalRef(jcurs); |
| |
| if (awtCursor == NULL) { |
| return NULL; |
| } |
| return awtCursor->GetHCursor(); |
| |
| } else { |
| env->DeleteLocalRef(jcomp); |
| } |
| |
| //if component's cursor is null, get the parent's cursor |
| AwtComponent *parent = comp->GetParent() ; |
| |
| return AwtCursor::GetCursor(env, parent); |
| } |
| |
| void AwtCursor::UpdateCursor(AwtComponent *comp) { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| if (env->EnsureLocalCapacity(1) < 0) { |
| return; |
| } |
| jobject jcomp = comp->GetTarget(env); |
| try { |
| //4372119:Disappearing of busy cursor on JDK 1.3 |
| HWND captureWnd = GetCapture(); |
| if ( !AwtComponent::isMenuLoopActive() && |
| (captureWnd==NULL || captureWnd==comp->GetHWnd())) |
| { |
| if (IsWindow(AwtWindow::GetModalBlocker( |
| AwtComponent::GetTopLevelParentForWindow( |
| comp->GetHWnd())))) |
| { |
| static HCURSOR hArrowCursor = LoadCursor(NULL, IDC_ARROW); |
| SetCursor(hArrowCursor); |
| } else { |
| HCURSOR cur = comp->getCursorCache(); |
| if (cur == NULL) { |
| cur = GetCursor(env , comp); |
| } |
| if (cur != NULL) { |
| ::SetCursor(cur); |
| } else { |
| if (safe_ExceptionOccurred(env)) { |
| env->ExceptionClear(); |
| } |
| } |
| if (AwtCursor::updateCursorID == NULL) { |
| jclass cls = |
| env->FindClass("sun/awt/windows/WGlobalCursorManager"); |
| if(cls != NULL){ |
| AwtCursor::globalCursorManagerClass = |
| (jclass)env->NewGlobalRef(cls); |
| AwtCursor::updateCursorID = |
| env->GetStaticMethodID(cls, "nativeUpdateCursor", |
| "(Ljava/awt/Component;)V"); |
| env->DeleteLocalRef(cls); |
| DASSERT(AwtCursor::globalCursorManagerClass != NULL); |
| DASSERT(AwtCursor::updateCursorID != NULL); |
| } |
| } |
| if (AwtCursor::updateCursorID != NULL |
| && AwtCursor::globalCursorManagerClass != NULL) { |
| env->CallStaticVoidMethod(AwtCursor::globalCursorManagerClass, |
| AwtCursor::updateCursorID, jcomp); |
| } |
| } |
| } |
| } catch (...) { |
| env->DeleteLocalRef(jcomp); |
| throw; |
| } |
| env->DeleteLocalRef(jcomp); |
| } |
| |
| void AwtCursor::Rebuild() { |
| if (!dirty) { |
| return; |
| } |
| |
| ::DestroyIcon(hCursor); |
| hCursor = NULL; |
| |
| HBITMAP hMask = ::CreateBitmap(nWidth, nHeight, 1, 1, mask); |
| HBITMAP hColor = create_BMP(NULL, cols, nSS, nWidth, nHeight); |
| if (hMask && hColor) { |
| ICONINFO icnInfo; |
| memset(&icnInfo, 0, sizeof(ICONINFO)); |
| icnInfo.hbmMask = hMask; |
| icnInfo.hbmColor = hColor; |
| icnInfo.fIcon = FALSE; |
| icnInfo.xHotspot = xHotSpot; |
| icnInfo.yHotspot = yHotSpot; |
| |
| hCursor = ::CreateIconIndirect(&icnInfo); |
| |
| destroy_BMP(hColor); |
| destroy_BMP(hMask); |
| } |
| DASSERT(hCursor); |
| dirty = FALSE; |
| } |
| |
| extern "C" { |
| |
| /************************************************************************ |
| * AwtCursor methods |
| */ |
| |
| /* |
| * Class: jave_awt_Cursor |
| * Method: initIDs |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_java_awt_Cursor_initIDs(JNIEnv *env, jclass cls) |
| { |
| TRY; |
| |
| AwtCursor::mSetPDataID = env->GetMethodID(cls, "setPData", "(J)V"); |
| DASSERT(AwtCursor::mSetPDataID != NULL); |
| CHECK_NULL(AwtCursor::mSetPDataID); |
| AwtCursor::pDataID = env->GetFieldID(cls, "pData", "J"); |
| DASSERT(AwtCursor::pDataID != NULL); |
| CHECK_NULL(AwtCursor::pDataID); |
| AwtCursor::typeID = env->GetFieldID(cls, "type", "I"); |
| DASSERT(AwtCursor::typeID != NULL); |
| CHECK_NULL(AwtCursor::typeID); |
| |
| cls = env->FindClass("java/awt/Point"); |
| CHECK_NULL(cls); |
| |
| AwtCursor::pointXID = env->GetFieldID(cls, "x", "I"); |
| DASSERT(AwtCursor::pointXID != NULL); |
| CHECK_NULL(AwtCursor::pointXID); |
| AwtCursor::pointYID = env->GetFieldID(cls, "y", "I"); |
| DASSERT(AwtCursor::pointYID != NULL); |
| |
| AwtCursor::updateCursorID = NULL; |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: java_awt_Cursor |
| * Method: finalizeImpl |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL |
| Java_java_awt_Cursor_finalizeImpl(JNIEnv *env, jclass clazz, jlong pData) |
| { |
| TRY_NO_VERIFY; |
| |
| AwtObject::_Dispose((PDATA)pData); |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| /************************************************************************ |
| * WCustomCursor native methods |
| */ |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WCustomCursor_createCursorIndirect( |
| JNIEnv *env, jobject self, jintArray intRasterData, jbyteArray andMask, |
| jint nSS, jint nW, jint nH, jint xHotSpot, jint yHotSpot) |
| { |
| TRY; |
| |
| JNI_CHECK_NULL_RETURN(intRasterData, "intRasterData argument"); |
| |
| if (nW != ::GetSystemMetrics(SM_CXCURSOR) || |
| nH != ::GetSystemMetrics(SM_CYCURSOR)) { |
| JNU_ThrowArrayIndexOutOfBoundsException(env, |
| "bad width and/or height"); |
| return; |
| } |
| |
| jsize length = env->GetArrayLength(andMask); |
| jbyte *andMaskPtr = new jbyte[length]; // safe because sizeof(jbyte)==1 |
| env->GetByteArrayRegion(andMask, 0, length, andMaskPtr); |
| |
| HBITMAP hMask = ::CreateBitmap(nW, nH, 1, 1, (BYTE *)andMaskPtr); |
| ::GdiFlush(); |
| |
| int *cols = SAFE_SIZE_NEW_ARRAY2(int, nW, nH); |
| |
| jint *intRasterDataPtr = NULL; |
| HBITMAP hColor = NULL; |
| try { |
| intRasterDataPtr = |
| (jint *)env->GetPrimitiveArrayCritical(intRasterData, 0); |
| hColor = create_BMP(NULL, (int *)intRasterDataPtr, nSS, nW, nH); |
| memcpy(cols, intRasterDataPtr, nW*nH*sizeof(int)); |
| } catch (...) { |
| if (intRasterDataPtr != NULL) { |
| env->ReleasePrimitiveArrayCritical(intRasterData, |
| intRasterDataPtr, 0); |
| } |
| throw; |
| } |
| |
| env->ReleasePrimitiveArrayCritical(intRasterData, intRasterDataPtr, 0); |
| intRasterDataPtr = NULL; |
| |
| HCURSOR hCursor = NULL; |
| |
| if (hMask && hColor) { |
| ICONINFO icnInfo; |
| memset(&icnInfo, 0, sizeof(ICONINFO)); |
| icnInfo.hbmMask = hMask; |
| icnInfo.hbmColor = hColor; |
| icnInfo.fIcon = FALSE; |
| icnInfo.xHotspot = xHotSpot; |
| icnInfo.yHotspot = yHotSpot; |
| |
| hCursor = ::CreateIconIndirect(&icnInfo); |
| |
| destroy_BMP(hColor); |
| destroy_BMP(hMask); |
| } |
| |
| DASSERT(hCursor); |
| |
| try { |
| AwtCursor::setPData(self, ptr_to_jlong(new AwtCursor(env, hCursor, self, xHotSpot, |
| yHotSpot, nW, nH, nSS, cols, |
| (BYTE *)andMaskPtr))); |
| } catch (...) { |
| if (cols) { |
| delete[] cols; |
| } |
| throw; |
| } |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WCustomCursor |
| * Method: getCursorWidth |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WCustomCursor_getCursorWidth(JNIEnv *, jclass) |
| { |
| TRY; |
| |
| DTRACE_PRINTLN("WCustomCursor.getCursorWidth()"); |
| return (jint)::GetSystemMetrics(SM_CXCURSOR); |
| |
| CATCH_BAD_ALLOC_RET(0); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WCustomCursor |
| * Method: getCursorHeight |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_windows_WCustomCursor_getCursorHeight(JNIEnv *, jclass) |
| { |
| TRY; |
| |
| DTRACE_PRINTLN("WCustomCursor.getCursorHeight()"); |
| return (jint)::GetSystemMetrics(SM_CYCURSOR); |
| |
| CATCH_BAD_ALLOC_RET(0); |
| } |
| |
| /************************************************************************ |
| * WGlobalCursorManager native methods |
| */ |
| |
| /* |
| * Class: sun_awt_windows_WGlobalCursorManager |
| * Method: getCursorPos |
| * Signature: (Ljava/awt/Point;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WGlobalCursorManager_getCursorPos(JNIEnv *env, |
| jobject, |
| jobject point) |
| { |
| TRY; |
| |
| POINT p; |
| ::GetCursorPos(&p); |
| env->SetIntField(point, AwtCursor::pointXID, (jint)p.x); |
| env->SetIntField(point, AwtCursor::pointYID, (jint)p.y); |
| |
| CATCH_BAD_ALLOC; |
| } |
| |
| struct GlobalSetCursorStruct { |
| jobject cursor; |
| jboolean u; |
| }; |
| |
| static void GlobalSetCursor(void* pStruct) { |
| JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| jobject cursor = ((GlobalSetCursorStruct*)pStruct)->cursor; |
| jboolean u = ((GlobalSetCursorStruct*)pStruct)->u; |
| jlong pData = env->GetLongField(cursor, AwtCursor::pDataID); |
| AwtCursor *awtCursor = (AwtCursor *)jlong_to_ptr(pData); |
| |
| if (awtCursor == NULL) { |
| awtCursor = AwtCursor::CreateSystemCursor(cursor); |
| } |
| |
| HCURSOR hCursor = awtCursor->GetHCursor(); |
| |
| BOOL blocked = false; |
| if (jobject jcomp = AwtComponent::FindHeavyweightUnderCursor(u)) { |
| if(jobject jpeer = AwtObject::GetPeerForTarget(env, jcomp)) |
| { |
| if(AwtComponent *awtComponent = (AwtComponent*)JNI_GET_PDATA(jpeer)) { |
| blocked = ::IsWindow(AwtWindow::GetModalBlocker( |
| AwtComponent::GetTopLevelParentForWindow( |
| awtComponent->GetHWnd()))); |
| if (!blocked) { |
| awtComponent->setCursorCache(hCursor); |
| } |
| } |
| env->DeleteLocalRef(jpeer); |
| } |
| env->DeleteGlobalRef(jcomp); |
| } |
| |
| if (!blocked) { |
| ::SetCursor(hCursor); // don't need WM_AWT_SETCURSOR |
| } |
| |
| env->DeleteGlobalRef(((GlobalSetCursorStruct*)pStruct)->cursor); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WGlobalCursorManager |
| * Method: setCursor |
| * Signature: (Ljava/awt/Component;Ljava/awt/Cursor;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_windows_WGlobalCursorManager_setCursor(JNIEnv *env, jobject, |
| jobject, jobject cursor, jboolean u) |
| { |
| TRY; |
| |
| if (cursor != NULL) { // fix for 4430302 - getCursor() returns NULL |
| GlobalSetCursorStruct data; |
| data.cursor = env->NewGlobalRef(cursor); |
| data.u = u; |
| AwtToolkit::GetInstance().InvokeFunction( |
| GlobalSetCursor, |
| (void *)&data); |
| } else { |
| JNU_ThrowNullPointerException(env, "NullPointerException"); |
| } |
| CATCH_BAD_ALLOC; |
| } |
| |
| /* |
| * Class: sun_awt_windows_WGlobalCursorManager |
| * Method: findHeavyweight |
| * Signature: (II)Z |
| */ |
| JNIEXPORT jobject JNICALL |
| Java_sun_awt_windows_WGlobalCursorManager_findHeavyweightUnderCursor( |
| JNIEnv *env, jobject, jboolean useCache) |
| { |
| TRY; |
| |
| if (env->EnsureLocalCapacity(1) < 0) { |
| return NULL; |
| } |
| |
| jobject globalRef = (jobject)AwtToolkit::GetInstance(). |
| InvokeFunction((void*(*)(void*)) |
| AwtComponent::FindHeavyweightUnderCursor, |
| (void *)useCache); |
| jobject localRef = env->NewLocalRef(globalRef); |
| env->DeleteGlobalRef(globalRef); |
| return localRef; |
| |
| CATCH_BAD_ALLOC_RET(NULL); |
| } |
| |
| /* |
| * Class: sun_awt_windows_WGlobalCursorManager |
| * Method: getLocationOnScreen |
| * Signature: (L/java/awt/Component;)L/java/awt/Point |
| */ |
| JNIEXPORT jobject JNICALL |
| Java_sun_awt_windows_WGlobalCursorManager_getLocationOnScreen( |
| JNIEnv *env, jobject, jobject component) |
| { |
| TRY; |
| |
| JNI_CHECK_NULL_RETURN_NULL(component, "null component"); |
| jobject point = |
| env->CallObjectMethod(component, AwtComponent::getLocationOnScreenMID); |
| return point; |
| |
| CATCH_BAD_ALLOC_RET(NULL); |
| } |
| |
| } /* extern "C" */ |