1 /* 2 * Copyright (c) 1996, 2014, 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 #ifdef HEADLESS 27 #error This file should not be included in headless library 28 #endif 29 30 #include "awt_p.h" 31 #include "java_awt_Component.h" 32 33 #include "awt_Component.h" 34 35 #include <jni.h> 36 #include <jni_util.h> 37 #include <jawt_md.h> 38 39 extern struct ComponentIDs componentIDs; 40 41 #include "awt_GraphicsEnv.h" 42 extern jfieldID windowID; 43 extern jfieldID targetID; 44 extern jfieldID graphicsConfigID; 45 extern jfieldID drawStateID; 46 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs; 47 48 /* 49 * Lock the surface of the target component for native rendering. 50 * When finished drawing, the surface must be unlocked with 51 * Unlock(). This function returns a bitmask with one or more of the 52 * following values: 53 * 54 * JAWT_LOCK_ERROR - When an error has occurred and the surface could not 55 * be locked. 56 * 57 * JAWT_LOCK_CLIP_CHANGED - When the clip region has changed. 58 * 59 * JAWT_LOCK_BOUNDS_CHANGED - When the bounds of the surface have changed. 60 * 61 * JAWT_LOCK_SURFACE_CHANGED - When the surface itself has changed 62 */ 63 JNIEXPORT jint JNICALL awt_DrawingSurface_Lock(JAWT_DrawingSurface* ds) 64 { 65 JNIEnv* env; 66 jobject target, peer; 67 jclass componentClass; 68 jint drawState; 69 70 if (ds == NULL) { 71 #ifdef DEBUG 72 fprintf(stderr, "Drawing Surface is NULL\n"); 73 #endif 74 return (jint)JAWT_LOCK_ERROR; 75 } 76 env = ds->env; 77 target = ds->target; 78 79 /* Make sure the target is a java.awt.Component */ 80 componentClass = (*env)->FindClass(env, "java/awt/Component"); 81 CHECK_NULL_RETURN(componentClass, (jint)JAWT_LOCK_ERROR); 82 83 if (!(*env)->IsInstanceOf(env, target, componentClass)) { 84 #ifdef DEBUG 85 fprintf(stderr, "Target is not a component\n"); 86 #endif 87 return (jint)JAWT_LOCK_ERROR; 88 } 89 90 if (!awtLockInited) { 91 return (jint)JAWT_LOCK_ERROR; 92 } 93 AWT_LOCK(); 94 95 /* Get the peer of the target component */ 96 peer = (*env)->GetObjectField(env, target, componentIDs.peer); 97 if (JNU_IsNull(env, peer)) { 98 #ifdef DEBUG 99 fprintf(stderr, "Component peer is NULL\n"); 100 #endif 101 AWT_FLUSH_UNLOCK(); 102 return (jint)JAWT_LOCK_ERROR; 103 } 104 105 drawState = (*env)->GetIntField(env, peer, drawStateID); 106 (*env)->SetIntField(env, peer, drawStateID, 0); 107 return drawState; 108 } 109 110 JNIEXPORT int32_t JNICALL 111 awt_GetColor(JAWT_DrawingSurface* ds, int32_t r, int32_t g, int32_t b) 112 { 113 JNIEnv* env; 114 jobject target, peer; 115 jclass componentClass; 116 AwtGraphicsConfigDataPtr adata; 117 int32_t result; 118 jobject gc_object; 119 if (ds == NULL) { 120 #ifdef DEBUG 121 fprintf(stderr, "Drawing Surface is NULL\n"); 122 #endif 123 return (int32_t) 0; 124 } 125 126 env = ds->env; 127 target = ds->target; 128 129 /* Make sure the target is a java.awt.Component */ 130 componentClass = (*env)->FindClass(env, "java/awt/Component"); 131 CHECK_NULL_RETURN(componentClass, (int32_t) 0); 132 133 if (!(*env)->IsInstanceOf(env, target, componentClass)) { 134 #ifdef DEBUG 135 fprintf(stderr, "DrawingSurface target must be a component\n"); 136 #endif 137 return (int32_t) 0; 138 } 139 140 if (!awtLockInited) { 141 return (int32_t) 0; 142 } 143 144 AWT_LOCK(); 145 146 /* Get the peer of the target component */ 147 peer = (*env)->GetObjectField(env, target, componentIDs.peer); 148 if (JNU_IsNull(env, peer)) { 149 #ifdef DEBUG 150 fprintf(stderr, "Component peer is NULL\n"); 151 #endif 152 AWT_UNLOCK(); 153 return (int32_t) 0; 154 } 155 /* GraphicsConfiguration object of MComponentPeer */ 156 gc_object = (*env)->GetObjectField(env, peer, graphicsConfigID); 157 158 if (gc_object != NULL) { 159 adata = (AwtGraphicsConfigDataPtr) 160 JNU_GetLongFieldAsPtr(env, gc_object, 161 x11GraphicsConfigIDs.aData); 162 } else { 163 adata = getDefaultConfig(DefaultScreen(awt_display)); 164 } 165 166 result = adata->AwtColorMatch(r, g, b, adata); 167 AWT_UNLOCK(); 168 return result; 169 } 170 171 /* 172 * Get the drawing surface info. 173 * The value returned may be cached, but the values may change if 174 * additional calls to Lock() or Unlock() are made. 175 * Lock() must be called before this can return a valid value. 176 * Returns NULL if an error has occurred. 177 * When finished with the returned value, FreeDrawingSurfaceInfo must be 178 * called. 179 */ 180 JNIEXPORT JAWT_DrawingSurfaceInfo* JNICALL 181 awt_DrawingSurface_GetDrawingSurfaceInfo(JAWT_DrawingSurface* ds) 182 { 183 JNIEnv* env; 184 jobject target, peer; 185 jclass componentClass; 186 JAWT_X11DrawingSurfaceInfo* px; 187 JAWT_DrawingSurfaceInfo* p; 188 XWindowAttributes attrs; 189 190 if (ds == NULL) { 191 #ifdef DEBUG 192 fprintf(stderr, "Drawing Surface is NULL\n"); 193 #endif 194 return NULL; 195 } 196 197 env = ds->env; 198 target = ds->target; 199 200 /* Make sure the target is a java.awt.Component */ 201 componentClass = (*env)->FindClass(env, "java/awt/Component"); 202 CHECK_NULL_RETURN(componentClass, NULL); 203 204 if (!(*env)->IsInstanceOf(env, target, componentClass)) { 205 #ifdef DEBUG 206 fprintf(stderr, "DrawingSurface target must be a component\n"); 207 #endif 208 return NULL; 209 } 210 211 if (!awtLockInited) { 212 return NULL; 213 } 214 215 AWT_LOCK(); 216 217 /* Get the peer of the target component */ 218 peer = (*env)->GetObjectField(env, target, componentIDs.peer); 219 if (JNU_IsNull(env, peer)) { 220 #ifdef DEBUG 221 fprintf(stderr, "Component peer is NULL\n"); 222 #endif 223 AWT_UNLOCK(); 224 return NULL; 225 } 226 227 AWT_UNLOCK(); 228 229 /* Allocate platform-specific data */ 230 px = (JAWT_X11DrawingSurfaceInfo*) 231 malloc(sizeof(JAWT_X11DrawingSurfaceInfo)); 232 233 /* Set drawable and display */ 234 px->drawable = (*env)->GetLongField(env, peer, windowID); 235 px->display = awt_display; 236 237 /* Get window attributes to set other values */ 238 XGetWindowAttributes(awt_display, (Window)(px->drawable), &attrs); 239 240 /* Set the other values */ 241 px->visualID = XVisualIDFromVisual(attrs.visual); 242 px->colormapID = attrs.colormap; 243 px->depth = attrs.depth; 244 px->GetAWTColor = awt_GetColor; 245 246 /* Allocate and initialize platform-independent data */ 247 p = (JAWT_DrawingSurfaceInfo*)malloc(sizeof(JAWT_DrawingSurfaceInfo)); 248 p->platformInfo = px; 249 p->ds = ds; 250 p->bounds.x = (*env)->GetIntField(env, target, componentIDs.x); 251 p->bounds.y = (*env)->GetIntField(env, target, componentIDs.y); 252 p->bounds.width = (*env)->GetIntField(env, target, componentIDs.width); 253 p->bounds.height = (*env)->GetIntField(env, target, componentIDs.height); 254 p->clipSize = 1; 255 p->clip = &(p->bounds); 256 257 /* Return our new structure */ 258 return p; 259 } 260 261 /* 262 * Free the drawing surface info. 263 */ 264 JNIEXPORT void JNICALL 265 awt_DrawingSurface_FreeDrawingSurfaceInfo(JAWT_DrawingSurfaceInfo* dsi) 266 { 267 if (dsi == NULL ) { 268 #ifdef DEBUG 269 fprintf(stderr, "Drawing Surface Info is NULL\n"); 270 #endif 271 return; 272 } 273 free(dsi->platformInfo); 274 free(dsi); 275 } 276 277 /* 278 * Unlock the drawing surface of the target component for native rendering. 279 */ 280 JNIEXPORT void JNICALL awt_DrawingSurface_Unlock(JAWT_DrawingSurface* ds) 281 { 282 JNIEnv* env; 283 if (ds == NULL) { 284 #ifdef DEBUG 285 fprintf(stderr, "Drawing Surface is NULL\n"); 286 #endif 287 return; 288 } 289 env = ds->env; 290 AWT_FLUSH_UNLOCK(); 291 } 292 293 JNIEXPORT JAWT_DrawingSurface* JNICALL 294 awt_GetDrawingSurface(JNIEnv* env, jobject target) 295 { 296 jclass componentClass; 297 JAWT_DrawingSurface* p; 298 299 /* Make sure the target component is a java.awt.Component */ 300 componentClass = (*env)->FindClass(env, "java/awt/Component"); 301 CHECK_NULL_RETURN(componentClass, NULL); 302 303 if (!(*env)->IsInstanceOf(env, target, componentClass)) { 304 #ifdef DEBUG 305 fprintf(stderr, 306 "GetDrawingSurface target must be a java.awt.Component\n"); 307 #endif 308 return NULL; 309 } 310 311 p = (JAWT_DrawingSurface*)malloc(sizeof(JAWT_DrawingSurface)); 312 p->env = env; 313 p->target = (*env)->NewGlobalRef(env, target); 314 p->Lock = awt_DrawingSurface_Lock; 315 p->GetDrawingSurfaceInfo = awt_DrawingSurface_GetDrawingSurfaceInfo; 316 p->FreeDrawingSurfaceInfo = awt_DrawingSurface_FreeDrawingSurfaceInfo; 317 p->Unlock = awt_DrawingSurface_Unlock; 318 return p; 319 } 320 321 JNIEXPORT void JNICALL 322 awt_FreeDrawingSurface(JAWT_DrawingSurface* ds) 323 { 324 JNIEnv* env; 325 326 if (ds == NULL ) { 327 #ifdef DEBUG 328 fprintf(stderr, "Drawing Surface is NULL\n"); 329 #endif 330 return; 331 } 332 env = ds->env; 333 (*env)->DeleteGlobalRef(env, ds->target); 334 free(ds); 335 } 336 337 JNIEXPORT void JNICALL 338 awt_Lock(JNIEnv* env) 339 { 340 if (awtLockInited) { 341 AWT_LOCK(); 342 } 343 } 344 345 JNIEXPORT void JNICALL 346 awt_Unlock(JNIEnv* env) 347 { 348 if (awtLockInited) { 349 AWT_FLUSH_UNLOCK(); 350 } 351 } 352 353 JNIEXPORT jobject JNICALL 354 awt_GetComponent(JNIEnv* env, void* platformInfo) 355 { 356 Window window = (Window)platformInfo; 357 jobject peer = NULL; 358 jobject target = NULL; 359 360 AWT_LOCK(); 361 362 if (window != None) { 363 peer = JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XToolkit", 364 "windowToXWindow", "(J)Lsun/awt/X11/XBaseWindow;", (jlong)window).l; 365 if ((*env)->ExceptionCheck(env)) { 366 AWT_UNLOCK(); 367 return (jobject)NULL; 368 } 369 } 370 if ((peer != NULL) && 371 (JNU_IsInstanceOfByName(env, peer, "sun/awt/X11/XWindow") == 1)) { 372 target = (*env)->GetObjectField(env, peer, targetID); 373 } 374 375 if (target == NULL) { 376 (*env)->ExceptionClear(env); 377 JNU_ThrowNullPointerException(env, "NullPointerException"); 378 AWT_UNLOCK(); 379 return (jobject)NULL; 380 } 381 382 AWT_UNLOCK(); 383 384 return target; 385 }