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