Path: blob/master/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
66646 views
/*1* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#ifdef HEADLESS26#error This file should not be included in headless library27#endif2829#include "jni_util.h"30#include "awt_p.h"31#include "awt.h"32#include "color.h"33#include <java_awt_DisplayMode.h>34#include <sun_awt_X11GraphicsEnvironment.h>35#include <sun_awt_X11GraphicsDevice.h>36#include <sun_awt_X11GraphicsConfig.h>37#include <X11/extensions/Xdbe.h>38#include <X11/XKBlib.h>39#ifndef NO_XRANDR40#include <X11/extensions/Xrandr.h>41#endif42#include "GLXGraphicsConfig.h"4344#include <jni.h>45#include <jni_util.h>46#include <jvm.h>47#include <jvm_md.h>48#include <jlong.h>49#include "systemScale.h"50#include <stdlib.h>5152#include "awt_GraphicsEnv.h"53#include "awt_util.h"54#include "gdefs.h"55#include <dlfcn.h>56#include "Trace.h"5758int awt_numScreens; /* Xinerama-aware number of screens */5960AwtScreenDataPtr x11Screens; // should be guarded by AWT_LOCK()/AWT_UNLOCK()6162/*63* Set in initDisplay() to indicate whether we should attempt to initialize64* GLX for the default configuration.65*/66static jboolean glxRequested = JNI_FALSE;6768Display *awt_display;6970jclass tkClass = NULL;71jmethodID awtLockMID = NULL;72jmethodID awtUnlockMID = NULL;73jmethodID awtWaitMID = NULL;74jmethodID awtNotifyMID = NULL;75jmethodID awtNotifyAllMID = NULL;76jboolean awtLockInited = JNI_FALSE;7778/** Convenience macro for loading the lock-related method IDs. */79#define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \80do { \81method_id = (*env)->GetStaticMethodID(env, klass, \82method_name, method_sig); \83if (method_id == NULL) return NULL; \84} while (0)8586struct X11GraphicsConfigIDs x11GraphicsConfigIDs;8788int awtCreateX11Colormap(AwtGraphicsConfigDataPtr adata);8990static char *x11GraphicsConfigClassName = "sun/awt/X11GraphicsConfig";9192/* AWT and Xinerama93*94* As of fix 4356756, AWT is Xinerama-aware. X11GraphicsDevices are created for95* each screen of a Xinerama setup, though X11 itself still only sees a single96* display.97* In many places where we talk to X11, a xinawareScreen variable is used to98* pass the correct Display value, depending on the circumstances (a single99* X display, multiple X displays, or a single X display with multiple100* Xinerama screens).101*/102103#define MAXFRAMEBUFFERS 16104typedef struct {105int screen_number;106short x_org;107short y_org;108short width;109short height;110} XineramaScreenInfo;111112typedef XineramaScreenInfo* XineramaQueryScreensFunc(Display*, int*);113static XineramaQueryScreensFunc* XineramaQueryScreens = NULL;114Bool usingXinerama = False;115116JNIEXPORT void JNICALL117Java_sun_awt_X11GraphicsConfig_initIDs (JNIEnv *env, jclass cls)118{119x11GraphicsConfigIDs.aData = NULL;120x11GraphicsConfigIDs.bitsPerPixel = NULL;121122x11GraphicsConfigIDs.aData = (*env)->GetFieldID (env, cls, "aData", "J");123CHECK_NULL(x11GraphicsConfigIDs.aData);124x11GraphicsConfigIDs.bitsPerPixel = (*env)->GetFieldID (env, cls, "bitsPerPixel", "I");125CHECK_NULL(x11GraphicsConfigIDs.bitsPerPixel);126}127128/*129* XIOErrorHandler130*/131static int xioerror_handler(Display *disp)132{133if (awtLockInited) {134if (errno == EPIPE) {135jio_fprintf(stderr, "X connection to %s host broken (explicit kill or server shutdown)\n", XDisplayName(NULL));136}137/*SignalError(lockedee->lastpc, lockedee, "fp/ade/gui/GUIException", "I/O error"); */138}139return 0;140}141142static AwtGraphicsConfigDataPtr143findWithTemplate(XVisualInfo *vinfo,144long mask)145{146147XVisualInfo *visualList;148XColor color;149AwtGraphicsConfigDataPtr defaultConfig;150int visualsMatched, i;151152visualList = XGetVisualInfo(awt_display,153mask, vinfo, &visualsMatched);154if (visualList) {155int id = -1;156VisualID defaultVisual = XVisualIDFromVisual(DefaultVisual(awt_display, vinfo->screen));157defaultConfig = ZALLOC(_AwtGraphicsConfigData);158if (defaultConfig == NULL) {159XFree(visualList);160return NULL;161}162for (i = 0; i < visualsMatched; i++) {163memcpy(&defaultConfig->awt_visInfo, &visualList[i], sizeof(XVisualInfo));164defaultConfig->awt_depth = visualList[i].depth;165166/* we can't use awtJNI_CreateColorData here, because it'll pull,167SystemColor, which in turn will cause toolkit to be reinitialized */168if (awtCreateX11Colormap(defaultConfig)) {169if (visualList[i].visualid == defaultVisual) {170id = i;171break;172} else if (-1 == id) {173// Keep 1st match for fallback174id = i;175}176}177}178if (-1 != id) {179memcpy(&defaultConfig->awt_visInfo, &visualList[id], sizeof(XVisualInfo));180defaultConfig->awt_depth = visualList[id].depth;181/* Allocate white and black pixels for this visual */182color.flags = DoRed | DoGreen | DoBlue;183color.red = color.green = color.blue = 0x0000;184XAllocColor(awt_display, defaultConfig->awt_cmap, &color);185x11Screens[visualList[id].screen].blackpixel = color.pixel;186color.flags = DoRed | DoGreen | DoBlue;187color.red = color.green = color.blue = 0xffff;188XAllocColor(awt_display, defaultConfig->awt_cmap, &color);189x11Screens[visualList[id].screen].whitepixel = color.pixel;190191XFree(visualList);192return defaultConfig;193}194XFree(visualList);195free((void *)defaultConfig);196}197return NULL;198}199200/* default config is based on X11 screen. All Xinerama screens of that X11201screen will have the same default config */202/* Need more notes about which fields of the structure are based on the X203screen, and which are based on the Xinerama screen */204static AwtGraphicsConfigDataPtr205makeDefaultConfig(JNIEnv *env, int screen) {206207AwtGraphicsConfigDataPtr defaultConfig;208int xinawareScreen = 0;209VisualID forcedVisualID = 0, defaultVisualID;210char *forcedVisualStr;211XVisualInfo vinfo;212long mask;213214xinawareScreen = usingXinerama ? 0 : screen;215defaultVisualID =216XVisualIDFromVisual(DefaultVisual(awt_display, xinawareScreen));217218memset(&vinfo, 0, sizeof(XVisualInfo));219vinfo.screen = xinawareScreen;220221if ((forcedVisualStr = getenv("FORCEDEFVIS"))) {222mask = VisualIDMask | VisualScreenMask;223if (sscanf(forcedVisualStr, "%lx", &forcedVisualID) > 0 &&224forcedVisualID > 0)225{226vinfo.visualid = forcedVisualID;227} else {228vinfo.visualid = defaultVisualID;229}230} else {231VisualID bestGLXVisualID;232if (glxRequested &&233(bestGLXVisualID = GLXGC_FindBestVisual(env, xinawareScreen)) > 0)234{235/* we've found the best visual for use with GLX, so use it */236vinfo.visualid = bestGLXVisualID;237mask = VisualIDMask | VisualScreenMask;238} else {239/* otherwise, continue looking for the best X11 visual */240vinfo.depth = 24;241vinfo.class = TrueColor;242mask = VisualDepthMask | VisualScreenMask | VisualClassMask;243}244}245246/* try the best, or forced visual */247defaultConfig = findWithTemplate(&vinfo, mask);248if (defaultConfig) {249return defaultConfig;250}251252/* try the default visual */253vinfo.visualid = defaultVisualID;254mask = VisualIDMask | VisualScreenMask;255defaultConfig = findWithTemplate(&vinfo, mask);256if (defaultConfig) {257return defaultConfig;258}259260/* try any TrueColor */261vinfo.class = TrueColor;262mask = VisualScreenMask | VisualClassMask;263defaultConfig = findWithTemplate(&vinfo, mask);264if (defaultConfig) {265return defaultConfig;266}267268/* try 8-bit PseudoColor */269vinfo.depth = 8;270vinfo.class = PseudoColor;271mask = VisualDepthMask | VisualScreenMask | VisualClassMask;272defaultConfig = findWithTemplate(&vinfo, mask);273if (defaultConfig) {274return defaultConfig;275}276277/* try any 8-bit */278vinfo.depth = 8;279mask = VisualDepthMask | VisualScreenMask;280defaultConfig = findWithTemplate(&vinfo, mask);281if (defaultConfig) {282return defaultConfig;283}284285/* we tried everything, give up */286JNU_ThrowInternalError(env, "Can't find supported visual");287XCloseDisplay(awt_display);288awt_display = NULL;289return NULL;290}291292static void293getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) {294295int i;296int n8p=0, n12p=0, n8s=0, n8gs=0, n8sg=0, n1sg=0, nTrue=0;297int nConfig;298XVisualInfo *pVI8p, *pVI12p, *pVI8s, *pVITrue, *pVI8gs,299*pVI8sg, *pVI1sg = NULL, viTmp;300AwtGraphicsConfigDataPtr *graphicsConfigs;301AwtGraphicsConfigDataPtr defaultConfig;302int ind;303char errmsg[128];304int xinawareScreen;305void* xrenderLibHandle = NULL;306XRenderFindVisualFormatFunc* xrenderFindVisualFormat = NULL;307int major_opcode, first_event, first_error;308309if (usingXinerama) {310xinawareScreen = 0;311}312else {313xinawareScreen = screen;314}315316AWT_LOCK ();317318viTmp.screen = xinawareScreen;319320viTmp.depth = 8;321viTmp.class = PseudoColor;322viTmp.colormap_size = 256;323pVI8p = XGetVisualInfo (awt_display,324VisualDepthMask | VisualClassMask |325VisualColormapSizeMask | VisualScreenMask,326&viTmp, &n8p);327328viTmp.depth = 12;329viTmp.class = PseudoColor;330viTmp.colormap_size = 4096;331pVI12p = XGetVisualInfo (awt_display,332VisualDepthMask | VisualClassMask |333VisualColormapSizeMask | VisualScreenMask,334&viTmp, &n12p);335336viTmp.class = TrueColor;337pVITrue = XGetVisualInfo (awt_display,338VisualClassMask |339VisualScreenMask,340&viTmp, &nTrue);341342viTmp.depth = 8;343viTmp.class = StaticColor;344pVI8s = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask |345VisualScreenMask, &viTmp, &n8s);346347viTmp.depth = 8;348viTmp.class = GrayScale;349viTmp.colormap_size = 256;350pVI8gs = XGetVisualInfo (awt_display,351VisualDepthMask | VisualClassMask |352VisualColormapSizeMask | VisualScreenMask,353&viTmp, &n8gs);354viTmp.depth = 8;355viTmp.class = StaticGray;356viTmp.colormap_size = 256;357pVI8sg = XGetVisualInfo (awt_display,358VisualDepthMask | VisualClassMask |359VisualColormapSizeMask | VisualScreenMask,360&viTmp, &n8sg);361362/* REMIND.. remove when we have support for the color classes below */363/* viTmp.depth = 1; */364/* viTmp.class = StaticGray; */365/* pVI1sg = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask, */366/* viTmp, &n1sg); */367368nConfig = n8p + n12p + n8s + n8gs + n8sg + n1sg + nTrue + 1;369graphicsConfigs = (AwtGraphicsConfigDataPtr *)370calloc(nConfig, sizeof(AwtGraphicsConfigDataPtr));371if (graphicsConfigs == NULL) {372JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),373NULL);374AWT_UNLOCK();375return;376}377378if (screenDataPtr->defaultConfig == NULL) {379/*380* After a display change event, the default config field will have381* been reset, so we need to recreate the default config here.382*/383screenDataPtr->defaultConfig = makeDefaultConfig(env, screen);384}385386defaultConfig = screenDataPtr->defaultConfig;387graphicsConfigs[0] = defaultConfig;388nConfig = 1; /* reserve index 0 for default config */389390// Only use the RENDER extension if it is available on the X server391if (XQueryExtension(awt_display, "RENDER",392&major_opcode, &first_event, &first_error))393{394DTRACE_PRINTLN("RENDER extension available");395xrenderLibHandle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL);396397if (xrenderLibHandle == NULL) {398xrenderLibHandle = dlopen("libXrender.so", RTLD_LAZY | RTLD_GLOBAL);399}400401#if defined(_AIX)402if (xrenderLibHandle == NULL) {403xrenderLibHandle = dlopen("libXrender.a(libXrender.so.0)",404RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);405}406#endif407if (xrenderLibHandle != NULL) {408DTRACE_PRINTLN("Loaded libXrender");409xrenderFindVisualFormat =410(XRenderFindVisualFormatFunc*)dlsym(xrenderLibHandle,411"XRenderFindVisualFormat");412if (xrenderFindVisualFormat == NULL) {413DTRACE_PRINTLN1("Can't find 'XRenderFindVisualFormat' in libXrender (%s)", dlerror());414}415} else {416DTRACE_PRINTLN1("Can't load libXrender (%s)", dlerror());417}418} else {419DTRACE_PRINTLN("RENDER extension NOT available");420}421422for (i = 0; i < nTrue; i++) {423if (XVisualIDFromVisual(pVITrue[i].visual) ==424XVisualIDFromVisual(defaultConfig->awt_visInfo.visual) ||425pVITrue[i].depth == 12) {426/* Skip the non-supported 12-bit TrueColor visual */427continue;428} else {429ind = nConfig++;430}431graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);432if (graphicsConfigs[ind] == NULL) {433JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");434goto cleanup;435}436graphicsConfigs[ind]->awt_depth = pVITrue [i].depth;437memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVITrue [i],438sizeof (XVisualInfo));439if (xrenderFindVisualFormat != NULL) {440XRenderPictFormat *format = xrenderFindVisualFormat (awt_display,441pVITrue [i].visual);442if (format &&443format->type == PictTypeDirect &&444format->direct.alphaMask)445{446DTRACE_PRINTLN1("GraphicsConfig[%d] supports Translucency", ind);447graphicsConfigs [ind]->isTranslucencySupported = 1;448memcpy(&graphicsConfigs [ind]->renderPictFormat, format,449sizeof(*format));450} else {451DTRACE_PRINTLN1(format ?452"GraphicsConfig[%d] has no Translucency support" :453"Error calling 'XRenderFindVisualFormat'", ind);454}455}456}457458if (xrenderLibHandle != NULL) {459dlclose(xrenderLibHandle);460xrenderLibHandle = NULL;461}462463for (i = 0; i < n8p; i++) {464if (XVisualIDFromVisual(pVI8p[i].visual) ==465XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {466continue;467} else {468ind = nConfig++;469}470graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);471if (graphicsConfigs[ind] == NULL) {472JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");473goto cleanup;474}475graphicsConfigs[ind]->awt_depth = pVI8p [i].depth;476memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8p [i],477sizeof (XVisualInfo));478}479480for (i = 0; i < n12p; i++) {481if (XVisualIDFromVisual(pVI12p[i].visual) ==482XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {483continue;484} else {485ind = nConfig++;486}487graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);488if (graphicsConfigs[ind] == NULL) {489JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");490goto cleanup;491}492graphicsConfigs[ind]->awt_depth = pVI12p [i].depth;493memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI12p [i],494sizeof (XVisualInfo));495}496497for (i = 0; i < n8s; i++) {498if (XVisualIDFromVisual(pVI8s[i].visual) ==499XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {500continue;501} else {502ind = nConfig++;503}504graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);505if (graphicsConfigs[ind] == NULL) {506JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");507goto cleanup;508}509graphicsConfigs[ind]->awt_depth = pVI8s [i].depth;510memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8s [i],511sizeof (XVisualInfo));512}513514for (i = 0; i < n8gs; i++) {515if (XVisualIDFromVisual(pVI8gs[i].visual) ==516XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {517continue;518} else {519ind = nConfig++;520}521graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);522if (graphicsConfigs[ind] == NULL) {523JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");524goto cleanup;525}526graphicsConfigs[ind]->awt_depth = pVI8gs [i].depth;527memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8gs [i],528sizeof (XVisualInfo));529}530531for (i = 0; i < n8sg; i++) {532if (XVisualIDFromVisual(pVI8sg[i].visual) ==533XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {534continue;535} else {536ind = nConfig++;537}538graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);539if (graphicsConfigs[ind] == NULL) {540JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");541goto cleanup;542}543graphicsConfigs[ind]->awt_depth = pVI8sg [i].depth;544memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8sg [i],545sizeof (XVisualInfo));546}547548for (i = 0; i < n1sg; i++) {549if (XVisualIDFromVisual(pVI1sg[i].visual) ==550XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) {551continue;552} else {553ind = nConfig++;554}555graphicsConfigs[ind] = ZALLOC (_AwtGraphicsConfigData);556if (graphicsConfigs[ind] == NULL) {557JNU_ThrowOutOfMemoryError(env, "allocation in getAllConfigs failed");558goto cleanup;559}560graphicsConfigs[ind]->awt_depth = pVI1sg [i].depth;561memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI1sg [i],562sizeof (XVisualInfo));563}564565screenDataPtr->numConfigs = nConfig;566screenDataPtr->configs = graphicsConfigs;567568cleanup:569if (n8p != 0)570XFree (pVI8p);571if (n12p != 0)572XFree (pVI12p);573if (n8s != 0)574XFree (pVI8s);575if (n8gs != 0)576XFree (pVI8gs);577if (n8sg != 0)578XFree (pVI8sg);579if (n1sg != 0)580XFree (pVI1sg);581if (nTrue != 0)582XFree (pVITrue);583AWT_UNLOCK ();584}585586/*587* Checks if Xinerama is running and perform Xinerama-related initialization.588*/589static void xineramaInit(void) {590char* XinExtName = "XINERAMA";591int32_t major_opcode, first_event, first_error;592Bool gotXinExt = False;593void* libHandle = NULL;594char* XineramaQueryScreensName = "XineramaQueryScreens";595596gotXinExt = XQueryExtension(awt_display, XinExtName, &major_opcode,597&first_event, &first_error);598599if (!gotXinExt) {600DTRACE_PRINTLN("Xinerama extension is not available");601return;602}603604DTRACE_PRINTLN("Xinerama extension is available");605606/* load library */607libHandle = dlopen(VERSIONED_JNI_LIB_NAME("Xinerama", "1"),608RTLD_LAZY | RTLD_GLOBAL);609if (libHandle == NULL) {610#if defined(_AIX)611libHandle = dlopen("libXext.a(shr_64.o)", RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);612#else613libHandle = dlopen(JNI_LIB_NAME("Xinerama"), RTLD_LAZY | RTLD_GLOBAL);614#endif615}616if (libHandle != NULL) {617XineramaQueryScreens = (XineramaQueryScreensFunc*)618dlsym(libHandle, XineramaQueryScreensName);619620if (XineramaQueryScreens == NULL) {621DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol");622dlclose(libHandle);623}624} else {625DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());626}627}628629static void resetNativeData(int screen) {630/*631* Reset references to the various configs; the actual native config data632* will be free'd later by the Disposer mechanism when the Java-level633* X11GraphicsConfig objects go away. By setting these values to NULL,634* we ensure that they will be reinitialized as necessary (for example,635* see the getNumConfigs() method).636*/637if (x11Screens[screen].configs) {638free(x11Screens[screen].configs);639x11Screens[screen].configs = NULL;640}641x11Screens[screen].defaultConfig = NULL;642x11Screens[screen].numConfigs = 0;643}644645/*646* Class: sun_awt_X11GraphicsEnvironment647* Method: initDevices648* Signature: (Z)V649*/650JNIEXPORT void JNICALL651Java_sun_awt_X11GraphicsEnvironment_initNativeData(JNIEnv *env, jobject this) {652usingXinerama = False;653if (x11Screens) {654for (int i = 0; i < awt_numScreens; ++i) {655resetNativeData(i);656}657free((void *)x11Screens);658x11Screens = NULL;659awt_numScreens = 0;660}661662// will try xinerama first663if (XineramaQueryScreens) {664int32_t locNumScr = 0;665XineramaScreenInfo *xinInfo;666DTRACE_PRINTLN("calling XineramaQueryScreens func");667xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);668if (xinInfo != NULL) {669if (locNumScr > XScreenCount(awt_display)) {670DTRACE_PRINTLN("Enabling Xinerama support");671usingXinerama = True;672/* set global number of screens */673DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);674awt_numScreens = locNumScr;675} else {676DTRACE_PRINTLN("XineramaQueryScreens <= XScreenCount");677}678XFree(xinInfo);679} else {680DTRACE_PRINTLN("calling XineramaQueryScreens didn't work");681}682}683// if xinerama is not enabled or does not work will use X11684if (!usingXinerama) {685awt_numScreens = XScreenCount(awt_display);686}687DTRACE_PRINTLN1("allocating %i screens\n", awt_numScreens);688/* Allocate screen data structure array */689x11Screens = calloc(awt_numScreens, sizeof(AwtScreenData));690if (x11Screens == NULL) {691JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),692NULL);693return;694}695696for (int i = 0; i < awt_numScreens; i++) {697if (usingXinerama) {698/* All Xinerama screens use the same X11 root for now */699x11Screens[i].root = RootWindow(awt_display, 0);700}701else {702x11Screens[i].root = RootWindow(awt_display, i);703}704x11Screens[i].defaultConfig = makeDefaultConfig(env, i);705JNU_CHECK_EXCEPTION(env);706}707}708709Display *710awt_init_Display(JNIEnv *env, jobject this)711{712jclass klass;713Display *dpy;714char errmsg[128];715int i;716717if (awt_display) {718return awt_display;719}720721/* Load AWT lock-related methods in SunToolkit */722klass = (*env)->FindClass(env, "sun/awt/SunToolkit");723if (klass == NULL) return NULL;724GET_STATIC_METHOD(klass, awtLockMID, "awtLock", "()V");725GET_STATIC_METHOD(klass, awtUnlockMID, "awtUnlock", "()V");726GET_STATIC_METHOD(klass, awtWaitMID, "awtLockWait", "(J)V");727GET_STATIC_METHOD(klass, awtNotifyMID, "awtLockNotify", "()V");728GET_STATIC_METHOD(klass, awtNotifyAllMID, "awtLockNotifyAll", "()V");729tkClass = (*env)->NewGlobalRef(env, klass);730awtLockInited = JNI_TRUE;731732if (getenv("_AWT_IGNORE_XKB") != NULL &&733strlen(getenv("_AWT_IGNORE_XKB")) > 0) {734if (XkbIgnoreExtension(True)) {735printf("Ignoring XKB.\n");736}737}738739dpy = awt_display = XOpenDisplay(NULL);740if (!dpy) {741jio_snprintf(errmsg,742sizeof(errmsg),743"Can't connect to X11 window server using '%s' as the value of the DISPLAY variable.",744(getenv("DISPLAY") == NULL) ? ":0.0" : getenv("DISPLAY"));745JNU_ThrowByName(env, "java/awt/AWTError", errmsg);746return NULL;747}748749XSetIOErrorHandler(xioerror_handler);750JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "init", "(J)V",751ptr_to_jlong(awt_display));752JNU_CHECK_EXCEPTION_RETURN(env, NULL);753754/* set awt_numScreens, and whether or not we're using Xinerama */755xineramaInit();756return dpy;757}758759/*760* Class: sun_awt_X11GraphicsEnvironment761* Method: getDefaultScreenNum762* Signature: ()I763*/764JNIEXPORT jint JNICALL765Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum(766JNIEnv *env, jobject this)767{768return DefaultScreen(awt_display);769}770771static void ensureConfigsInited(JNIEnv* env, int screen) {772if (x11Screens[screen].numConfigs == 0) {773if (env == NULL) {774env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);775}776getAllConfigs (env, screen, &(x11Screens[screen]));777}778}779780AwtGraphicsConfigDataPtr781getDefaultConfig(int screen) {782ensureConfigsInited(NULL, screen);783return x11Screens[screen].defaultConfig;784}785786/*787* Class: sun_awt_X11GraphicsEnvironment788* Method: initDisplay789* Signature: (Z)V790*/791JNIEXPORT void JNICALL792Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv *env, jobject this,793jboolean glxReq)794{795glxRequested = glxReq;796(void) awt_init_Display(env, this);797}798799/*800* Class: sun_awt_X11GraphicsEnvironment801* Method: initGLX802* Signature: ()Z803*/804JNIEXPORT jboolean JNICALL805Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv *env, jclass x11ge)806{807jboolean glxAvailable;808809AWT_LOCK();810glxAvailable = GLXGC_IsGLXAvailable();811AWT_UNLOCK();812813return glxAvailable;814}815816/*817* Class: sun_awt_X11GraphicsEnvironment818* Method: getNumScreens819* Signature: ()I820*/821JNIEXPORT jint JNICALL822Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv *env, jobject this)823{824return awt_numScreens;825}826827/*828* Class: sun_awt_X11GraphicsDevice829* Method: getDisplay830* Signature: ()J831*/832JNIEXPORT jlong JNICALL833Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv *env, jobject this)834{835return ptr_to_jlong(awt_display);836}837838#ifdef MITSHM839840static jint canUseShmExt = UNSET_MITSHM;841static jint canUseShmExtPixmaps = UNSET_MITSHM;842static jboolean xshmAttachFailed = JNI_FALSE;843844int XShmAttachXErrHandler(Display *display, XErrorEvent *xerr) {845if (xerr->minor_code == X_ShmAttach) {846xshmAttachFailed = JNI_TRUE;847}848return 0;849}850jboolean isXShmAttachFailed() {851return xshmAttachFailed;852}853void resetXShmAttachFailed() {854xshmAttachFailed = JNI_FALSE;855}856857extern int mitShmPermissionMask;858859void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {860XShmSegmentInfo shminfo;861int XShmMajor, XShmMinor;862int a, b, c;863864AWT_LOCK();865if (canUseShmExt != UNSET_MITSHM) {866*shmExt = canUseShmExt;867*shmPixmaps = canUseShmExtPixmaps;868AWT_UNLOCK();869return;870}871872*shmExt = canUseShmExt = CANT_USE_MITSHM;873*shmPixmaps = canUseShmExtPixmaps = CANT_USE_MITSHM;874875if (awt_display == (Display *)NULL) {876AWT_NOFLUSH_UNLOCK();877return;878}879880/**881* XShmQueryExtension returns False in remote server case.882* Unfortunately it also returns True in ssh case, so883* we need to test that we can actually do XShmAttach.884*/885if (XShmQueryExtension(awt_display)) {886shminfo.shmid = shmget(IPC_PRIVATE, 0x10000,887IPC_CREAT|mitShmPermissionMask);888if (shminfo.shmid < 0) {889AWT_UNLOCK();890J2dRlsTraceLn1(J2D_TRACE_ERROR,891"TryInitMITShm: shmget has failed: %s",892strerror(errno));893return;894}895shminfo.shmaddr = (char *) shmat(shminfo.shmid, 0, 0);896if (shminfo.shmaddr == ((char *) -1)) {897shmctl(shminfo.shmid, IPC_RMID, 0);898AWT_UNLOCK();899J2dRlsTraceLn1(J2D_TRACE_ERROR,900"TryInitMITShm: shmat has failed: %s",901strerror(errno));902return;903}904shminfo.readOnly = True;905906resetXShmAttachFailed();907/**908* The J2DXErrHandler handler will set xshmAttachFailed909* to JNI_TRUE if any Shm error has occured.910*/911EXEC_WITH_XERROR_HANDLER(XShmAttachXErrHandler,912XShmAttach(awt_display, &shminfo));913914/**915* Get rid of the id now to reduce chances of leaking916* system resources.917*/918shmctl(shminfo.shmid, IPC_RMID, 0);919920if (isXShmAttachFailed() == JNI_FALSE) {921canUseShmExt = CAN_USE_MITSHM;922/* check if we can use shared pixmaps */923XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor,924(Bool*)&canUseShmExtPixmaps);925canUseShmExtPixmaps = canUseShmExtPixmaps &&926(XShmPixmapFormat(awt_display) == ZPixmap);927XShmDetach(awt_display, &shminfo);928}929shmdt(shminfo.shmaddr);930*shmExt = canUseShmExt;931*shmPixmaps = canUseShmExtPixmaps;932}933AWT_UNLOCK();934}935#endif /* MITSHM */936937/*938* Class: sun_awt_X11GraphicsEnvironment939* Method: checkShmExt940* Signature: ()I941*/942JNIEXPORT jint JNICALL943Java_sun_awt_X11GraphicsEnvironment_checkShmExt(JNIEnv *env, jobject this)944{945946int shmExt = NOEXT_MITSHM, shmPixmaps;947#ifdef MITSHM948TryInitMITShm(env, &shmExt, &shmPixmaps);949#endif950return shmExt;951}952953/*954* Class: sun_awt_X11GraphicsEnvironment955* Method: getDisplayString956* Signature: ()Ljava/lang/String957*/958JNIEXPORT jstring JNICALL959Java_sun_awt_X11GraphicsEnvironment_getDisplayString960(JNIEnv *env, jobject this)961{962return (*env)->NewStringUTF(env, DisplayString(awt_display));963}964965966/*967* Class: sun_awt_X11GraphicsDevice968* Method: getNumConfigs969* Signature: ()I970*/971JNIEXPORT jint JNICALL972Java_sun_awt_X11GraphicsDevice_getNumConfigs(973JNIEnv *env, jobject this, jint screen)974{975AWT_LOCK();976ensureConfigsInited(env, screen);977int configs = x11Screens[screen].numConfigs;978AWT_UNLOCK();979return configs;980}981982/*983* Class: sun_awt_X11GraphicsDevice984* Method: getConfigVisualId985* Signature: (I)I986*/987JNIEXPORT jint JNICALL988Java_sun_awt_X11GraphicsDevice_getConfigVisualId(989JNIEnv *env, jobject this, jint index, jint screen)990{991int visNum;992AWT_LOCK();993ensureConfigsInited(env, screen);994jint id = (jint) (index == 0 ? x11Screens[screen].defaultConfig995: x11Screens[screen].configs[index])->awt_visInfo.visualid;996AWT_UNLOCK();997return id;998}9991000/*1001* Class: sun_awt_X11GraphicsDevice1002* Method: getConfigDepth1003* Signature: (I)I1004*/1005JNIEXPORT jint JNICALL1006Java_sun_awt_X11GraphicsDevice_getConfigDepth(1007JNIEnv *env, jobject this, jint index, jint screen)1008{1009int visNum;1010AWT_LOCK();1011ensureConfigsInited(env, screen);1012jint depth = (jint) (index == 0 ? x11Screens[screen].defaultConfig1013: x11Screens[screen].configs[index])->awt_visInfo.depth;1014AWT_UNLOCK();1015return depth;1016}10171018/*1019* Class: sun_awt_X11GraphicsDevice1020* Method: getConfigColormap1021* Signature: (I)I1022*/1023JNIEXPORT jint JNICALL1024Java_sun_awt_X11GraphicsDevice_getConfigColormap(1025JNIEnv *env, jobject this, jint index, jint screen)1026{1027int visNum;1028AWT_LOCK();1029ensureConfigsInited(env, screen);1030jint colormap = (jint) (index == 0 ? x11Screens[screen].defaultConfig1031: x11Screens[screen].configs[index])->awt_cmap;1032AWT_UNLOCK();1033return colormap;1034}103510361037/*1038* Class: sun_awt_X11GraphicsConfig1039* Method: dispose1040* Signature: (J)V1041*/1042JNIEXPORT void JNICALL1043Java_sun_awt_X11GraphicsConfig_dispose1044(JNIEnv *env, jclass x11gc, jlong configData)1045{1046AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)1047jlong_to_ptr(configData);10481049if (aData == NULL) {1050return;1051}10521053AWT_LOCK();1054if (aData->awt_cmap) {1055XFreeColormap(awt_display, aData->awt_cmap);1056}1057if (aData->awtImage) {1058free(aData->awtImage);1059}1060if (aData->monoImage) {1061XFree(aData->monoImage);1062}1063if (aData->monoPixmap) {1064XFreePixmap(awt_display, aData->monoPixmap);1065}1066if (aData->monoPixmapGC) {1067XFreeGC(awt_display, aData->monoPixmapGC);1068}1069if (aData->color_data) {1070free(aData->color_data);1071}1072AWT_UNLOCK();10731074if (aData->glxInfo) {1075/*1076* The native GLXGraphicsConfig data needs to be disposed separately1077* on the OGL queue flushing thread (should not be called while1078* the AWT lock is held).1079*/1080JNU_CallStaticMethodByName(env, NULL,1081"sun/java2d/opengl/OGLRenderQueue",1082"disposeGraphicsConfig", "(J)V",1083ptr_to_jlong(aData->glxInfo));1084}10851086free(aData);1087}10881089/*1090* Class: sun_awt_X11GraphicsConfig1091* Method: getXResolution1092* Signature: ()I1093*/1094JNIEXPORT jdouble JNICALL1095Java_sun_awt_X11GraphicsConfig_getXResolution(1096JNIEnv *env, jobject this, jint screen)1097{1098return ((DisplayWidth(awt_display, screen) * 25.4) /1099DisplayWidthMM(awt_display, screen));1100}11011102/*1103* Class: sun_awt_X11GraphicsConfig1104* Method: getYResolution1105* Signature: ()I1106*/1107JNIEXPORT jdouble JNICALL1108Java_sun_awt_X11GraphicsConfig_getYResolution(1109JNIEnv *env, jobject this, jint screen)1110{1111return ((DisplayHeight(awt_display, screen) * 25.4) /1112DisplayHeightMM(awt_display, screen));1113}111411151116/*1117* Class: sun_awt_X11GraphicsConfig1118* Method: getNumColors1119* Signature: ()I1120*/1121JNIEXPORT jint JNICALL1122Java_sun_awt_X11GraphicsConfig_getNumColors(1123JNIEnv *env, jobject this)1124{1125AwtGraphicsConfigData *adata;11261127adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,1128x11GraphicsConfigIDs.aData);11291130return adata->awt_num_colors;1131}11321133/*1134* Class: sun_awt_X11GraphicsConfig1135* Method: init1136* Signature: (I)V1137*/1138JNIEXPORT void JNICALL1139Java_sun_awt_X11GraphicsConfig_init(1140JNIEnv *env, jobject this, jint visualNum, jint screen)1141{1142AwtGraphicsConfigData *adata = NULL;1143AWT_LOCK();1144AwtScreenData asd = x11Screens[screen];1145int i, n;1146int depth;1147XImage * tempImage;11481149/* If haven't gotten all of the configs yet, do it now. */1150if (asd.numConfigs == 0) {1151getAllConfigs (env, screen, &asd);1152}11531154/* Check the graphicsConfig for this visual */1155for (i = 0; i < asd.numConfigs; i++) {1156AwtGraphicsConfigDataPtr agcPtr = asd.configs[i];1157if ((jint)agcPtr->awt_visInfo.visualid == visualNum) {1158adata = agcPtr;1159break;1160}1161}11621163/* If didn't find the visual, throw an exception... */1164if (adata == (AwtGraphicsConfigData *) NULL) {1165AWT_UNLOCK();1166JNU_ThrowIllegalArgumentException(env, "Unknown Visual Specified");1167return;1168}11691170/* adata->awt_cmap initialization has been deferred to1171* makeColorModel call1172*/11731174JNU_SetLongFieldFromPtr(env, this, x11GraphicsConfigIDs.aData, adata);11751176depth = adata->awt_visInfo.depth;1177tempImage = XCreateImage(awt_display,1178adata->awt_visInfo.visual,1179depth, ZPixmap, 0, NULL, 1, 1, 32, 0);1180adata->pixelStride = (tempImage->bits_per_pixel + 7) / 8;1181(*env)->SetIntField(env, this, x11GraphicsConfigIDs.bitsPerPixel,1182(jint)tempImage->bits_per_pixel);1183XDestroyImage(tempImage);1184AWT_UNLOCK();1185}11861187/*1188* Class: sun_awt_X11GraphicsConfig1189* Method: makeColorModel1190* Signature: ()Ljava/awt/image/ColorModel1191*/1192JNIEXPORT jobject JNICALL1193Java_sun_awt_X11GraphicsConfig_makeColorModel(1194JNIEnv *env, jobject this)1195{1196AwtGraphicsConfigData *adata;1197jobject colorModel;11981199/*1200* If awt is not locked yet, return null since the toolkit is not1201* initialized yet.1202*/1203if (!awtLockInited) {1204return NULL;1205}12061207AWT_LOCK ();12081209adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,1210x11GraphicsConfigIDs.aData);12111212/* If colormap entry of adata is NULL, need to create it now */1213if (adata->awt_cmap == (Colormap) NULL) {1214awtJNI_CreateColorData (env, adata, 1);1215}12161217/* Make Color Model object for this GraphicsConfiguration */1218colorModel = (*env)->ExceptionCheck(env)1219? NULL : awtJNI_GetColorModel (env, adata);12201221AWT_UNLOCK ();12221223return colorModel;1224}122512261227/*1228* Class: sun_awt_X11GraphicsDevice1229* Method: getBounds1230* Signature: ()Ljava/awt/Rectangle1231*/1232JNIEXPORT jobject JNICALL1233Java_sun_awt_X11GraphicsDevice_pGetBounds(JNIEnv *env, jobject this, jint screen)1234{1235jclass clazz;1236jmethodID mid;1237jobject bounds = NULL;1238int32_t locNumScr = 0;1239XineramaScreenInfo *xinInfo;12401241clazz = (*env)->FindClass(env, "java/awt/Rectangle");1242CHECK_NULL_RETURN(clazz, NULL);1243mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V");1244if (mid != NULL) {1245if (usingXinerama) {1246if (0 <= screen && screen < awt_numScreens) {1247AWT_LOCK();1248xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);1249AWT_UNLOCK();1250if (xinInfo != NULL && locNumScr > 0) {1251if (screen >= locNumScr) {1252screen = 0; // fallback to the main screen1253}1254DASSERT(xinInfo[screen].screen_number == screen);1255bounds = (*env)->NewObject(env, clazz, mid,1256xinInfo[screen].x_org,1257xinInfo[screen].y_org,1258xinInfo[screen].width,1259xinInfo[screen].height);1260XFree(xinInfo);1261}1262} else {1263jclass exceptionClass = (*env)->FindClass(env, "java/lang/IllegalArgumentException");1264if (exceptionClass != NULL) {1265(*env)->ThrowNew(env, exceptionClass, "Illegal screen index");1266}1267}1268}1269if (!bounds) {1270// Xinerama cannot provide correct bounds, will try X111271XWindowAttributes xwa;1272memset(&xwa, 0, sizeof(xwa));12731274AWT_LOCK ();1275XGetWindowAttributes(awt_display, RootWindow(awt_display, screen),1276&xwa);1277AWT_UNLOCK ();12781279bounds = (*env)->NewObject(env, clazz, mid, 0, 0,1280xwa.width, xwa.height);1281}12821283if ((*env)->ExceptionOccurred(env)) {1284return NULL;1285}1286}1287return bounds;1288}12891290/*1291* Class: sun_awt_X11GraphicsConfig1292* Method: createBackBuffer1293* Signature: (JI)J1294*/1295JNIEXPORT jlong JNICALL1296Java_sun_awt_X11GraphicsConfig_createBackBuffer1297(JNIEnv *env, jobject this, jlong window, jint swapAction)1298{1299int32_t v1, v2;1300XdbeBackBuffer ret = (unsigned long) 0;1301Window w = (Window)window;1302AWT_LOCK();1303if (!XdbeQueryExtension(awt_display, &v1, &v2)) {1304JNU_ThrowByName(env, "java/lang/Exception",1305"Could not query double-buffer extension");1306AWT_UNLOCK();1307return (jlong)0;1308}1309ret = XdbeAllocateBackBufferName(awt_display, w,1310(XdbeSwapAction)swapAction);1311AWT_FLUSH_UNLOCK();1312return (jlong)ret;1313}13141315/*1316* Class: sun_awt_X11GraphicsConfig1317* Method: destroyBackBuffer1318* Signature: (J)V1319*/1320JNIEXPORT void JNICALL1321Java_sun_awt_X11GraphicsConfig_destroyBackBuffer1322(JNIEnv *env, jobject this, jlong backBuffer)1323{1324AWT_LOCK();1325XdbeDeallocateBackBufferName(awt_display, (XdbeBackBuffer)backBuffer);1326AWT_FLUSH_UNLOCK();1327}13281329/*1330* Class: sun_awt_X11GraphicsConfig1331* Method: swapBuffers1332* Signature: (JI)V1333*/1334JNIEXPORT void JNICALL1335Java_sun_awt_X11GraphicsConfig_swapBuffers1336(JNIEnv *env, jobject this,1337jlong window, jint swapAction)1338{1339XdbeSwapInfo swapInfo;13401341AWT_LOCK();13421343XdbeBeginIdiom(awt_display);1344swapInfo.swap_window = (Window)window;1345swapInfo.swap_action = (XdbeSwapAction)swapAction;1346if (!XdbeSwapBuffers(awt_display, &swapInfo, 1)) {1347JNU_ThrowInternalError(env, "Could not swap buffers");1348}1349XdbeEndIdiom(awt_display);13501351AWT_FLUSH_UNLOCK();1352}13531354/*1355* Class: sun_awt_X11GraphicsConfig1356* Method: isTranslucencyCapable1357* Signature: (J)V1358*/1359JNIEXPORT jboolean JNICALL1360Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable1361(JNIEnv *env, jobject this, jlong configData)1362{1363AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(configData);1364if (aData == NULL) {1365return JNI_FALSE;1366}1367return aData->isTranslucencySupported ? JNI_TRUE : JNI_FALSE;1368}13691370/*1371* Class: sun_awt_X11GraphicsDevice1372* Method: isDBESupported1373* Signature: ()Z1374*/1375JNIEXPORT jboolean JNICALL1376Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv *env, jobject this)1377{1378int opcode = 0, firstEvent = 0, firstError = 0;1379jboolean ret;13801381AWT_LOCK();1382ret = (jboolean)XQueryExtension(awt_display, "DOUBLE-BUFFER",1383&opcode, &firstEvent, &firstError);1384AWT_FLUSH_UNLOCK();1385return ret;1386}13871388/*1389* Class: sun_awt_X11GraphicsDevice1390* Method: getDoubleBufferVisuals1391* Signature: (I)V1392*/1393JNIEXPORT void JNICALL1394Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env,1395jobject this, jint screen)1396{1397jclass clazz;1398jmethodID midAddVisual;1399Window rootWindow;1400int i, n = 1;1401XdbeScreenVisualInfo* visScreenInfo;1402int xinawareScreen;14031404if (usingXinerama) {1405xinawareScreen = 0;1406}1407else {1408xinawareScreen = screen;1409}14101411clazz = (*env)->GetObjectClass(env, this);1412midAddVisual = (*env)->GetMethodID(env, clazz, "addDoubleBufferVisual",1413"(I)V");1414CHECK_NULL(midAddVisual);1415AWT_LOCK();1416rootWindow = RootWindow(awt_display, xinawareScreen);1417visScreenInfo = XdbeGetVisualInfo(awt_display, &rootWindow, &n);1418if (visScreenInfo == NULL) {1419JNU_ThrowInternalError(env, "Could not get visual info");1420AWT_UNLOCK();1421return;1422}1423AWT_FLUSH_UNLOCK();1424for (i = 0; i < visScreenInfo->count; i++) {1425XdbeVisualInfo* visInfo = visScreenInfo->visinfo;1426(*env)->CallVoidMethod(env, this, midAddVisual, (visInfo[i]).visual);1427if ((*env)->ExceptionCheck(env)) {1428break;1429}1430}1431AWT_LOCK();1432XdbeFreeVisualInfo(visScreenInfo);1433AWT_UNLOCK();1434}14351436/*1437* Class: sun_awt_X11GraphicsEnvironment1438* Method: pRunningXinerama1439* Signature: ()Z1440*/1441JNIEXPORT jboolean JNICALL1442Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv *env,1443jobject this)1444{1445return usingXinerama ? JNI_TRUE : JNI_FALSE;1446}14471448/**1449* Begin DisplayMode/FullScreen support1450*/14511452#ifndef NO_XRANDR14531454#define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI1455#define REFRESH_RATE_UNKNOWN java_awt_DisplayMode_REFRESH_RATE_UNKNOWN14561457typedef Status1458(*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp);1459typedef XRRScreenConfiguration*1460(*XRRGetScreenInfoType)(Display *dpy, Drawable root);1461typedef void1462(*XRRFreeScreenConfigInfoType)(XRRScreenConfiguration *config);1463typedef short*1464(*XRRConfigRatesType)(XRRScreenConfiguration *config,1465int sizeID, int *nrates);1466typedef short1467(*XRRConfigCurrentRateType)(XRRScreenConfiguration *config);1468typedef XRRScreenSize*1469(*XRRConfigSizesType)(XRRScreenConfiguration *config,1470int *nsizes);1471typedef SizeID1472(*XRRConfigCurrentConfigurationType)(XRRScreenConfiguration *config,1473Rotation *rotation);1474typedef Status1475(*XRRSetScreenConfigAndRateType)(Display *dpy,1476XRRScreenConfiguration *config,1477Drawable draw,1478int size_index,1479Rotation rotation,1480short rate,1481Time timestamp);1482typedef Rotation1483(*XRRConfigRotationsType)(XRRScreenConfiguration *config,1484Rotation *current_rotation);14851486typedef XRRScreenResources* (*XRRGetScreenResourcesType)(Display *dpy,1487Window window);14881489typedef void (*XRRFreeScreenResourcesType)(XRRScreenResources *resources);14901491typedef XRROutputInfo * (*XRRGetOutputInfoType)(Display *dpy,1492XRRScreenResources *resources, RROutput output);14931494typedef void (*XRRFreeOutputInfoType)(XRROutputInfo *outputInfo);14951496typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,1497XRRScreenResources *resources, RRCrtc crtc);14981499typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo);15001501static XRRQueryVersionType awt_XRRQueryVersion;1502static XRRGetScreenInfoType awt_XRRGetScreenInfo;1503static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo;1504static XRRConfigRatesType awt_XRRConfigRates;1505static XRRConfigCurrentRateType awt_XRRConfigCurrentRate;1506static XRRConfigSizesType awt_XRRConfigSizes;1507static XRRConfigCurrentConfigurationType awt_XRRConfigCurrentConfiguration;1508static XRRSetScreenConfigAndRateType awt_XRRSetScreenConfigAndRate;1509static XRRConfigRotationsType awt_XRRConfigRotations;1510static XRRGetScreenResourcesType awt_XRRGetScreenResources;1511static XRRFreeScreenResourcesType awt_XRRFreeScreenResources;1512static XRRGetOutputInfoType awt_XRRGetOutputInfo;1513static XRRFreeOutputInfoType awt_XRRFreeOutputInfo;1514static XRRGetCrtcInfoType awt_XRRGetCrtcInfo;1515static XRRFreeCrtcInfoType awt_XRRFreeCrtcInfo;15161517#define LOAD_XRANDR_FUNC(f) \1518do { \1519awt_##f = (f##Type)dlsym(pLibRandR, #f); \1520if (awt_##f == NULL) { \1521J2dRlsTraceLn1(J2D_TRACE_ERROR, \1522"X11GD_InitXrandrFuncs: Could not load %s", #f); \1523dlclose(pLibRandR); \1524return JNI_FALSE; \1525} \1526} while (0)15271528static jboolean1529X11GD_InitXrandrFuncs(JNIEnv *env)1530{1531int rr_maj_ver = 0, rr_min_ver = 0;15321533void *pLibRandR = dlopen(VERSIONED_JNI_LIB_NAME("Xrandr", "2"),1534RTLD_LAZY | RTLD_LOCAL);1535if (pLibRandR == NULL) {1536pLibRandR = dlopen(JNI_LIB_NAME("Xrandr"), RTLD_LAZY | RTLD_LOCAL);1537}1538if (pLibRandR == NULL) {1539J2dRlsTraceLn(J2D_TRACE_ERROR,1540"X11GD_InitXrandrFuncs: Could not open libXrandr.so.2");1541return JNI_FALSE;1542}15431544LOAD_XRANDR_FUNC(XRRQueryVersion);15451546if (!(*awt_XRRQueryVersion)(awt_display, &rr_maj_ver, &rr_min_ver)) {1547J2dRlsTraceLn(J2D_TRACE_ERROR,1548"X11GD_InitXrandrFuncs: XRRQueryVersion returned an error status");1549dlclose(pLibRandR);1550return JNI_FALSE;1551}15521553if (usingXinerama) {1554/*1555* We can proceed as long as this is RANDR 1.2 or above.1556* As of Xorg server 1.3 onwards the Xinerama backend may actually be1557* a fake one provided by RANDR itself. See Java bug 6636469 for info.1558*/1559if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) {1560J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "1561"Xinerama is active and Xrandr version is %d.%d",1562rr_maj_ver, rr_min_ver);1563dlclose(pLibRandR);1564return JNI_FALSE;1565}15661567/*1568* REMIND: Fullscreen mode doesn't work quite right with multi-monitor1569* setups and RANDR 1.2.1570*/1571if ((rr_maj_ver == 1 && rr_min_ver <= 2) && awt_numScreens > 1) {1572J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "1573"Multiple screens in use");1574dlclose(pLibRandR);1575return JNI_FALSE;1576}1577}15781579LOAD_XRANDR_FUNC(XRRGetScreenInfo);1580LOAD_XRANDR_FUNC(XRRFreeScreenConfigInfo);1581LOAD_XRANDR_FUNC(XRRConfigRates);1582LOAD_XRANDR_FUNC(XRRConfigCurrentRate);1583LOAD_XRANDR_FUNC(XRRConfigSizes);1584LOAD_XRANDR_FUNC(XRRConfigCurrentConfiguration);1585LOAD_XRANDR_FUNC(XRRSetScreenConfigAndRate);1586LOAD_XRANDR_FUNC(XRRConfigRotations);1587LOAD_XRANDR_FUNC(XRRGetScreenResources);1588LOAD_XRANDR_FUNC(XRRFreeScreenResources);1589LOAD_XRANDR_FUNC(XRRGetOutputInfo);1590LOAD_XRANDR_FUNC(XRRFreeOutputInfo);1591LOAD_XRANDR_FUNC(XRRGetCrtcInfo);1592LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);15931594return JNI_TRUE;1595}15961597static jobject1598X11GD_CreateDisplayMode(JNIEnv *env, jint width, jint height,1599jint bitDepth, jint refreshRate)1600{1601jclass displayModeClass;1602jmethodID cid;1603jint validRefreshRate = refreshRate;16041605displayModeClass = (*env)->FindClass(env, "java/awt/DisplayMode");1606CHECK_NULL_RETURN(displayModeClass, NULL);1607if (JNU_IsNull(env, displayModeClass)) {1608JNU_ThrowInternalError(env,1609"Could not get display mode class");1610return NULL;1611}16121613cid = (*env)->GetMethodID(env, displayModeClass, "<init>", "(IIII)V");1614CHECK_NULL_RETURN(cid, NULL);1615if (cid == NULL) {1616JNU_ThrowInternalError(env,1617"Could not get display mode constructor");1618return NULL;1619}16201621// early versions of xrandr may report "empty" rates (6880694)1622if (validRefreshRate <= 0) {1623validRefreshRate = REFRESH_RATE_UNKNOWN;1624}16251626return (*env)->NewObject(env, displayModeClass, cid,1627width, height, bitDepth, validRefreshRate);1628}16291630static void1631X11GD_AddDisplayMode(JNIEnv *env, jobject arrayList,1632jint width, jint height,1633jint bitDepth, jint refreshRate)1634{1635jobject displayMode = X11GD_CreateDisplayMode(env, width, height,1636bitDepth, refreshRate);1637if (!JNU_IsNull(env, displayMode)) {1638jclass arrayListClass;1639jmethodID mid;1640arrayListClass = (*env)->GetObjectClass(env, arrayList);1641if (JNU_IsNull(env, arrayListClass)) {1642JNU_ThrowInternalError(env,1643"Could not get class java.util.ArrayList");1644return;1645}1646mid = (*env)->GetMethodID(env, arrayListClass, "add",1647"(Ljava/lang/Object;)Z");1648CHECK_NULL(mid);1649if (mid == NULL) {1650JNU_ThrowInternalError(env,1651"Could not get method java.util.ArrayList.add()");1652return;1653}1654(*env)->CallObjectMethod(env, arrayList, mid, displayMode);1655(*env)->DeleteLocalRef(env, displayMode);1656}1657}16581659#endif /* !NO_XRANDR */16601661static void1662X11GD_SetFullscreenMode(Window win, jboolean enabled)1663{1664Atom wmState = XInternAtom(awt_display, "_NET_WM_STATE", False);1665Atom wmStateFs = XInternAtom(awt_display,1666"_NET_WM_STATE_FULLSCREEN", False);1667XWindowAttributes attr;1668XEvent event;16691670if (wmState == None || wmStateFs == None1671|| !XGetWindowAttributes(awt_display, win, &attr)) {1672return;1673}16741675memset(&event, 0, sizeof(event));1676event.xclient.type = ClientMessage;1677event.xclient.message_type = wmState;1678event.xclient.display = awt_display;1679event.xclient.window = win;1680event.xclient.format = 32;1681event.xclient.data.l[0] = enabled ? 1 : 0; // 1==add, 0==remove1682event.xclient.data.l[1] = wmStateFs;16831684XSendEvent(awt_display, attr.root, False,1685SubstructureRedirectMask | SubstructureNotifyMask,1686&event);1687XSync(awt_display, False);1688}16891690/*1691* Class: sun_awt_X11GraphicsDevice1692* Method: initXrandrExtension1693* Signature: ()Z1694*/1695JNIEXPORT jboolean JNICALL1696Java_sun_awt_X11GraphicsDevice_initXrandrExtension1697(JNIEnv *env, jclass x11gd)1698{1699#if defined(NO_XRANDR)1700return JNI_FALSE;1701#else1702int opcode = 0, firstEvent = 0, firstError = 0;1703jboolean ret;17041705AWT_LOCK();1706ret = (jboolean)XQueryExtension(awt_display, "RANDR",1707&opcode, &firstEvent, &firstError);1708if (ret) {1709ret = X11GD_InitXrandrFuncs(env);1710}1711AWT_FLUSH_UNLOCK();17121713return ret;1714#endif /* NO_XRANDR */1715}17161717/*1718* Class: sun_awt_X11GraphicsDevice1719* Method: getCurrentDisplayMode1720* Signature: (I)Ljava/awt/DisplayMode;1721*/1722JNIEXPORT jobject JNICALL1723Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode1724(JNIEnv* env, jclass x11gd, jint screen)1725{1726#if defined(NO_XRANDR)1727return NULL;1728#else1729XRRScreenConfiguration *config;1730jobject displayMode = NULL;17311732AWT_LOCK();17331734if (screen < ScreenCount(awt_display)) {17351736config = awt_XRRGetScreenInfo(awt_display,1737RootWindow(awt_display, screen));1738if (config != NULL) {1739Rotation rotation;1740short curRate;1741SizeID curSizeIndex;1742XRRScreenSize *sizes;1743int nsizes;17441745curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation);1746sizes = awt_XRRConfigSizes(config, &nsizes);1747curRate = awt_XRRConfigCurrentRate(config);17481749if ((sizes != NULL) &&1750(curSizeIndex < nsizes))1751{1752XRRScreenSize curSize = sizes[curSizeIndex];1753displayMode = X11GD_CreateDisplayMode(env,1754curSize.width,1755curSize.height,1756BIT_DEPTH_MULTI,1757curRate);1758}17591760awt_XRRFreeScreenConfigInfo(config);1761}1762}17631764AWT_FLUSH_UNLOCK();17651766return displayMode;1767#endif /* NO_XRANDR */1768}17691770/*1771* Class: sun_awt_X11GraphicsDevice1772* Method: enumDisplayModes1773* Signature: (ILjava/util/ArrayList;)V1774*/1775JNIEXPORT void JNICALL1776Java_sun_awt_X11GraphicsDevice_enumDisplayModes1777(JNIEnv* env, jclass x11gd,1778jint screen, jobject arrayList)1779{1780#if !defined(NO_XRANDR)17811782AWT_LOCK();17831784if (XScreenCount(awt_display) > 0) {17851786XRRScreenConfiguration *config;17871788config = awt_XRRGetScreenInfo(awt_display,1789RootWindow(awt_display, screen));1790if (config != NULL) {1791int nsizes, i, j;1792XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);17931794if (sizes != NULL) {1795for (i = 0; i < nsizes; i++) {1796int nrates;1797XRRScreenSize size = sizes[i];1798short *rates = awt_XRRConfigRates(config, i, &nrates);17991800for (j = 0; j < nrates; j++) {1801X11GD_AddDisplayMode(env, arrayList,1802size.width,1803size.height,1804BIT_DEPTH_MULTI,1805rates[j]);1806if ((*env)->ExceptionCheck(env)) {1807goto ret1;1808}1809}1810}1811}1812ret1:1813awt_XRRFreeScreenConfigInfo(config);1814}1815}18161817AWT_FLUSH_UNLOCK();1818#endif /* !NO_XRANDR */1819}18201821/*1822* Class: sun_awt_X11GraphicsDevice1823* Method: configDisplayMode1824* Signature: (IIII)V1825*/1826JNIEXPORT void JNICALL1827Java_sun_awt_X11GraphicsDevice_configDisplayMode1828(JNIEnv* env, jclass x11gd,1829jint screen, jint width, jint height, jint refreshRate)1830{1831#if !defined(NO_XRANDR)1832jboolean success = JNI_FALSE;1833XRRScreenConfiguration *config;1834Drawable root;1835Rotation currentRotation = RR_Rotate_0;18361837AWT_LOCK();18381839root = RootWindow(awt_display, screen);1840config = awt_XRRGetScreenInfo(awt_display, root);1841if (config != NULL) {1842jboolean foundConfig = JNI_FALSE;1843int chosenSizeIndex = -1;1844short chosenRate = -1;1845int nsizes;1846XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);1847awt_XRRConfigRotations(config, ¤tRotation);18481849if (sizes != NULL) {1850int i, j;18511852/* find the size index that matches the requested dimensions */1853for (i = 0; i < nsizes; i++) {1854XRRScreenSize size = sizes[i];18551856if ((size.width == width) && (size.height == height)) {1857/* we've found our size index... */1858int nrates;1859short *rates = awt_XRRConfigRates(config, i, &nrates);18601861/* now find rate that matches requested refresh rate */1862for (j = 0; j < nrates; j++) {1863if (rates[j] == refreshRate) {1864/* we've found our rate; break out of the loop */1865chosenSizeIndex = i;1866chosenRate = rates[j];1867foundConfig = JNI_TRUE;1868break;1869}1870}18711872break;1873}1874}1875}18761877if (foundConfig) {1878Status status =1879awt_XRRSetScreenConfigAndRate(awt_display, config, root,1880chosenSizeIndex,1881currentRotation,1882chosenRate,1883CurrentTime);18841885/* issue XSync to ensure immediate mode change */1886XSync(awt_display, False);18871888if (status == RRSetConfigSuccess) {1889success = JNI_TRUE;1890}1891}18921893awt_XRRFreeScreenConfigInfo(config);1894}18951896AWT_FLUSH_UNLOCK();18971898if (!success && !(*env)->ExceptionCheck(env)) {1899JNU_ThrowInternalError(env, "Could not set display mode");1900}1901#endif /* !NO_XRANDR */1902}19031904/*1905* Class: sun_awt_X11GraphicsDevice1906* Method: enterFullScreenExclusive1907* Signature: (J)V1908*/1909JNIEXPORT void JNICALL1910Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive1911(JNIEnv* env, jclass x11gd,1912jlong window)1913{1914Window win = (Window)window;19151916AWT_LOCK();1917XSync(awt_display, False); /* ensures window is visible first */1918X11GD_SetFullscreenMode(win, JNI_TRUE);1919AWT_UNLOCK();1920}19211922/*1923* Class: sun_awt_X11GraphicsDevice1924* Method: exitFullScreenExclusive1925* Signature: (J)V1926*/1927JNIEXPORT void JNICALL1928Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive1929(JNIEnv* env, jclass x11gd,1930jlong window)1931{1932Window win = (Window)window;19331934AWT_LOCK();1935X11GD_SetFullscreenMode(win, JNI_FALSE);1936AWT_UNLOCK();1937}19381939/**1940* End DisplayMode/FullScreen support1941*/19421943/*1944* Class: sun_awt_X11GraphicsDevice1945* Method: getNativeScaleFactor1946* Signature: (I)D1947*/1948JNIEXPORT jdouble JNICALL1949Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor1950(JNIEnv *env, jobject this, jint screen) {19511952return getNativeScaleFactor();1953}195419551956