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