1 /* 2 * Copyright (c) 1997, 2012, 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 909 int J2DXErrHandler(Display *display, XErrorEvent *xerr) { 910 int ret = 0; 911 if (xerr->minor_code == X_ShmAttach) { 912 xshmAttachFailed = JNI_TRUE; 913 } else { 914 ret = (*xerror_saved_handler)(display, xerr); 915 } 916 return ret; 917 } 918 jboolean isXShmAttachFailed() { 919 return xshmAttachFailed; 920 } 921 void resetXShmAttachFailed() { 922 xshmAttachFailed = JNI_FALSE; 923 } 924 925 void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) { 926 XShmSegmentInfo shminfo; 927 int XShmMajor, XShmMinor; 928 int a, b, c; 929 930 AWT_LOCK(); 931 if (canUseShmExt != UNSET_MITSHM) { 932 *shmExt = canUseShmExt; 933 *shmPixmaps = canUseShmExtPixmaps; 934 AWT_UNLOCK(); 935 return; 936 } 937 938 *shmExt = canUseShmExt = CANT_USE_MITSHM; 939 *shmPixmaps = canUseShmExtPixmaps = CANT_USE_MITSHM; 940 941 /** 942 * XShmQueryExtension returns False in remote server case. 943 * Unfortunately it also returns True in ssh case, so 944 * we need to test that we can actually do XShmAttach. 945 */ 946 if (XShmQueryExtension(awt_display)) { 947 shminfo.shmid = shmget(IPC_PRIVATE, 0x10000, IPC_CREAT|0777); 948 if (shminfo.shmid < 0) { 949 AWT_UNLOCK(); 950 J2dRlsTraceLn1(J2D_TRACE_ERROR, 951 "TryInitMITShm: shmget has failed: %s", 952 strerror(errno)); 953 return; 954 } 955 shminfo.shmaddr = (char *) shmat(shminfo.shmid, 0, 0); 956 if (shminfo.shmaddr == ((char *) -1)) { 957 shmctl(shminfo.shmid, IPC_RMID, 0); 958 AWT_UNLOCK(); 959 J2dRlsTraceLn1(J2D_TRACE_ERROR, 960 "TryInitMITShm: shmat has failed: %s", 961 strerror(errno)); 962 return; 963 } 964 shminfo.readOnly = True; 965 966 resetXShmAttachFailed(); 967 /** 968 * The J2DXErrHandler handler will set xshmAttachFailed 969 * to JNI_TRUE if any Shm error has occured. 970 */ 971 EXEC_WITH_XERROR_HANDLER(J2DXErrHandler, 972 XShmAttach(awt_display, &shminfo)); 973 974 /** 975 * Get rid of the id now to reduce chances of leaking 976 * system resources. 977 */ 978 shmctl(shminfo.shmid, IPC_RMID, 0); 979 980 if (isXShmAttachFailed() == JNI_FALSE) { 981 canUseShmExt = CAN_USE_MITSHM; 982 /* check if we can use shared pixmaps */ 983 XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor, 984 (Bool*)&canUseShmExtPixmaps); 985 canUseShmExtPixmaps = canUseShmExtPixmaps && 986 (XShmPixmapFormat(awt_display) == ZPixmap); 987 XShmDetach(awt_display, &shminfo); 988 } 989 shmdt(shminfo.shmaddr); 990 *shmExt = canUseShmExt; 991 *shmPixmaps = canUseShmExtPixmaps; 992 } 993 AWT_UNLOCK(); 994 } 995 #endif /* MITSHM */ 996 997 /* 998 * Class: sun_awt_X11GraphicsEnvironment 999 * Method: checkShmExt 1000 * Signature: ()I 1001 */ 1002 JNIEXPORT jint JNICALL 1003 Java_sun_awt_X11GraphicsEnvironment_checkShmExt(JNIEnv *env, jobject this) 1004 { 1005 1006 int shmExt = NOEXT_MITSHM, shmPixmaps; 1007 #ifdef MITSHM 1008 TryInitMITShm(env, &shmExt, &shmPixmaps); 1009 #endif 1010 return shmExt; 1011 } 1012 1013 /* 1014 * Class: sun_awt_X11GraphicsEnvironment 1015 * Method: getDisplayString 1016 * Signature: ()Ljava/lang/String 1017 */ 1018 JNIEXPORT jstring JNICALL 1019 Java_sun_awt_X11GraphicsEnvironment_getDisplayString 1020 (JNIEnv *env, jobject this) 1021 { 1022 #ifdef HEADLESS 1023 return (jstring)NULL; 1024 #else 1025 return (*env)->NewStringUTF(env, DisplayString(awt_display)); 1026 #endif /* HEADLESS */ 1027 } 1028 1029 1030 /* 1031 * Class: sun_awt_X11GraphicsDevice 1032 * Method: getNumConfigs 1033 * Signature: ()I 1034 */ 1035 JNIEXPORT jint JNICALL 1036 Java_sun_awt_X11GraphicsDevice_getNumConfigs( 1037 JNIEnv *env, jobject this, jint screen) 1038 { 1039 #ifdef HEADLESS 1040 return (jint)0; 1041 #else 1042 ensureConfigsInited(env, screen); 1043 return x11Screens[screen].numConfigs; 1044 #endif /* !HEADLESS */ 1045 } 1046 1047 /* 1048 * Class: sun_awt_X11GraphicsDevice 1049 * Method: getConfigVisualId 1050 * Signature: (I)I 1051 */ 1052 JNIEXPORT jint JNICALL 1053 Java_sun_awt_X11GraphicsDevice_getConfigVisualId( 1054 JNIEnv *env, jobject this, jint index, jint screen) 1055 { 1056 #ifdef HEADLESS 1057 return (jint)0; 1058 #else 1059 int visNum; 1060 1061 ensureConfigsInited(env, screen); 1062 if (index == 0) { 1063 return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.visualid); 1064 } else { 1065 return ((jint)x11Screens[screen].configs[index]->awt_visInfo.visualid); 1066 } 1067 #endif /* !HEADLESS */ 1068 } 1069 1070 /* 1071 * Class: sun_awt_X11GraphicsDevice 1072 * Method: getConfigDepth 1073 * Signature: (I)I 1074 */ 1075 JNIEXPORT jint JNICALL 1076 Java_sun_awt_X11GraphicsDevice_getConfigDepth( 1077 JNIEnv *env, jobject this, jint index, jint screen) 1078 { 1079 #ifdef HEADLESS 1080 return (jint)0; 1081 #else 1082 int visNum; 1083 1084 ensureConfigsInited(env, screen); 1085 if (index == 0) { 1086 return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.depth); 1087 } else { 1088 return ((jint)x11Screens[screen].configs[index]->awt_visInfo.depth); 1089 } 1090 #endif /* !HEADLESS */ 1091 } 1092 1093 /* 1094 * Class: sun_awt_X11GraphicsDevice 1095 * Method: getConfigColormap 1096 * Signature: (I)I 1097 */ 1098 JNIEXPORT jint JNICALL 1099 Java_sun_awt_X11GraphicsDevice_getConfigColormap( 1100 JNIEnv *env, jobject this, jint index, jint screen) 1101 { 1102 #ifdef HEADLESS 1103 return (jint)0; 1104 #else 1105 int visNum; 1106 1107 ensureConfigsInited(env, screen); 1108 if (index == 0) { 1109 return ((jint)x11Screens[screen].defaultConfig->awt_cmap); 1110 } else { 1111 return ((jint)x11Screens[screen].configs[index]->awt_cmap); 1112 } 1113 #endif /* !HEADLESS */ 1114 } 1115 1116 /* 1117 * Class: sun_awt_X11GraphicsDevice 1118 * Method: resetNativeData 1119 * Signature: (I)V 1120 */ 1121 JNIEXPORT void JNICALL 1122 Java_sun_awt_X11GraphicsDevice_resetNativeData 1123 (JNIEnv *env, jclass x11gd, jint screen) 1124 { 1125 #ifndef HEADLESS 1126 /* 1127 * Reset references to the various configs; the actual native config data 1128 * will be free'd later by the Disposer mechanism when the Java-level 1129 * X11GraphicsConfig objects go away. By setting these values to NULL, 1130 * we ensure that they will be reinitialized as necessary (for example, 1131 * see the getNumConfigs() method). 1132 */ 1133 if (x11Screens[screen].configs) { 1134 free(x11Screens[screen].configs); 1135 x11Screens[screen].configs = NULL; 1136 } 1137 x11Screens[screen].defaultConfig = NULL; 1138 x11Screens[screen].numConfigs = 0; 1139 #endif /* !HEADLESS */ 1140 } 1141 1142 /* 1143 * Class: sun_awt_X11GraphicsConfig 1144 * Method: dispose 1145 * Signature: (J)V 1146 */ 1147 JNIEXPORT void JNICALL 1148 Java_sun_awt_X11GraphicsConfig_dispose 1149 (JNIEnv *env, jclass x11gc, jlong configData) 1150 { 1151 #ifndef HEADLESS 1152 AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr) 1153 jlong_to_ptr(configData); 1154 1155 if (aData == NULL) { 1156 return; 1157 } 1158 1159 AWT_LOCK(); 1160 if (aData->awt_cmap) { 1161 XFreeColormap(awt_display, aData->awt_cmap); 1162 } 1163 if (aData->awtImage) { 1164 free(aData->awtImage); 1165 } 1166 if (aData->monoImage) { 1167 XFree(aData->monoImage); 1168 } 1169 if (aData->monoPixmap) { 1170 XFreePixmap(awt_display, aData->monoPixmap); 1171 } 1172 if (aData->monoPixmapGC) { 1173 XFreeGC(awt_display, aData->monoPixmapGC); 1174 } 1175 if (aData->color_data) { 1176 free(aData->color_data); 1177 } 1178 AWT_UNLOCK(); 1179 1180 if (aData->glxInfo) { 1181 /* 1182 * The native GLXGraphicsConfig data needs to be disposed separately 1183 * on the OGL queue flushing thread (should not be called while 1184 * the AWT lock is held). 1185 */ 1186 JNU_CallStaticMethodByName(env, NULL, 1187 "sun/java2d/opengl/OGLRenderQueue", 1188 "disposeGraphicsConfig", "(J)V", 1189 ptr_to_jlong(aData->glxInfo)); 1190 } 1191 1192 free(aData); 1193 #endif /* !HEADLESS */ 1194 } 1195 1196 /* 1197 * Class: sun_awt_X11GraphicsConfig 1198 * Method: getXResolution 1199 * Signature: ()I 1200 */ 1201 JNIEXPORT jdouble JNICALL 1202 Java_sun_awt_X11GraphicsConfig_getXResolution( 1203 JNIEnv *env, jobject this, jint screen) 1204 { 1205 #ifdef HEADLESS 1206 return (jdouble)0; 1207 #else 1208 return ((DisplayWidth(awt_display, screen) * 25.4) / 1209 DisplayWidthMM(awt_display, screen)); 1210 #endif /* !HEADLESS */ 1211 } 1212 1213 /* 1214 * Class: sun_awt_X11GraphicsConfig 1215 * Method: getYResolution 1216 * Signature: ()I 1217 */ 1218 JNIEXPORT jdouble JNICALL 1219 Java_sun_awt_X11GraphicsConfig_getYResolution( 1220 JNIEnv *env, jobject this, jint screen) 1221 { 1222 #ifdef HEADLESS 1223 return (jdouble)0; 1224 #else 1225 return ((DisplayHeight(awt_display, screen) * 25.4) / 1226 DisplayHeightMM(awt_display, screen)); 1227 #endif /* !HEADLESS */ 1228 } 1229 1230 1231 /* 1232 * Class: sun_awt_X11GraphicsConfig 1233 * Method: getNumColors 1234 * Signature: ()I 1235 */ 1236 JNIEXPORT jint JNICALL 1237 Java_sun_awt_X11GraphicsConfig_getNumColors( 1238 JNIEnv *env, jobject this) 1239 { 1240 #ifdef HEADLESS 1241 return (jint)0; 1242 #else 1243 AwtGraphicsConfigData *adata; 1244 1245 adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this, 1246 x11GraphicsConfigIDs.aData); 1247 1248 return adata->awt_num_colors; 1249 #endif /* !HEADLESS */ 1250 } 1251 1252 /* 1253 * Class: sun_awt_X11GraphicsConfig 1254 * Method: init 1255 * Signature: (I)V 1256 */ 1257 JNIEXPORT void JNICALL 1258 Java_sun_awt_X11GraphicsConfig_init( 1259 JNIEnv *env, jobject this, jint visualNum, jint screen) 1260 { 1261 #ifndef HEADLESS 1262 AwtGraphicsConfigData *adata = NULL; 1263 AwtScreenData asd = x11Screens[screen]; 1264 int i, n; 1265 int depth; 1266 XImage * tempImage; 1267 1268 /* If haven't gotten all of the configs yet, do it now. */ 1269 if (asd.numConfigs == 0) { 1270 getAllConfigs (env, screen, &asd); 1271 } 1272 1273 /* Check the graphicsConfig for this visual */ 1274 for (i = 0; i < asd.numConfigs; i++) { 1275 AwtGraphicsConfigDataPtr agcPtr = asd.configs[i]; 1276 if ((jint)agcPtr->awt_visInfo.visualid == visualNum) { 1277 adata = agcPtr; 1278 break; 1279 } 1280 } 1281 1282 /* If didn't find the visual, throw an exception... */ 1283 if (adata == (AwtGraphicsConfigData *) NULL) { 1284 JNU_ThrowIllegalArgumentException(env, "Unknown Visual Specified"); 1285 return; 1286 } 1287 1288 /* adata->awt_cmap initialization has been deferred to 1289 * makeColorModel call 1290 */ 1291 1292 JNU_SetLongFieldFromPtr(env, this, x11GraphicsConfigIDs.aData, adata); 1293 1294 depth = adata->awt_visInfo.depth; 1295 tempImage = XCreateImage(awt_display, 1296 adata->awt_visInfo.visual, 1297 depth, ZPixmap, 0, NULL, 1, 1, 32, 0); 1298 adata->pixelStride = (tempImage->bits_per_pixel + 7) / 8; 1299 (*env)->SetIntField(env, this, x11GraphicsConfigIDs.bitsPerPixel, 1300 (jint)tempImage->bits_per_pixel); 1301 XDestroyImage(tempImage); 1302 #endif /* !HEADLESS */ 1303 } 1304 1305 1306 1307 /* 1308 * Class: sun_awt_X11GraphicsConfig 1309 * Method: makeColorModel 1310 * Signature: ()Ljava/awt/image/ColorModel 1311 */ 1312 JNIEXPORT jobject JNICALL 1313 Java_sun_awt_X11GraphicsConfig_makeColorModel( 1314 JNIEnv *env, jobject this) 1315 { 1316 #ifdef HEADLESS 1317 return NULL; 1318 #else 1319 AwtGraphicsConfigData *adata; 1320 jobject colorModel; 1321 1322 /* 1323 * If awt is not locked yet, return null since the toolkit is not 1324 * initialized yet. 1325 */ 1326 if (!awtLockInited) { 1327 return NULL; 1328 } 1329 1330 AWT_LOCK (); 1331 1332 adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this, 1333 x11GraphicsConfigIDs.aData); 1334 1335 /* If colormap entry of adata is NULL, need to create it now */ 1336 if (adata->awt_cmap == (Colormap) NULL) { 1337 awtJNI_CreateColorData (env, adata, 1); 1338 } 1339 1340 /* Make Color Model object for this GraphicsConfiguration */ 1341 colorModel = awtJNI_GetColorModel (env, adata); 1342 1343 AWT_UNLOCK (); 1344 1345 return colorModel; 1346 #endif /* !HEADLESS */ 1347 } 1348 1349 1350 /* 1351 * Class: sun_awt_X11GraphicsConfig 1352 * Method: getBounds 1353 * Signature: ()Ljava/awt/Rectangle 1354 */ 1355 JNIEXPORT jobject JNICALL 1356 Java_sun_awt_X11GraphicsConfig_pGetBounds(JNIEnv *env, jobject this, jint screen) 1357 { 1358 #ifdef HEADLESS 1359 return NULL; 1360 #else 1361 jclass clazz; 1362 jmethodID mid; 1363 jobject bounds = NULL; 1364 AwtGraphicsConfigDataPtr adata; 1365 1366 adata = (AwtGraphicsConfigDataPtr) 1367 JNU_GetLongFieldAsPtr(env, this, x11GraphicsConfigIDs.aData); 1368 1369 clazz = (*env)->FindClass(env, "java/awt/Rectangle"); 1370 mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V"); 1371 if (mid != NULL) { 1372 if (usingXinerama) { 1373 bounds = (*env)->NewObject(env, clazz, mid, fbrects[screen].x, 1374 fbrects[screen].y, 1375 fbrects[screen].width, 1376 fbrects[screen].height); 1377 } 1378 else { 1379 XWindowAttributes xwa; 1380 memset(&xwa, 0, sizeof(xwa)); 1381 1382 AWT_LOCK (); 1383 XGetWindowAttributes(awt_display, 1384 RootWindow(awt_display, adata->awt_visInfo.screen), 1385 &xwa); 1386 AWT_UNLOCK (); 1387 1388 bounds = (*env)->NewObject(env, clazz, mid, 0, 0, 1389 xwa.width, xwa.height); 1390 } 1391 1392 if ((*env)->ExceptionOccurred(env)) { 1393 return NULL; 1394 } 1395 } 1396 return bounds; 1397 #endif /* !HEADLESS */ 1398 } 1399 1400 /* 1401 * Class: sun_awt_X11GraphicsConfig 1402 * Method: createBackBuffer 1403 * Signature: (JI)J 1404 */ 1405 JNIEXPORT jlong JNICALL 1406 Java_sun_awt_X11GraphicsConfig_createBackBuffer 1407 (JNIEnv *env, jobject this, jlong window, jint swapAction) 1408 { 1409 int32_t v1, v2; 1410 XdbeBackBuffer ret = (unsigned long) 0; 1411 Window w = (Window)window; 1412 AWT_LOCK(); 1413 if (!XdbeQueryExtension(awt_display, &v1, &v2)) { 1414 JNU_ThrowByName(env, "java/lang/Exception", 1415 "Could not query double-buffer extension"); 1416 AWT_UNLOCK(); 1417 return (jlong)0; 1418 } 1419 ret = XdbeAllocateBackBufferName(awt_display, w, 1420 (XdbeSwapAction)swapAction); 1421 AWT_FLUSH_UNLOCK(); 1422 return (jlong)ret; 1423 } 1424 1425 /* 1426 * Class: sun_awt_X11GraphicsConfig 1427 * Method: destroyBackBuffer 1428 * Signature: (J)V 1429 */ 1430 JNIEXPORT void JNICALL 1431 Java_sun_awt_X11GraphicsConfig_destroyBackBuffer 1432 (JNIEnv *env, jobject this, jlong backBuffer) 1433 { 1434 AWT_LOCK(); 1435 XdbeDeallocateBackBufferName(awt_display, (XdbeBackBuffer)backBuffer); 1436 AWT_FLUSH_UNLOCK(); 1437 } 1438 1439 /* 1440 * Class: sun_awt_X11GraphicsConfig 1441 * Method: swapBuffers 1442 * Signature: (JI)V 1443 */ 1444 JNIEXPORT void JNICALL 1445 Java_sun_awt_X11GraphicsConfig_swapBuffers 1446 (JNIEnv *env, jobject this, 1447 jlong window, jint swapAction) 1448 { 1449 XdbeSwapInfo swapInfo; 1450 1451 AWT_LOCK(); 1452 1453 XdbeBeginIdiom(awt_display); 1454 swapInfo.swap_window = (Window)window; 1455 swapInfo.swap_action = (XdbeSwapAction)swapAction; 1456 if (!XdbeSwapBuffers(awt_display, &swapInfo, 1)) { 1457 JNU_ThrowInternalError(env, "Could not swap buffers"); 1458 } 1459 XdbeEndIdiom(awt_display); 1460 1461 AWT_FLUSH_UNLOCK(); 1462 } 1463 1464 /* 1465 * Class: sun_awt_X11GraphicsConfig 1466 * Method: isTranslucencyCapable 1467 * Signature: (J)V 1468 */ 1469 JNIEXPORT jboolean JNICALL 1470 Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable 1471 (JNIEnv *env, jobject this, jlong configData) 1472 { 1473 #ifdef HEADLESS 1474 return JNI_FALSE; 1475 #else 1476 AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(configData); 1477 if (aData == NULL) { 1478 return JNI_FALSE; 1479 } 1480 return (jboolean)aData->isTranslucencySupported; 1481 #endif 1482 } 1483 1484 /* 1485 * Class: sun_awt_X11GraphicsDevice 1486 * Method: isDBESupported 1487 * Signature: ()Z 1488 */ 1489 JNIEXPORT jboolean JNICALL 1490 Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv *env, jobject this) 1491 { 1492 #ifdef HEADLESS 1493 return JNI_FALSE; 1494 #else 1495 int opcode = 0, firstEvent = 0, firstError = 0; 1496 jboolean ret; 1497 1498 AWT_LOCK(); 1499 ret = (jboolean)XQueryExtension(awt_display, "DOUBLE-BUFFER", 1500 &opcode, &firstEvent, &firstError); 1501 AWT_FLUSH_UNLOCK(); 1502 return ret; 1503 #endif /* !HEADLESS */ 1504 } 1505 1506 /* 1507 * Class: sun_awt_X11GraphicsDevice 1508 * Method: getDoubleBufferVisuals 1509 * Signature: (I)V 1510 */ 1511 JNIEXPORT void JNICALL 1512 Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env, 1513 jobject this, jint screen) 1514 { 1515 #ifndef HEADLESS 1516 jclass clazz; 1517 jmethodID midAddVisual; 1518 Window rootWindow; 1519 int i, n = 1; 1520 XdbeScreenVisualInfo* visScreenInfo; 1521 int xinawareScreen; 1522 1523 if (usingXinerama) { 1524 xinawareScreen = 0; 1525 } 1526 else { 1527 xinawareScreen = screen; 1528 } 1529 1530 clazz = (*env)->GetObjectClass(env, this); 1531 midAddVisual = (*env)->GetMethodID(env, clazz, "addDoubleBufferVisual", 1532 "(I)V"); 1533 1534 AWT_LOCK(); 1535 rootWindow = RootWindow(awt_display, xinawareScreen); 1536 visScreenInfo = XdbeGetVisualInfo(awt_display, &rootWindow, &n); 1537 if (visScreenInfo == NULL) { 1538 JNU_ThrowInternalError(env, "Could not get visual info"); 1539 AWT_UNLOCK(); 1540 return; 1541 } 1542 AWT_FLUSH_UNLOCK(); 1543 for (i = 0; i < visScreenInfo->count; i++) { 1544 XdbeVisualInfo* visInfo = visScreenInfo->visinfo; 1545 (*env)->CallVoidMethod(env, this, midAddVisual, (visInfo[i]).visual); 1546 } 1547 #endif /* !HEADLESS */ 1548 } 1549 1550 /* 1551 * Class: sun_awt_X11GraphicsEnvironment 1552 * Method: pRunningXinerama 1553 * Signature: ()Z 1554 */ 1555 JNIEXPORT jboolean JNICALL 1556 Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv *env, 1557 jobject this) 1558 { 1559 #ifdef HEADLESS 1560 return false; 1561 #else 1562 return usingXinerama; 1563 #endif /* HEADLESS */ 1564 } 1565 1566 /* 1567 * Can return NULL. 1568 * 1569 * Class: sun_awt_X11GraphicsEnvironment 1570 * Method: getXineramaCenterPoint 1571 * Signature: ()Ljava/awt/Point 1572 */ 1573 JNIEXPORT jobject JNICALL 1574 Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv *env, 1575 jobject this) 1576 { 1577 jobject point = NULL; 1578 #ifndef HEADLESS /* return NULL in HEADLESS, Linux */ 1579 #if !defined(__linux__) && !defined(MACOSX) 1580 int x,y; 1581 1582 AWT_LOCK(); 1583 DASSERT(usingXinerama); 1584 if (XineramaSolarisCenterFunc != NULL) { 1585 (XineramaSolarisCenterFunc)(awt_display, 0, &x, &y); 1586 point = JNU_NewObjectByName(env, "java/awt/Point","(II)V", x, y); 1587 DASSERT(point); 1588 } else { 1589 DTRACE_PRINTLN("unable to call XineramaSolarisCenterFunc: symbol is null"); 1590 } 1591 AWT_FLUSH_UNLOCK(); 1592 #endif /* __linux __ || MACOSX */ 1593 #endif /* HEADLESS */ 1594 return point; 1595 } 1596 1597 1598 /** 1599 * Begin DisplayMode/FullScreen support 1600 */ 1601 1602 #ifndef HEADLESS 1603 1604 #define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI 1605 #define REFRESH_RATE_UNKNOWN java_awt_DisplayMode_REFRESH_RATE_UNKNOWN 1606 1607 typedef Status 1608 (*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp); 1609 typedef XRRScreenConfiguration* 1610 (*XRRGetScreenInfoType)(Display *dpy, Drawable root); 1611 typedef void 1612 (*XRRFreeScreenConfigInfoType)(XRRScreenConfiguration *config); 1613 typedef short* 1614 (*XRRConfigRatesType)(XRRScreenConfiguration *config, 1615 int sizeID, int *nrates); 1616 typedef short 1617 (*XRRConfigCurrentRateType)(XRRScreenConfiguration *config); 1618 typedef XRRScreenSize* 1619 (*XRRConfigSizesType)(XRRScreenConfiguration *config, 1620 int *nsizes); 1621 typedef SizeID 1622 (*XRRConfigCurrentConfigurationType)(XRRScreenConfiguration *config, 1623 Rotation *rotation); 1624 typedef Status 1625 (*XRRSetScreenConfigAndRateType)(Display *dpy, 1626 XRRScreenConfiguration *config, 1627 Drawable draw, 1628 int size_index, 1629 Rotation rotation, 1630 short rate, 1631 Time timestamp); 1632 typedef Rotation 1633 (*XRRConfigRotationsType)(XRRScreenConfiguration *config, 1634 Rotation *current_rotation); 1635 1636 static XRRQueryVersionType awt_XRRQueryVersion; 1637 static XRRGetScreenInfoType awt_XRRGetScreenInfo; 1638 static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo; 1639 static XRRConfigRatesType awt_XRRConfigRates; 1640 static XRRConfigCurrentRateType awt_XRRConfigCurrentRate; 1641 static XRRConfigSizesType awt_XRRConfigSizes; 1642 static XRRConfigCurrentConfigurationType awt_XRRConfigCurrentConfiguration; 1643 static XRRSetScreenConfigAndRateType awt_XRRSetScreenConfigAndRate; 1644 static XRRConfigRotationsType awt_XRRConfigRotations; 1645 1646 #define LOAD_XRANDR_FUNC(f) \ 1647 do { \ 1648 awt_##f = (f##Type)dlsym(pLibRandR, #f); \ 1649 if (awt_##f == NULL) { \ 1650 J2dRlsTraceLn1(J2D_TRACE_ERROR, \ 1651 "X11GD_InitXrandrFuncs: Could not load %s", #f); \ 1652 dlclose(pLibRandR); \ 1653 return JNI_FALSE; \ 1654 } \ 1655 } while (0) 1656 1657 static jboolean 1658 X11GD_InitXrandrFuncs(JNIEnv *env) 1659 { 1660 int rr_maj_ver = 0, rr_min_ver = 0; 1661 1662 void *pLibRandR = dlopen(VERSIONED_JNI_LIB_NAME("Xrandr", "2"), 1663 RTLD_LAZY | RTLD_LOCAL); 1664 if (pLibRandR == NULL) { 1665 pLibRandR = dlopen(JNI_LIB_NAME("Xrandr"), RTLD_LAZY | RTLD_LOCAL); 1666 } 1667 if (pLibRandR == NULL) { 1668 J2dRlsTraceLn(J2D_TRACE_ERROR, 1669 "X11GD_InitXrandrFuncs: Could not open libXrandr.so.2"); 1670 return JNI_FALSE; 1671 } 1672 1673 LOAD_XRANDR_FUNC(XRRQueryVersion); 1674 1675 if (!(*awt_XRRQueryVersion)(awt_display, &rr_maj_ver, &rr_min_ver)) { 1676 J2dRlsTraceLn(J2D_TRACE_ERROR, 1677 "X11GD_InitXrandrFuncs: XRRQueryVersion returned an error status"); 1678 dlclose(pLibRandR); 1679 return JNI_FALSE; 1680 } 1681 1682 if (usingXinerama) { 1683 /* 1684 * We can proceed as long as this is RANDR 1.2 or above. 1685 * As of Xorg server 1.3 onwards the Xinerama backend may actually be 1686 * a fake one provided by RANDR itself. See Java bug 6636469 for info. 1687 */ 1688 if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) { 1689 J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. " 1690 "Xinerama is active and Xrandr version is %d.%d", 1691 rr_maj_ver, rr_min_ver); 1692 dlclose(pLibRandR); 1693 return JNI_FALSE; 1694 } 1695 1696 /* 1697 * REMIND: Fullscreen mode doesn't work quite right with multi-monitor 1698 * setups and RANDR 1.2. So for now we also require a single screen. 1699 */ 1700 if (awt_numScreens > 1 ) { 1701 J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. " 1702 "Multiple screens in use"); 1703 dlclose(pLibRandR); 1704 return JNI_FALSE; 1705 } 1706 } 1707 1708 LOAD_XRANDR_FUNC(XRRGetScreenInfo); 1709 LOAD_XRANDR_FUNC(XRRFreeScreenConfigInfo); 1710 LOAD_XRANDR_FUNC(XRRConfigRates); 1711 LOAD_XRANDR_FUNC(XRRConfigCurrentRate); 1712 LOAD_XRANDR_FUNC(XRRConfigSizes); 1713 LOAD_XRANDR_FUNC(XRRConfigCurrentConfiguration); 1714 LOAD_XRANDR_FUNC(XRRSetScreenConfigAndRate); 1715 LOAD_XRANDR_FUNC(XRRConfigRotations); 1716 1717 return JNI_TRUE; 1718 } 1719 1720 static jobject 1721 X11GD_CreateDisplayMode(JNIEnv *env, jint width, jint height, 1722 jint bitDepth, jint refreshRate) 1723 { 1724 jclass displayModeClass; 1725 jmethodID cid; 1726 jint validRefreshRate = refreshRate; 1727 1728 displayModeClass = (*env)->FindClass(env, "java/awt/DisplayMode"); 1729 if (JNU_IsNull(env, displayModeClass)) { 1730 JNU_ThrowInternalError(env, 1731 "Could not get display mode class"); 1732 return NULL; 1733 } 1734 1735 cid = (*env)->GetMethodID(env, displayModeClass, "<init>", "(IIII)V"); 1736 if (cid == NULL) { 1737 JNU_ThrowInternalError(env, 1738 "Could not get display mode constructor"); 1739 return NULL; 1740 } 1741 1742 // early versions of xrandr may report "empty" rates (6880694) 1743 if (validRefreshRate <= 0) { 1744 validRefreshRate = REFRESH_RATE_UNKNOWN; 1745 } 1746 1747 return (*env)->NewObject(env, displayModeClass, cid, 1748 width, height, bitDepth, validRefreshRate); 1749 } 1750 1751 static void 1752 X11GD_AddDisplayMode(JNIEnv *env, jobject arrayList, 1753 jint width, jint height, 1754 jint bitDepth, jint refreshRate) 1755 { 1756 jobject displayMode = X11GD_CreateDisplayMode(env, width, height, 1757 bitDepth, refreshRate); 1758 if (!JNU_IsNull(env, displayMode)) { 1759 jclass arrayListClass; 1760 jmethodID mid; 1761 arrayListClass = (*env)->GetObjectClass(env, arrayList); 1762 if (JNU_IsNull(env, arrayListClass)) { 1763 JNU_ThrowInternalError(env, 1764 "Could not get class java.util.ArrayList"); 1765 return; 1766 } 1767 mid = (*env)->GetMethodID(env, arrayListClass, "add", 1768 "(Ljava/lang/Object;)Z"); 1769 if (mid == NULL) { 1770 JNU_ThrowInternalError(env, 1771 "Could not get method java.util.ArrayList.add()"); 1772 return; 1773 } 1774 (*env)->CallObjectMethod(env, arrayList, mid, displayMode); 1775 (*env)->DeleteLocalRef(env, displayMode); 1776 } 1777 } 1778 1779 static void 1780 X11GD_SetFullscreenMode(Window win, jboolean enabled) 1781 { 1782 Atom wmState = XInternAtom(awt_display, "_NET_WM_STATE", False); 1783 Atom wmStateFs = XInternAtom(awt_display, 1784 "_NET_WM_STATE_FULLSCREEN", False); 1785 Window root, parent, *children = NULL; 1786 unsigned int numchildren; 1787 XEvent event; 1788 Status status; 1789 1790 if (wmState == None || wmStateFs == None) { 1791 return; 1792 } 1793 1794 /* 1795 * Note: the Window passed to this method is typically the "content 1796 * window" of the top-level, but we need the actual shell window for 1797 * the purposes of constructing the XEvent. Therefore, we walk up the 1798 * window hierarchy here to find the true top-level. 1799 */ 1800 do { 1801 if (!XQueryTree(awt_display, win, 1802 &root, &parent, 1803 &children, &numchildren)) 1804 { 1805 return; 1806 } 1807 1808 if (children != NULL) { 1809 XFree(children); 1810 } 1811 1812 if (parent == root) { 1813 break; 1814 } 1815 1816 win = parent; 1817 } while (root != parent); 1818 1819 memset(&event, 0, sizeof(event)); 1820 event.xclient.type = ClientMessage; 1821 event.xclient.message_type = wmState; 1822 event.xclient.display = awt_display; 1823 event.xclient.window = win; 1824 event.xclient.format = 32; 1825 event.xclient.data.l[0] = enabled ? 1 : 0; // 1==add, 0==remove 1826 event.xclient.data.l[1] = wmStateFs; 1827 1828 XSendEvent(awt_display, root, False, 1829 SubstructureRedirectMask | SubstructureNotifyMask, 1830 &event); 1831 XSync(awt_display, False); 1832 } 1833 #endif /* !HEADLESS */ 1834 1835 /* 1836 * Class: sun_awt_X11GraphicsDevice 1837 * Method: initXrandrExtension 1838 * Signature: ()Z 1839 */ 1840 JNIEXPORT jboolean JNICALL 1841 Java_sun_awt_X11GraphicsDevice_initXrandrExtension 1842 (JNIEnv *env, jclass x11gd) 1843 { 1844 #ifdef HEADLESS 1845 return JNI_FALSE; 1846 #else 1847 int opcode = 0, firstEvent = 0, firstError = 0; 1848 jboolean ret; 1849 1850 AWT_LOCK(); 1851 ret = (jboolean)XQueryExtension(awt_display, "RANDR", 1852 &opcode, &firstEvent, &firstError); 1853 if (ret) { 1854 ret = X11GD_InitXrandrFuncs(env); 1855 } 1856 AWT_FLUSH_UNLOCK(); 1857 1858 return ret; 1859 #endif /* HEADLESS */ 1860 } 1861 1862 /* 1863 * Class: sun_awt_X11GraphicsDevice 1864 * Method: getCurrentDisplayMode 1865 * Signature: (I)Ljava/awt/DisplayMode; 1866 */ 1867 JNIEXPORT jobject JNICALL 1868 Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode 1869 (JNIEnv* env, jclass x11gd, jint screen) 1870 { 1871 #ifdef HEADLESS 1872 return NULL; 1873 #else 1874 XRRScreenConfiguration *config; 1875 jobject displayMode = NULL; 1876 1877 AWT_LOCK(); 1878 1879 config = awt_XRRGetScreenInfo(awt_display, 1880 RootWindow(awt_display, screen)); 1881 if (config != NULL) { 1882 Rotation rotation; 1883 short curRate; 1884 SizeID curSizeIndex; 1885 XRRScreenSize *sizes; 1886 int nsizes; 1887 1888 curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation); 1889 sizes = awt_XRRConfigSizes(config, &nsizes); 1890 curRate = awt_XRRConfigCurrentRate(config); 1891 1892 if ((sizes != NULL) && 1893 (curSizeIndex < nsizes)) 1894 { 1895 XRRScreenSize curSize = sizes[curSizeIndex]; 1896 displayMode = X11GD_CreateDisplayMode(env, 1897 curSize.width, 1898 curSize.height, 1899 BIT_DEPTH_MULTI, 1900 curRate); 1901 } 1902 1903 awt_XRRFreeScreenConfigInfo(config); 1904 } 1905 1906 AWT_FLUSH_UNLOCK(); 1907 1908 return displayMode; 1909 #endif /* HEADLESS */ 1910 } 1911 1912 /* 1913 * Class: sun_awt_X11GraphicsDevice 1914 * Method: enumDisplayModes 1915 * Signature: (ILjava/util/ArrayList;)V 1916 */ 1917 JNIEXPORT void JNICALL 1918 Java_sun_awt_X11GraphicsDevice_enumDisplayModes 1919 (JNIEnv* env, jclass x11gd, 1920 jint screen, jobject arrayList) 1921 { 1922 #ifndef HEADLESS 1923 XRRScreenConfiguration *config; 1924 1925 AWT_LOCK(); 1926 1927 config = awt_XRRGetScreenInfo(awt_display, 1928 RootWindow(awt_display, screen)); 1929 if (config != NULL) { 1930 int nsizes, i, j; 1931 XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes); 1932 1933 if (sizes != NULL) { 1934 for (i = 0; i < nsizes; i++) { 1935 int nrates; 1936 XRRScreenSize size = sizes[i]; 1937 short *rates = awt_XRRConfigRates(config, i, &nrates); 1938 1939 for (j = 0; j < nrates; j++) { 1940 X11GD_AddDisplayMode(env, arrayList, 1941 size.width, 1942 size.height, 1943 BIT_DEPTH_MULTI, 1944 rates[j]); 1945 } 1946 } 1947 } 1948 1949 awt_XRRFreeScreenConfigInfo(config); 1950 } 1951 1952 AWT_FLUSH_UNLOCK(); 1953 #endif /* !HEADLESS */ 1954 } 1955 1956 /* 1957 * Class: sun_awt_X11GraphicsDevice 1958 * Method: configDisplayMode 1959 * Signature: (IIII)V 1960 */ 1961 JNIEXPORT void JNICALL 1962 Java_sun_awt_X11GraphicsDevice_configDisplayMode 1963 (JNIEnv* env, jclass x11gd, 1964 jint screen, jint width, jint height, jint refreshRate) 1965 { 1966 #ifndef HEADLESS 1967 jboolean success = JNI_FALSE; 1968 XRRScreenConfiguration *config; 1969 Drawable root; 1970 Rotation currentRotation = RR_Rotate_0; 1971 1972 AWT_LOCK(); 1973 1974 root = RootWindow(awt_display, screen); 1975 config = awt_XRRGetScreenInfo(awt_display, root); 1976 if (config != NULL) { 1977 jboolean foundConfig = JNI_FALSE; 1978 int chosenSizeIndex = -1; 1979 short chosenRate = -1; 1980 int nsizes; 1981 XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes); 1982 awt_XRRConfigRotations(config, ¤tRotation); 1983 1984 if (sizes != NULL) { 1985 int i, j; 1986 1987 /* find the size index that matches the requested dimensions */ 1988 for (i = 0; i < nsizes; i++) { 1989 XRRScreenSize size = sizes[i]; 1990 1991 if ((size.width == width) && (size.height == height)) { 1992 /* we've found our size index... */ 1993 int nrates; 1994 short *rates = awt_XRRConfigRates(config, i, &nrates); 1995 1996 /* now find rate that matches requested refresh rate */ 1997 for (j = 0; j < nrates; j++) { 1998 if (rates[j] == refreshRate) { 1999 /* we've found our rate; break out of the loop */ 2000 chosenSizeIndex = i; 2001 chosenRate = rates[j]; 2002 foundConfig = JNI_TRUE; 2003 break; 2004 } 2005 } 2006 2007 break; 2008 } 2009 } 2010 } 2011 2012 if (foundConfig) { 2013 Status status = 2014 awt_XRRSetScreenConfigAndRate(awt_display, config, root, 2015 chosenSizeIndex, 2016 currentRotation, 2017 chosenRate, 2018 CurrentTime); 2019 2020 /* issue XSync to ensure immediate mode change */ 2021 XSync(awt_display, False); 2022 2023 if (status == RRSetConfigSuccess) { 2024 success = JNI_TRUE; 2025 } 2026 } 2027 2028 awt_XRRFreeScreenConfigInfo(config); 2029 } 2030 2031 AWT_FLUSH_UNLOCK(); 2032 2033 if (!success) { 2034 JNU_ThrowInternalError(env, "Could not set display mode"); 2035 } 2036 #endif /* !HEADLESS */ 2037 } 2038 2039 /* 2040 * Class: sun_awt_X11GraphicsDevice 2041 * Method: enterFullScreenExclusive 2042 * Signature: (J)V 2043 */ 2044 JNIEXPORT void JNICALL 2045 Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive 2046 (JNIEnv* env, jclass x11gd, 2047 jlong window) 2048 { 2049 #ifndef HEADLESS 2050 Window win = (Window)window; 2051 2052 AWT_LOCK(); 2053 XSync(awt_display, False); /* ensures window is visible first */ 2054 X11GD_SetFullscreenMode(win, JNI_TRUE); 2055 AWT_UNLOCK(); 2056 #endif /* !HEADLESS */ 2057 } 2058 2059 /* 2060 * Class: sun_awt_X11GraphicsDevice 2061 * Method: exitFullScreenExclusive 2062 * Signature: (J)V 2063 */ 2064 JNIEXPORT void JNICALL 2065 Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive 2066 (JNIEnv* env, jclass x11gd, 2067 jlong window) 2068 { 2069 #ifndef HEADLESS 2070 Window win = (Window)window; 2071 2072 AWT_LOCK(); 2073 X11GD_SetFullscreenMode(win, JNI_FALSE); 2074 AWT_UNLOCK(); 2075 #endif /* !HEADLESS */ 2076 } 2077 2078 /** 2079 * End DisplayMode/FullScreen support 2080 */