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