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