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