1/*
2 * Copyright (c) 1996, 2016, 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
39extern struct ComponentIDs componentIDs;
40
41#include "awt_GraphicsEnv.h"
42extern jfieldID windowID;
43extern jfieldID targetID;
44extern jfieldID graphicsConfigID;
45extern jfieldID drawStateID;
46extern 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 */
63JNIEXPORT 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
110JNIEXPORT int32_t JNICALL
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 */
180JNIEXPORT JAWT_DrawingSurfaceInfo* JNICALL
181awt_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 */
264JNIEXPORT void JNICALL
265awt_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 */
280JNIEXPORT 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
293JNIEXPORT JAWT_DrawingSurface* JNICALL
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
321JNIEXPORT void JNICALL
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
337JNIEXPORT void JNICALL
338 awt_Lock(JNIEnv* env)
339{
340 if (awtLockInited) {
341 AWT_LOCK();
342 }
343}
344
345JNIEXPORT void JNICALL
346 awt_Unlock(JNIEnv* env)
347{
348 if (awtLockInited) {
349 AWT_FLUSH_UNLOCK();
350 }
351}
352
353JNIEXPORT jobject JNICALL
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
387// EmbeddedFrame support
388
389static char *const embeddedClassName = "sun/awt/X11/XEmbeddedFrame";
390
391JNIEXPORT jobject JNICALL awt_CreateEmbeddedFrame
392(JNIEnv* env, void* platformInfo)
393{
394 static jmethodID mid = NULL;
395 static jclass cls;
396 if (mid == NULL) {
397 cls = (*env)->FindClass(env, embeddedClassName);
398 CHECK_NULL_RETURN(cls, NULL);
399 mid = (*env)->GetMethodID(env, cls, "<init>", "(JZ)V");
400 CHECK_NULL_RETURN(mid, NULL);
401 }
402 return (*env)->NewObject(env, cls, mid, platformInfo, JNI_TRUE);
403}
404
405
406JNIEXPORT void JNICALL awt_SetBounds
407(JNIEnv *env, jobject embeddedFrame, jint x, jint y, jint w, jint h)
408{
409 static jmethodID mid = NULL;
410 if (mid == NULL) {
411 jclass cls = (*env)->FindClass(env, embeddedClassName);
412 CHECK_NULL(cls);
413 mid = (*env)->GetMethodID(env, cls, "setBoundsPrivate", "(IIII)V");
414 CHECK_NULL(mid);
415 }
416 (*env)->CallVoidMethod(env, embeddedFrame, mid, x, y, w, h);
417}
418
419JNIEXPORT void JNICALL awt_SynthesizeWindowActivation
420(JNIEnv *env, jobject embeddedFrame, jboolean doActivate)
421{
422 static jmethodID mid = NULL;
423 if (mid == NULL) {
424 jclass cls = (*env)->FindClass(env, embeddedClassName);
425 CHECK_NULL(cls);
426 mid = (*env)->GetMethodID(env, cls, "synthesizeWindowActivation", "(Z)V");
427 CHECK_NULL(mid);
428 }
429 (*env)->CallVoidMethod(env, embeddedFrame, mid, doActivate);
430}
431