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