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