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