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