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