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