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
AwtCursor(JNIEnv * env,HCURSOR hCur,jobject jCur)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
AwtCursor(JNIEnv * env,HCURSOR hCur,jobject jCur,int xH,int yH,int nWid,int nHgt,int nS,int * col,BYTE * hM)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
~AwtCursor()84 AwtCursor::~AwtCursor()
85 {
86 }
87
Dispose()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
CreateSystemCursor(jobject jCursor)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
GetCursor(JNIEnv * env,AwtComponent * comp)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
UpdateCursor(AwtComponent * comp)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
Rebuild()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
Java_java_awt_Cursor_initIDs(JNIEnv * env,jclass cls)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
Java_java_awt_Cursor_finalizeImpl(JNIEnv * env,jclass clazz,jlong pData)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
Java_sun_awt_windows_WCustomCursor_createCursorIndirect(JNIEnv * env,jobject self,jintArray intRasterData,jbyteArray andMask,jint nSS,jint nW,jint nH,jint xHotSpot,jint yHotSpot)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
Java_sun_awt_windows_WCustomCursor_getCursorWidth(JNIEnv *,jclass)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
Java_sun_awt_windows_WCustomCursor_getCursorHeight(JNIEnv *,jclass)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
Java_sun_awt_windows_WGlobalCursorManager_getCursorPos(JNIEnv * env,jobject,jobject point)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
GlobalSetCursor(void * pStruct)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
Java_sun_awt_windows_WGlobalCursorManager_setCursor(JNIEnv * env,jobject,jobject,jobject cursor,jboolean u)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
Java_sun_awt_windows_WGlobalCursorManager_findHeavyweightUnderCursor(JNIEnv * env,jobject,jboolean useCache)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
Java_sun_awt_windows_WGlobalCursorManager_getLocationOnScreen(JNIEnv * env,jobject,jobject component)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" */
600