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 }