rev 60071 : 8211999: Window positioning bugs due to overlapping GraphicsDevice bounds (Windows/HiDPI) Reviewed-by: XXX
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 /* Copy the raster data because GDI may fail on some Java heap 377 * allocated memory. 378 */ 379 length = env->GetArrayLength(intRasterData); 380 jint *intRasterDataPtr = new jint[length]; 381 HBITMAP hColor = NULL; 382 try { 383 env->GetIntArrayRegion(intRasterData, 0, length, intRasterDataPtr); 384 hColor = create_BMP(NULL, (int *)intRasterDataPtr, nSS, nW, nH); 385 memcpy(cols, intRasterDataPtr, nW*nH*sizeof(int)); 386 } catch (...) { 387 delete[] intRasterDataPtr; 388 throw; 389 } 390 delete[] intRasterDataPtr; 391 392 HCURSOR hCursor = NULL; 393 394 if (hMask && hColor) { 395 ICONINFO icnInfo; 396 memset(&icnInfo, 0, sizeof(ICONINFO)); 397 icnInfo.hbmMask = hMask; 398 icnInfo.hbmColor = hColor; 399 icnInfo.fIcon = FALSE; 400 icnInfo.xHotspot = xHotSpot; 401 icnInfo.yHotspot = yHotSpot; 402 403 hCursor = ::CreateIconIndirect(&icnInfo); 404 405 destroy_BMP(hColor); 406 destroy_BMP(hMask); 407 } 408 409 DASSERT(hCursor); 410 411 try { 412 AwtCursor::setPData(self, ptr_to_jlong(new AwtCursor(env, hCursor, self, xHotSpot, 413 yHotSpot, nW, nH, nSS, cols, 414 (BYTE *)andMaskPtr))); 415 } catch (...) { 416 if (cols) { 417 delete[] cols; 418 } 419 throw; 420 } 421 CATCH_BAD_ALLOC; 422 } 423 424 /* 425 * Class: sun_awt_windows_WCustomCursor 426 * Method: getCursorWidth 427 * Signature: ()I 428 */ 429 JNIEXPORT jint JNICALL 430 Java_sun_awt_windows_WCustomCursor_getCursorWidth(JNIEnv *, jclass) 431 { 432 TRY; 433 434 DTRACE_PRINTLN("WCustomCursor.getCursorWidth()"); 435 return (jint)::GetSystemMetrics(SM_CXCURSOR); 436 437 CATCH_BAD_ALLOC_RET(0); 438 } 439 440 /* 441 * Class: sun_awt_windows_WCustomCursor 442 * Method: getCursorHeight 443 * Signature: ()I 444 */ 445 JNIEXPORT jint JNICALL 446 Java_sun_awt_windows_WCustomCursor_getCursorHeight(JNIEnv *, jclass) 447 { 448 TRY; 449 450 DTRACE_PRINTLN("WCustomCursor.getCursorHeight()"); 451 return (jint)::GetSystemMetrics(SM_CYCURSOR); 452 453 CATCH_BAD_ALLOC_RET(0); 454 } 455 456 /************************************************************************ 457 * WGlobalCursorManager native methods 458 */ 459 460 /* 461 * Class: sun_awt_windows_WGlobalCursorManager 462 * Method: getCursorPos 463 * Signature: (Ljava/awt/Point;)V 464 */ 465 JNIEXPORT void JNICALL 466 Java_sun_awt_windows_WGlobalCursorManager_getCursorPos(JNIEnv *env, 467 jobject, 468 jobject point) 469 { 470 TRY; 471 472 POINT p; 473 ::GetCursorPos(&p); 474 HMONITOR monitor = MonitorFromPoint(p, MONITOR_DEFAULTTOPRIMARY); 475 int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(monitor); 476 Devices::InstanceAccess devices; 477 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 478 int x = (device == NULL) ? p.x : device->ScaleDownX(p.x); 479 int y = (device == NULL) ? p.y : device->ScaleDownY(p.y); 480 env->SetIntField(point, AwtCursor::pointXID, x); 481 env->SetIntField(point, AwtCursor::pointYID, y); 482 483 CATCH_BAD_ALLOC; 484 } 485 486 struct GlobalSetCursorStruct { 487 jobject cursor; 488 jboolean u; 489 }; 490 491 static void GlobalSetCursor(void* pStruct) { 492 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 493 jobject cursor = ((GlobalSetCursorStruct*)pStruct)->cursor; 494 jboolean u = ((GlobalSetCursorStruct*)pStruct)->u; 495 jlong pData = env->GetLongField(cursor, AwtCursor::pDataID); 496 AwtCursor *awtCursor = (AwtCursor *)jlong_to_ptr(pData); 497 498 if (awtCursor == NULL) { 499 awtCursor = AwtCursor::CreateSystemCursor(cursor); 500 } 501 502 HCURSOR hCursor = awtCursor->GetHCursor(); 503 504 BOOL blocked = false; 505 if (jobject jcomp = AwtComponent::FindHeavyweightUnderCursor(u)) { 506 if(jobject jpeer = AwtObject::GetPeerForTarget(env, jcomp)) 507 { 508 if(AwtComponent *awtComponent = (AwtComponent*)JNI_GET_PDATA(jpeer)) { 509 blocked = ::IsWindow(AwtWindow::GetModalBlocker( 510 AwtComponent::GetTopLevelParentForWindow( 511 awtComponent->GetHWnd()))); 512 if (!blocked) { 513 awtComponent->setCursorCache(hCursor); 514 } 515 } 516 env->DeleteLocalRef(jpeer); 517 } 518 env->DeleteGlobalRef(jcomp); 519 } 520 521 if (!blocked) { 522 ::SetCursor(hCursor); // don't need WM_AWT_SETCURSOR 523 } 524 525 env->DeleteGlobalRef(((GlobalSetCursorStruct*)pStruct)->cursor); 526 } 527 528 /* 529 * Class: sun_awt_windows_WGlobalCursorManager 530 * Method: setCursor 531 * Signature: (Ljava/awt/Component;Ljava/awt/Cursor;)V 532 */ 533 JNIEXPORT void JNICALL 534 Java_sun_awt_windows_WGlobalCursorManager_setCursor(JNIEnv *env, jobject, 535 jobject, jobject cursor, jboolean u) 536 { 537 TRY; 538 539 if (cursor != NULL) { // fix for 4430302 - getCursor() returns NULL 540 GlobalSetCursorStruct data; 541 data.cursor = env->NewGlobalRef(cursor); 542 data.u = u; 543 AwtToolkit::GetInstance().InvokeFunction( 544 GlobalSetCursor, 545 (void *)&data); 546 } else { 547 JNU_ThrowNullPointerException(env, "NullPointerException"); 548 } 549 CATCH_BAD_ALLOC; 550 } 551 552 /* 553 * Class: sun_awt_windows_WGlobalCursorManager 554 * Method: findHeavyweight 555 * Signature: (II)Z 556 */ 557 JNIEXPORT jobject JNICALL 558 Java_sun_awt_windows_WGlobalCursorManager_findHeavyweightUnderCursor( 559 JNIEnv *env, jobject, jboolean useCache) 560 { 561 TRY; 562 563 if (env->EnsureLocalCapacity(1) < 0) { 564 return NULL; 565 } 566 567 jobject globalRef = (jobject)AwtToolkit::GetInstance(). 568 InvokeFunction((void*(*)(void*)) 569 AwtComponent::FindHeavyweightUnderCursor, 570 (void *)useCache); 571 jobject localRef = env->NewLocalRef(globalRef); 572 env->DeleteGlobalRef(globalRef); 573 return localRef; 574 575 CATCH_BAD_ALLOC_RET(NULL); 576 } 577 578 /* 579 * Class: sun_awt_windows_WGlobalCursorManager 580 * Method: getLocationOnScreen 581 * Signature: (L/java/awt/Component;)L/java/awt/Point 582 */ 583 JNIEXPORT jobject JNICALL 584 Java_sun_awt_windows_WGlobalCursorManager_getLocationOnScreen( 585 JNIEnv *env, jobject, jobject component) 586 { 587 TRY; 588 589 JNI_CHECK_NULL_RETURN_NULL(component, "null component"); 590 jobject point = 591 env->CallObjectMethod(component, AwtComponent::getLocationOnScreenMID); 592 return point; 593 594 CATCH_BAD_ALLOC_RET(NULL); 595 } 596 597 } /* extern "C" */ --- EOF ---