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