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