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