1 /*
2 * Copyright (c) 1997, 2018, 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 #include "jni_util.h"
27 #include "awt_p.h"
28 #include "awt.h"
29 #include "color.h"
30 #include <java_awt_DisplayMode.h>
31 #include <sun_awt_X11GraphicsEnvironment.h>
32 #include <sun_awt_X11GraphicsDevice.h>
33 #include <sun_awt_X11GraphicsConfig.h>
34 #ifndef HEADLESS
35 #include <X11/extensions/Xdbe.h>
36 #include <X11/XKBlib.h>
37 #ifndef _AIX
38 #include <X11/extensions/Xrandr.h>
39 #endif
40 #include "GLXGraphicsConfig.h"
41 #endif /* !HEADLESS */
42
43 #include <jni.h>
44 #include <jni_util.h>
45 #include <jvm.h>
46 #include <jvm_md.h>
47 #include <jlong.h>
48 #include "systemScale.h"
49 #include <stdlib.h>
50
51 #include "awt_GraphicsEnv.h"
52 #include "awt_util.h"
53 #include "gdefs.h"
54 #include <dlfcn.h>
55 #include "Trace.h"
56
57 #ifdef NETSCAPE
58 #include <signal.h>
59 extern int awt_init_xt;
60 #endif
61
62 #ifndef HEADLESS
63
64 int awt_numScreens; /* Xinerama-aware number of screens */
65
66 AwtScreenDataPtr x11Screens;
67
68 /*
69 * Set in initDisplay() to indicate whether we should attempt to initialize
70 * GLX for the default configuration.
71 */
72 static jboolean glxRequested = JNI_FALSE;
73
74 #endif /* !HEADLESS */
75
76 #ifdef HEADLESS
77 #define Display void
78 #endif /* HEADLESS */
79
80 Display *awt_display;
81
82 jclass tkClass = NULL;
83 jmethodID awtLockMID = NULL;
84 jmethodID awtUnlockMID = NULL;
85 jmethodID awtWaitMID = NULL;
86 jmethodID awtNotifyMID = NULL;
87 jmethodID awtNotifyAllMID = NULL;
88 jboolean awtLockInited = JNI_FALSE;
89
90 /** Convenience macro for loading the lock-related method IDs. */
91 #define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \
92 do { \
93 method_id = (*env)->GetStaticMethodID(env, klass, \
94 method_name, method_sig); \
95 if (method_id == NULL) return NULL; \
96 } while (0)
97
98 struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
99 struct X11GraphicsDeviceIDs x11GraphicsDeviceIDs;
100
101 #ifndef HEADLESS
102 int awtCreateX11Colormap(AwtGraphicsConfigDataPtr adata);
103 #endif /* HEADLESS */
104
105 static char *x11GraphicsConfigClassName = "sun/awt/X11GraphicsConfig";
106
107 /* AWT and Xinerama
108 *
109 * As of fix 4356756, AWT is Xinerama-aware. X11GraphicsDevices are created for
110 * each screen of a Xinerama setup, though X11 itself still only sees a single
111 * display.
112 * In many places where we talk to X11, a xinawareScreen variable is used to
113 * pass the correct Display value, depending on the circumstances (a single
114 * X display, multiple X displays, or a single X display with multiple
115 * Xinerama screens).
116 *
117 * Solaris and Linux differ in the functions used to access Xinerama-related
118 * data. This is in part because at this time, the X consortium has not
119 * finalized the "official" Xinerama API. Once this spec is available, and
120 * both OSes are conformant, one code base should be sufficient for Xinerama
121 * operation on both OSes. Until then, some of the Xinerama-related code
122 * is ifdef'd appropriately. -bchristi, 7/12/01
123 */
124
125 #define MAXFRAMEBUFFERS 16
126 #if defined(__solaris__)
127 typedef Status XineramaGetInfoFunc(Display* display, int screen_number,
128 XRectangle* framebuffer_rects, unsigned char* framebuffer_hints,
129 int* num_framebuffers);
130 typedef Status XineramaGetCenterHintFunc(Display* display, int screen_number,
131 int* x, int* y);
132
133 XineramaGetCenterHintFunc* XineramaSolarisCenterFunc = NULL;
134 #else /* Linux, Mac, AIX */
135 typedef struct {
136 int screen_number;
137 short x_org;
138 short y_org;
139 short width;
140 short height;
141 } XineramaScreenInfo;
142
143 typedef XineramaScreenInfo* XineramaQueryScreensFunc(Display*, int*);
144 #endif
145
146 Bool usingXinerama = False;
147 XRectangle fbrects[MAXFRAMEBUFFERS];
148
149 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_initIDs(JNIEnv * env,jclass cls)150 Java_sun_awt_X11GraphicsConfig_initIDs (JNIEnv *env, jclass cls)
151 {
152 x11GraphicsConfigIDs.aData = NULL;
153 x11GraphicsConfigIDs.bitsPerPixel = NULL;
154 x11GraphicsConfigIDs.screen = NULL;
155
156 x11GraphicsConfigIDs.aData = (*env)->GetFieldID (env, cls, "aData", "J");
157 CHECK_NULL(x11GraphicsConfigIDs.aData);
158 x11GraphicsConfigIDs.bitsPerPixel = (*env)->GetFieldID (env, cls, "bitsPerPixel", "I");
159 CHECK_NULL(x11GraphicsConfigIDs.bitsPerPixel);
160 x11GraphicsConfigIDs.screen = (*env)->GetFieldID (env, cls, "screen", "Lsun/awt/X11GraphicsDevice;");
161 CHECK_NULL(x11GraphicsConfigIDs.screen);
162
163 if (x11GraphicsConfigIDs.aData == NULL ||
164 x11GraphicsConfigIDs.bitsPerPixel == NULL ||
165 x11GraphicsConfigIDs.screen == NULL) {
166
167 JNU_ThrowNoSuchFieldError(env, "Can't find a field");
168 return;
169 }
170 }
171
172 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_initIDs(JNIEnv * env,jclass cls)173 Java_sun_awt_X11GraphicsDevice_initIDs (JNIEnv *env, jclass cls)
174 {
175 x11GraphicsDeviceIDs.screen = NULL;
176 x11GraphicsDeviceIDs.screen = (*env)->GetFieldID (env, cls, "screen", "I");
177 DASSERT(x11GraphicsDeviceIDs.screen);
178 }
179
180 #ifndef HEADLESS
181
182 /*
183 * XIOErrorHandler
184 */
xioerror_handler(Display * disp)185 static int xioerror_handler(Display *disp)
186 {
187 if (awtLockInited) {
188 if (errno == EPIPE) {
189 jio_fprintf(stderr, "X connection to %s host broken (explicit kill or server shutdown)\n", XDisplayName(NULL));
190 }
191 /*SignalError(lockedee->lastpc, lockedee, "fp/ade/gui/GUIException", "I/O error"); */
192 }
193 return 0;
194 }
195
196 static AwtGraphicsConfigDataPtr
findWithTemplate(XVisualInfo * vinfo,long mask)197 findWithTemplate(XVisualInfo *vinfo,
198 long mask)
199 {
200
201 XVisualInfo *visualList;
202 XColor color;
203 AwtGraphicsConfigDataPtr defaultConfig;
204 int visualsMatched, i;
205
206 visualList = XGetVisualInfo(awt_display,
207 mask, vinfo, &visualsMatched);
208 if (visualList) {
209 int id = -1;
210 VisualID defaultVisual = XVisualIDFromVisual(DefaultVisual(awt_display, vinfo->screen));
211 defaultConfig = ZALLOC(_AwtGraphicsConfigData);
212 if (defaultConfig == NULL) {
213 XFree(visualList);
214 return NULL;
215 }
216 for (i = 0; i < visualsMatched; i++) {
217 memcpy(&defaultConfig->awt_visInfo, &visualList[i], sizeof(XVisualInfo));
218 defaultConfig->awt_depth = visualList[i].depth;
219
220 /* we can't use awtJNI_CreateColorData here, because it'll pull,
221 SystemColor, which in turn will cause toolkit to be reinitialized */
222 if (awtCreateX11Colormap(defaultConfig)) {
223 if (visualList[i].visualid == defaultVisual) {
224 id = i;
225 break;
226 } else if (-1 == id) {
227 // Keep 1st match for fallback
228 id = i;
229 }
230 }
231 }
232 if (-1 != id) {
233 memcpy(&defaultConfig->awt_visInfo, &visualList[id], sizeof(XVisualInfo));
234 defaultConfig->awt_depth = visualList[id].depth;
235 /* Allocate white and black pixels for this visual */
236 color.flags = DoRed | DoGreen | DoBlue;
237 color.red = color.green = color.blue = 0x0000;
238 XAllocColor(awt_display, defaultConfig->awt_cmap, &color);
239 x11Screens[visualList[id].screen].blackpixel = color.pixel;
240 color.flags = DoRed | DoGreen | DoBlue;
241 color.red = color.green = color.blue = 0xffff;
242 XAllocColor(awt_display, defaultConfig->awt_cmap, &color);
243 x11Screens[visualList[id].screen].whitepixel = color.pixel;
244
245 XFree(visualList);
246 return defaultConfig;
247 }
248 XFree(visualList);
249 free((void *)defaultConfig);
250 }
251 return NULL;
252 }
253
254 /* default config is based on X11 screen. All Xinerama screens of that X11
255 screen will have the same default config */
256 /* Need more notes about which fields of the structure are based on the X
257 screen, and which are based on the Xinerama screen */
258 static AwtGraphicsConfigDataPtr
makeDefaultConfig(JNIEnv * env,int screen)259 makeDefaultConfig(JNIEnv *env, int screen) {
260
261 AwtGraphicsConfigDataPtr defaultConfig;
262 int xinawareScreen = 0;
263 VisualID forcedVisualID = 0, defaultVisualID;
264 char *forcedVisualStr;
265 XVisualInfo vinfo;
266 long mask;
267
268 xinawareScreen = usingXinerama ? 0 : screen;
269 defaultVisualID =
270 XVisualIDFromVisual(DefaultVisual(awt_display, xinawareScreen));
271
272 memset(&vinfo, 0, sizeof(XVisualInfo));
273 vinfo.screen = xinawareScreen;
274
275 if ((forcedVisualStr = getenv("FORCEDEFVIS"))) {
276 mask = VisualIDMask | VisualScreenMask;
277 if (sscanf(forcedVisualStr, "%lx", &forcedVisualID) > 0 &&
278 forcedVisualID > 0)
279 {
280 vinfo.visualid = forcedVisualID;
281 } else {
282 vinfo.visualid = defaultVisualID;
283 }
284 } else {
285 VisualID bestGLXVisualID;
286 if (glxRequested &&
287 (bestGLXVisualID = GLXGC_FindBestVisual(env, xinawareScreen)) > 0)
288 {
289 /* we've found the best visual for use with GLX, so use it */
290 vinfo.visualid = bestGLXVisualID;
291 mask = VisualIDMask | VisualScreenMask;
292 } else {
293 /* otherwise, continue looking for the best X11 visual */
294 vinfo.depth = 24;
295 vinfo.class = TrueColor;
296 mask = VisualDepthMask | VisualScreenMask | VisualClassMask;
297 }
298 }
299
300 /* try the best, or forced visual */
301 defaultConfig = findWithTemplate(&vinfo, mask);
302 if (defaultConfig) {
303 return defaultConfig;
304 }
305
306 /* try the default visual */
307 vinfo.visualid = defaultVisualID;
308 mask = VisualIDMask | VisualScreenMask;
309 defaultConfig = findWithTemplate(&vinfo, mask);
310 if (defaultConfig) {
311 return defaultConfig;
312 }
313
314 /* try any TrueColor */
315 vinfo.class = TrueColor;
316 mask = VisualScreenMask | VisualClassMask;
317 defaultConfig = findWithTemplate(&vinfo, mask);
318 if (defaultConfig) {
319 return defaultConfig;
320 }
321
322 /* try 8-bit PseudoColor */
323 vinfo.depth = 8;
324 vinfo.class = PseudoColor;
325 mask = VisualDepthMask | VisualScreenMask | VisualClassMask;
326 defaultConfig = findWithTemplate(&vinfo, mask);
327 if (defaultConfig) {
328 return defaultConfig;
329 }
330
331 /* try any 8-bit */
332 vinfo.depth = 8;
333 mask = VisualDepthMask | VisualScreenMask;
334 defaultConfig = findWithTemplate(&vinfo, mask);
335 if (defaultConfig) {
336 return defaultConfig;
337 }
338
339 /* we tried everything, give up */
340 JNU_ThrowInternalError(env, "Can't find supported visual");
341 XCloseDisplay(awt_display);
342 awt_display = NULL;
343 return NULL;
344 }
345
346 static void
getAllConfigs(JNIEnv * env,int screen,AwtScreenDataPtr screenDataPtr)347 getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) {
348
349 int i;
350 int n8p=0, n12p=0, n8s=0, n8gs=0, n8sg=0, n1sg=0, nTrue=0;
351 int nConfig;
352 XVisualInfo *pVI8p, *pVI12p, *pVI8s, *pVITrue, *pVI8gs,
353 *pVI8sg, *pVI1sg = NULL, viTmp;
354 AwtGraphicsConfigDataPtr *graphicsConfigs;
355 AwtGraphicsConfigDataPtr defaultConfig;
356 int ind;
357 char errmsg[128];
358 int xinawareScreen;
359 void* xrenderLibHandle = NULL;
360 XRenderFindVisualFormatFunc* xrenderFindVisualFormat = NULL;
361 int major_opcode, first_event, first_error;
362
363 if (usingXinerama) {
364 xinawareScreen = 0;
365 }
366 else {
367 xinawareScreen = screen;
368 }
369
370 AWT_LOCK ();
371
372 viTmp.screen = xinawareScreen;
373
374 viTmp.depth = 8;
375 viTmp.class = PseudoColor;
376 viTmp.colormap_size = 256;
377 pVI8p = XGetVisualInfo (awt_display,
378 VisualDepthMask | VisualClassMask |
379 VisualColormapSizeMask | VisualScreenMask,
380 &viTmp, &n8p);
381
382 viTmp.depth = 12;
383 viTmp.class = PseudoColor;
384 viTmp.colormap_size = 4096;
385 pVI12p = XGetVisualInfo (awt_display,
386 VisualDepthMask | VisualClassMask |
387 VisualColormapSizeMask | VisualScreenMask,
388 &viTmp, &n12p);
389
390 viTmp.class = TrueColor;
391 pVITrue = XGetVisualInfo (awt_display,
392 VisualClassMask |
393 VisualScreenMask,
394 &viTmp, &nTrue);
395
396 viTmp.depth = 8;
397 viTmp.class = StaticColor;
398 pVI8s = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask |
399 VisualScreenMask, &viTmp, &n8s);
400
401 viTmp.depth = 8;
402 viTmp.class = GrayScale;
403 viTmp.colormap_size = 256;
404 pVI8gs = XGetVisualInfo (awt_display,
405 VisualDepthMask | VisualClassMask |
406 VisualColormapSizeMask | VisualScreenMask,
407 &viTmp, &n8gs);
408 viTmp.depth = 8;
409 viTmp.class = StaticGray;
410 viTmp.colormap_size = 256;
411 pVI8sg = XGetVisualInfo (awt_display,
412 VisualDepthMask | VisualClassMask |
413 VisualColormapSizeMask | VisualScreenMask,
414 &viTmp, &n8sg);
415
416 /* REMIND.. remove when we have support for the color classes below */
417 /* viTmp.depth = 1; */
418 /* viTmp.class = StaticGray; */
419 /* pVI1sg = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask, */
420 /* viTmp, &n1sg); */
421
422 nConfig = n8p + n12p + n8s + n8gs + n8sg + n1sg + nTrue + 1;
423 graphicsConfigs = (AwtGraphicsConfigDataPtr *)
424 calloc(nConfig, sizeof(AwtGraphicsConfigDataPtr));
425 if (graphicsConfigs == NULL) {
426 JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),
427 NULL);
428 AWT_UNLOCK();
429 return;
430 }
431
432 if (screenDataPtr->defaultConfig == NULL) {
433 /*
434 * After a display change event, the default config field will have
435 * been reset, so we need to recreate the default config here.
436 */
437 screenDataPtr->defaultConfig = makeDefaultConfig(env, screen);
438 }
439
440 defaultConfig = screenDataPtr->defaultConfig;
441 graphicsConfigs[0] = defaultConfig;
442 nConfig = 1; /* reserve index 0 for default config */
443
444 // Only use the RENDER extension if it is available on the X server
445 if (XQueryExtension(awt_display, "RENDER",
446 &major_opcode, &first_event, &first_error))
447 {
448 DTRACE_PRINTLN("RENDER extension available");
449 xrenderLibHandle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL);
450
451 #ifdef MACOSX
452 #define XRENDER_LIB "/usr/X11/lib/libXrender.dylib"
453 #else
454 #define XRENDER_LIB "libXrender.so"
455 #endif
456
457 if (xrenderLibHandle == NULL) {
458 xrenderLibHandle = dlopen(XRENDER_LIB,
459 RTLD_LAZY | RTLD_GLOBAL);
460 }
461
462 #if defined(__solaris__)
463 if (xrenderLibHandle == NULL) {
464 xrenderLibHandle = dlopen("/usr/lib/libXrender.so.1",
465 RTLD_LAZY | RTLD_GLOBAL);
466 }
467 #elif defined(_AIX)
468 if (xrenderLibHandle == NULL) {
469 xrenderLibHandle = dlopen("libXrender.a(libXrender.so.0)",
470 RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
471 }
472 #endif
473 if (xrenderLibHandle != NULL) {
474 DTRACE_PRINTLN("Loaded libXrender");
475 xrenderFindVisualFormat =
476 (XRenderFindVisualFormatFunc*)dlsym(xrenderLibHandle,
477 "XRenderFindVisualFormat");
478 if (xrenderFindVisualFormat == NULL) {
479 DTRACE_PRINTLN1("Can't find 'XRenderFindVisualFormat' in libXrender (%s)", dlerror());
480 }
481 } else {
482 DTRACE_PRINTLN1("Can't load libXrender (%s)", dlerror());
483 }
484 } else {
485 DTRACE_PRINTLN("RENDER extension NOT available");
486 }
487
488 for (i = 0; i < nTrue; i++) {
489 if (XVisualIDFromVisual(pVITrue[i].visual) ==
490 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual) ||
491 pVITrue[i].depth == 12) {
492 /* Skip the non-supported 12-bit TrueColor visual */
493 continue;
494 } else {
495 ind = nConfig++;
496 }
497 graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
498 if (graphicsConfigs[ind] == NULL) {
499 JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
500 goto cleanup;
501 }
502 graphicsConfigs[ind]->awt_depth = pVITrue [i].depth;
503 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVITrue [i],
504 sizeof (XVisualInfo));
505 if (xrenderFindVisualFormat != NULL) {
506 XRenderPictFormat *format = xrenderFindVisualFormat (awt_display,
507 pVITrue [i].visual);
508 if (format &&
509 format->type == PictTypeDirect &&
510 format->direct.alphaMask)
511 {
512 DTRACE_PRINTLN1("GraphicsConfig[%d] supports Translucency", ind);
513 graphicsConfigs [ind]->isTranslucencySupported = 1;
514 memcpy(&graphicsConfigs [ind]->renderPictFormat, format,
515 sizeof(*format));
516 } else {
517 DTRACE_PRINTLN1(format ?
518 "GraphicsConfig[%d] has no Translucency support" :
519 "Error calling 'XRenderFindVisualFormat'", ind);
520 }
521 }
522 }
523
524 if (xrenderLibHandle != NULL) {
525 dlclose(xrenderLibHandle);
526 xrenderLibHandle = NULL;
527 }
528
529 for (i = 0; i < n8p; i++) {
530 if (XVisualIDFromVisual(pVI8p[i].visual) ==
531 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
532 continue;
533 } else {
534 ind = nConfig++;
535 }
536 graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
537 if (graphicsConfigs[ind] == NULL) {
538 JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
539 goto cleanup;
540 }
541 graphicsConfigs[ind]->awt_depth = pVI8p [i].depth;
542 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8p [i],
543 sizeof (XVisualInfo));
544 }
545
546 for (i = 0; i < n12p; i++) {
547 if (XVisualIDFromVisual(pVI12p[i].visual) ==
548 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
549 continue;
550 } else {
551 ind = nConfig++;
552 }
553 graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
554 if (graphicsConfigs[ind] == NULL) {
555 JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
556 goto cleanup;
557 }
558 graphicsConfigs[ind]->awt_depth = pVI12p [i].depth;
559 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI12p [i],
560 sizeof (XVisualInfo));
561 }
562
563 for (i = 0; i < n8s; i++) {
564 if (XVisualIDFromVisual(pVI8s[i].visual) ==
565 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
566 continue;
567 } else {
568 ind = nConfig++;
569 }
570 graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
571 if (graphicsConfigs[ind] == NULL) {
572 JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
573 goto cleanup;
574 }
575 graphicsConfigs[ind]->awt_depth = pVI8s [i].depth;
576 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8s [i],
577 sizeof (XVisualInfo));
578 }
579
580 for (i = 0; i < n8gs; i++) {
581 if (XVisualIDFromVisual(pVI8gs[i].visual) ==
582 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
583 continue;
584 } else {
585 ind = nConfig++;
586 }
587 graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
588 if (graphicsConfigs[ind] == NULL) {
589 JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
590 goto cleanup;
591 }
592 graphicsConfigs[ind]->awt_depth = pVI8gs [i].depth;
593 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8gs [i],
594 sizeof (XVisualInfo));
595 }
596
597 for (i = 0; i < n8sg; i++) {
598 if (XVisualIDFromVisual(pVI8sg[i].visual) ==
599 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
600 continue;
601 } else {
602 ind = nConfig++;
603 }
604 graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
605 if (graphicsConfigs[ind] == NULL) {
606 JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
607 goto cleanup;
608 }
609 graphicsConfigs[ind]->awt_depth = pVI8sg [i].depth;
610 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8sg [i],
611 sizeof (XVisualInfo));
612 }
613
614 for (i = 0; i < n1sg; i++) {
615 if (XVisualIDFromVisual(pVI1sg[i].visual) ==
616 XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {
617 continue;
618 } else {
619 ind = nConfig++;
620 }
621 graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);
622 if (graphicsConfigs[ind] == NULL) {
623 JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");
624 goto cleanup;
625 }
626 graphicsConfigs[ind]->awt_depth = pVI1sg [i].depth;
627 memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI1sg [i],
628 sizeof (XVisualInfo));
629 }
630
631 screenDataPtr->numConfigs = nConfig;
632 screenDataPtr->configs = graphicsConfigs;
633
634 cleanup:
635 if (n8p != 0)
636 XFree (pVI8p);
637 if (n12p != 0)
638 XFree (pVI12p);
639 if (n8s != 0)
640 XFree (pVI8s);
641 if (n8gs != 0)
642 XFree (pVI8gs);
643 if (n8sg != 0)
644 XFree (pVI8sg);
645 if (n1sg != 0)
646 XFree (pVI1sg);
647
648 AWT_UNLOCK ();
649 }
650
651 #ifndef HEADLESS
652 #if defined(__linux__) || defined(MACOSX) || defined(_AIX) || defined(_ALLBSD_SOURCE)
xinerama_init_linux()653 static void xinerama_init_linux()
654 {
655 void* libHandle = NULL;
656 int32_t locNumScr = 0;
657 XineramaScreenInfo *xinInfo;
658 char* XineramaQueryScreensName = "XineramaQueryScreens";
659 XineramaQueryScreensFunc* XineramaQueryScreens = NULL;
660
661 /* load library */
662 libHandle = dlopen(VERSIONED_JNI_LIB_NAME("Xinerama", "1"),
663 RTLD_LAZY | RTLD_GLOBAL);
664 if (libHandle == NULL) {
665 #if defined(_AIX)
666 libHandle = dlopen("libXext.a(shr_64.o)", RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);
667 #else
668 libHandle = dlopen(JNI_LIB_NAME("Xinerama"), RTLD_LAZY | RTLD_GLOBAL);
669 #endif
670 }
671 if (libHandle != NULL) {
672 XineramaQueryScreens = (XineramaQueryScreensFunc*)
673 dlsym(libHandle, XineramaQueryScreensName);
674
675 if (XineramaQueryScreens != NULL) {
676 DTRACE_PRINTLN("calling XineramaQueryScreens func");
677 xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);
678 if (xinInfo != NULL && locNumScr > XScreenCount(awt_display)) {
679 int32_t idx;
680 DTRACE_PRINTLN("Enabling Xinerama support");
681 usingXinerama = True;
682 /* set global number of screens */
683 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
684 awt_numScreens = locNumScr;
685
686 /* stuff values into fbrects */
687 for (idx = 0; idx < awt_numScreens; idx++) {
688 DASSERT(xinInfo[idx].screen_number == idx);
689
690 fbrects[idx].width = xinInfo[idx].width;
691 fbrects[idx].height = xinInfo[idx].height;
692 fbrects[idx].x = xinInfo[idx].x_org;
693 fbrects[idx].y = xinInfo[idx].y_org;
694 }
695 } else {
696 DTRACE_PRINTLN((xinInfo == NULL) ?
697 "calling XineramaQueryScreens didn't work" :
698 "XineramaQueryScreens <= XScreenCount"
699 );
700 }
701 } else {
702 DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol");
703 }
704 dlclose(libHandle);
705 } else {
706 DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
707 }
708 }
709 #elif defined(__solaris__)
xinerama_init_solaris()710 static void xinerama_init_solaris()
711 {
712 void* libHandle = NULL;
713 unsigned char fbhints[MAXFRAMEBUFFERS];
714 int32_t locNumScr = 0;
715 /* load and run XineramaGetInfo */
716 char* XineramaGetInfoName = "XineramaGetInfo";
717 char* XineramaGetCenterHintName = "XineramaGetCenterHint";
718 XineramaGetInfoFunc* XineramaSolarisFunc = NULL;
719
720 /* load library */
721 libHandle = dlopen(JNI_LIB_NAME("Xext"), RTLD_LAZY | RTLD_GLOBAL);
722 if (libHandle != NULL) {
723 XineramaSolarisFunc = (XineramaGetInfoFunc*)dlsym(libHandle, XineramaGetInfoName);
724 XineramaSolarisCenterFunc =
725 (XineramaGetCenterHintFunc*)dlsym(libHandle, XineramaGetCenterHintName);
726
727 if (XineramaSolarisFunc != NULL) {
728 DTRACE_PRINTLN("calling XineramaGetInfo func on Solaris");
729 if ((*XineramaSolarisFunc)(awt_display, 0, &fbrects[0],
730 &fbhints[0], &locNumScr) != 0 &&
731 locNumScr > XScreenCount(awt_display))
732 {
733 DTRACE_PRINTLN("Enabling Xinerama support");
734 usingXinerama = True;
735 /* set global number of screens */
736 DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);
737 awt_numScreens = locNumScr;
738 } else {
739 DTRACE_PRINTLN("calling XineramaGetInfo didn't work");
740 }
741 } else {
742 DTRACE_PRINTLN("couldn't load XineramaGetInfo symbol");
743 }
744 dlclose(libHandle);
745 } else {
746 DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());
747 }
748 }
749 #endif
750
751 /*
752 * Checks if Xinerama is running and perform Xinerama-related
753 * platform dependent initialization.
754 */
xineramaInit(void)755 static void xineramaInit(void) {
756 char* XinExtName = "XINERAMA";
757 int32_t major_opcode, first_event, first_error;
758 Bool gotXinExt = False;
759
760 gotXinExt = XQueryExtension(awt_display, XinExtName, &major_opcode,
761 &first_event, &first_error);
762
763 if (!gotXinExt) {
764 DTRACE_PRINTLN("Xinerama extension is not available");
765 return;
766 }
767
768 DTRACE_PRINTLN("Xinerama extension is available");
769 #if defined(__solaris__)
770 xinerama_init_solaris();
771 #else /* Linux, Mac, AIX */
772 xinerama_init_linux();
773 #endif
774 }
775 #endif /* HEADLESS */
776
777 Display *
awt_init_Display(JNIEnv * env,jobject this)778 awt_init_Display(JNIEnv *env, jobject this)
779 {
780 jclass klass;
781 Display *dpy;
782 char errmsg[128];
783 int i;
784 #ifdef NETSCAPE
785 sigset_t alarm_set, oldset;
786 #endif
787
788 if (awt_display) {
789 return awt_display;
790 }
791
792 #ifdef NETSCAPE
793 /* Disable interrupts during XtOpenDisplay to avoid bugs in unix os select
794 code: some unix systems don't implement SA_RESTART properly and
795 because of this, select returns with EINTR. Most implementations of
796 gethostbyname don't cope with EINTR properly and as a result we get
797 stuck (forever) in the gethostbyname code
798 */
799 sigemptyset(&alarm_set);
800 sigaddset(&alarm_set, SIGALRM);
801 sigprocmask(SIG_BLOCK, &alarm_set, &oldset);
802 #endif
803
804 /* Load AWT lock-related methods in SunToolkit */
805 klass = (*env)->FindClass(env, "sun/awt/SunToolkit");
806 if (klass == NULL) return NULL;
807 GET_STATIC_METHOD(klass, awtLockMID, "awtLock", "()V");
808 GET_STATIC_METHOD(klass, awtUnlockMID, "awtUnlock", "()V");
809 GET_STATIC_METHOD(klass, awtWaitMID, "awtLockWait", "(J)V");
810 GET_STATIC_METHOD(klass, awtNotifyMID, "awtLockNotify", "()V");
811 GET_STATIC_METHOD(klass, awtNotifyAllMID, "awtLockNotifyAll", "()V");
812 tkClass = (*env)->NewGlobalRef(env, klass);
813 awtLockInited = JNI_TRUE;
814
815 if (getenv("_AWT_IGNORE_XKB") != NULL &&
816 strlen(getenv("_AWT_IGNORE_XKB")) > 0) {
817 if (XkbIgnoreExtension(True)) {
818 printf("Ignoring XKB.\n");
819 }
820 }
821
822 dpy = awt_display = XOpenDisplay(NULL);
823 #ifdef NETSCAPE
824 sigprocmask(SIG_SETMASK, &oldset, NULL);
825 #endif
826 if (!dpy) {
827 jio_snprintf(errmsg,
828 sizeof(errmsg),
829 "Can't connect to X11 window server using '%s' as the value of the DISPLAY variable.",
830 (getenv("DISPLAY") == NULL) ? ":0.0" : getenv("DISPLAY"));
831 JNU_ThrowByName(env, "java/awt/AWTError", errmsg);
832 return NULL;
833 }
834
835 XSetIOErrorHandler(xioerror_handler);
836 JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "init", "(J)V",
837 ptr_to_jlong(awt_display));
838 JNU_CHECK_EXCEPTION_RETURN(env, NULL);
839
840 /* set awt_numScreens, and whether or not we're using Xinerama */
841 xineramaInit();
842
843 if (!usingXinerama) {
844 awt_numScreens = XScreenCount(awt_display);
845 }
846
847 DTRACE_PRINTLN1("allocating %i screens\n", awt_numScreens);
848 /* Allocate screen data structure array */
849 x11Screens = calloc(awt_numScreens, sizeof(AwtScreenData));
850 if (x11Screens == NULL) {
851 JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),
852 NULL);
853 return NULL;
854 }
855
856 for (i = 0; i < awt_numScreens; i++) {
857 if (usingXinerama) {
858 /* All Xinerama screens use the same X11 root for now */
859 x11Screens[i].root = RootWindow(awt_display, 0);
860 }
861 else {
862 x11Screens[i].root = RootWindow(awt_display, i);
863 }
864 x11Screens[i].defaultConfig = makeDefaultConfig(env, i);
865 JNU_CHECK_EXCEPTION_RETURN(env, NULL);
866 }
867
868 return dpy;
869 }
870 #endif /* !HEADLESS */
871
872 /*
873 * Class: sun_awt_X11GraphicsEnvironment
874 * Method: getDefaultScreenNum
875 * Signature: ()I
876 */
877 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum(JNIEnv * env,jobject this)878 Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum(
879 JNIEnv *env, jobject this)
880 {
881 #ifdef HEADLESS
882 return (jint)0;
883 #else
884 return DefaultScreen(awt_display);
885 #endif /* !HEADLESS */
886 }
887
888 #ifndef HEADLESS
ensureConfigsInited(JNIEnv * env,int screen)889 static void ensureConfigsInited(JNIEnv* env, int screen) {
890 if (x11Screens[screen].numConfigs == 0) {
891 if (env == NULL) {
892 env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
893 }
894 getAllConfigs (env, screen, &(x11Screens[screen]));
895 }
896 }
897 #endif
898
899 #ifdef HEADLESS
getDefaultConfig(int screen)900 void* getDefaultConfig(int screen) {
901 return NULL;
902 }
903 #else
904 AwtGraphicsConfigDataPtr
getDefaultConfig(int screen)905 getDefaultConfig(int screen) {
906 ensureConfigsInited(NULL, screen);
907 return x11Screens[screen].defaultConfig;
908 }
909
910 AwtScreenDataPtr
getScreenData(int screen)911 getScreenData(int screen) {
912 return &(x11Screens[screen]);
913 }
914 #endif /* !HEADLESS */
915
916 /*
917 * Class: sun_awt_X11GraphicsEnvironment
918 * Method: initDisplay
919 * Signature: (Z)V
920 */
921 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv * env,jobject this,jboolean glxReq)922 Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv *env, jobject this,
923 jboolean glxReq)
924 {
925 #ifndef HEADLESS
926 glxRequested = glxReq;
927 (void) awt_init_Display(env, this);
928 #endif /* !HEADLESS */
929 }
930
931 /*
932 * Class: sun_awt_X11GraphicsEnvironment
933 * Method: initGLX
934 * Signature: ()Z
935 */
936 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv * env,jclass x11ge)937 Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv *env, jclass x11ge)
938 {
939 #ifndef HEADLESS
940 jboolean glxAvailable;
941
942 AWT_LOCK();
943 glxAvailable = GLXGC_IsGLXAvailable();
944 AWT_UNLOCK();
945
946 return glxAvailable;
947 #else
948 return JNI_FALSE;
949 #endif /* !HEADLESS */
950 }
951
952 /*
953 * Class: sun_awt_X11GraphicsEnvironment
954 * Method: getNumScreens
955 * Signature: ()I
956 */
957 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv * env,jobject this)958 Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv *env, jobject this)
959 {
960 #ifdef HEADLESS
961 return (jint)0;
962 #else
963 return awt_numScreens;
964 #endif /* !HEADLESS */
965 }
966
967 /*
968 * Class: sun_awt_X11GraphicsDevice
969 * Method: getDisplay
970 * Signature: ()J
971 */
972 JNIEXPORT jlong JNICALL
Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv * env,jobject this)973 Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv *env, jobject this)
974 {
975 #ifdef HEADLESS
976 return NULL;
977 #else
978 return ptr_to_jlong(awt_display);
979 #endif /* !HEADLESS */
980 }
981
982 #ifdef MITSHM
983
984 static jint canUseShmExt = UNSET_MITSHM;
985 static jint canUseShmExtPixmaps = UNSET_MITSHM;
986 static jboolean xshmAttachFailed = JNI_FALSE;
987
XShmAttachXErrHandler(Display * display,XErrorEvent * xerr)988 int XShmAttachXErrHandler(Display *display, XErrorEvent *xerr) {
989 if (xerr->minor_code == X_ShmAttach) {
990 xshmAttachFailed = JNI_TRUE;
991 }
992 return 0;
993 }
isXShmAttachFailed()994 jboolean isXShmAttachFailed() {
995 return xshmAttachFailed;
996 }
resetXShmAttachFailed()997 void resetXShmAttachFailed() {
998 xshmAttachFailed = JNI_FALSE;
999 }
1000
1001 extern int mitShmPermissionMask;
1002
TryInitMITShm(JNIEnv * env,jint * shmExt,jint * shmPixmaps)1003 void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {
1004 XShmSegmentInfo shminfo;
1005 int XShmMajor, XShmMinor;
1006 int a, b, c;
1007
1008 AWT_LOCK();
1009 if (canUseShmExt != UNSET_MITSHM) {
1010 *shmExt = canUseShmExt;
1011 *shmPixmaps = canUseShmExtPixmaps;
1012 AWT_UNLOCK();
1013 return;
1014 }
1015
1016 *shmExt = canUseShmExt = CANT_USE_MITSHM;
1017 *shmPixmaps = canUseShmExtPixmaps = CANT_USE_MITSHM;
1018
1019 if (awt_display == (Display *)NULL) {
1020 AWT_NOFLUSH_UNLOCK();
1021 return;
1022 }
1023
1024 /**
1025 * XShmQueryExtension returns False in remote server case.
1026 * Unfortunately it also returns True in ssh case, so
1027 * we need to test that we can actually do XShmAttach.
1028 */
1029 if (XShmQueryExtension(awt_display)) {
1030 shminfo.shmid = shmget(IPC_PRIVATE, 0x10000,
1031 IPC_CREAT|mitShmPermissionMask);
1032 if (shminfo.shmid < 0) {
1033 AWT_UNLOCK();
1034 J2dRlsTraceLn1(J2D_TRACE_ERROR,
1035 "TryInitMITShm: shmget has failed: %s",
1036 strerror(errno));
1037 return;
1038 }
1039 shminfo.shmaddr = (char *) shmat(shminfo.shmid, 0, 0);
1040 if (shminfo.shmaddr == ((char *) -1)) {
1041 shmctl(shminfo.shmid, IPC_RMID, 0);
1042 AWT_UNLOCK();
1043 J2dRlsTraceLn1(J2D_TRACE_ERROR,
1044 "TryInitMITShm: shmat has failed: %s",
1045 strerror(errno));
1046 return;
1047 }
1048 shminfo.readOnly = True;
1049
1050 resetXShmAttachFailed();
1051 /**
1052 * The J2DXErrHandler handler will set xshmAttachFailed
1053 * to JNI_TRUE if any Shm error has occured.
1054 */
1055 EXEC_WITH_XERROR_HANDLER(XShmAttachXErrHandler,
1056 XShmAttach(awt_display, &shminfo));
1057
1058 /**
1059 * Get rid of the id now to reduce chances of leaking
1060 * system resources.
1061 */
1062 shmctl(shminfo.shmid, IPC_RMID, 0);
1063
1064 if (isXShmAttachFailed() == JNI_FALSE) {
1065 canUseShmExt = CAN_USE_MITSHM;
1066 /* check if we can use shared pixmaps */
1067 XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor,
1068 (Bool*)&canUseShmExtPixmaps);
1069 canUseShmExtPixmaps = canUseShmExtPixmaps &&
1070 (XShmPixmapFormat(awt_display) == ZPixmap);
1071 XShmDetach(awt_display, &shminfo);
1072 }
1073 shmdt(shminfo.shmaddr);
1074 *shmExt = canUseShmExt;
1075 *shmPixmaps = canUseShmExtPixmaps;
1076 }
1077 AWT_UNLOCK();
1078 }
1079 #endif /* MITSHM */
1080
1081 /*
1082 * Class: sun_awt_X11GraphicsEnvironment
1083 * Method: checkShmExt
1084 * Signature: ()I
1085 */
1086 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsEnvironment_checkShmExt(JNIEnv * env,jobject this)1087 Java_sun_awt_X11GraphicsEnvironment_checkShmExt(JNIEnv *env, jobject this)
1088 {
1089
1090 int shmExt = NOEXT_MITSHM, shmPixmaps;
1091 #ifdef MITSHM
1092 TryInitMITShm(env, &shmExt, &shmPixmaps);
1093 #endif
1094 return shmExt;
1095 }
1096
1097 /*
1098 * Class: sun_awt_X11GraphicsEnvironment
1099 * Method: getDisplayString
1100 * Signature: ()Ljava/lang/String
1101 */
1102 JNIEXPORT jstring JNICALL
Java_sun_awt_X11GraphicsEnvironment_getDisplayString(JNIEnv * env,jobject this)1103 Java_sun_awt_X11GraphicsEnvironment_getDisplayString
1104 (JNIEnv *env, jobject this)
1105 {
1106 #ifdef HEADLESS
1107 return (jstring)NULL;
1108 #else
1109 return (*env)->NewStringUTF(env, DisplayString(awt_display));
1110 #endif /* HEADLESS */
1111 }
1112
1113
1114 /*
1115 * Class: sun_awt_X11GraphicsDevice
1116 * Method: getNumConfigs
1117 * Signature: ()I
1118 */
1119 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getNumConfigs(JNIEnv * env,jobject this,jint screen)1120 Java_sun_awt_X11GraphicsDevice_getNumConfigs(
1121 JNIEnv *env, jobject this, jint screen)
1122 {
1123 #ifdef HEADLESS
1124 return (jint)0;
1125 #else
1126 ensureConfigsInited(env, screen);
1127 return x11Screens[screen].numConfigs;
1128 #endif /* !HEADLESS */
1129 }
1130
1131 /*
1132 * Class: sun_awt_X11GraphicsDevice
1133 * Method: getConfigVisualId
1134 * Signature: (I)I
1135 */
1136 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getConfigVisualId(JNIEnv * env,jobject this,jint index,jint screen)1137 Java_sun_awt_X11GraphicsDevice_getConfigVisualId(
1138 JNIEnv *env, jobject this, jint index, jint screen)
1139 {
1140 #ifdef HEADLESS
1141 return (jint)0;
1142 #else
1143 int visNum;
1144
1145 ensureConfigsInited(env, screen);
1146 if (index == 0) {
1147 return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.visualid);
1148 } else {
1149 return ((jint)x11Screens[screen].configs[index]->awt_visInfo.visualid);
1150 }
1151 #endif /* !HEADLESS */
1152 }
1153
1154 /*
1155 * Class: sun_awt_X11GraphicsDevice
1156 * Method: getConfigDepth
1157 * Signature: (I)I
1158 */
1159 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getConfigDepth(JNIEnv * env,jobject this,jint index,jint screen)1160 Java_sun_awt_X11GraphicsDevice_getConfigDepth(
1161 JNIEnv *env, jobject this, jint index, jint screen)
1162 {
1163 #ifdef HEADLESS
1164 return (jint)0;
1165 #else
1166 int visNum;
1167
1168 ensureConfigsInited(env, screen);
1169 if (index == 0) {
1170 return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.depth);
1171 } else {
1172 return ((jint)x11Screens[screen].configs[index]->awt_visInfo.depth);
1173 }
1174 #endif /* !HEADLESS */
1175 }
1176
1177 /*
1178 * Class: sun_awt_X11GraphicsDevice
1179 * Method: getConfigColormap
1180 * Signature: (I)I
1181 */
1182 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsDevice_getConfigColormap(JNIEnv * env,jobject this,jint index,jint screen)1183 Java_sun_awt_X11GraphicsDevice_getConfigColormap(
1184 JNIEnv *env, jobject this, jint index, jint screen)
1185 {
1186 #ifdef HEADLESS
1187 return (jint)0;
1188 #else
1189 int visNum;
1190
1191 ensureConfigsInited(env, screen);
1192 if (index == 0) {
1193 return ((jint)x11Screens[screen].defaultConfig->awt_cmap);
1194 } else {
1195 return ((jint)x11Screens[screen].configs[index]->awt_cmap);
1196 }
1197 #endif /* !HEADLESS */
1198 }
1199
1200 /*
1201 * Class: sun_awt_X11GraphicsDevice
1202 * Method: resetNativeData
1203 * Signature: (I)V
1204 */
1205 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_resetNativeData(JNIEnv * env,jclass x11gd,jint screen)1206 Java_sun_awt_X11GraphicsDevice_resetNativeData
1207 (JNIEnv *env, jclass x11gd, jint screen)
1208 {
1209 #ifndef HEADLESS
1210 /*
1211 * Reset references to the various configs; the actual native config data
1212 * will be free'd later by the Disposer mechanism when the Java-level
1213 * X11GraphicsConfig objects go away. By setting these values to NULL,
1214 * we ensure that they will be reinitialized as necessary (for example,
1215 * see the getNumConfigs() method).
1216 */
1217 if (x11Screens[screen].configs) {
1218 free(x11Screens[screen].configs);
1219 x11Screens[screen].configs = NULL;
1220 }
1221 x11Screens[screen].defaultConfig = NULL;
1222 x11Screens[screen].numConfigs = 0;
1223 #endif /* !HEADLESS */
1224 }
1225
1226 /*
1227 * Class: sun_awt_X11GraphicsConfig
1228 * Method: dispose
1229 * Signature: (J)V
1230 */
1231 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_dispose(JNIEnv * env,jclass x11gc,jlong configData)1232 Java_sun_awt_X11GraphicsConfig_dispose
1233 (JNIEnv *env, jclass x11gc, jlong configData)
1234 {
1235 #ifndef HEADLESS
1236 AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)
1237 jlong_to_ptr(configData);
1238
1239 if (aData == NULL) {
1240 return;
1241 }
1242
1243 AWT_LOCK();
1244 if (aData->awt_cmap) {
1245 XFreeColormap(awt_display, aData->awt_cmap);
1246 }
1247 if (aData->awtImage) {
1248 free(aData->awtImage);
1249 }
1250 if (aData->monoImage) {
1251 XFree(aData->monoImage);
1252 }
1253 if (aData->monoPixmap) {
1254 XFreePixmap(awt_display, aData->monoPixmap);
1255 }
1256 if (aData->monoPixmapGC) {
1257 XFreeGC(awt_display, aData->monoPixmapGC);
1258 }
1259 if (aData->color_data) {
1260 free(aData->color_data);
1261 }
1262 AWT_UNLOCK();
1263
1264 if (aData->glxInfo) {
1265 /*
1266 * The native GLXGraphicsConfig data needs to be disposed separately
1267 * on the OGL queue flushing thread (should not be called while
1268 * the AWT lock is held).
1269 */
1270 JNU_CallStaticMethodByName(env, NULL,
1271 "sun/java2d/opengl/OGLRenderQueue",
1272 "disposeGraphicsConfig", "(J)V",
1273 ptr_to_jlong(aData->glxInfo));
1274 }
1275
1276 free(aData);
1277 #endif /* !HEADLESS */
1278 }
1279
1280 /*
1281 * Class: sun_awt_X11GraphicsConfig
1282 * Method: getXResolution
1283 * Signature: ()I
1284 */
1285 JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsConfig_getXResolution(JNIEnv * env,jobject this,jint screen)1286 Java_sun_awt_X11GraphicsConfig_getXResolution(
1287 JNIEnv *env, jobject this, jint screen)
1288 {
1289 #ifdef HEADLESS
1290 return (jdouble)0;
1291 #else
1292 return ((DisplayWidth(awt_display, screen) * 25.4) /
1293 DisplayWidthMM(awt_display, screen));
1294 #endif /* !HEADLESS */
1295 }
1296
1297 /*
1298 * Class: sun_awt_X11GraphicsConfig
1299 * Method: getYResolution
1300 * Signature: ()I
1301 */
1302 JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsConfig_getYResolution(JNIEnv * env,jobject this,jint screen)1303 Java_sun_awt_X11GraphicsConfig_getYResolution(
1304 JNIEnv *env, jobject this, jint screen)
1305 {
1306 #ifdef HEADLESS
1307 return (jdouble)0;
1308 #else
1309 return ((DisplayHeight(awt_display, screen) * 25.4) /
1310 DisplayHeightMM(awt_display, screen));
1311 #endif /* !HEADLESS */
1312 }
1313
1314
1315 /*
1316 * Class: sun_awt_X11GraphicsConfig
1317 * Method: getNumColors
1318 * Signature: ()I
1319 */
1320 JNIEXPORT jint JNICALL
Java_sun_awt_X11GraphicsConfig_getNumColors(JNIEnv * env,jobject this)1321 Java_sun_awt_X11GraphicsConfig_getNumColors(
1322 JNIEnv *env, jobject this)
1323 {
1324 #ifdef HEADLESS
1325 return (jint)0;
1326 #else
1327 AwtGraphicsConfigData *adata;
1328
1329 adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,
1330 x11GraphicsConfigIDs.aData);
1331
1332 return adata->awt_num_colors;
1333 #endif /* !HEADLESS */
1334 }
1335
1336 /*
1337 * Class: sun_awt_X11GraphicsConfig
1338 * Method: init
1339 * Signature: (I)V
1340 */
1341 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_init(JNIEnv * env,jobject this,jint visualNum,jint screen)1342 Java_sun_awt_X11GraphicsConfig_init(
1343 JNIEnv *env, jobject this, jint visualNum, jint screen)
1344 {
1345 #ifndef HEADLESS
1346 AwtGraphicsConfigData *adata = NULL;
1347 AwtScreenData asd = x11Screens[screen];
1348 int i, n;
1349 int depth;
1350 XImage * tempImage;
1351
1352 /* If haven't gotten all of the configs yet, do it now. */
1353 if (asd.numConfigs == 0) {
1354 getAllConfigs (env, screen, &asd);
1355 }
1356
1357 /* Check the graphicsConfig for this visual */
1358 for (i = 0; i < asd.numConfigs; i++) {
1359 AwtGraphicsConfigDataPtr agcPtr = asd.configs[i];
1360 if ((jint)agcPtr->awt_visInfo.visualid == visualNum) {
1361 adata = agcPtr;
1362 break;
1363 }
1364 }
1365
1366 /* If didn't find the visual, throw an exception... */
1367 if (adata == (AwtGraphicsConfigData *) NULL) {
1368 JNU_ThrowIllegalArgumentException(env, "Unknown Visual Specified");
1369 return;
1370 }
1371
1372 /* adata->awt_cmap initialization has been deferred to
1373 * makeColorModel call
1374 */
1375
1376 JNU_SetLongFieldFromPtr(env, this, x11GraphicsConfigIDs.aData, adata);
1377
1378 depth = adata->awt_visInfo.depth;
1379 tempImage = XCreateImage(awt_display,
1380 adata->awt_visInfo.visual,
1381 depth, ZPixmap, 0, NULL, 1, 1, 32, 0);
1382 adata->pixelStride = (tempImage->bits_per_pixel + 7) / 8;
1383 (*env)->SetIntField(env, this, x11GraphicsConfigIDs.bitsPerPixel,
1384 (jint)tempImage->bits_per_pixel);
1385 XDestroyImage(tempImage);
1386 #endif /* !HEADLESS */
1387 }
1388
1389
1390
1391 /*
1392 * Class: sun_awt_X11GraphicsConfig
1393 * Method: makeColorModel
1394 * Signature: ()Ljava/awt/image/ColorModel
1395 */
1396 JNIEXPORT jobject JNICALL
Java_sun_awt_X11GraphicsConfig_makeColorModel(JNIEnv * env,jobject this)1397 Java_sun_awt_X11GraphicsConfig_makeColorModel(
1398 JNIEnv *env, jobject this)
1399 {
1400 #ifdef HEADLESS
1401 return NULL;
1402 #else
1403 AwtGraphicsConfigData *adata;
1404 jobject colorModel;
1405
1406 /*
1407 * If awt is not locked yet, return null since the toolkit is not
1408 * initialized yet.
1409 */
1410 if (!awtLockInited) {
1411 return NULL;
1412 }
1413
1414 AWT_LOCK ();
1415
1416 adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,
1417 x11GraphicsConfigIDs.aData);
1418
1419 /* If colormap entry of adata is NULL, need to create it now */
1420 if (adata->awt_cmap == (Colormap) NULL) {
1421 awtJNI_CreateColorData (env, adata, 1);
1422 }
1423
1424 /* Make Color Model object for this GraphicsConfiguration */
1425 colorModel = (*env)->ExceptionCheck(env)
1426 ? NULL : awtJNI_GetColorModel (env, adata);
1427
1428 AWT_UNLOCK ();
1429
1430 return colorModel;
1431 #endif /* !HEADLESS */
1432 }
1433
1434
1435 /*
1436 * Class: sun_awt_X11GraphicsConfig
1437 * Method: getBounds
1438 * Signature: ()Ljava/awt/Rectangle
1439 */
1440 JNIEXPORT jobject JNICALL
Java_sun_awt_X11GraphicsConfig_pGetBounds(JNIEnv * env,jobject this,jint screen)1441 Java_sun_awt_X11GraphicsConfig_pGetBounds(JNIEnv *env, jobject this, jint screen)
1442 {
1443 #ifdef HEADLESS
1444 return NULL;
1445 #else
1446 jclass clazz;
1447 jmethodID mid;
1448 jobject bounds = NULL;
1449 AwtGraphicsConfigDataPtr adata;
1450
1451 adata = (AwtGraphicsConfigDataPtr)
1452 JNU_GetLongFieldAsPtr(env, this, x11GraphicsConfigIDs.aData);
1453
1454 clazz = (*env)->FindClass(env, "java/awt/Rectangle");
1455 CHECK_NULL_RETURN(clazz, NULL);
1456 mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V");
1457 if (mid != NULL) {
1458 if (usingXinerama) {
1459 if (0 <= screen && screen < awt_numScreens) {
1460 bounds = (*env)->NewObject(env, clazz, mid, fbrects[screen].x,
1461 fbrects[screen].y,
1462 fbrects[screen].width,
1463 fbrects[screen].height);
1464 } else {
1465 jclass exceptionClass = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
1466 if (exceptionClass != NULL) {
1467 (*env)->ThrowNew(env, exceptionClass, "Illegal screen index");
1468 }
1469 }
1470 } else {
1471 XWindowAttributes xwa;
1472 memset(&xwa, 0, sizeof(xwa));
1473
1474 AWT_LOCK ();
1475 XGetWindowAttributes(awt_display,
1476 RootWindow(awt_display, adata->awt_visInfo.screen),
1477 &xwa);
1478 AWT_UNLOCK ();
1479
1480 bounds = (*env)->NewObject(env, clazz, mid, 0, 0,
1481 xwa.width, xwa.height);
1482 }
1483
1484 if ((*env)->ExceptionOccurred(env)) {
1485 return NULL;
1486 }
1487 }
1488 return bounds;
1489 #endif /* !HEADLESS */
1490 }
1491
1492 /*
1493 * Class: sun_awt_X11GraphicsConfig
1494 * Method: createBackBuffer
1495 * Signature: (JI)J
1496 */
1497 JNIEXPORT jlong JNICALL
Java_sun_awt_X11GraphicsConfig_createBackBuffer(JNIEnv * env,jobject this,jlong window,jint swapAction)1498 Java_sun_awt_X11GraphicsConfig_createBackBuffer
1499 (JNIEnv *env, jobject this, jlong window, jint swapAction)
1500 {
1501 int32_t v1, v2;
1502 XdbeBackBuffer ret = (unsigned long) 0;
1503 Window w = (Window)window;
1504 AWT_LOCK();
1505 if (!XdbeQueryExtension(awt_display, &v1, &v2)) {
1506 JNU_ThrowByName(env, "java/lang/Exception",
1507 "Could not query double-buffer extension");
1508 AWT_UNLOCK();
1509 return (jlong)0;
1510 }
1511 ret = XdbeAllocateBackBufferName(awt_display, w,
1512 (XdbeSwapAction)swapAction);
1513 AWT_FLUSH_UNLOCK();
1514 return (jlong)ret;
1515 }
1516
1517 /*
1518 * Class: sun_awt_X11GraphicsConfig
1519 * Method: destroyBackBuffer
1520 * Signature: (J)V
1521 */
1522 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_destroyBackBuffer(JNIEnv * env,jobject this,jlong backBuffer)1523 Java_sun_awt_X11GraphicsConfig_destroyBackBuffer
1524 (JNIEnv *env, jobject this, jlong backBuffer)
1525 {
1526 AWT_LOCK();
1527 XdbeDeallocateBackBufferName(awt_display, (XdbeBackBuffer)backBuffer);
1528 AWT_FLUSH_UNLOCK();
1529 }
1530
1531 /*
1532 * Class: sun_awt_X11GraphicsConfig
1533 * Method: swapBuffers
1534 * Signature: (JI)V
1535 */
1536 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsConfig_swapBuffers(JNIEnv * env,jobject this,jlong window,jint swapAction)1537 Java_sun_awt_X11GraphicsConfig_swapBuffers
1538 (JNIEnv *env, jobject this,
1539 jlong window, jint swapAction)
1540 {
1541 XdbeSwapInfo swapInfo;
1542
1543 AWT_LOCK();
1544
1545 XdbeBeginIdiom(awt_display);
1546 swapInfo.swap_window = (Window)window;
1547 swapInfo.swap_action = (XdbeSwapAction)swapAction;
1548 if (!XdbeSwapBuffers(awt_display, &swapInfo, 1)) {
1549 JNU_ThrowInternalError(env, "Could not swap buffers");
1550 }
1551 XdbeEndIdiom(awt_display);
1552
1553 AWT_FLUSH_UNLOCK();
1554 }
1555
1556 /*
1557 * Class: sun_awt_X11GraphicsConfig
1558 * Method: isTranslucencyCapable
1559 * Signature: (J)V
1560 */
1561 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable(JNIEnv * env,jobject this,jlong configData)1562 Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable
1563 (JNIEnv *env, jobject this, jlong configData)
1564 {
1565 #ifdef HEADLESS
1566 return JNI_FALSE;
1567 #else
1568 AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(configData);
1569 if (aData == NULL) {
1570 return JNI_FALSE;
1571 }
1572 return aData->isTranslucencySupported ? JNI_TRUE : JNI_FALSE;
1573 #endif
1574 }
1575
1576 /*
1577 * Class: sun_awt_X11GraphicsDevice
1578 * Method: isDBESupported
1579 * Signature: ()Z
1580 */
1581 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv * env,jobject this)1582 Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv *env, jobject this)
1583 {
1584 #ifdef HEADLESS
1585 return JNI_FALSE;
1586 #else
1587 int opcode = 0, firstEvent = 0, firstError = 0;
1588 jboolean ret;
1589
1590 AWT_LOCK();
1591 ret = (jboolean)XQueryExtension(awt_display, "DOUBLE-BUFFER",
1592 &opcode, &firstEvent, &firstError);
1593 AWT_FLUSH_UNLOCK();
1594 return ret;
1595 #endif /* !HEADLESS */
1596 }
1597
1598 /*
1599 * Class: sun_awt_X11GraphicsDevice
1600 * Method: getDoubleBufferVisuals
1601 * Signature: (I)V
1602 */
1603 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv * env,jobject this,jint screen)1604 Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env,
1605 jobject this, jint screen)
1606 {
1607 #ifndef HEADLESS
1608 jclass clazz;
1609 jmethodID midAddVisual;
1610 Window rootWindow;
1611 int i, n = 1;
1612 XdbeScreenVisualInfo* visScreenInfo;
1613 int xinawareScreen;
1614
1615 if (usingXinerama) {
1616 xinawareScreen = 0;
1617 }
1618 else {
1619 xinawareScreen = screen;
1620 }
1621
1622 clazz = (*env)->GetObjectClass(env, this);
1623 midAddVisual = (*env)->GetMethodID(env, clazz, "addDoubleBufferVisual",
1624 "(I)V");
1625 CHECK_NULL(midAddVisual);
1626 AWT_LOCK();
1627 rootWindow = RootWindow(awt_display, xinawareScreen);
1628 visScreenInfo = XdbeGetVisualInfo(awt_display, &rootWindow, &n);
1629 if (visScreenInfo == NULL) {
1630 JNU_ThrowInternalError(env, "Could not get visual info");
1631 AWT_UNLOCK();
1632 return;
1633 }
1634 AWT_FLUSH_UNLOCK();
1635 for (i = 0; i < visScreenInfo->count; i++) {
1636 XdbeVisualInfo* visInfo = visScreenInfo->visinfo;
1637 (*env)->CallVoidMethod(env, this, midAddVisual, (visInfo[i]).visual);
1638 if ((*env)->ExceptionCheck(env)) {
1639 break;
1640 }
1641 }
1642 #endif /* !HEADLESS */
1643 }
1644
1645 /*
1646 * Class: sun_awt_X11GraphicsEnvironment
1647 * Method: pRunningXinerama
1648 * Signature: ()Z
1649 */
1650 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv * env,jobject this)1651 Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv *env,
1652 jobject this)
1653 {
1654 #ifdef HEADLESS
1655 return JNI_FALSE;
1656 #else
1657 return usingXinerama ? JNI_TRUE : JNI_FALSE;
1658 #endif /* HEADLESS */
1659 }
1660
1661 /*
1662 * Can return NULL.
1663 *
1664 * Class: sun_awt_X11GraphicsEnvironment
1665 * Method: getXineramaCenterPoint
1666 * Signature: ()Ljava/awt/Point
1667 */
1668 JNIEXPORT jobject JNICALL
Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv * env,jobject this)1669 Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv *env,
1670 jobject this)
1671 {
1672 jobject point = NULL;
1673 #ifndef HEADLESS /* return NULL in HEADLESS, Linux */
1674 #if defined(__solaris__)
1675 int x,y;
1676
1677 AWT_LOCK();
1678 DASSERT(usingXinerama);
1679 if (XineramaSolarisCenterFunc != NULL) {
1680 (XineramaSolarisCenterFunc)(awt_display, 0, &x, &y);
1681 point = JNU_NewObjectByName(env, "java/awt/Point","(II)V", x, y);
1682 DASSERT(point);
1683 } else {
1684 DTRACE_PRINTLN("unable to call XineramaSolarisCenterFunc: symbol is null");
1685 }
1686 AWT_FLUSH_UNLOCK();
1687 #endif /* __solaris__ */
1688 #endif /* HEADLESS */
1689 return point;
1690 }
1691
1692
1693 /**
1694 * Begin DisplayMode/FullScreen support
1695 */
1696
1697 #ifndef HEADLESS
1698
1699 #ifndef _AIX
1700
1701 #define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI
1702 #define REFRESH_RATE_UNKNOWN java_awt_DisplayMode_REFRESH_RATE_UNKNOWN
1703
1704 typedef Status
1705 (*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp);
1706 typedef XRRScreenConfiguration*
1707 (*XRRGetScreenInfoType)(Display *dpy, Drawable root);
1708 typedef void
1709 (*XRRFreeScreenConfigInfoType)(XRRScreenConfiguration *config);
1710 typedef short*
1711 (*XRRConfigRatesType)(XRRScreenConfiguration *config,
1712 int sizeID, int *nrates);
1713 typedef short
1714 (*XRRConfigCurrentRateType)(XRRScreenConfiguration *config);
1715 typedef XRRScreenSize*
1716 (*XRRConfigSizesType)(XRRScreenConfiguration *config,
1717 int *nsizes);
1718 typedef SizeID
1719 (*XRRConfigCurrentConfigurationType)(XRRScreenConfiguration *config,
1720 Rotation *rotation);
1721 typedef Status
1722 (*XRRSetScreenConfigAndRateType)(Display *dpy,
1723 XRRScreenConfiguration *config,
1724 Drawable draw,
1725 int size_index,
1726 Rotation rotation,
1727 short rate,
1728 Time timestamp);
1729 typedef Rotation
1730 (*XRRConfigRotationsType)(XRRScreenConfiguration *config,
1731 Rotation *current_rotation);
1732
1733 typedef XRRScreenResources* (*XRRGetScreenResourcesType)(Display *dpy,
1734 Window window);
1735
1736 typedef void (*XRRFreeScreenResourcesType)(XRRScreenResources *resources);
1737
1738 typedef XRROutputInfo * (*XRRGetOutputInfoType)(Display *dpy,
1739 XRRScreenResources *resources, RROutput output);
1740
1741 typedef void (*XRRFreeOutputInfoType)(XRROutputInfo *outputInfo);
1742
1743 typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,
1744 XRRScreenResources *resources, RRCrtc crtc);
1745
1746 typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo);
1747
1748 static XRRQueryVersionType awt_XRRQueryVersion;
1749 static XRRGetScreenInfoType awt_XRRGetScreenInfo;
1750 static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo;
1751 static XRRConfigRatesType awt_XRRConfigRates;
1752 static XRRConfigCurrentRateType awt_XRRConfigCurrentRate;
1753 static XRRConfigSizesType awt_XRRConfigSizes;
1754 static XRRConfigCurrentConfigurationType awt_XRRConfigCurrentConfiguration;
1755 static XRRSetScreenConfigAndRateType awt_XRRSetScreenConfigAndRate;
1756 static XRRConfigRotationsType awt_XRRConfigRotations;
1757 static XRRGetScreenResourcesType awt_XRRGetScreenResources;
1758 static XRRFreeScreenResourcesType awt_XRRFreeScreenResources;
1759 static XRRGetOutputInfoType awt_XRRGetOutputInfo;
1760 static XRRFreeOutputInfoType awt_XRRFreeOutputInfo;
1761 static XRRGetCrtcInfoType awt_XRRGetCrtcInfo;
1762 static XRRFreeCrtcInfoType awt_XRRFreeCrtcInfo;
1763
1764 #define LOAD_XRANDR_FUNC(f) \
1765 do { \
1766 awt_##f = (f##Type)dlsym(pLibRandR, #f); \
1767 if (awt_##f == NULL) { \
1768 J2dRlsTraceLn1(J2D_TRACE_ERROR, \
1769 "X11GD_InitXrandrFuncs: Could not load %s", #f); \
1770 dlclose(pLibRandR); \
1771 return JNI_FALSE; \
1772 } \
1773 } while (0)
1774
1775 static jboolean
X11GD_InitXrandrFuncs(JNIEnv * env)1776 X11GD_InitXrandrFuncs(JNIEnv *env)
1777 {
1778 int rr_maj_ver = 0, rr_min_ver = 0;
1779
1780 void *pLibRandR = dlopen(VERSIONED_JNI_LIB_NAME("Xrandr", "2"),
1781 RTLD_LAZY | RTLD_LOCAL);
1782 if (pLibRandR == NULL) {
1783 pLibRandR = dlopen(JNI_LIB_NAME("Xrandr"), RTLD_LAZY | RTLD_LOCAL);
1784 }
1785 if (pLibRandR == NULL) {
1786 J2dRlsTraceLn(J2D_TRACE_ERROR,
1787 "X11GD_InitXrandrFuncs: Could not open libXrandr.so.2");
1788 return JNI_FALSE;
1789 }
1790
1791 LOAD_XRANDR_FUNC(XRRQueryVersion);
1792
1793 if (!(*awt_XRRQueryVersion)(awt_display, &rr_maj_ver, &rr_min_ver)) {
1794 J2dRlsTraceLn(J2D_TRACE_ERROR,
1795 "X11GD_InitXrandrFuncs: XRRQueryVersion returned an error status");
1796 dlclose(pLibRandR);
1797 return JNI_FALSE;
1798 }
1799
1800 if (usingXinerama) {
1801 /*
1802 * We can proceed as long as this is RANDR 1.2 or above.
1803 * As of Xorg server 1.3 onwards the Xinerama backend may actually be
1804 * a fake one provided by RANDR itself. See Java bug 6636469 for info.
1805 */
1806 if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) {
1807 J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "
1808 "Xinerama is active and Xrandr version is %d.%d",
1809 rr_maj_ver, rr_min_ver);
1810 dlclose(pLibRandR);
1811 return JNI_FALSE;
1812 }
1813
1814 /*
1815 * REMIND: Fullscreen mode doesn't work quite right with multi-monitor
1816 * setups and RANDR 1.2.
1817 */
1818 if ((rr_maj_ver == 1 && rr_min_ver <= 2) && awt_numScreens > 1) {
1819 J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "
1820 "Multiple screens in use");
1821 dlclose(pLibRandR);
1822 return JNI_FALSE;
1823 }
1824 }
1825
1826 LOAD_XRANDR_FUNC(XRRGetScreenInfo);
1827 LOAD_XRANDR_FUNC(XRRFreeScreenConfigInfo);
1828 LOAD_XRANDR_FUNC(XRRConfigRates);
1829 LOAD_XRANDR_FUNC(XRRConfigCurrentRate);
1830 LOAD_XRANDR_FUNC(XRRConfigSizes);
1831 LOAD_XRANDR_FUNC(XRRConfigCurrentConfiguration);
1832 LOAD_XRANDR_FUNC(XRRSetScreenConfigAndRate);
1833 LOAD_XRANDR_FUNC(XRRConfigRotations);
1834 LOAD_XRANDR_FUNC(XRRGetScreenResources);
1835 LOAD_XRANDR_FUNC(XRRFreeScreenResources);
1836 LOAD_XRANDR_FUNC(XRRGetOutputInfo);
1837 LOAD_XRANDR_FUNC(XRRFreeOutputInfo);
1838 LOAD_XRANDR_FUNC(XRRGetCrtcInfo);
1839 LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);
1840
1841 return JNI_TRUE;
1842 }
1843
1844 static jobject
X11GD_CreateDisplayMode(JNIEnv * env,jint width,jint height,jint bitDepth,jint refreshRate)1845 X11GD_CreateDisplayMode(JNIEnv *env, jint width, jint height,
1846 jint bitDepth, jint refreshRate)
1847 {
1848 jclass displayModeClass;
1849 jmethodID cid;
1850 jint validRefreshRate = refreshRate;
1851
1852 displayModeClass = (*env)->FindClass(env, "java/awt/DisplayMode");
1853 CHECK_NULL_RETURN(displayModeClass, NULL);
1854 if (JNU_IsNull(env, displayModeClass)) {
1855 JNU_ThrowInternalError(env,
1856 "Could not get display mode class");
1857 return NULL;
1858 }
1859
1860 cid = (*env)->GetMethodID(env, displayModeClass, "<init>", "(IIII)V");
1861 CHECK_NULL_RETURN(cid, NULL);
1862 if (cid == NULL) {
1863 JNU_ThrowInternalError(env,
1864 "Could not get display mode constructor");
1865 return NULL;
1866 }
1867
1868 // early versions of xrandr may report "empty" rates (6880694)
1869 if (validRefreshRate <= 0) {
1870 validRefreshRate = REFRESH_RATE_UNKNOWN;
1871 }
1872
1873 return (*env)->NewObject(env, displayModeClass, cid,
1874 width, height, bitDepth, validRefreshRate);
1875 }
1876
1877 static void
X11GD_AddDisplayMode(JNIEnv * env,jobject arrayList,jint width,jint height,jint bitDepth,jint refreshRate)1878 X11GD_AddDisplayMode(JNIEnv *env, jobject arrayList,
1879 jint width, jint height,
1880 jint bitDepth, jint refreshRate)
1881 {
1882 jobject displayMode = X11GD_CreateDisplayMode(env, width, height,
1883 bitDepth, refreshRate);
1884 if (!JNU_IsNull(env, displayMode)) {
1885 jclass arrayListClass;
1886 jmethodID mid;
1887 arrayListClass = (*env)->GetObjectClass(env, arrayList);
1888 if (JNU_IsNull(env, arrayListClass)) {
1889 JNU_ThrowInternalError(env,
1890 "Could not get class java.util.ArrayList");
1891 return;
1892 }
1893 mid = (*env)->GetMethodID(env, arrayListClass, "add",
1894 "(Ljava/lang/Object;)Z");
1895 CHECK_NULL(mid);
1896 if (mid == NULL) {
1897 JNU_ThrowInternalError(env,
1898 "Could not get method java.util.ArrayList.add()");
1899 return;
1900 }
1901 (*env)->CallObjectMethod(env, arrayList, mid, displayMode);
1902 (*env)->DeleteLocalRef(env, displayMode);
1903 }
1904 }
1905
1906 #endif /* !_AIX */
1907
1908 static void
X11GD_SetFullscreenMode(Window win,jboolean enabled)1909 X11GD_SetFullscreenMode(Window win, jboolean enabled)
1910 {
1911 Atom wmState = XInternAtom(awt_display, "_NET_WM_STATE", False);
1912 Atom wmStateFs = XInternAtom(awt_display,
1913 "_NET_WM_STATE_FULLSCREEN", False);
1914 XWindowAttributes attr;
1915 XEvent event;
1916
1917 if (wmState == None || wmStateFs == None
1918 || !XGetWindowAttributes(awt_display, win, &attr)) {
1919 return;
1920 }
1921
1922 memset(&event, 0, sizeof(event));
1923 event.xclient.type = ClientMessage;
1924 event.xclient.message_type = wmState;
1925 event.xclient.display = awt_display;
1926 event.xclient.window = win;
1927 event.xclient.format = 32;
1928 event.xclient.data.l[0] = enabled ? 1 : 0; // 1==add, 0==remove
1929 event.xclient.data.l[1] = wmStateFs;
1930
1931 XSendEvent(awt_display, attr.root, False,
1932 SubstructureRedirectMask | SubstructureNotifyMask,
1933 &event);
1934 XSync(awt_display, False);
1935 }
1936 #endif /* !HEADLESS */
1937
1938 /*
1939 * Class: sun_awt_X11GraphicsDevice
1940 * Method: initXrandrExtension
1941 * Signature: ()Z
1942 */
1943 JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsDevice_initXrandrExtension(JNIEnv * env,jclass x11gd)1944 Java_sun_awt_X11GraphicsDevice_initXrandrExtension
1945 (JNIEnv *env, jclass x11gd)
1946 {
1947 #if defined(HEADLESS) || defined(_AIX)
1948 return JNI_FALSE;
1949 #else
1950 int opcode = 0, firstEvent = 0, firstError = 0;
1951 jboolean ret;
1952
1953 AWT_LOCK();
1954 ret = (jboolean)XQueryExtension(awt_display, "RANDR",
1955 &opcode, &firstEvent, &firstError);
1956 if (ret) {
1957 ret = X11GD_InitXrandrFuncs(env);
1958 }
1959 AWT_FLUSH_UNLOCK();
1960
1961 return ret;
1962 #endif /* HEADLESS */
1963 }
1964
1965 /*
1966 * Class: sun_awt_X11GraphicsDevice
1967 * Method: getCurrentDisplayMode
1968 * Signature: (I)Ljava/awt/DisplayMode;
1969 */
1970 JNIEXPORT jobject JNICALL
Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode(JNIEnv * env,jclass x11gd,jint screen)1971 Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode
1972 (JNIEnv* env, jclass x11gd, jint screen)
1973 {
1974 #if defined(HEADLESS) || defined(_AIX)
1975 return NULL;
1976 #else
1977 XRRScreenConfiguration *config;
1978 jobject displayMode = NULL;
1979
1980 AWT_LOCK();
1981
1982 if (usingXinerama && XScreenCount(awt_display) > 0) {
1983 XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
1984 RootWindow(awt_display, 0));
1985 if (res) {
1986 if (res->noutput > screen) {
1987 XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
1988 res, res->outputs[screen]);
1989 if (output_info) {
1990 if (output_info->crtc) {
1991 XRRCrtcInfo *crtc_info =
1992 awt_XRRGetCrtcInfo (awt_display, res,
1993 output_info->crtc);
1994 if (crtc_info) {
1995 if (crtc_info->mode) {
1996 int i;
1997 for (i = 0; i < res->nmode; i++) {
1998 XRRModeInfo *mode = &res->modes[i];
1999 if (mode->id == crtc_info->mode) {
2000 float rate = 0;
2001 if (mode->hTotal && mode->vTotal) {
2002 rate = ((float)mode->dotClock /
2003 ((float)mode->hTotal *
2004 (float)mode->vTotal));
2005 }
2006 displayMode = X11GD_CreateDisplayMode(
2007 env,
2008 mode->width,
2009 mode->height,
2010 BIT_DEPTH_MULTI,
2011 (int)(rate +.2));
2012 break;
2013 }
2014 }
2015 }
2016 awt_XRRFreeCrtcInfo(crtc_info);
2017 }
2018 }
2019 awt_XRRFreeOutputInfo(output_info);
2020 }
2021 }
2022 awt_XRRFreeScreenResources(res);
2023 }
2024 } else {
2025
2026 config = awt_XRRGetScreenInfo(awt_display,
2027 RootWindow(awt_display, screen));
2028 if (config != NULL) {
2029 Rotation rotation;
2030 short curRate;
2031 SizeID curSizeIndex;
2032 XRRScreenSize *sizes;
2033 int nsizes;
2034
2035 curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation);
2036 sizes = awt_XRRConfigSizes(config, &nsizes);
2037 curRate = awt_XRRConfigCurrentRate(config);
2038
2039 if ((sizes != NULL) &&
2040 (curSizeIndex < nsizes))
2041 {
2042 XRRScreenSize curSize = sizes[curSizeIndex];
2043 displayMode = X11GD_CreateDisplayMode(env,
2044 curSize.width,
2045 curSize.height,
2046 BIT_DEPTH_MULTI,
2047 curRate);
2048 }
2049
2050 awt_XRRFreeScreenConfigInfo(config);
2051 }
2052 }
2053
2054 AWT_FLUSH_UNLOCK();
2055
2056 return displayMode;
2057 #endif /* HEADLESS */
2058 }
2059
2060 /*
2061 * Class: sun_awt_X11GraphicsDevice
2062 * Method: enumDisplayModes
2063 * Signature: (ILjava/util/ArrayList;)V
2064 */
2065 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_enumDisplayModes(JNIEnv * env,jclass x11gd,jint screen,jobject arrayList)2066 Java_sun_awt_X11GraphicsDevice_enumDisplayModes
2067 (JNIEnv* env, jclass x11gd,
2068 jint screen, jobject arrayList)
2069 {
2070 #if !defined(HEADLESS) && !defined(_AIX)
2071
2072 AWT_LOCK();
2073
2074 if (usingXinerama && XScreenCount(awt_display) > 0) {
2075 XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
2076 RootWindow(awt_display, 0));
2077 if (res) {
2078 if (res->noutput > screen) {
2079 XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
2080 res, res->outputs[screen]);
2081 if (output_info) {
2082 int i;
2083 for (i = 0; i < output_info->nmode; i++) {
2084 RRMode m = output_info->modes[i];
2085 int j;
2086 XRRModeInfo *mode;
2087 for (j = 0; j < res->nmode; j++) {
2088 mode = &res->modes[j];
2089 if (mode->id == m) {
2090 float rate = 0;
2091 if (mode->hTotal && mode->vTotal) {
2092 rate = ((float)mode->dotClock /
2093 ((float)mode->hTotal *
2094 (float)mode->vTotal));
2095 }
2096 X11GD_AddDisplayMode(env, arrayList,
2097 mode->width, mode->height,
2098 BIT_DEPTH_MULTI, (int)(rate +.2));
2099 if ((*env)->ExceptionCheck(env)) {
2100 goto ret0;
2101 }
2102 break;
2103 }
2104 }
2105 }
2106 ret0:
2107 awt_XRRFreeOutputInfo(output_info);
2108 }
2109 }
2110 awt_XRRFreeScreenResources(res);
2111 }
2112 } else {
2113 XRRScreenConfiguration *config;
2114
2115 config = awt_XRRGetScreenInfo(awt_display,
2116 RootWindow(awt_display, screen));
2117 if (config != NULL) {
2118 int nsizes, i, j;
2119 XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
2120
2121 if (sizes != NULL) {
2122 for (i = 0; i < nsizes; i++) {
2123 int nrates;
2124 XRRScreenSize size = sizes[i];
2125 short *rates = awt_XRRConfigRates(config, i, &nrates);
2126
2127 for (j = 0; j < nrates; j++) {
2128 X11GD_AddDisplayMode(env, arrayList,
2129 size.width,
2130 size.height,
2131 BIT_DEPTH_MULTI,
2132 rates[j]);
2133 if ((*env)->ExceptionCheck(env)) {
2134 goto ret1;
2135 }
2136 }
2137 }
2138 }
2139 ret1:
2140 awt_XRRFreeScreenConfigInfo(config);
2141 }
2142 }
2143
2144 AWT_FLUSH_UNLOCK();
2145 #endif /* !HEADLESS */
2146 }
2147
2148 /*
2149 * Class: sun_awt_X11GraphicsDevice
2150 * Method: configDisplayMode
2151 * Signature: (IIII)V
2152 */
2153 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_configDisplayMode(JNIEnv * env,jclass x11gd,jint screen,jint width,jint height,jint refreshRate)2154 Java_sun_awt_X11GraphicsDevice_configDisplayMode
2155 (JNIEnv* env, jclass x11gd,
2156 jint screen, jint width, jint height, jint refreshRate)
2157 {
2158 #if !defined(HEADLESS) && !defined(_AIX)
2159 jboolean success = JNI_FALSE;
2160 XRRScreenConfiguration *config;
2161 Drawable root;
2162 Rotation currentRotation = RR_Rotate_0;
2163
2164 AWT_LOCK();
2165
2166 root = RootWindow(awt_display, screen);
2167 config = awt_XRRGetScreenInfo(awt_display, root);
2168 if (config != NULL) {
2169 jboolean foundConfig = JNI_FALSE;
2170 int chosenSizeIndex = -1;
2171 short chosenRate = -1;
2172 int nsizes;
2173 XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
2174 awt_XRRConfigRotations(config, ¤tRotation);
2175
2176 if (sizes != NULL) {
2177 int i, j;
2178
2179 /* find the size index that matches the requested dimensions */
2180 for (i = 0; i < nsizes; i++) {
2181 XRRScreenSize size = sizes[i];
2182
2183 if ((size.width == width) && (size.height == height)) {
2184 /* we've found our size index... */
2185 int nrates;
2186 short *rates = awt_XRRConfigRates(config, i, &nrates);
2187
2188 /* now find rate that matches requested refresh rate */
2189 for (j = 0; j < nrates; j++) {
2190 if (rates[j] == refreshRate) {
2191 /* we've found our rate; break out of the loop */
2192 chosenSizeIndex = i;
2193 chosenRate = rates[j];
2194 foundConfig = JNI_TRUE;
2195 break;
2196 }
2197 }
2198
2199 break;
2200 }
2201 }
2202 }
2203
2204 if (foundConfig) {
2205 Status status =
2206 awt_XRRSetScreenConfigAndRate(awt_display, config, root,
2207 chosenSizeIndex,
2208 currentRotation,
2209 chosenRate,
2210 CurrentTime);
2211
2212 /* issue XSync to ensure immediate mode change */
2213 XSync(awt_display, False);
2214
2215 if (status == RRSetConfigSuccess) {
2216 success = JNI_TRUE;
2217 }
2218 }
2219
2220 awt_XRRFreeScreenConfigInfo(config);
2221 }
2222
2223 AWT_FLUSH_UNLOCK();
2224
2225 if (!success && !(*env)->ExceptionCheck(env)) {
2226 JNU_ThrowInternalError(env, "Could not set display mode");
2227 }
2228 #endif /* !HEADLESS */
2229 }
2230
2231 /*
2232 * Class: sun_awt_X11GraphicsDevice
2233 * Method: enterFullScreenExclusive
2234 * Signature: (J)V
2235 */
2236 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive(JNIEnv * env,jclass x11gd,jlong window)2237 Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive
2238 (JNIEnv* env, jclass x11gd,
2239 jlong window)
2240 {
2241 #ifndef HEADLESS
2242 Window win = (Window)window;
2243
2244 AWT_LOCK();
2245 XSync(awt_display, False); /* ensures window is visible first */
2246 X11GD_SetFullscreenMode(win, JNI_TRUE);
2247 AWT_UNLOCK();
2248 #endif /* !HEADLESS */
2249 }
2250
2251 /*
2252 * Class: sun_awt_X11GraphicsDevice
2253 * Method: exitFullScreenExclusive
2254 * Signature: (J)V
2255 */
2256 JNIEXPORT void JNICALL
Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive(JNIEnv * env,jclass x11gd,jlong window)2257 Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive
2258 (JNIEnv* env, jclass x11gd,
2259 jlong window)
2260 {
2261 #ifndef HEADLESS
2262 Window win = (Window)window;
2263
2264 AWT_LOCK();
2265 X11GD_SetFullscreenMode(win, JNI_FALSE);
2266 AWT_UNLOCK();
2267 #endif /* !HEADLESS */
2268 }
2269
2270 /**
2271 * End DisplayMode/FullScreen support
2272 */
2273
get_output_screen_name(JNIEnv * env,int screen)2274 static char *get_output_screen_name(JNIEnv *env, int screen) {
2275 #ifdef _AIX
2276 return NULL;
2277 #else
2278 if (!awt_XRRGetScreenResources || !awt_XRRGetOutputInfo) {
2279 return NULL;
2280 }
2281 char *name = NULL;
2282 AWT_LOCK();
2283 int scr = 0, out = 0;
2284 if (usingXinerama && XScreenCount(awt_display) > 0) {
2285 out = screen;
2286 } else {
2287 scr = screen;
2288 }
2289
2290 XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
2291 RootWindow(awt_display, scr));
2292 if (res) {
2293 if (res->noutput > out) {
2294 XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
2295 res, res->outputs[out]);
2296 if (output_info) {
2297 if (output_info->name) {
2298 name = strdup(output_info->name);
2299 }
2300 awt_XRRFreeOutputInfo(output_info);
2301 }
2302 }
2303 awt_XRRFreeScreenResources(res);
2304 }
2305 AWT_UNLOCK();
2306 return name;
2307 #endif /* _AIX */
2308 }
2309
2310 /*
2311 * Class: sun_awt_X11GraphicsDevice
2312 * Method: getNativeScaleFactor
2313 * Signature: (I)D
2314 */
2315 JNIEXPORT jdouble JNICALL
Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor(JNIEnv * env,jobject this,jint screen)2316 Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor
2317 (JNIEnv *env, jobject this, jint screen) {
2318 // in case of Xinerama individual screen scales are not supported
2319 char *name = get_output_screen_name(env, usingXinerama ? 0 : screen);
2320 double scale = getNativeScaleFactor(name);
2321 if (name) {
2322 free(name);
2323 }
2324 return scale;
2325 }
2326