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