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