1/* 2 * Copyright (c) 1996, 2016, 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 39extern struct ComponentIDs componentIDs; 40 41#include "awt_GraphicsEnv.h" 42extern jfieldID windowID; 43extern jfieldID targetID; 44extern jfieldID graphicsConfigID; 45extern jfieldID drawStateID; 46extern 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 */ 63JNIEXPORT 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 110JNIEXPORT 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 */ 180JNIEXPORT JAWT_DrawingSurfaceInfo* JNICALL 181awt_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 */ 264JNIEXPORT void JNICALL 265awt_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 */ 280JNIEXPORT 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 293JNIEXPORT 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 321JNIEXPORT 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 337JNIEXPORT void JNICALL 338 awt_Lock(JNIEnv* env) 339{ 340 if (awtLockInited) { 341 AWT_LOCK(); 342 } 343} 344 345JNIEXPORT void JNICALL 346 awt_Unlock(JNIEnv* env) 347{ 348 if (awtLockInited) { 349 AWT_FLUSH_UNLOCK(); 350 } 351} 352 353JNIEXPORT 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} 386 387// EmbeddedFrame support 388 389static char *const embeddedClassName = "sun/awt/X11/XEmbeddedFrame"; 390 391JNIEXPORT jobject JNICALL awt_CreateEmbeddedFrame 392(JNIEnv* env, void* platformInfo) 393{ 394 static jmethodID mid = NULL; 395 static jclass cls; 396 if (mid == NULL) { 397 cls = (*env)->FindClass(env, embeddedClassName); 398 CHECK_NULL_RETURN(cls, NULL); 399 mid = (*env)->GetMethodID(env, cls, "<init>", "(JZ)V"); 400 CHECK_NULL_RETURN(mid, NULL); 401 } 402 return (*env)->NewObject(env, cls, mid, platformInfo, JNI_TRUE); 403} 404 405 406JNIEXPORT void JNICALL awt_SetBounds 407(JNIEnv *env, jobject embeddedFrame, jint x, jint y, jint w, jint h) 408{ 409 static jmethodID mid = NULL; 410 if (mid == NULL) { 411 jclass cls = (*env)->FindClass(env, embeddedClassName); 412 CHECK_NULL(cls); 413 mid = (*env)->GetMethodID(env, cls, "setBoundsPrivate", "(IIII)V"); 414 CHECK_NULL(mid); 415 } 416 (*env)->CallVoidMethod(env, embeddedFrame, mid, x, y, w, h); 417} 418 419JNIEXPORT void JNICALL awt_SynthesizeWindowActivation 420(JNIEnv *env, jobject embeddedFrame, jboolean doActivate) 421{ 422 static jmethodID mid = NULL; 423 if (mid == NULL) { 424 jclass cls = (*env)->FindClass(env, embeddedClassName); 425 CHECK_NULL(cls); 426 mid = (*env)->GetMethodID(env, cls, "synthesizeWindowActivation", "(Z)V"); 427 CHECK_NULL(mid); 428 } 429 (*env)->CallVoidMethod(env, embeddedFrame, mid, doActivate); 430} 431