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  */
awt_DrawingSurface_Lock(JAWT_DrawingSurface * ds)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
awt_GetColor(JAWT_DrawingSurface * ds,int32_t r,int32_t g,int32_t b)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
awt_DrawingSurface_GetDrawingSurfaceInfo(JAWT_DrawingSurface * ds)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
awt_DrawingSurface_FreeDrawingSurfaceInfo(JAWT_DrawingSurfaceInfo * dsi)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  */
awt_DrawingSurface_Unlock(JAWT_DrawingSurface * ds)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
awt_GetDrawingSurface(JNIEnv * env,jobject target)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
awt_FreeDrawingSurface(JAWT_DrawingSurface * ds)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
awt_Lock(JNIEnv * env)338     awt_Lock(JNIEnv* env)
339 {
340     if (awtLockInited) {
341         AWT_LOCK();
342     }
343 }
344 
345 JNIEXPORT void JNICALL
awt_Unlock(JNIEnv * env)346     awt_Unlock(JNIEnv* env)
347 {
348     if (awtLockInited) {
349         AWT_FLUSH_UNLOCK();
350     }
351 }
352 
353 JNIEXPORT jobject JNICALL
awt_GetComponent(JNIEnv * env,void * platformInfo)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