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