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