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