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