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