1 /*
   2  * Copyright (c) 1996, 2010, 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     }
 306     free(dsi->platformInfo);
 307     free(dsi);
 308 }
 309 
 310 /*
 311  * Unlock the drawing surface of the target component for native rendering.
 312  */
 313 JNIEXPORT void JNICALL awt_DrawingSurface_Unlock(JAWT_DrawingSurface* ds)
 314 {
 315     JNIEnv* env;
 316     if (ds == NULL) {
 317 #ifdef DEBUG
 318         fprintf(stderr, "Drawing Surface is NULL\n");
 319 #endif
 320         return;
 321     }
 322     env = ds->env;
 323     AWT_FLUSH_UNLOCK();
 324 }
 325 
 326 JNIEXPORT JAWT_DrawingSurface* JNICALL
 327     awt_GetDrawingSurface(JNIEnv* env, jobject target)
 328 {
 329     jclass componentClass;
 330     JAWT_DrawingSurface* p;
 331 
 332     /* Make sure the target component is a java.awt.Component */
 333     componentClass = (*env)->FindClass(env, "java/awt/Component");
 334     if (!(*env)->IsInstanceOf(env, target, componentClass)) {
 335 #ifdef DEBUG
 336         fprintf(stderr,
 337             "GetDrawingSurface target must be a java.awt.Component\n");
 338 #endif
 339         return NULL;
 340     }
 341 
 342     p = (JAWT_DrawingSurface*)malloc(sizeof(JAWT_DrawingSurface));
 343     p->env = env;
 344     p->target = (*env)->NewGlobalRef(env, target);
 345     p->Lock = awt_DrawingSurface_Lock;
 346     p->GetDrawingSurfaceInfo = awt_DrawingSurface_GetDrawingSurfaceInfo;
 347     p->FreeDrawingSurfaceInfo = awt_DrawingSurface_FreeDrawingSurfaceInfo;
 348     p->Unlock = awt_DrawingSurface_Unlock;
 349     return p;
 350 }
 351 
 352 JNIEXPORT void JNICALL
 353     awt_FreeDrawingSurface(JAWT_DrawingSurface* ds)
 354 {
 355     JNIEnv* env;
 356 
 357     if (ds == NULL ) {
 358 #ifdef DEBUG
 359         fprintf(stderr, "Drawing Surface is NULL\n");
 360 #endif
 361         return;
 362     }
 363     env = ds->env;
 364     (*env)->DeleteGlobalRef(env, ds->target);
 365     free(ds);
 366 }
 367 
 368 JNIEXPORT void JNICALL
 369     awt_Lock(JNIEnv* env)
 370 {
 371     if (awtLockInited) {
 372         AWT_LOCK();
 373     }
 374 }
 375 
 376 JNIEXPORT void JNICALL
 377     awt_Unlock(JNIEnv* env)
 378 {
 379     if (awtLockInited) {
 380         AWT_FLUSH_UNLOCK();
 381     }
 382 }
 383 
 384 JNIEXPORT jobject JNICALL
 385     awt_GetComponent(JNIEnv* env, void* platformInfo)
 386 {
 387     Window window = (Window)platformInfo;
 388     Widget widget = NULL;
 389     jobject peer = NULL;
 390     jobject target = NULL;
 391 
 392     AWT_LOCK();
 393 
 394 #ifndef XAWT
 395     if (window != None) {
 396         widget = XtWindowToWidget(awt_display, window);
 397     }
 398 
 399     if (widget != NULL) {
 400         XtVaGetValues (widget, XmNuserData, &peer, NULL);
 401     }
 402 
 403     if (peer != NULL) {
 404         target = (*env)->GetObjectField(env, peer, mComponentPeerIDs.target);
 405     }
 406 #else
 407     target =  (*env)->GetObjectField(env, peer, targetID);
 408 #endif
 409 
 410     if (target == NULL) {
 411         JNU_ThrowNullPointerException(env, "NullPointerException");
 412         AWT_UNLOCK();
 413         return (jobject)NULL;
 414     }
 415 
 416 
 417     AWT_UNLOCK();
 418 
 419     return target;
 420 }