1 /* 2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "jlong.h" 27 #include "awt_Cursor.h" 28 #include "awt_Component.h" 29 #include "awt_Container.h" 30 #include "awt_IconCursor.h" 31 #include "awt_Toolkit.h" 32 #include "awt_Window.h" 33 #include <java_awt_Cursor.h> 34 #include <sun_awt_windows_WCustomCursor.h> 35 #include <sun_awt_windows_WGlobalCursorManager.h> 36 37 38 /************************************************************************ 39 * AwtCursor fields 40 */ 41 jmethodID AwtCursor::mSetPDataID; 42 jfieldID AwtCursor::pDataID; 43 jfieldID AwtCursor::typeID; 44 45 jfieldID AwtCursor::pointXID; 46 jfieldID AwtCursor::pointYID; 47 48 jclass AwtCursor::globalCursorManagerClass; 49 jmethodID AwtCursor::updateCursorID; 50 51 AwtObjectList AwtCursor::customCursors; 52 53 54 AwtCursor::AwtCursor(JNIEnv *env, HCURSOR hCur, jobject jCur) 55 { 56 hCursor = hCur; 57 jCursor = env->NewWeakGlobalRef(jCur); 58 59 xHotSpot = yHotSpot = nWidth = nHeight = nSS = 0; 60 cols = NULL; 61 mask = NULL; 62 63 custom = dirty = FALSE; 64 } 65 66 AwtCursor::AwtCursor(JNIEnv *env, HCURSOR hCur, jobject jCur, int xH, int yH, 67 int nWid, int nHgt, int nS, int *col, BYTE *hM) 68 { 69 hCursor = hCur; 70 jCursor = env->NewWeakGlobalRef(jCur); 71 72 xHotSpot = xH; 73 yHotSpot = yH; 74 nWidth = nWid; 75 nHeight = nHgt; 76 nSS = nS; 77 cols = col; 78 mask = hM; 79 80 custom = TRUE; 81 dirty = FALSE; 82 } 83 84 AwtCursor::~AwtCursor() 85 { 86 } 87 88 void AwtCursor::Dispose() 89 { 90 delete[] mask; 91 delete[] cols; 92 93 if (custom) { 94 ::DestroyIcon(hCursor); 95 } 96 97 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 98 jobject localObj = env->NewLocalRef(jCursor); 99 if (localObj != NULL) { 100 setPData(localObj, ptr_to_jlong(NULL)); 101 env->DeleteLocalRef(localObj); 102 } 103 env->DeleteWeakGlobalRef(jCursor); 104 105 AwtObject::Dispose(); 106 } 107 108 AwtCursor * AwtCursor::CreateSystemCursor(jobject jCursor) 109 { 110 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 111 112 jint type = env->GetIntField(jCursor, AwtCursor::typeID); 113 DASSERT(type != java_awt_Cursor_CUSTOM_CURSOR); 114 115 LPCTSTR winCursor; 116 switch (type) { 117 case java_awt_Cursor_DEFAULT_CURSOR: 118 default: 119 winCursor = IDC_ARROW; 120 break; 121 case java_awt_Cursor_CROSSHAIR_CURSOR: 122 winCursor = IDC_CROSS; 123 break; 124 case java_awt_Cursor_TEXT_CURSOR: 125 winCursor = IDC_IBEAM; 126 break; 127 case java_awt_Cursor_WAIT_CURSOR: 128 winCursor = IDC_WAIT; 129 break; 130 case java_awt_Cursor_NE_RESIZE_CURSOR: 131 case java_awt_Cursor_SW_RESIZE_CURSOR: 132 winCursor = IDC_SIZENESW; 133 break; 134 case java_awt_Cursor_SE_RESIZE_CURSOR: 135 case java_awt_Cursor_NW_RESIZE_CURSOR: 136 winCursor = IDC_SIZENWSE; 137 break; 138 case java_awt_Cursor_N_RESIZE_CURSOR: 139 case java_awt_Cursor_S_RESIZE_CURSOR: 140 winCursor = IDC_SIZENS; 141 break; 142 case java_awt_Cursor_W_RESIZE_CURSOR: 143 case java_awt_Cursor_E_RESIZE_CURSOR: 144 winCursor = IDC_SIZEWE; 145 break; 146 case java_awt_Cursor_HAND_CURSOR: 147 winCursor = IDC_HAND; 148 break; 149 case java_awt_Cursor_MOVE_CURSOR: 150 winCursor = IDC_SIZEALL; 151 break; 152 } 153 HCURSOR hCursor = ::LoadCursor(NULL, winCursor); 154 if (hCursor == NULL) { 155 /* Not a system cursor, check for resource. */ 156 hCursor = ::LoadCursor(AwtToolkit::GetInstance().GetModuleHandle(), 157 winCursor); 158 } 159 if (hCursor == NULL) { 160 hCursor = ::LoadCursor(NULL, IDC_ARROW); 161 DASSERT(hCursor != NULL); 162 } 163 164 AwtCursor *awtCursor = new AwtCursor(env, hCursor, jCursor); 165 setPData(jCursor, ptr_to_jlong(awtCursor)); 166 167 return awtCursor; 168 } 169 170 HCURSOR AwtCursor::GetCursor(JNIEnv *env, AwtComponent *comp) { 171 jlong pData ; 172 173 if (comp == NULL) { 174 return NULL; 175 } 176 if (env->EnsureLocalCapacity(2) < 0) { 177 return NULL; 178 } 179 jobject jcomp = comp->GetTarget(env); 180 if (jcomp == NULL) 181 return NULL; 182 jobject jcurs = env->GetObjectField (jcomp, AwtComponent::cursorID); 183 184 if (jcurs != NULL) { 185 pData = env->GetLongField(jcurs, AwtCursor::pDataID); 186 AwtCursor *awtCursor = (AwtCursor *)jlong_to_ptr(pData); 187 188 env->DeleteLocalRef(jcomp); 189 env->DeleteLocalRef(jcurs); 190 191 if (awtCursor == NULL) { 192 return NULL; 193 } 194 return awtCursor->GetHCursor(); 195 196 } else { 197 env->DeleteLocalRef(jcomp); 198 } 199 200 //if component's cursor is null, get the parent's cursor 201 AwtComponent *parent = comp->GetParent() ; 202 203 return AwtCursor::GetCursor(env, parent); 204 } 205 206 void AwtCursor::UpdateCursor(AwtComponent *comp) { 207 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 208 if (env->EnsureLocalCapacity(1) < 0) { 209 return; 210 } 211 jobject jcomp = comp->GetTarget(env); 212 try { 213 //4372119:Disappearing of busy cursor on JDK 1.3 214 HWND captureWnd = GetCapture(); 215 if ( !AwtComponent::isMenuLoopActive() && 216 (captureWnd==NULL || captureWnd==comp->GetHWnd())) 217 { 218 if (IsWindow(AwtWindow::GetModalBlocker( 219 AwtComponent::GetTopLevelParentForWindow( 220 comp->GetHWnd())))) 221 { 222 static HCURSOR hArrowCursor = LoadCursor(NULL, IDC_ARROW); 223 SetCursor(hArrowCursor); 224 } else { 225 HCURSOR cur = comp->getCursorCache(); 226 if (cur == NULL) { 227 cur = GetCursor(env , comp); 228 } 229 if (cur != NULL) { 230 ::SetCursor(cur); 231 } else { 232 if (safe_ExceptionOccurred(env)) { 233 env->ExceptionClear(); 234 } 235 } 236 if (AwtCursor::updateCursorID == NULL) { 237 jclass cls = 238 env->FindClass("sun/awt/windows/WGlobalCursorManager"); 239 if(cls != NULL){ 240 AwtCursor::globalCursorManagerClass = 241 (jclass)env->NewGlobalRef(cls); 242 AwtCursor::updateCursorID = 243 env->GetStaticMethodID(cls, "nativeUpdateCursor", 244 "(Ljava/awt/Component;)V"); 245 env->DeleteLocalRef(cls); 246 DASSERT(AwtCursor::globalCursorManagerClass != NULL); 247 DASSERT(AwtCursor::updateCursorID != NULL); 248 } 249 } 250 if (AwtCursor::updateCursorID != NULL 251 && AwtCursor::globalCursorManagerClass != NULL) { 252 env->CallStaticVoidMethod(AwtCursor::globalCursorManagerClass, 253 AwtCursor::updateCursorID, jcomp); 254 } 255 } 256 } 257 } catch (...) { 258 env->DeleteLocalRef(jcomp); 259 throw; 260 } 261 env->DeleteLocalRef(jcomp); 262 } 263 264 void AwtCursor::Rebuild() { 265 if (!dirty) { 266 return; 267 } 268 269 ::DestroyIcon(hCursor); 270 hCursor = NULL; 271 272 HBITMAP hMask = ::CreateBitmap(nWidth, nHeight, 1, 1, mask); 273 HBITMAP hColor = create_BMP(NULL, cols, nSS, nWidth, nHeight); 274 if (hMask && hColor) { 275 ICONINFO icnInfo; 276 memset(&icnInfo, 0, sizeof(ICONINFO)); 277 icnInfo.hbmMask = hMask; 278 icnInfo.hbmColor = hColor; 279 icnInfo.fIcon = FALSE; 280 icnInfo.xHotspot = xHotSpot; 281 icnInfo.yHotspot = yHotSpot; 282 283 hCursor = ::CreateIconIndirect(&icnInfo); 284 285 destroy_BMP(hColor); 286 destroy_BMP(hMask); 287 } 288 DASSERT(hCursor); 289 dirty = FALSE; 290 } 291 292 extern "C" { 293 294 /************************************************************************ 295 * AwtCursor methods 296 */ 297 298 /* 299 * Class: jave_awt_Cursor 300 * Method: initIDs 301 * Signature: ()V 302 */ 303 JNIEXPORT void JNICALL 304 Java_java_awt_Cursor_initIDs(JNIEnv *env, jclass cls) 305 { 306 TRY; 307 308 AwtCursor::mSetPDataID = env->GetMethodID(cls, "setPData", "(J)V"); 309 DASSERT(AwtCursor::mSetPDataID != NULL); 310 CHECK_NULL(AwtCursor::mSetPDataID); 311 AwtCursor::pDataID = env->GetFieldID(cls, "pData", "J"); 312 DASSERT(AwtCursor::pDataID != NULL); 313 CHECK_NULL(AwtCursor::pDataID); 314 AwtCursor::typeID = env->GetFieldID(cls, "type", "I"); 315 DASSERT(AwtCursor::typeID != NULL); 316 CHECK_NULL(AwtCursor::typeID); 317 318 cls = env->FindClass("java/awt/Point"); 319 CHECK_NULL(cls); 320 321 AwtCursor::pointXID = env->GetFieldID(cls, "x", "I"); 322 DASSERT(AwtCursor::pointXID != NULL); 323 CHECK_NULL(AwtCursor::pointXID); 324 AwtCursor::pointYID = env->GetFieldID(cls, "y", "I"); 325 DASSERT(AwtCursor::pointYID != NULL); 326 327 AwtCursor::updateCursorID = NULL; 328 329 CATCH_BAD_ALLOC; 330 } 331 332 /* 333 * Class: java_awt_Cursor 334 * Method: finalizeImpl 335 * Signature: ()V 336 */ 337 JNIEXPORT void JNICALL 338 Java_java_awt_Cursor_finalizeImpl(JNIEnv *env, jclass clazz, jlong pData) 339 { 340 TRY_NO_VERIFY; 341 342 AwtObject::_Dispose((PDATA)pData); 343 344 CATCH_BAD_ALLOC; 345 } 346 347 /************************************************************************ 348 * WCustomCursor native methods 349 */ 350 351 JNIEXPORT void JNICALL 352 Java_sun_awt_windows_WCustomCursor_createCursorIndirect( 353 JNIEnv *env, jobject self, jintArray intRasterData, jbyteArray andMask, 354 jint nSS, jint nW, jint nH, jint xHotSpot, jint yHotSpot) 355 { 356 TRY; 357 358 JNI_CHECK_NULL_RETURN(intRasterData, "intRasterData argument"); 359 360 if (nW != ::GetSystemMetrics(SM_CXCURSOR) || 361 nH != ::GetSystemMetrics(SM_CYCURSOR)) { 362 JNU_ThrowArrayIndexOutOfBoundsException(env, 363 "bad width and/or height"); 364 return; 365 } 366 367 jsize length = env->GetArrayLength(andMask); 368 jbyte *andMaskPtr = new jbyte[length]; // safe because sizeof(jbyte)==1 369 env->GetByteArrayRegion(andMask, 0, length, andMaskPtr); 370 371 HBITMAP hMask = ::CreateBitmap(nW, nH, 1, 1, (BYTE *)andMaskPtr); 372 ::GdiFlush(); 373 374 int *cols = SAFE_SIZE_NEW_ARRAY2(int, nW, nH); 375 376 jint *intRasterDataPtr = NULL; 377 HBITMAP hColor = NULL; 378 try { 379 intRasterDataPtr = 380 (jint *)env->GetPrimitiveArrayCritical(intRasterData, 0); 381 hColor = create_BMP(NULL, (int *)intRasterDataPtr, nSS, nW, nH); 382 memcpy(cols, intRasterDataPtr, nW*nH*sizeof(int)); 383 } catch (...) { 384 if (intRasterDataPtr != NULL) { 385 env->ReleasePrimitiveArrayCritical(intRasterData, 386 intRasterDataPtr, 0); 387 } 388 throw; 389 } 390 391 env->ReleasePrimitiveArrayCritical(intRasterData, intRasterDataPtr, 0); 392 intRasterDataPtr = NULL; 393 394 HCURSOR hCursor = NULL; 395 396 if (hMask && hColor) { 397 ICONINFO icnInfo; 398 memset(&icnInfo, 0, sizeof(ICONINFO)); 399 icnInfo.hbmMask = hMask; 400 icnInfo.hbmColor = hColor; 401 icnInfo.fIcon = FALSE; 402 icnInfo.xHotspot = xHotSpot; 403 icnInfo.yHotspot = yHotSpot; 404 405 hCursor = ::CreateIconIndirect(&icnInfo); 406 407 destroy_BMP(hColor); 408 destroy_BMP(hMask); 409 } 410 411 DASSERT(hCursor); 412 413 try { 414 AwtCursor::setPData(self, ptr_to_jlong(new AwtCursor(env, hCursor, self, xHotSpot, 415 yHotSpot, nW, nH, nSS, cols, 416 (BYTE *)andMaskPtr))); 417 } catch (...) { 418 if (cols) { 419 delete[] cols; 420 } 421 throw; 422 } 423 CATCH_BAD_ALLOC; 424 } 425 426 /* 427 * Class: sun_awt_windows_WCustomCursor 428 * Method: getCursorWidth 429 * Signature: ()I 430 */ 431 JNIEXPORT jint JNICALL 432 Java_sun_awt_windows_WCustomCursor_getCursorWidth(JNIEnv *, jclass) 433 { 434 TRY; 435 436 DTRACE_PRINTLN("WCustomCursor.getCursorWidth()"); 437 return (jint)::GetSystemMetrics(SM_CXCURSOR); 438 439 CATCH_BAD_ALLOC_RET(0); 440 } 441 442 /* 443 * Class: sun_awt_windows_WCustomCursor 444 * Method: getCursorHeight 445 * Signature: ()I 446 */ 447 JNIEXPORT jint JNICALL 448 Java_sun_awt_windows_WCustomCursor_getCursorHeight(JNIEnv *, jclass) 449 { 450 TRY; 451 452 DTRACE_PRINTLN("WCustomCursor.getCursorHeight()"); 453 return (jint)::GetSystemMetrics(SM_CYCURSOR); 454 455 CATCH_BAD_ALLOC_RET(0); 456 } 457 458 /************************************************************************ 459 * WGlobalCursorManager native methods 460 */ 461 462 /* 463 * Class: sun_awt_windows_WGlobalCursorManager 464 * Method: getCursorPos 465 * Signature: (Ljava/awt/Point;)V 466 */ 467 JNIEXPORT void JNICALL 468 Java_sun_awt_windows_WGlobalCursorManager_getCursorPos(JNIEnv *env, 469 jobject, 470 jobject point) 471 { 472 TRY; 473 474 POINT p; 475 ::GetCursorPos(&p); 476 HMONITOR monitor = MonitorFromPoint(p, MONITOR_DEFAULTTOPRIMARY); 477 int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(monitor); 478 Devices::InstanceAccess devices; 479 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 480 int x = (device == NULL) ? p.x : device->ScaleDownX(p.x); 481 int y = (device == NULL) ? p.y : device->ScaleDownY(p.y); 482 env->SetIntField(point, AwtCursor::pointXID, x); 483 env->SetIntField(point, AwtCursor::pointYID, y); 484 485 CATCH_BAD_ALLOC; 486 } 487 488 struct GlobalSetCursorStruct { 489 jobject cursor; 490 jboolean u; 491 }; 492 493 static void GlobalSetCursor(void* pStruct) { 494 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 495 jobject cursor = ((GlobalSetCursorStruct*)pStruct)->cursor; 496 jboolean u = ((GlobalSetCursorStruct*)pStruct)->u; 497 jlong pData = env->GetLongField(cursor, AwtCursor::pDataID); 498 AwtCursor *awtCursor = (AwtCursor *)jlong_to_ptr(pData); 499 500 if (awtCursor == NULL) { 501 awtCursor = AwtCursor::CreateSystemCursor(cursor); 502 } 503 504 HCURSOR hCursor = awtCursor->GetHCursor(); 505 506 BOOL blocked = false; 507 if (jobject jcomp = AwtComponent::FindHeavyweightUnderCursor(u)) { 508 if(jobject jpeer = AwtObject::GetPeerForTarget(env, jcomp)) 509 { 510 if(AwtComponent *awtComponent = (AwtComponent*)JNI_GET_PDATA(jpeer)) { 511 blocked = ::IsWindow(AwtWindow::GetModalBlocker( 512 AwtComponent::GetTopLevelParentForWindow( 513 awtComponent->GetHWnd()))); 514 if (!blocked) { 515 awtComponent->setCursorCache(hCursor); 516 } 517 } 518 env->DeleteLocalRef(jpeer); 519 } 520 env->DeleteGlobalRef(jcomp); 521 } 522 523 if (!blocked) { 524 ::SetCursor(hCursor); // don't need WM_AWT_SETCURSOR 525 } 526 527 env->DeleteGlobalRef(((GlobalSetCursorStruct*)pStruct)->cursor); 528 } 529 530 /* 531 * Class: sun_awt_windows_WGlobalCursorManager 532 * Method: setCursor 533 * Signature: (Ljava/awt/Component;Ljava/awt/Cursor;)V 534 */ 535 JNIEXPORT void JNICALL 536 Java_sun_awt_windows_WGlobalCursorManager_setCursor(JNIEnv *env, jobject, 537 jobject, jobject cursor, jboolean u) 538 { 539 TRY; 540 541 if (cursor != NULL) { // fix for 4430302 - getCursor() returns NULL 542 GlobalSetCursorStruct data; 543 data.cursor = env->NewGlobalRef(cursor); 544 data.u = u; 545 AwtToolkit::GetInstance().InvokeFunction( 546 GlobalSetCursor, 547 (void *)&data); 548 } else { 549 JNU_ThrowNullPointerException(env, "NullPointerException"); 550 } 551 CATCH_BAD_ALLOC; 552 } 553 554 /* 555 * Class: sun_awt_windows_WGlobalCursorManager 556 * Method: findHeavyweight 557 * Signature: (II)Z 558 */ 559 JNIEXPORT jobject JNICALL 560 Java_sun_awt_windows_WGlobalCursorManager_findHeavyweightUnderCursor( 561 JNIEnv *env, jobject, jboolean useCache) 562 { 563 TRY; 564 565 if (env->EnsureLocalCapacity(1) < 0) { 566 return NULL; 567 } 568 569 jobject globalRef = (jobject)AwtToolkit::GetInstance(). 570 InvokeFunction((void*(*)(void*)) 571 AwtComponent::FindHeavyweightUnderCursor, 572 (void *)useCache); 573 jobject localRef = env->NewLocalRef(globalRef); 574 env->DeleteGlobalRef(globalRef); 575 return localRef; 576 577 CATCH_BAD_ALLOC_RET(NULL); 578 } 579 580 /* 581 * Class: sun_awt_windows_WGlobalCursorManager 582 * Method: getLocationOnScreen 583 * Signature: (L/java/awt/Component;)L/java/awt/Point 584 */ 585 JNIEXPORT jobject JNICALL 586 Java_sun_awt_windows_WGlobalCursorManager_getLocationOnScreen( 587 JNIEnv *env, jobject, jobject component) 588 { 589 TRY; 590 591 JNI_CHECK_NULL_RETURN_NULL(component, "null component"); 592 jobject point = 593 env->CallObjectMethod(component, AwtComponent::getLocationOnScreenMID); 594 return point; 595 596 CATCH_BAD_ALLOC_RET(NULL); 597 } 598 599 } /* extern "C" */