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