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