Path: blob/master/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
41154 views
/*1* Copyright (c) 1997, 2021, 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);581582AWT_UNLOCK ();583}584585/*586* Checks if Xinerama is running and perform Xinerama-related initialization.587*/588static void xineramaInit(void) {589char* XinExtName = "XINERAMA";590int32_t major_opcode, first_event, first_error;591Bool gotXinExt = False;592void* libHandle = NULL;593char* XineramaQueryScreensName = "XineramaQueryScreens";594595gotXinExt = XQueryExtension(awt_display, XinExtName, &major_opcode,596&first_event, &first_error);597598if (!gotXinExt) {599DTRACE_PRINTLN("Xinerama extension is not available");600return;601}602603DTRACE_PRINTLN("Xinerama extension is available");604605/* load library */606libHandle = dlopen(VERSIONED_JNI_LIB_NAME("Xinerama", "1"),607RTLD_LAZY | RTLD_GLOBAL);608if (libHandle == NULL) {609#if defined(_AIX)610libHandle = dlopen("libXext.a(shr_64.o)", RTLD_MEMBER | RTLD_LAZY | RTLD_GLOBAL);611#else612libHandle = dlopen(JNI_LIB_NAME("Xinerama"), RTLD_LAZY | RTLD_GLOBAL);613#endif614}615if (libHandle != NULL) {616XineramaQueryScreens = (XineramaQueryScreensFunc*)617dlsym(libHandle, XineramaQueryScreensName);618619if (XineramaQueryScreens == NULL) {620DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol");621dlclose(libHandle);622}623} else {624DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror());625}626}627628static void resetNativeData(int screen) {629/*630* Reset references to the various configs; the actual native config data631* will be free'd later by the Disposer mechanism when the Java-level632* X11GraphicsConfig objects go away. By setting these values to NULL,633* we ensure that they will be reinitialized as necessary (for example,634* see the getNumConfigs() method).635*/636if (x11Screens[screen].configs) {637free(x11Screens[screen].configs);638x11Screens[screen].configs = NULL;639}640x11Screens[screen].defaultConfig = NULL;641x11Screens[screen].numConfigs = 0;642}643644/*645* Class: sun_awt_X11GraphicsEnvironment646* Method: initDevices647* Signature: (Z)V648*/649JNIEXPORT void JNICALL650Java_sun_awt_X11GraphicsEnvironment_initNativeData(JNIEnv *env, jobject this) {651usingXinerama = False;652if (x11Screens) {653for (int i = 0; i < awt_numScreens; ++i) {654resetNativeData(i);655}656free((void *)x11Screens);657x11Screens = NULL;658awt_numScreens = 0;659}660661// will try xinerama first662if (XineramaQueryScreens) {663int32_t locNumScr = 0;664XineramaScreenInfo *xinInfo;665DTRACE_PRINTLN("calling XineramaQueryScreens func");666xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);667if (xinInfo != NULL) {668if (locNumScr > XScreenCount(awt_display)) {669DTRACE_PRINTLN("Enabling Xinerama support");670usingXinerama = True;671/* set global number of screens */672DTRACE_PRINTLN1(" num screens = %i\n", locNumScr);673awt_numScreens = locNumScr;674} else {675DTRACE_PRINTLN("XineramaQueryScreens <= XScreenCount");676}677XFree(xinInfo);678} else {679DTRACE_PRINTLN("calling XineramaQueryScreens didn't work");680}681}682// if xinerama is not enabled or does not work will use X11683if (!usingXinerama) {684awt_numScreens = XScreenCount(awt_display);685}686DTRACE_PRINTLN1("allocating %i screens\n", awt_numScreens);687/* Allocate screen data structure array */688x11Screens = calloc(awt_numScreens, sizeof(AwtScreenData));689if (x11Screens == NULL) {690JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2),691NULL);692return;693}694695for (int i = 0; i < awt_numScreens; i++) {696if (usingXinerama) {697/* All Xinerama screens use the same X11 root for now */698x11Screens[i].root = RootWindow(awt_display, 0);699}700else {701x11Screens[i].root = RootWindow(awt_display, i);702}703x11Screens[i].defaultConfig = makeDefaultConfig(env, i);704JNU_CHECK_EXCEPTION(env);705}706}707708Display *709awt_init_Display(JNIEnv *env, jobject this)710{711jclass klass;712Display *dpy;713char errmsg[128];714int i;715716if (awt_display) {717return awt_display;718}719720/* Load AWT lock-related methods in SunToolkit */721klass = (*env)->FindClass(env, "sun/awt/SunToolkit");722if (klass == NULL) return NULL;723GET_STATIC_METHOD(klass, awtLockMID, "awtLock", "()V");724GET_STATIC_METHOD(klass, awtUnlockMID, "awtUnlock", "()V");725GET_STATIC_METHOD(klass, awtWaitMID, "awtLockWait", "(J)V");726GET_STATIC_METHOD(klass, awtNotifyMID, "awtLockNotify", "()V");727GET_STATIC_METHOD(klass, awtNotifyAllMID, "awtLockNotifyAll", "()V");728tkClass = (*env)->NewGlobalRef(env, klass);729awtLockInited = JNI_TRUE;730731if (getenv("_AWT_IGNORE_XKB") != NULL &&732strlen(getenv("_AWT_IGNORE_XKB")) > 0) {733if (XkbIgnoreExtension(True)) {734printf("Ignoring XKB.\n");735}736}737738dpy = awt_display = XOpenDisplay(NULL);739if (!dpy) {740jio_snprintf(errmsg,741sizeof(errmsg),742"Can't connect to X11 window server using '%s' as the value of the DISPLAY variable.",743(getenv("DISPLAY") == NULL) ? ":0.0" : getenv("DISPLAY"));744JNU_ThrowByName(env, "java/awt/AWTError", errmsg);745return NULL;746}747748XSetIOErrorHandler(xioerror_handler);749JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "init", "(J)V",750ptr_to_jlong(awt_display));751JNU_CHECK_EXCEPTION_RETURN(env, NULL);752753/* set awt_numScreens, and whether or not we're using Xinerama */754xineramaInit();755return dpy;756}757758/*759* Class: sun_awt_X11GraphicsEnvironment760* Method: getDefaultScreenNum761* Signature: ()I762*/763JNIEXPORT jint JNICALL764Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum(765JNIEnv *env, jobject this)766{767return DefaultScreen(awt_display);768}769770static void ensureConfigsInited(JNIEnv* env, int screen) {771if (x11Screens[screen].numConfigs == 0) {772if (env == NULL) {773env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);774}775getAllConfigs (env, screen, &(x11Screens[screen]));776}777}778779AwtGraphicsConfigDataPtr780getDefaultConfig(int screen) {781ensureConfigsInited(NULL, screen);782return x11Screens[screen].defaultConfig;783}784785/*786* Class: sun_awt_X11GraphicsEnvironment787* Method: initDisplay788* Signature: (Z)V789*/790JNIEXPORT void JNICALL791Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv *env, jobject this,792jboolean glxReq)793{794glxRequested = glxReq;795(void) awt_init_Display(env, this);796}797798/*799* Class: sun_awt_X11GraphicsEnvironment800* Method: initGLX801* Signature: ()Z802*/803JNIEXPORT jboolean JNICALL804Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv *env, jclass x11ge)805{806jboolean glxAvailable;807808AWT_LOCK();809glxAvailable = GLXGC_IsGLXAvailable();810AWT_UNLOCK();811812return glxAvailable;813}814815/*816* Class: sun_awt_X11GraphicsEnvironment817* Method: getNumScreens818* Signature: ()I819*/820JNIEXPORT jint JNICALL821Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv *env, jobject this)822{823return awt_numScreens;824}825826/*827* Class: sun_awt_X11GraphicsDevice828* Method: getDisplay829* Signature: ()J830*/831JNIEXPORT jlong JNICALL832Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv *env, jobject this)833{834return ptr_to_jlong(awt_display);835}836837#ifdef MITSHM838839static jint canUseShmExt = UNSET_MITSHM;840static jint canUseShmExtPixmaps = UNSET_MITSHM;841static jboolean xshmAttachFailed = JNI_FALSE;842843int XShmAttachXErrHandler(Display *display, XErrorEvent *xerr) {844if (xerr->minor_code == X_ShmAttach) {845xshmAttachFailed = JNI_TRUE;846}847return 0;848}849jboolean isXShmAttachFailed() {850return xshmAttachFailed;851}852void resetXShmAttachFailed() {853xshmAttachFailed = JNI_FALSE;854}855856extern int mitShmPermissionMask;857858void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) {859XShmSegmentInfo shminfo;860int XShmMajor, XShmMinor;861int a, b, c;862863AWT_LOCK();864if (canUseShmExt != UNSET_MITSHM) {865*shmExt = canUseShmExt;866*shmPixmaps = canUseShmExtPixmaps;867AWT_UNLOCK();868return;869}870871*shmExt = canUseShmExt = CANT_USE_MITSHM;872*shmPixmaps = canUseShmExtPixmaps = CANT_USE_MITSHM;873874if (awt_display == (Display *)NULL) {875AWT_NOFLUSH_UNLOCK();876return;877}878879/**880* XShmQueryExtension returns False in remote server case.881* Unfortunately it also returns True in ssh case, so882* we need to test that we can actually do XShmAttach.883*/884if (XShmQueryExtension(awt_display)) {885shminfo.shmid = shmget(IPC_PRIVATE, 0x10000,886IPC_CREAT|mitShmPermissionMask);887if (shminfo.shmid < 0) {888AWT_UNLOCK();889J2dRlsTraceLn1(J2D_TRACE_ERROR,890"TryInitMITShm: shmget has failed: %s",891strerror(errno));892return;893}894shminfo.shmaddr = (char *) shmat(shminfo.shmid, 0, 0);895if (shminfo.shmaddr == ((char *) -1)) {896shmctl(shminfo.shmid, IPC_RMID, 0);897AWT_UNLOCK();898J2dRlsTraceLn1(J2D_TRACE_ERROR,899"TryInitMITShm: shmat has failed: %s",900strerror(errno));901return;902}903shminfo.readOnly = True;904905resetXShmAttachFailed();906/**907* The J2DXErrHandler handler will set xshmAttachFailed908* to JNI_TRUE if any Shm error has occured.909*/910EXEC_WITH_XERROR_HANDLER(XShmAttachXErrHandler,911XShmAttach(awt_display, &shminfo));912913/**914* Get rid of the id now to reduce chances of leaking915* system resources.916*/917shmctl(shminfo.shmid, IPC_RMID, 0);918919if (isXShmAttachFailed() == JNI_FALSE) {920canUseShmExt = CAN_USE_MITSHM;921/* check if we can use shared pixmaps */922XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor,923(Bool*)&canUseShmExtPixmaps);924canUseShmExtPixmaps = canUseShmExtPixmaps &&925(XShmPixmapFormat(awt_display) == ZPixmap);926XShmDetach(awt_display, &shminfo);927}928shmdt(shminfo.shmaddr);929*shmExt = canUseShmExt;930*shmPixmaps = canUseShmExtPixmaps;931}932AWT_UNLOCK();933}934#endif /* MITSHM */935936/*937* Class: sun_awt_X11GraphicsEnvironment938* Method: checkShmExt939* Signature: ()I940*/941JNIEXPORT jint JNICALL942Java_sun_awt_X11GraphicsEnvironment_checkShmExt(JNIEnv *env, jobject this)943{944945int shmExt = NOEXT_MITSHM, shmPixmaps;946#ifdef MITSHM947TryInitMITShm(env, &shmExt, &shmPixmaps);948#endif949return shmExt;950}951952/*953* Class: sun_awt_X11GraphicsEnvironment954* Method: getDisplayString955* Signature: ()Ljava/lang/String956*/957JNIEXPORT jstring JNICALL958Java_sun_awt_X11GraphicsEnvironment_getDisplayString959(JNIEnv *env, jobject this)960{961return (*env)->NewStringUTF(env, DisplayString(awt_display));962}963964965/*966* Class: sun_awt_X11GraphicsDevice967* Method: getNumConfigs968* Signature: ()I969*/970JNIEXPORT jint JNICALL971Java_sun_awt_X11GraphicsDevice_getNumConfigs(972JNIEnv *env, jobject this, jint screen)973{974AWT_LOCK();975ensureConfigsInited(env, screen);976int configs = x11Screens[screen].numConfigs;977AWT_UNLOCK();978return configs;979}980981/*982* Class: sun_awt_X11GraphicsDevice983* Method: getConfigVisualId984* Signature: (I)I985*/986JNIEXPORT jint JNICALL987Java_sun_awt_X11GraphicsDevice_getConfigVisualId(988JNIEnv *env, jobject this, jint index, jint screen)989{990int visNum;991AWT_LOCK();992ensureConfigsInited(env, screen);993jint id = (jint) (index == 0 ? x11Screens[screen].defaultConfig994: x11Screens[screen].configs[index])->awt_visInfo.visualid;995AWT_UNLOCK();996return id;997}998999/*1000* Class: sun_awt_X11GraphicsDevice1001* Method: getConfigDepth1002* Signature: (I)I1003*/1004JNIEXPORT jint JNICALL1005Java_sun_awt_X11GraphicsDevice_getConfigDepth(1006JNIEnv *env, jobject this, jint index, jint screen)1007{1008int visNum;1009AWT_LOCK();1010ensureConfigsInited(env, screen);1011jint depth = (jint) (index == 0 ? x11Screens[screen].defaultConfig1012: x11Screens[screen].configs[index])->awt_visInfo.depth;1013AWT_UNLOCK();1014return depth;1015}10161017/*1018* Class: sun_awt_X11GraphicsDevice1019* Method: getConfigColormap1020* Signature: (I)I1021*/1022JNIEXPORT jint JNICALL1023Java_sun_awt_X11GraphicsDevice_getConfigColormap(1024JNIEnv *env, jobject this, jint index, jint screen)1025{1026int visNum;1027AWT_LOCK();1028ensureConfigsInited(env, screen);1029jint colormap = (jint) (index == 0 ? x11Screens[screen].defaultConfig1030: x11Screens[screen].configs[index])->awt_cmap;1031AWT_UNLOCK();1032return colormap;1033}103410351036/*1037* Class: sun_awt_X11GraphicsConfig1038* Method: dispose1039* Signature: (J)V1040*/1041JNIEXPORT void JNICALL1042Java_sun_awt_X11GraphicsConfig_dispose1043(JNIEnv *env, jclass x11gc, jlong configData)1044{1045AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)1046jlong_to_ptr(configData);10471048if (aData == NULL) {1049return;1050}10511052AWT_LOCK();1053if (aData->awt_cmap) {1054XFreeColormap(awt_display, aData->awt_cmap);1055}1056if (aData->awtImage) {1057free(aData->awtImage);1058}1059if (aData->monoImage) {1060XFree(aData->monoImage);1061}1062if (aData->monoPixmap) {1063XFreePixmap(awt_display, aData->monoPixmap);1064}1065if (aData->monoPixmapGC) {1066XFreeGC(awt_display, aData->monoPixmapGC);1067}1068if (aData->color_data) {1069free(aData->color_data);1070}1071AWT_UNLOCK();10721073if (aData->glxInfo) {1074/*1075* The native GLXGraphicsConfig data needs to be disposed separately1076* on the OGL queue flushing thread (should not be called while1077* the AWT lock is held).1078*/1079JNU_CallStaticMethodByName(env, NULL,1080"sun/java2d/opengl/OGLRenderQueue",1081"disposeGraphicsConfig", "(J)V",1082ptr_to_jlong(aData->glxInfo));1083}10841085free(aData);1086}10871088/*1089* Class: sun_awt_X11GraphicsConfig1090* Method: getXResolution1091* Signature: ()I1092*/1093JNIEXPORT jdouble JNICALL1094Java_sun_awt_X11GraphicsConfig_getXResolution(1095JNIEnv *env, jobject this, jint screen)1096{1097return ((DisplayWidth(awt_display, screen) * 25.4) /1098DisplayWidthMM(awt_display, screen));1099}11001101/*1102* Class: sun_awt_X11GraphicsConfig1103* Method: getYResolution1104* Signature: ()I1105*/1106JNIEXPORT jdouble JNICALL1107Java_sun_awt_X11GraphicsConfig_getYResolution(1108JNIEnv *env, jobject this, jint screen)1109{1110return ((DisplayHeight(awt_display, screen) * 25.4) /1111DisplayHeightMM(awt_display, screen));1112}111311141115/*1116* Class: sun_awt_X11GraphicsConfig1117* Method: getNumColors1118* Signature: ()I1119*/1120JNIEXPORT jint JNICALL1121Java_sun_awt_X11GraphicsConfig_getNumColors(1122JNIEnv *env, jobject this)1123{1124AwtGraphicsConfigData *adata;11251126adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,1127x11GraphicsConfigIDs.aData);11281129return adata->awt_num_colors;1130}11311132/*1133* Class: sun_awt_X11GraphicsConfig1134* Method: init1135* Signature: (I)V1136*/1137JNIEXPORT void JNICALL1138Java_sun_awt_X11GraphicsConfig_init(1139JNIEnv *env, jobject this, jint visualNum, jint screen)1140{1141AwtGraphicsConfigData *adata = NULL;1142AWT_LOCK();1143AwtScreenData asd = x11Screens[screen];1144int i, n;1145int depth;1146XImage * tempImage;11471148/* If haven't gotten all of the configs yet, do it now. */1149if (asd.numConfigs == 0) {1150getAllConfigs (env, screen, &asd);1151}11521153/* Check the graphicsConfig for this visual */1154for (i = 0; i < asd.numConfigs; i++) {1155AwtGraphicsConfigDataPtr agcPtr = asd.configs[i];1156if ((jint)agcPtr->awt_visInfo.visualid == visualNum) {1157adata = agcPtr;1158break;1159}1160}11611162/* If didn't find the visual, throw an exception... */1163if (adata == (AwtGraphicsConfigData *) NULL) {1164AWT_UNLOCK();1165JNU_ThrowIllegalArgumentException(env, "Unknown Visual Specified");1166return;1167}11681169/* adata->awt_cmap initialization has been deferred to1170* makeColorModel call1171*/11721173JNU_SetLongFieldFromPtr(env, this, x11GraphicsConfigIDs.aData, adata);11741175depth = adata->awt_visInfo.depth;1176tempImage = XCreateImage(awt_display,1177adata->awt_visInfo.visual,1178depth, ZPixmap, 0, NULL, 1, 1, 32, 0);1179adata->pixelStride = (tempImage->bits_per_pixel + 7) / 8;1180(*env)->SetIntField(env, this, x11GraphicsConfigIDs.bitsPerPixel,1181(jint)tempImage->bits_per_pixel);1182XDestroyImage(tempImage);1183AWT_UNLOCK();1184}11851186/*1187* Class: sun_awt_X11GraphicsConfig1188* Method: makeColorModel1189* Signature: ()Ljava/awt/image/ColorModel1190*/1191JNIEXPORT jobject JNICALL1192Java_sun_awt_X11GraphicsConfig_makeColorModel(1193JNIEnv *env, jobject this)1194{1195AwtGraphicsConfigData *adata;1196jobject colorModel;11971198/*1199* If awt is not locked yet, return null since the toolkit is not1200* initialized yet.1201*/1202if (!awtLockInited) {1203return NULL;1204}12051206AWT_LOCK ();12071208adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this,1209x11GraphicsConfigIDs.aData);12101211/* If colormap entry of adata is NULL, need to create it now */1212if (adata->awt_cmap == (Colormap) NULL) {1213awtJNI_CreateColorData (env, adata, 1);1214}12151216/* Make Color Model object for this GraphicsConfiguration */1217colorModel = (*env)->ExceptionCheck(env)1218? NULL : awtJNI_GetColorModel (env, adata);12191220AWT_UNLOCK ();12211222return colorModel;1223}122412251226/*1227* Class: sun_awt_X11GraphicsDevice1228* Method: getBounds1229* Signature: ()Ljava/awt/Rectangle1230*/1231JNIEXPORT jobject JNICALL1232Java_sun_awt_X11GraphicsDevice_pGetBounds(JNIEnv *env, jobject this, jint screen)1233{1234jclass clazz;1235jmethodID mid;1236jobject bounds = NULL;1237int32_t locNumScr = 0;1238XineramaScreenInfo *xinInfo;12391240clazz = (*env)->FindClass(env, "java/awt/Rectangle");1241CHECK_NULL_RETURN(clazz, NULL);1242mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V");1243if (mid != NULL) {1244if (usingXinerama) {1245if (0 <= screen && screen < awt_numScreens) {1246AWT_LOCK();1247xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);1248AWT_UNLOCK();1249if (xinInfo != NULL && locNumScr > 0) {1250if (screen >= locNumScr) {1251screen = 0; // fallback to the main screen1252}1253DASSERT(xinInfo[screen].screen_number == screen);1254bounds = (*env)->NewObject(env, clazz, mid,1255xinInfo[screen].x_org,1256xinInfo[screen].y_org,1257xinInfo[screen].width,1258xinInfo[screen].height);1259XFree(xinInfo);1260}1261} else {1262jclass exceptionClass = (*env)->FindClass(env, "java/lang/IllegalArgumentException");1263if (exceptionClass != NULL) {1264(*env)->ThrowNew(env, exceptionClass, "Illegal screen index");1265}1266}1267}1268if (!bounds) {1269// Xinerama cannot provide correct bounds, will try X111270XWindowAttributes xwa;1271memset(&xwa, 0, sizeof(xwa));12721273AWT_LOCK ();1274XGetWindowAttributes(awt_display, RootWindow(awt_display, screen),1275&xwa);1276AWT_UNLOCK ();12771278bounds = (*env)->NewObject(env, clazz, mid, 0, 0,1279xwa.width, xwa.height);1280}12811282if ((*env)->ExceptionOccurred(env)) {1283return NULL;1284}1285}1286return bounds;1287}12881289/*1290* Class: sun_awt_X11GraphicsConfig1291* Method: createBackBuffer1292* Signature: (JI)J1293*/1294JNIEXPORT jlong JNICALL1295Java_sun_awt_X11GraphicsConfig_createBackBuffer1296(JNIEnv *env, jobject this, jlong window, jint swapAction)1297{1298int32_t v1, v2;1299XdbeBackBuffer ret = (unsigned long) 0;1300Window w = (Window)window;1301AWT_LOCK();1302if (!XdbeQueryExtension(awt_display, &v1, &v2)) {1303JNU_ThrowByName(env, "java/lang/Exception",1304"Could not query double-buffer extension");1305AWT_UNLOCK();1306return (jlong)0;1307}1308ret = XdbeAllocateBackBufferName(awt_display, w,1309(XdbeSwapAction)swapAction);1310AWT_FLUSH_UNLOCK();1311return (jlong)ret;1312}13131314/*1315* Class: sun_awt_X11GraphicsConfig1316* Method: destroyBackBuffer1317* Signature: (J)V1318*/1319JNIEXPORT void JNICALL1320Java_sun_awt_X11GraphicsConfig_destroyBackBuffer1321(JNIEnv *env, jobject this, jlong backBuffer)1322{1323AWT_LOCK();1324XdbeDeallocateBackBufferName(awt_display, (XdbeBackBuffer)backBuffer);1325AWT_FLUSH_UNLOCK();1326}13271328/*1329* Class: sun_awt_X11GraphicsConfig1330* Method: swapBuffers1331* Signature: (JI)V1332*/1333JNIEXPORT void JNICALL1334Java_sun_awt_X11GraphicsConfig_swapBuffers1335(JNIEnv *env, jobject this,1336jlong window, jint swapAction)1337{1338XdbeSwapInfo swapInfo;13391340AWT_LOCK();13411342XdbeBeginIdiom(awt_display);1343swapInfo.swap_window = (Window)window;1344swapInfo.swap_action = (XdbeSwapAction)swapAction;1345if (!XdbeSwapBuffers(awt_display, &swapInfo, 1)) {1346JNU_ThrowInternalError(env, "Could not swap buffers");1347}1348XdbeEndIdiom(awt_display);13491350AWT_FLUSH_UNLOCK();1351}13521353/*1354* Class: sun_awt_X11GraphicsConfig1355* Method: isTranslucencyCapable1356* Signature: (J)V1357*/1358JNIEXPORT jboolean JNICALL1359Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable1360(JNIEnv *env, jobject this, jlong configData)1361{1362AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(configData);1363if (aData == NULL) {1364return JNI_FALSE;1365}1366return aData->isTranslucencySupported ? JNI_TRUE : JNI_FALSE;1367}13681369/*1370* Class: sun_awt_X11GraphicsDevice1371* Method: isDBESupported1372* Signature: ()Z1373*/1374JNIEXPORT jboolean JNICALL1375Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv *env, jobject this)1376{1377int opcode = 0, firstEvent = 0, firstError = 0;1378jboolean ret;13791380AWT_LOCK();1381ret = (jboolean)XQueryExtension(awt_display, "DOUBLE-BUFFER",1382&opcode, &firstEvent, &firstError);1383AWT_FLUSH_UNLOCK();1384return ret;1385}13861387/*1388* Class: sun_awt_X11GraphicsDevice1389* Method: getDoubleBufferVisuals1390* Signature: (I)V1391*/1392JNIEXPORT void JNICALL1393Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env,1394jobject this, jint screen)1395{1396jclass clazz;1397jmethodID midAddVisual;1398Window rootWindow;1399int i, n = 1;1400XdbeScreenVisualInfo* visScreenInfo;1401int xinawareScreen;14021403if (usingXinerama) {1404xinawareScreen = 0;1405}1406else {1407xinawareScreen = screen;1408}14091410clazz = (*env)->GetObjectClass(env, this);1411midAddVisual = (*env)->GetMethodID(env, clazz, "addDoubleBufferVisual",1412"(I)V");1413CHECK_NULL(midAddVisual);1414AWT_LOCK();1415rootWindow = RootWindow(awt_display, xinawareScreen);1416visScreenInfo = XdbeGetVisualInfo(awt_display, &rootWindow, &n);1417if (visScreenInfo == NULL) {1418JNU_ThrowInternalError(env, "Could not get visual info");1419AWT_UNLOCK();1420return;1421}1422AWT_FLUSH_UNLOCK();1423for (i = 0; i < visScreenInfo->count; i++) {1424XdbeVisualInfo* visInfo = visScreenInfo->visinfo;1425(*env)->CallVoidMethod(env, this, midAddVisual, (visInfo[i]).visual);1426if ((*env)->ExceptionCheck(env)) {1427break;1428}1429}1430}14311432/*1433* Class: sun_awt_X11GraphicsEnvironment1434* Method: pRunningXinerama1435* Signature: ()Z1436*/1437JNIEXPORT jboolean JNICALL1438Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv *env,1439jobject this)1440{1441return usingXinerama ? JNI_TRUE : JNI_FALSE;1442}14431444/**1445* Begin DisplayMode/FullScreen support1446*/14471448#ifndef NO_XRANDR14491450#define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI1451#define REFRESH_RATE_UNKNOWN java_awt_DisplayMode_REFRESH_RATE_UNKNOWN14521453typedef Status1454(*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp);1455typedef XRRScreenConfiguration*1456(*XRRGetScreenInfoType)(Display *dpy, Drawable root);1457typedef void1458(*XRRFreeScreenConfigInfoType)(XRRScreenConfiguration *config);1459typedef short*1460(*XRRConfigRatesType)(XRRScreenConfiguration *config,1461int sizeID, int *nrates);1462typedef short1463(*XRRConfigCurrentRateType)(XRRScreenConfiguration *config);1464typedef XRRScreenSize*1465(*XRRConfigSizesType)(XRRScreenConfiguration *config,1466int *nsizes);1467typedef SizeID1468(*XRRConfigCurrentConfigurationType)(XRRScreenConfiguration *config,1469Rotation *rotation);1470typedef Status1471(*XRRSetScreenConfigAndRateType)(Display *dpy,1472XRRScreenConfiguration *config,1473Drawable draw,1474int size_index,1475Rotation rotation,1476short rate,1477Time timestamp);1478typedef Rotation1479(*XRRConfigRotationsType)(XRRScreenConfiguration *config,1480Rotation *current_rotation);14811482typedef XRRScreenResources* (*XRRGetScreenResourcesType)(Display *dpy,1483Window window);14841485typedef void (*XRRFreeScreenResourcesType)(XRRScreenResources *resources);14861487typedef XRROutputInfo * (*XRRGetOutputInfoType)(Display *dpy,1488XRRScreenResources *resources, RROutput output);14891490typedef void (*XRRFreeOutputInfoType)(XRROutputInfo *outputInfo);14911492typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,1493XRRScreenResources *resources, RRCrtc crtc);14941495typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo);14961497static XRRQueryVersionType awt_XRRQueryVersion;1498static XRRGetScreenInfoType awt_XRRGetScreenInfo;1499static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo;1500static XRRConfigRatesType awt_XRRConfigRates;1501static XRRConfigCurrentRateType awt_XRRConfigCurrentRate;1502static XRRConfigSizesType awt_XRRConfigSizes;1503static XRRConfigCurrentConfigurationType awt_XRRConfigCurrentConfiguration;1504static XRRSetScreenConfigAndRateType awt_XRRSetScreenConfigAndRate;1505static XRRConfigRotationsType awt_XRRConfigRotations;1506static XRRGetScreenResourcesType awt_XRRGetScreenResources;1507static XRRFreeScreenResourcesType awt_XRRFreeScreenResources;1508static XRRGetOutputInfoType awt_XRRGetOutputInfo;1509static XRRFreeOutputInfoType awt_XRRFreeOutputInfo;1510static XRRGetCrtcInfoType awt_XRRGetCrtcInfo;1511static XRRFreeCrtcInfoType awt_XRRFreeCrtcInfo;15121513#define LOAD_XRANDR_FUNC(f) \1514do { \1515awt_##f = (f##Type)dlsym(pLibRandR, #f); \1516if (awt_##f == NULL) { \1517J2dRlsTraceLn1(J2D_TRACE_ERROR, \1518"X11GD_InitXrandrFuncs: Could not load %s", #f); \1519dlclose(pLibRandR); \1520return JNI_FALSE; \1521} \1522} while (0)15231524static jboolean1525X11GD_InitXrandrFuncs(JNIEnv *env)1526{1527int rr_maj_ver = 0, rr_min_ver = 0;15281529void *pLibRandR = dlopen(VERSIONED_JNI_LIB_NAME("Xrandr", "2"),1530RTLD_LAZY | RTLD_LOCAL);1531if (pLibRandR == NULL) {1532pLibRandR = dlopen(JNI_LIB_NAME("Xrandr"), RTLD_LAZY | RTLD_LOCAL);1533}1534if (pLibRandR == NULL) {1535J2dRlsTraceLn(J2D_TRACE_ERROR,1536"X11GD_InitXrandrFuncs: Could not open libXrandr.so.2");1537return JNI_FALSE;1538}15391540LOAD_XRANDR_FUNC(XRRQueryVersion);15411542if (!(*awt_XRRQueryVersion)(awt_display, &rr_maj_ver, &rr_min_ver)) {1543J2dRlsTraceLn(J2D_TRACE_ERROR,1544"X11GD_InitXrandrFuncs: XRRQueryVersion returned an error status");1545dlclose(pLibRandR);1546return JNI_FALSE;1547}15481549if (usingXinerama) {1550/*1551* We can proceed as long as this is RANDR 1.2 or above.1552* As of Xorg server 1.3 onwards the Xinerama backend may actually be1553* a fake one provided by RANDR itself. See Java bug 6636469 for info.1554*/1555if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) {1556J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "1557"Xinerama is active and Xrandr version is %d.%d",1558rr_maj_ver, rr_min_ver);1559dlclose(pLibRandR);1560return JNI_FALSE;1561}15621563/*1564* REMIND: Fullscreen mode doesn't work quite right with multi-monitor1565* setups and RANDR 1.2.1566*/1567if ((rr_maj_ver == 1 && rr_min_ver <= 2) && awt_numScreens > 1) {1568J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. "1569"Multiple screens in use");1570dlclose(pLibRandR);1571return JNI_FALSE;1572}1573}15741575LOAD_XRANDR_FUNC(XRRGetScreenInfo);1576LOAD_XRANDR_FUNC(XRRFreeScreenConfigInfo);1577LOAD_XRANDR_FUNC(XRRConfigRates);1578LOAD_XRANDR_FUNC(XRRConfigCurrentRate);1579LOAD_XRANDR_FUNC(XRRConfigSizes);1580LOAD_XRANDR_FUNC(XRRConfigCurrentConfiguration);1581LOAD_XRANDR_FUNC(XRRSetScreenConfigAndRate);1582LOAD_XRANDR_FUNC(XRRConfigRotations);1583LOAD_XRANDR_FUNC(XRRGetScreenResources);1584LOAD_XRANDR_FUNC(XRRFreeScreenResources);1585LOAD_XRANDR_FUNC(XRRGetOutputInfo);1586LOAD_XRANDR_FUNC(XRRFreeOutputInfo);1587LOAD_XRANDR_FUNC(XRRGetCrtcInfo);1588LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);15891590return JNI_TRUE;1591}15921593static jobject1594X11GD_CreateDisplayMode(JNIEnv *env, jint width, jint height,1595jint bitDepth, jint refreshRate)1596{1597jclass displayModeClass;1598jmethodID cid;1599jint validRefreshRate = refreshRate;16001601displayModeClass = (*env)->FindClass(env, "java/awt/DisplayMode");1602CHECK_NULL_RETURN(displayModeClass, NULL);1603if (JNU_IsNull(env, displayModeClass)) {1604JNU_ThrowInternalError(env,1605"Could not get display mode class");1606return NULL;1607}16081609cid = (*env)->GetMethodID(env, displayModeClass, "<init>", "(IIII)V");1610CHECK_NULL_RETURN(cid, NULL);1611if (cid == NULL) {1612JNU_ThrowInternalError(env,1613"Could not get display mode constructor");1614return NULL;1615}16161617// early versions of xrandr may report "empty" rates (6880694)1618if (validRefreshRate <= 0) {1619validRefreshRate = REFRESH_RATE_UNKNOWN;1620}16211622return (*env)->NewObject(env, displayModeClass, cid,1623width, height, bitDepth, validRefreshRate);1624}16251626static void1627X11GD_AddDisplayMode(JNIEnv *env, jobject arrayList,1628jint width, jint height,1629jint bitDepth, jint refreshRate)1630{1631jobject displayMode = X11GD_CreateDisplayMode(env, width, height,1632bitDepth, refreshRate);1633if (!JNU_IsNull(env, displayMode)) {1634jclass arrayListClass;1635jmethodID mid;1636arrayListClass = (*env)->GetObjectClass(env, arrayList);1637if (JNU_IsNull(env, arrayListClass)) {1638JNU_ThrowInternalError(env,1639"Could not get class java.util.ArrayList");1640return;1641}1642mid = (*env)->GetMethodID(env, arrayListClass, "add",1643"(Ljava/lang/Object;)Z");1644CHECK_NULL(mid);1645if (mid == NULL) {1646JNU_ThrowInternalError(env,1647"Could not get method java.util.ArrayList.add()");1648return;1649}1650(*env)->CallObjectMethod(env, arrayList, mid, displayMode);1651(*env)->DeleteLocalRef(env, displayMode);1652}1653}16541655#endif /* !NO_XRANDR */16561657static void1658X11GD_SetFullscreenMode(Window win, jboolean enabled)1659{1660Atom wmState = XInternAtom(awt_display, "_NET_WM_STATE", False);1661Atom wmStateFs = XInternAtom(awt_display,1662"_NET_WM_STATE_FULLSCREEN", False);1663XWindowAttributes attr;1664XEvent event;16651666if (wmState == None || wmStateFs == None1667|| !XGetWindowAttributes(awt_display, win, &attr)) {1668return;1669}16701671memset(&event, 0, sizeof(event));1672event.xclient.type = ClientMessage;1673event.xclient.message_type = wmState;1674event.xclient.display = awt_display;1675event.xclient.window = win;1676event.xclient.format = 32;1677event.xclient.data.l[0] = enabled ? 1 : 0; // 1==add, 0==remove1678event.xclient.data.l[1] = wmStateFs;16791680XSendEvent(awt_display, attr.root, False,1681SubstructureRedirectMask | SubstructureNotifyMask,1682&event);1683XSync(awt_display, False);1684}16851686/*1687* Class: sun_awt_X11GraphicsDevice1688* Method: initXrandrExtension1689* Signature: ()Z1690*/1691JNIEXPORT jboolean JNICALL1692Java_sun_awt_X11GraphicsDevice_initXrandrExtension1693(JNIEnv *env, jclass x11gd)1694{1695#if defined(NO_XRANDR)1696return JNI_FALSE;1697#else1698int opcode = 0, firstEvent = 0, firstError = 0;1699jboolean ret;17001701AWT_LOCK();1702ret = (jboolean)XQueryExtension(awt_display, "RANDR",1703&opcode, &firstEvent, &firstError);1704if (ret) {1705ret = X11GD_InitXrandrFuncs(env);1706}1707AWT_FLUSH_UNLOCK();17081709return ret;1710#endif /* NO_XRANDR */1711}17121713/*1714* Class: sun_awt_X11GraphicsDevice1715* Method: getCurrentDisplayMode1716* Signature: (I)Ljava/awt/DisplayMode;1717*/1718JNIEXPORT jobject JNICALL1719Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode1720(JNIEnv* env, jclass x11gd, jint screen)1721{1722#if defined(NO_XRANDR)1723return NULL;1724#else1725XRRScreenConfiguration *config;1726jobject displayMode = NULL;17271728AWT_LOCK();17291730if (screen < ScreenCount(awt_display)) {17311732config = awt_XRRGetScreenInfo(awt_display,1733RootWindow(awt_display, screen));1734if (config != NULL) {1735Rotation rotation;1736short curRate;1737SizeID curSizeIndex;1738XRRScreenSize *sizes;1739int nsizes;17401741curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation);1742sizes = awt_XRRConfigSizes(config, &nsizes);1743curRate = awt_XRRConfigCurrentRate(config);17441745if ((sizes != NULL) &&1746(curSizeIndex < nsizes))1747{1748XRRScreenSize curSize = sizes[curSizeIndex];1749displayMode = X11GD_CreateDisplayMode(env,1750curSize.width,1751curSize.height,1752BIT_DEPTH_MULTI,1753curRate);1754}17551756awt_XRRFreeScreenConfigInfo(config);1757}1758}17591760AWT_FLUSH_UNLOCK();17611762return displayMode;1763#endif /* NO_XRANDR */1764}17651766/*1767* Class: sun_awt_X11GraphicsDevice1768* Method: enumDisplayModes1769* Signature: (ILjava/util/ArrayList;)V1770*/1771JNIEXPORT void JNICALL1772Java_sun_awt_X11GraphicsDevice_enumDisplayModes1773(JNIEnv* env, jclass x11gd,1774jint screen, jobject arrayList)1775{1776#if !defined(NO_XRANDR)17771778AWT_LOCK();17791780if (XScreenCount(awt_display) > 0) {17811782XRRScreenConfiguration *config;17831784config = awt_XRRGetScreenInfo(awt_display,1785RootWindow(awt_display, screen));1786if (config != NULL) {1787int nsizes, i, j;1788XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);17891790if (sizes != NULL) {1791for (i = 0; i < nsizes; i++) {1792int nrates;1793XRRScreenSize size = sizes[i];1794short *rates = awt_XRRConfigRates(config, i, &nrates);17951796for (j = 0; j < nrates; j++) {1797X11GD_AddDisplayMode(env, arrayList,1798size.width,1799size.height,1800BIT_DEPTH_MULTI,1801rates[j]);1802if ((*env)->ExceptionCheck(env)) {1803goto ret1;1804}1805}1806}1807}1808ret1:1809awt_XRRFreeScreenConfigInfo(config);1810}1811}18121813AWT_FLUSH_UNLOCK();1814#endif /* !NO_XRANDR */1815}18161817/*1818* Class: sun_awt_X11GraphicsDevice1819* Method: configDisplayMode1820* Signature: (IIII)V1821*/1822JNIEXPORT void JNICALL1823Java_sun_awt_X11GraphicsDevice_configDisplayMode1824(JNIEnv* env, jclass x11gd,1825jint screen, jint width, jint height, jint refreshRate)1826{1827#if !defined(NO_XRANDR)1828jboolean success = JNI_FALSE;1829XRRScreenConfiguration *config;1830Drawable root;1831Rotation currentRotation = RR_Rotate_0;18321833AWT_LOCK();18341835root = RootWindow(awt_display, screen);1836config = awt_XRRGetScreenInfo(awt_display, root);1837if (config != NULL) {1838jboolean foundConfig = JNI_FALSE;1839int chosenSizeIndex = -1;1840short chosenRate = -1;1841int nsizes;1842XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);1843awt_XRRConfigRotations(config, ¤tRotation);18441845if (sizes != NULL) {1846int i, j;18471848/* find the size index that matches the requested dimensions */1849for (i = 0; i < nsizes; i++) {1850XRRScreenSize size = sizes[i];18511852if ((size.width == width) && (size.height == height)) {1853/* we've found our size index... */1854int nrates;1855short *rates = awt_XRRConfigRates(config, i, &nrates);18561857/* now find rate that matches requested refresh rate */1858for (j = 0; j < nrates; j++) {1859if (rates[j] == refreshRate) {1860/* we've found our rate; break out of the loop */1861chosenSizeIndex = i;1862chosenRate = rates[j];1863foundConfig = JNI_TRUE;1864break;1865}1866}18671868break;1869}1870}1871}18721873if (foundConfig) {1874Status status =1875awt_XRRSetScreenConfigAndRate(awt_display, config, root,1876chosenSizeIndex,1877currentRotation,1878chosenRate,1879CurrentTime);18801881/* issue XSync to ensure immediate mode change */1882XSync(awt_display, False);18831884if (status == RRSetConfigSuccess) {1885success = JNI_TRUE;1886}1887}18881889awt_XRRFreeScreenConfigInfo(config);1890}18911892AWT_FLUSH_UNLOCK();18931894if (!success && !(*env)->ExceptionCheck(env)) {1895JNU_ThrowInternalError(env, "Could not set display mode");1896}1897#endif /* !NO_XRANDR */1898}18991900/*1901* Class: sun_awt_X11GraphicsDevice1902* Method: enterFullScreenExclusive1903* Signature: (J)V1904*/1905JNIEXPORT void JNICALL1906Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive1907(JNIEnv* env, jclass x11gd,1908jlong window)1909{1910Window win = (Window)window;19111912AWT_LOCK();1913XSync(awt_display, False); /* ensures window is visible first */1914X11GD_SetFullscreenMode(win, JNI_TRUE);1915AWT_UNLOCK();1916}19171918/*1919* Class: sun_awt_X11GraphicsDevice1920* Method: exitFullScreenExclusive1921* Signature: (J)V1922*/1923JNIEXPORT void JNICALL1924Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive1925(JNIEnv* env, jclass x11gd,1926jlong window)1927{1928Window win = (Window)window;19291930AWT_LOCK();1931X11GD_SetFullscreenMode(win, JNI_FALSE);1932AWT_UNLOCK();1933}19341935/**1936* End DisplayMode/FullScreen support1937*/19381939/*1940* Class: sun_awt_X11GraphicsDevice1941* Method: getNativeScaleFactor1942* Signature: (I)D1943*/1944JNIEXPORT jdouble JNICALL1945Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor1946(JNIEnv *env, jobject this, jint screen) {19471948return getNativeScaleFactor();1949}195019511952