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