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