| /* |
| * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #include "jni_util.h" |
| #include "awt_p.h" |
| #include "awt.h" |
| #include "color.h" |
| #include <java_awt_DisplayMode.h> |
| #include <sun_awt_X11GraphicsEnvironment.h> |
| #include <sun_awt_X11GraphicsDevice.h> |
| #include <sun_awt_X11GraphicsConfig.h> |
| #ifndef HEADLESS |
| #include <X11/extensions/Xdbe.h> |
| #include <X11/XKBlib.h> |
| #include "Xrandr.h" |
| #include "GLXGraphicsConfig.h" |
| #endif /* !HEADLESS */ |
| |
| #include <jni.h> |
| #include <jni_util.h> |
| #include <jvm.h> |
| #include <jvm_md.h> |
| #include <jlong.h> |
| #include "systemScale.h" |
| #include <stdlib.h> |
| |
| #include "awt_GraphicsEnv.h" |
| #include "awt_util.h" |
| #include "gdefs.h" |
| #include <dlfcn.h> |
| #include "Trace.h" |
| |
| #ifdef NETSCAPE |
| #include <signal.h> |
| extern int awt_init_xt; |
| #endif |
| |
| #ifndef HEADLESS |
| |
| int awt_numScreens; /* Xinerama-aware number of screens */ |
| |
| AwtScreenDataPtr x11Screens; |
| |
| /* |
| * Set in initDisplay() to indicate whether we should attempt to initialize |
| * GLX for the default configuration. |
| */ |
| static jboolean glxRequested = JNI_FALSE; |
| |
| #endif /* !HEADLESS */ |
| |
| #ifdef HEADLESS |
| #define Display void |
| #endif /* HEADLESS */ |
| |
| Display *awt_display; |
| |
| jclass tkClass = NULL; |
| jmethodID awtLockMID = NULL; |
| jmethodID awtUnlockMID = NULL; |
| jmethodID awtWaitMID = NULL; |
| jmethodID awtNotifyMID = NULL; |
| jmethodID awtNotifyAllMID = NULL; |
| jboolean awtLockInited = JNI_FALSE; |
| |
| /** Convenience macro for loading the lock-related method IDs. */ |
| #define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \ |
| do { \ |
| method_id = (*env)->GetStaticMethodID(env, klass, \ |
| method_name, method_sig); \ |
| if (method_id == NULL) return NULL; \ |
| } while (0) |
| |
| struct X11GraphicsConfigIDs x11GraphicsConfigIDs; |
| struct X11GraphicsDeviceIDs x11GraphicsDeviceIDs; |
| |
| #ifndef HEADLESS |
| int awtCreateX11Colormap(AwtGraphicsConfigDataPtr adata); |
| #endif /* HEADLESS */ |
| |
| static char *x11GraphicsConfigClassName = "sun/awt/X11GraphicsConfig"; |
| |
| /* AWT and Xinerama |
| * |
| * As of fix 4356756, AWT is Xinerama-aware. X11GraphicsDevices are created for |
| * each screen of a Xinerama setup, though X11 itself still only sees a single |
| * display. |
| * In many places where we talk to X11, a xinawareScreen variable is used to |
| * pass the correct Display value, depending on the circumstances (a single |
| * X display, multiple X displays, or a single X display with multiple |
| * Xinerama screens). |
| * |
| * Solaris and Linux differ in the functions used to access Xinerama-related |
| * data. This is in part because at this time, the X consortium has not |
| * finalized the "official" Xinerama API. Once this spec is available, and |
| * both OSes are conformant, one code base should be sufficient for Xinerama |
| * operation on both OSes. Until then, some of the Xinerama-related code |
| * is ifdef'd appropriately. -bchristi, 7/12/01 |
| */ |
| |
| #define MAXFRAMEBUFFERS 16 |
| #if defined(__linux__) || defined(MACOSX) |
| typedef struct { |
| int screen_number; |
| short x_org; |
| short y_org; |
| short width; |
| short height; |
| } XineramaScreenInfo; |
| |
| typedef XineramaScreenInfo* XineramaQueryScreensFunc(Display*, int*); |
| |
| #else /* SOLARIS */ |
| typedef Status XineramaGetInfoFunc(Display* display, int screen_number, |
| XRectangle* framebuffer_rects, unsigned char* framebuffer_hints, |
| int* num_framebuffers); |
| typedef Status XineramaGetCenterHintFunc(Display* display, int screen_number, |
| int* x, int* y); |
| |
| XineramaGetCenterHintFunc* XineramaSolarisCenterFunc = NULL; |
| #endif |
| |
| Bool usingXinerama = False; |
| XRectangle fbrects[MAXFRAMEBUFFERS]; |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsConfig_initIDs (JNIEnv *env, jclass cls) |
| { |
| x11GraphicsConfigIDs.aData = NULL; |
| x11GraphicsConfigIDs.bitsPerPixel = NULL; |
| x11GraphicsConfigIDs.screen = NULL; |
| |
| x11GraphicsConfigIDs.aData = (*env)->GetFieldID (env, cls, "aData", "J"); |
| CHECK_NULL(x11GraphicsConfigIDs.aData); |
| x11GraphicsConfigIDs.bitsPerPixel = (*env)->GetFieldID (env, cls, "bitsPerPixel", "I"); |
| CHECK_NULL(x11GraphicsConfigIDs.bitsPerPixel); |
| x11GraphicsConfigIDs.screen = (*env)->GetFieldID (env, cls, "screen", "Lsun/awt/X11GraphicsDevice;"); |
| CHECK_NULL(x11GraphicsConfigIDs.screen); |
| |
| if (x11GraphicsConfigIDs.aData == NULL || |
| x11GraphicsConfigIDs.bitsPerPixel == NULL || |
| x11GraphicsConfigIDs.screen == NULL) { |
| |
| JNU_ThrowNoSuchFieldError(env, "Can't find a field"); |
| return; |
| } |
| } |
| |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsDevice_initIDs (JNIEnv *env, jclass cls) |
| { |
| x11GraphicsDeviceIDs.screen = NULL; |
| x11GraphicsDeviceIDs.screen = (*env)->GetFieldID (env, cls, "screen", "I"); |
| DASSERT(x11GraphicsDeviceIDs.screen); |
| } |
| |
| #ifndef HEADLESS |
| |
| /* |
| * XIOErrorHandler |
| */ |
| static int xioerror_handler(Display *disp) |
| { |
| if (awtLockInited) { |
| if (errno == EPIPE) { |
| jio_fprintf(stderr, "X connection to %s host broken (explicit kill or server shutdown)\n", XDisplayName(NULL)); |
| } |
| /*SignalError(lockedee->lastpc, lockedee, "fp/ade/gui/GUIException", "I/O error"); */ |
| } |
| return 0; |
| } |
| |
| static AwtGraphicsConfigDataPtr |
| findWithTemplate(XVisualInfo *vinfo, |
| long mask) |
| { |
| |
| XVisualInfo *visualList; |
| XColor color; |
| AwtGraphicsConfigDataPtr defaultConfig; |
| int visualsMatched, i; |
| |
| visualList = XGetVisualInfo(awt_display, |
| mask, vinfo, &visualsMatched); |
| if (visualList) { |
| defaultConfig = ZALLOC(_AwtGraphicsConfigData); |
| for (i = 0; i < visualsMatched; i++) { |
| memcpy(&defaultConfig->awt_visInfo, &visualList[i], sizeof(XVisualInfo)); |
| defaultConfig->awt_depth = visualList[i].depth; |
| |
| /* we can't use awtJNI_CreateColorData here, because it'll pull, |
| SystemColor, which in turn will cause toolkit to be reinitialized */ |
| if (awtCreateX11Colormap(defaultConfig)) { |
| /* Allocate white and black pixels for this visual */ |
| color.flags = DoRed | DoGreen | DoBlue; |
| color.red = color.green = color.blue = 0x0000; |
| XAllocColor(awt_display, defaultConfig->awt_cmap, &color); |
| x11Screens[visualList[i].screen].blackpixel = color.pixel; |
| color.flags = DoRed | DoGreen | DoBlue; |
| color.red = color.green = color.blue = 0xffff; |
| XAllocColor(awt_display, defaultConfig->awt_cmap, &color); |
| x11Screens[visualList[i].screen].whitepixel = color.pixel; |
| |
| XFree(visualList); |
| return defaultConfig; |
| } |
| } |
| XFree(visualList); |
| free((void *)defaultConfig); |
| } |
| return NULL; |
| } |
| |
| /* default config is based on X11 screen. All Xinerama screens of that X11 |
| screen will have the same default config */ |
| /* Need more notes about which fields of the structure are based on the X |
| screen, and which are based on the Xinerama screen */ |
| static AwtGraphicsConfigDataPtr |
| makeDefaultConfig(JNIEnv *env, int screen) { |
| |
| AwtGraphicsConfigDataPtr defaultConfig; |
| int xinawareScreen = 0; |
| VisualID forcedVisualID = 0, defaultVisualID; |
| char *forcedVisualStr; |
| XVisualInfo vinfo; |
| long mask; |
| |
| xinawareScreen = usingXinerama ? 0 : screen; |
| defaultVisualID = |
| XVisualIDFromVisual(DefaultVisual(awt_display, xinawareScreen)); |
| |
| memset(&vinfo, 0, sizeof(XVisualInfo)); |
| vinfo.screen = xinawareScreen; |
| |
| if ((forcedVisualStr = getenv("FORCEDEFVIS"))) { |
| mask = VisualIDMask | VisualScreenMask; |
| if (sscanf(forcedVisualStr, "%lx", &forcedVisualID) > 0 && |
| forcedVisualID > 0) |
| { |
| vinfo.visualid = forcedVisualID; |
| } else { |
| vinfo.visualid = defaultVisualID; |
| } |
| } else { |
| VisualID bestGLXVisualID; |
| if (glxRequested && |
| (bestGLXVisualID = GLXGC_FindBestVisual(env, xinawareScreen)) > 0) |
| { |
| /* we've found the best visual for use with GLX, so use it */ |
| vinfo.visualid = bestGLXVisualID; |
| mask = VisualIDMask | VisualScreenMask; |
| } else { |
| /* otherwise, continue looking for the best X11 visual */ |
| vinfo.depth = 24; |
| vinfo.class = TrueColor; |
| mask = VisualDepthMask | VisualScreenMask | VisualClassMask; |
| } |
| } |
| |
| /* try the best, or forced visual */ |
| defaultConfig = findWithTemplate(&vinfo, mask); |
| if (defaultConfig) { |
| return defaultConfig; |
| } |
| |
| /* try the default visual */ |
| vinfo.visualid = defaultVisualID; |
| mask = VisualIDMask | VisualScreenMask; |
| defaultConfig = findWithTemplate(&vinfo, mask); |
| if (defaultConfig) { |
| return defaultConfig; |
| } |
| |
| /* try any TrueColor */ |
| vinfo.class = TrueColor; |
| mask = VisualScreenMask | VisualClassMask; |
| defaultConfig = findWithTemplate(&vinfo, mask); |
| if (defaultConfig) { |
| return defaultConfig; |
| } |
| |
| /* try 8-bit PseudoColor */ |
| vinfo.depth = 8; |
| vinfo.class = PseudoColor; |
| mask = VisualDepthMask | VisualScreenMask | VisualClassMask; |
| defaultConfig = findWithTemplate(&vinfo, mask); |
| if (defaultConfig) { |
| return defaultConfig; |
| } |
| |
| /* try any 8-bit */ |
| vinfo.depth = 8; |
| mask = VisualDepthMask | VisualScreenMask; |
| defaultConfig = findWithTemplate(&vinfo, mask); |
| if (defaultConfig) { |
| return defaultConfig; |
| } |
| |
| /* we tried everything, give up */ |
| JNU_ThrowInternalError(env, "Can't find supported visual"); |
| XCloseDisplay(awt_display); |
| awt_display = NULL; |
| return NULL; |
| } |
| |
| static void |
| getAllConfigs (JNIEnv *env, int screen, AwtScreenDataPtr screenDataPtr) { |
| |
| int i; |
| int n8p=0, n12p=0, n8s=0, n8gs=0, n8sg=0, n1sg=0, nTrue=0; |
| int nConfig; |
| XVisualInfo *pVI8p, *pVI12p, *pVI8s, *pVITrue, *pVI8gs, |
| *pVI8sg, *pVI1sg = NULL, viTmp; |
| AwtGraphicsConfigDataPtr *graphicsConfigs; |
| AwtGraphicsConfigDataPtr defaultConfig; |
| int ind; |
| char errmsg[128]; |
| int xinawareScreen; |
| void* xrenderLibHandle = NULL; |
| XRenderFindVisualFormatFunc* xrenderFindVisualFormat = NULL; |
| int major_opcode, first_event, first_error; |
| |
| if (usingXinerama) { |
| xinawareScreen = 0; |
| } |
| else { |
| xinawareScreen = screen; |
| } |
| |
| AWT_LOCK (); |
| |
| viTmp.screen = xinawareScreen; |
| |
| viTmp.depth = 8; |
| viTmp.class = PseudoColor; |
| viTmp.colormap_size = 256; |
| pVI8p = XGetVisualInfo (awt_display, |
| VisualDepthMask | VisualClassMask | |
| VisualColormapSizeMask | VisualScreenMask, |
| &viTmp, &n8p); |
| |
| viTmp.depth = 12; |
| viTmp.class = PseudoColor; |
| viTmp.colormap_size = 4096; |
| pVI12p = XGetVisualInfo (awt_display, |
| VisualDepthMask | VisualClassMask | |
| VisualColormapSizeMask | VisualScreenMask, |
| &viTmp, &n12p); |
| |
| viTmp.class = TrueColor; |
| pVITrue = XGetVisualInfo (awt_display, |
| VisualClassMask | |
| VisualScreenMask, |
| &viTmp, &nTrue); |
| |
| viTmp.depth = 8; |
| viTmp.class = StaticColor; |
| pVI8s = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask | |
| VisualScreenMask, &viTmp, &n8s); |
| |
| viTmp.depth = 8; |
| viTmp.class = GrayScale; |
| viTmp.colormap_size = 256; |
| pVI8gs = XGetVisualInfo (awt_display, |
| VisualDepthMask | VisualClassMask | |
| VisualColormapSizeMask | VisualScreenMask, |
| &viTmp, &n8gs); |
| viTmp.depth = 8; |
| viTmp.class = StaticGray; |
| viTmp.colormap_size = 256; |
| pVI8sg = XGetVisualInfo (awt_display, |
| VisualDepthMask | VisualClassMask | |
| VisualColormapSizeMask | VisualScreenMask, |
| &viTmp, &n8sg); |
| |
| /* REMIND.. remove when we have support for the color classes below */ |
| /* viTmp.depth = 1; */ |
| /* viTmp.class = StaticGray; */ |
| /* pVI1sg = XGetVisualInfo (awt_display, VisualDepthMask | VisualClassMask, */ |
| /* viTmp, &n1sg); */ |
| |
| nConfig = n8p + n12p + n8s + n8gs + n8sg + n1sg + nTrue + 1; |
| graphicsConfigs = (AwtGraphicsConfigDataPtr *) |
| calloc(nConfig, sizeof(AwtGraphicsConfigDataPtr)); |
| if (graphicsConfigs == NULL) { |
| JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), |
| NULL); |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| if (screenDataPtr->defaultConfig == NULL) { |
| /* |
| * After a display change event, the default config field will have |
| * been reset, so we need to recreate the default config here. |
| */ |
| screenDataPtr->defaultConfig = makeDefaultConfig(env, screen); |
| } |
| |
| defaultConfig = screenDataPtr->defaultConfig; |
| graphicsConfigs[0] = defaultConfig; |
| nConfig = 1; /* reserve index 0 for default config */ |
| |
| // Only use the RENDER extension if it is available on the X server |
| if (XQueryExtension(awt_display, "RENDER", |
| &major_opcode, &first_event, &first_error)) |
| { |
| xrenderLibHandle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL); |
| |
| #ifdef MACOSX |
| #define XRENDER_LIB "/usr/X11/lib/libXrender.dylib" |
| #else |
| #define XRENDER_LIB "libXrender.so" |
| #endif |
| |
| if (xrenderLibHandle == NULL) { |
| xrenderLibHandle = dlopen(XRENDER_LIB, |
| RTLD_LAZY | RTLD_GLOBAL); |
| } |
| |
| #ifndef __linux__ /* SOLARIS */ |
| if (xrenderLibHandle == NULL) { |
| xrenderLibHandle = dlopen("/usr/sfw/lib/libXrender.so.1", |
| RTLD_LAZY | RTLD_GLOBAL); |
| } |
| #endif |
| |
| if (xrenderLibHandle != NULL) { |
| xrenderFindVisualFormat = |
| (XRenderFindVisualFormatFunc*)dlsym(xrenderLibHandle, |
| "XRenderFindVisualFormat"); |
| } |
| } |
| |
| for (i = 0; i < nTrue; i++) { |
| if (XVisualIDFromVisual(pVITrue[i].visual) == |
| XVisualIDFromVisual(defaultConfig->awt_visInfo.visual) || |
| pVITrue[i].depth == 12) { |
| /* Skip the non-supported 12-bit TrueColor visual */ |
| continue; |
| } else { |
| ind = nConfig++; |
| } |
| graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData); |
| graphicsConfigs [ind]->awt_depth = pVITrue [i].depth; |
| memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVITrue [i], |
| sizeof (XVisualInfo)); |
| if (xrenderFindVisualFormat != NULL) { |
| XRenderPictFormat *format = xrenderFindVisualFormat (awt_display, |
| pVITrue [i].visual); |
| if (format && |
| format->type == PictTypeDirect && |
| format->direct.alphaMask) |
| { |
| graphicsConfigs [ind]->isTranslucencySupported = 1; |
| memcpy(&graphicsConfigs [ind]->renderPictFormat, format, |
| sizeof(*format)); |
| } |
| } |
| } |
| |
| if (xrenderLibHandle != NULL) { |
| dlclose(xrenderLibHandle); |
| xrenderLibHandle = NULL; |
| } |
| |
| for (i = 0; i < n8p; i++) { |
| if (XVisualIDFromVisual(pVI8p[i].visual) == |
| XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) { |
| continue; |
| } else { |
| ind = nConfig++; |
| } |
| graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData); |
| graphicsConfigs [ind]->awt_depth = pVI8p [i].depth; |
| memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8p [i], |
| sizeof (XVisualInfo)); |
| } |
| |
| for (i = 0; i < n12p; i++) { |
| if (XVisualIDFromVisual(pVI12p[i].visual) == |
| XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) { |
| continue; |
| } else { |
| ind = nConfig++; |
| } |
| graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData); |
| graphicsConfigs [ind]->awt_depth = pVI12p [i].depth; |
| memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI12p [i], |
| sizeof (XVisualInfo)); |
| } |
| |
| for (i = 0; i < n8s; i++) { |
| if (XVisualIDFromVisual(pVI8s[i].visual) == |
| XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) { |
| continue; |
| } else { |
| ind = nConfig++; |
| } |
| graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData); |
| graphicsConfigs [ind]->awt_depth = pVI8s [i].depth; |
| memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8s [i], |
| sizeof (XVisualInfo)); |
| } |
| |
| for (i = 0; i < n8gs; i++) { |
| if (XVisualIDFromVisual(pVI8gs[i].visual) == |
| XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) { |
| continue; |
| } else { |
| ind = nConfig++; |
| } |
| graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData); |
| graphicsConfigs [ind]->awt_depth = pVI8gs [i].depth; |
| memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8gs [i], |
| sizeof (XVisualInfo)); |
| } |
| |
| for (i = 0; i < n8sg; i++) { |
| if (XVisualIDFromVisual(pVI8sg[i].visual) == |
| XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) { |
| continue; |
| } else { |
| ind = nConfig++; |
| } |
| graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData); |
| graphicsConfigs [ind]->awt_depth = pVI8sg [i].depth; |
| memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI8sg [i], |
| sizeof (XVisualInfo)); |
| } |
| |
| for (i = 0; i < n1sg; i++) { |
| if (XVisualIDFromVisual(pVI1sg[i].visual) == |
| XVisualIDFromVisual(defaultConfig->awt_visInfo.visual)) { |
| continue; |
| } else { |
| ind = nConfig++; |
| } |
| graphicsConfigs [ind] = ZALLOC (_AwtGraphicsConfigData); |
| graphicsConfigs [ind]->awt_depth = pVI1sg [i].depth; |
| memcpy (&graphicsConfigs [ind]->awt_visInfo, &pVI1sg [i], |
| sizeof (XVisualInfo)); |
| } |
| |
| if (n8p != 0) |
| XFree (pVI8p); |
| if (n12p != 0) |
| XFree (pVI12p); |
| if (n8s != 0) |
| XFree (pVI8s); |
| if (n8gs != 0) |
| XFree (pVI8gs); |
| if (n8sg != 0) |
| XFree (pVI8sg); |
| if (n1sg != 0) |
| XFree (pVI1sg); |
| |
| screenDataPtr->numConfigs = nConfig; |
| screenDataPtr->configs = graphicsConfigs; |
| |
| AWT_UNLOCK (); |
| } |
| |
| #ifndef HEADLESS |
| #if defined(__linux__) || defined(MACOSX) |
| static void xinerama_init_linux() |
| { |
| void* libHandle = NULL; |
| int32_t locNumScr = 0; |
| XineramaScreenInfo *xinInfo; |
| char* XineramaQueryScreensName = "XineramaQueryScreens"; |
| XineramaQueryScreensFunc* XineramaQueryScreens = NULL; |
| |
| /* load library */ |
| libHandle = dlopen(VERSIONED_JNI_LIB_NAME("Xinerama", "1"), |
| RTLD_LAZY | RTLD_GLOBAL); |
| if (libHandle == NULL) { |
| libHandle = dlopen(JNI_LIB_NAME("Xinerama"), RTLD_LAZY | RTLD_GLOBAL); |
| } |
| if (libHandle != NULL) { |
| XineramaQueryScreens = (XineramaQueryScreensFunc*) |
| dlsym(libHandle, XineramaQueryScreensName); |
| |
| if (XineramaQueryScreens != NULL) { |
| DTRACE_PRINTLN("calling XineramaQueryScreens func on Linux"); |
| xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr); |
| if (xinInfo != NULL && locNumScr > XScreenCount(awt_display)) { |
| int32_t idx; |
| DTRACE_PRINTLN("Enabling Xinerama support"); |
| usingXinerama = True; |
| /* set global number of screens */ |
| DTRACE_PRINTLN1(" num screens = %i\n", locNumScr); |
| awt_numScreens = locNumScr; |
| |
| /* stuff values into fbrects */ |
| for (idx = 0; idx < awt_numScreens; idx++) { |
| DASSERT(xinInfo[idx].screen_number == idx); |
| |
| fbrects[idx].width = xinInfo[idx].width; |
| fbrects[idx].height = xinInfo[idx].height; |
| fbrects[idx].x = xinInfo[idx].x_org; |
| fbrects[idx].y = xinInfo[idx].y_org; |
| } |
| } else { |
| DTRACE_PRINTLN("calling XineramaQueryScreens didn't work"); |
| } |
| } else { |
| DTRACE_PRINTLN("couldn't load XineramaQueryScreens symbol"); |
| } |
| dlclose(libHandle); |
| } else { |
| DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror()); |
| } |
| } |
| #endif |
| #if !defined(__linux__) && !defined(MACOSX) /* Solaris */ |
| static void xinerama_init_solaris() |
| { |
| void* libHandle = NULL; |
| unsigned char fbhints[MAXFRAMEBUFFERS]; |
| int32_t locNumScr = 0; |
| /* load and run XineramaGetInfo */ |
| char* XineramaGetInfoName = "XineramaGetInfo"; |
| char* XineramaGetCenterHintName = "XineramaGetCenterHint"; |
| XineramaGetInfoFunc* XineramaSolarisFunc = NULL; |
| |
| /* load library */ |
| libHandle = dlopen(JNI_LIB_NAME("Xext"), RTLD_LAZY | RTLD_GLOBAL); |
| if (libHandle != NULL) { |
| XineramaSolarisFunc = (XineramaGetInfoFunc*)dlsym(libHandle, XineramaGetInfoName); |
| XineramaSolarisCenterFunc = |
| (XineramaGetCenterHintFunc*)dlsym(libHandle, XineramaGetCenterHintName); |
| |
| if (XineramaSolarisFunc != NULL) { |
| DTRACE_PRINTLN("calling XineramaGetInfo func on Solaris"); |
| if ((*XineramaSolarisFunc)(awt_display, 0, &fbrects[0], |
| &fbhints[0], &locNumScr) != 0 && |
| locNumScr > XScreenCount(awt_display)) |
| { |
| DTRACE_PRINTLN("Enabling Xinerama support"); |
| usingXinerama = True; |
| /* set global number of screens */ |
| DTRACE_PRINTLN1(" num screens = %i\n", locNumScr); |
| awt_numScreens = locNumScr; |
| } else { |
| DTRACE_PRINTLN("calling XineramaGetInfo didn't work"); |
| } |
| } else { |
| DTRACE_PRINTLN("couldn't load XineramaGetInfo symbol"); |
| } |
| dlclose(libHandle); |
| } else { |
| DTRACE_PRINTLN1("\ncouldn't open shared library: %s\n", dlerror()); |
| } |
| } |
| #endif |
| |
| /* |
| * Checks if Xinerama is running and perform Xinerama-related |
| * platform dependent initialization. |
| */ |
| static void xineramaInit(void) { |
| char* XinExtName = "XINERAMA"; |
| int32_t major_opcode, first_event, first_error; |
| Bool gotXinExt = False; |
| |
| gotXinExt = XQueryExtension(awt_display, XinExtName, &major_opcode, |
| &first_event, &first_error); |
| |
| if (!gotXinExt) { |
| DTRACE_PRINTLN("Xinerama extension is not available"); |
| return; |
| } |
| |
| DTRACE_PRINTLN("Xinerama extension is available"); |
| #if defined(__linux__) || defined(MACOSX) |
| xinerama_init_linux(); |
| #else /* Solaris */ |
| xinerama_init_solaris(); |
| #endif /* __linux__ || MACOSX */ |
| } |
| #endif /* HEADLESS */ |
| |
| Display * |
| awt_init_Display(JNIEnv *env, jobject this) |
| { |
| jclass klass; |
| Display *dpy; |
| char errmsg[128]; |
| int i; |
| #ifdef NETSCAPE |
| sigset_t alarm_set, oldset; |
| #endif |
| |
| if (awt_display) { |
| return awt_display; |
| } |
| |
| #ifdef NETSCAPE |
| /* Disable interrupts during XtOpenDisplay to avoid bugs in unix os select |
| code: some unix systems don't implement SA_RESTART properly and |
| because of this, select returns with EINTR. Most implementations of |
| gethostbyname don't cope with EINTR properly and as a result we get |
| stuck (forever) in the gethostbyname code |
| */ |
| sigemptyset(&alarm_set); |
| sigaddset(&alarm_set, SIGALRM); |
| sigprocmask(SIG_BLOCK, &alarm_set, &oldset); |
| #endif |
| |
| /* Load AWT lock-related methods in SunToolkit */ |
| klass = (*env)->FindClass(env, "sun/awt/SunToolkit"); |
| if (klass == NULL) return NULL; |
| GET_STATIC_METHOD(klass, awtLockMID, "awtLock", "()V"); |
| GET_STATIC_METHOD(klass, awtUnlockMID, "awtUnlock", "()V"); |
| GET_STATIC_METHOD(klass, awtWaitMID, "awtLockWait", "(J)V"); |
| GET_STATIC_METHOD(klass, awtNotifyMID, "awtLockNotify", "()V"); |
| GET_STATIC_METHOD(klass, awtNotifyAllMID, "awtLockNotifyAll", "()V"); |
| tkClass = (*env)->NewGlobalRef(env, klass); |
| awtLockInited = JNI_TRUE; |
| |
| if (getenv("_AWT_IGNORE_XKB") != NULL && |
| strlen(getenv("_AWT_IGNORE_XKB")) > 0) { |
| if (XkbIgnoreExtension(True)) { |
| printf("Ignoring XKB.\n"); |
| } |
| } |
| |
| dpy = awt_display = XOpenDisplay(NULL); |
| #ifdef NETSCAPE |
| sigprocmask(SIG_SETMASK, &oldset, NULL); |
| #endif |
| if (!dpy) { |
| jio_snprintf(errmsg, |
| sizeof(errmsg), |
| "Can't connect to X11 window server using '%s' as the value of the DISPLAY variable.", |
| (getenv("DISPLAY") == NULL) ? ":0.0" : getenv("DISPLAY")); |
| JNU_ThrowByName(env, "java/awt/AWTError", errmsg); |
| return NULL; |
| } |
| |
| XSetIOErrorHandler(xioerror_handler); |
| JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", "init", "(J)V", |
| ptr_to_jlong(awt_display)); |
| JNU_CHECK_EXCEPTION_RETURN(env, NULL); |
| |
| /* set awt_numScreens, and whether or not we're using Xinerama */ |
| xineramaInit(); |
| |
| if (!usingXinerama) { |
| awt_numScreens = XScreenCount(awt_display); |
| } |
| |
| DTRACE_PRINTLN1("allocating %i screens\n", awt_numScreens); |
| /* Allocate screen data structure array */ |
| x11Screens = calloc(awt_numScreens, sizeof(AwtScreenData)); |
| if (x11Screens == NULL) { |
| JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), |
| NULL); |
| return NULL; |
| } |
| |
| for (i = 0; i < awt_numScreens; i++) { |
| if (usingXinerama) { |
| /* All Xinerama screens use the same X11 root for now */ |
| x11Screens[i].root = RootWindow(awt_display, 0); |
| } |
| else { |
| x11Screens[i].root = RootWindow(awt_display, i); |
| } |
| x11Screens[i].defaultConfig = makeDefaultConfig(env, i); |
| JNU_CHECK_EXCEPTION_RETURN(env, NULL); |
| } |
| |
| return dpy; |
| } |
| #endif /* !HEADLESS */ |
| |
| /* |
| * Class: sun_awt_X11GraphicsEnvironment |
| * Method: getDefaultScreenNum |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum( |
| JNIEnv *env, jobject this) |
| { |
| #ifdef HEADLESS |
| return (jint)0; |
| #else |
| return DefaultScreen(awt_display); |
| #endif /* !HEADLESS */ |
| } |
| |
| #ifndef HEADLESS |
| static void ensureConfigsInited(JNIEnv* env, int screen) { |
| if (x11Screens[screen].numConfigs == 0) { |
| if (env == NULL) { |
| env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); |
| } |
| getAllConfigs (env, screen, &(x11Screens[screen])); |
| } |
| } |
| #endif |
| |
| #ifdef HEADLESS |
| void* getDefaultConfig(int screen) { |
| return NULL; |
| } |
| #else |
| AwtGraphicsConfigDataPtr |
| getDefaultConfig(int screen) { |
| ensureConfigsInited(NULL, screen); |
| return x11Screens[screen].defaultConfig; |
| } |
| |
| AwtScreenDataPtr |
| getScreenData(int screen) { |
| return &(x11Screens[screen]); |
| } |
| #endif /* !HEADLESS */ |
| |
| /* |
| * Class: sun_awt_X11GraphicsEnvironment |
| * Method: initDisplay |
| * Signature: (Z)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsEnvironment_initDisplay(JNIEnv *env, jobject this, |
| jboolean glxReq) |
| { |
| #ifndef HEADLESS |
| glxRequested = glxReq; |
| (void) awt_init_Display(env, this); |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsEnvironment |
| * Method: initGLX |
| * Signature: ()Z |
| */ |
| JNIEXPORT jboolean JNICALL |
| Java_sun_awt_X11GraphicsEnvironment_initGLX(JNIEnv *env, jclass x11ge) |
| { |
| #ifndef HEADLESS |
| jboolean glxAvailable; |
| |
| AWT_LOCK(); |
| glxAvailable = GLXGC_IsGLXAvailable(); |
| AWT_UNLOCK(); |
| |
| return glxAvailable; |
| #else |
| return JNI_FALSE; |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsEnvironment |
| * Method: getNumScreens |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_X11GraphicsEnvironment_getNumScreens(JNIEnv *env, jobject this) |
| { |
| #ifdef HEADLESS |
| return (jint)0; |
| #else |
| return awt_numScreens; |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: getDisplay |
| * Signature: ()J |
| */ |
| JNIEXPORT jlong JNICALL |
| Java_sun_awt_X11GraphicsDevice_getDisplay(JNIEnv *env, jobject this) |
| { |
| #ifdef HEADLESS |
| return NULL; |
| #else |
| return ptr_to_jlong(awt_display); |
| #endif /* !HEADLESS */ |
| } |
| |
| #ifdef MITSHM |
| |
| static jint canUseShmExt = UNSET_MITSHM; |
| static jint canUseShmExtPixmaps = UNSET_MITSHM; |
| static jboolean xshmAttachFailed = JNI_FALSE; |
| |
| int XShmAttachXErrHandler(Display *display, XErrorEvent *xerr) { |
| if (xerr->minor_code == X_ShmAttach) { |
| xshmAttachFailed = JNI_TRUE; |
| } |
| return 0; |
| } |
| jboolean isXShmAttachFailed() { |
| return xshmAttachFailed; |
| } |
| void resetXShmAttachFailed() { |
| xshmAttachFailed = JNI_FALSE; |
| } |
| |
| extern int mitShmPermissionMask; |
| |
| void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) { |
| XShmSegmentInfo shminfo; |
| int XShmMajor, XShmMinor; |
| int a, b, c; |
| |
| AWT_LOCK(); |
| if (canUseShmExt != UNSET_MITSHM) { |
| *shmExt = canUseShmExt; |
| *shmPixmaps = canUseShmExtPixmaps; |
| AWT_UNLOCK(); |
| return; |
| } |
| |
| *shmExt = canUseShmExt = CANT_USE_MITSHM; |
| *shmPixmaps = canUseShmExtPixmaps = CANT_USE_MITSHM; |
| |
| if (awt_display == (Display *)NULL) { |
| AWT_NOFLUSH_UNLOCK(); |
| return; |
| } |
| |
| /** |
| * XShmQueryExtension returns False in remote server case. |
| * Unfortunately it also returns True in ssh case, so |
| * we need to test that we can actually do XShmAttach. |
| */ |
| if (XShmQueryExtension(awt_display)) { |
| shminfo.shmid = shmget(IPC_PRIVATE, 0x10000, |
| IPC_CREAT|mitShmPermissionMask); |
| if (shminfo.shmid < 0) { |
| AWT_UNLOCK(); |
| J2dRlsTraceLn1(J2D_TRACE_ERROR, |
| "TryInitMITShm: shmget has failed: %s", |
| strerror(errno)); |
| return; |
| } |
| shminfo.shmaddr = (char *) shmat(shminfo.shmid, 0, 0); |
| if (shminfo.shmaddr == ((char *) -1)) { |
| shmctl(shminfo.shmid, IPC_RMID, 0); |
| AWT_UNLOCK(); |
| J2dRlsTraceLn1(J2D_TRACE_ERROR, |
| "TryInitMITShm: shmat has failed: %s", |
| strerror(errno)); |
| return; |
| } |
| shminfo.readOnly = True; |
| |
| resetXShmAttachFailed(); |
| /** |
| * The J2DXErrHandler handler will set xshmAttachFailed |
| * to JNI_TRUE if any Shm error has occured. |
| */ |
| EXEC_WITH_XERROR_HANDLER(XShmAttachXErrHandler, |
| XShmAttach(awt_display, &shminfo)); |
| |
| /** |
| * Get rid of the id now to reduce chances of leaking |
| * system resources. |
| */ |
| shmctl(shminfo.shmid, IPC_RMID, 0); |
| |
| if (isXShmAttachFailed() == JNI_FALSE) { |
| canUseShmExt = CAN_USE_MITSHM; |
| /* check if we can use shared pixmaps */ |
| XShmQueryVersion(awt_display, &XShmMajor, &XShmMinor, |
| (Bool*)&canUseShmExtPixmaps); |
| canUseShmExtPixmaps = canUseShmExtPixmaps && |
| (XShmPixmapFormat(awt_display) == ZPixmap); |
| XShmDetach(awt_display, &shminfo); |
| } |
| shmdt(shminfo.shmaddr); |
| *shmExt = canUseShmExt; |
| *shmPixmaps = canUseShmExtPixmaps; |
| } |
| AWT_UNLOCK(); |
| } |
| #endif /* MITSHM */ |
| |
| /* |
| * Class: sun_awt_X11GraphicsEnvironment |
| * Method: checkShmExt |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_X11GraphicsEnvironment_checkShmExt(JNIEnv *env, jobject this) |
| { |
| |
| int shmExt = NOEXT_MITSHM, shmPixmaps; |
| #ifdef MITSHM |
| TryInitMITShm(env, &shmExt, &shmPixmaps); |
| #endif |
| return shmExt; |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsEnvironment |
| * Method: getDisplayString |
| * Signature: ()Ljava/lang/String |
| */ |
| JNIEXPORT jstring JNICALL |
| Java_sun_awt_X11GraphicsEnvironment_getDisplayString |
| (JNIEnv *env, jobject this) |
| { |
| #ifdef HEADLESS |
| return (jstring)NULL; |
| #else |
| return (*env)->NewStringUTF(env, DisplayString(awt_display)); |
| #endif /* HEADLESS */ |
| } |
| |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: getNumConfigs |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_X11GraphicsDevice_getNumConfigs( |
| JNIEnv *env, jobject this, jint screen) |
| { |
| #ifdef HEADLESS |
| return (jint)0; |
| #else |
| ensureConfigsInited(env, screen); |
| return x11Screens[screen].numConfigs; |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: getConfigVisualId |
| * Signature: (I)I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_X11GraphicsDevice_getConfigVisualId( |
| JNIEnv *env, jobject this, jint index, jint screen) |
| { |
| #ifdef HEADLESS |
| return (jint)0; |
| #else |
| int visNum; |
| |
| ensureConfigsInited(env, screen); |
| if (index == 0) { |
| return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.visualid); |
| } else { |
| return ((jint)x11Screens[screen].configs[index]->awt_visInfo.visualid); |
| } |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: getConfigDepth |
| * Signature: (I)I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_X11GraphicsDevice_getConfigDepth( |
| JNIEnv *env, jobject this, jint index, jint screen) |
| { |
| #ifdef HEADLESS |
| return (jint)0; |
| #else |
| int visNum; |
| |
| ensureConfigsInited(env, screen); |
| if (index == 0) { |
| return ((jint)x11Screens[screen].defaultConfig->awt_visInfo.depth); |
| } else { |
| return ((jint)x11Screens[screen].configs[index]->awt_visInfo.depth); |
| } |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: getConfigColormap |
| * Signature: (I)I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_X11GraphicsDevice_getConfigColormap( |
| JNIEnv *env, jobject this, jint index, jint screen) |
| { |
| #ifdef HEADLESS |
| return (jint)0; |
| #else |
| int visNum; |
| |
| ensureConfigsInited(env, screen); |
| if (index == 0) { |
| return ((jint)x11Screens[screen].defaultConfig->awt_cmap); |
| } else { |
| return ((jint)x11Screens[screen].configs[index]->awt_cmap); |
| } |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: resetNativeData |
| * Signature: (I)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsDevice_resetNativeData |
| (JNIEnv *env, jclass x11gd, jint screen) |
| { |
| #ifndef HEADLESS |
| /* |
| * Reset references to the various configs; the actual native config data |
| * will be free'd later by the Disposer mechanism when the Java-level |
| * X11GraphicsConfig objects go away. By setting these values to NULL, |
| * we ensure that they will be reinitialized as necessary (for example, |
| * see the getNumConfigs() method). |
| */ |
| if (x11Screens[screen].configs) { |
| free(x11Screens[screen].configs); |
| x11Screens[screen].configs = NULL; |
| } |
| x11Screens[screen].defaultConfig = NULL; |
| x11Screens[screen].numConfigs = 0; |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: dispose |
| * Signature: (J)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsConfig_dispose |
| (JNIEnv *env, jclass x11gc, jlong configData) |
| { |
| #ifndef HEADLESS |
| AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr) |
| jlong_to_ptr(configData); |
| |
| if (aData == NULL) { |
| return; |
| } |
| |
| AWT_LOCK(); |
| if (aData->awt_cmap) { |
| XFreeColormap(awt_display, aData->awt_cmap); |
| } |
| if (aData->awtImage) { |
| free(aData->awtImage); |
| } |
| if (aData->monoImage) { |
| XFree(aData->monoImage); |
| } |
| if (aData->monoPixmap) { |
| XFreePixmap(awt_display, aData->monoPixmap); |
| } |
| if (aData->monoPixmapGC) { |
| XFreeGC(awt_display, aData->monoPixmapGC); |
| } |
| if (aData->color_data) { |
| free(aData->color_data); |
| } |
| AWT_UNLOCK(); |
| |
| if (aData->glxInfo) { |
| /* |
| * The native GLXGraphicsConfig data needs to be disposed separately |
| * on the OGL queue flushing thread (should not be called while |
| * the AWT lock is held). |
| */ |
| JNU_CallStaticMethodByName(env, NULL, |
| "sun/java2d/opengl/OGLRenderQueue", |
| "disposeGraphicsConfig", "(J)V", |
| ptr_to_jlong(aData->glxInfo)); |
| } |
| |
| free(aData); |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: getXResolution |
| * Signature: ()I |
| */ |
| JNIEXPORT jdouble JNICALL |
| Java_sun_awt_X11GraphicsConfig_getXResolution( |
| JNIEnv *env, jobject this, jint screen) |
| { |
| #ifdef HEADLESS |
| return (jdouble)0; |
| #else |
| return ((DisplayWidth(awt_display, screen) * 25.4) / |
| DisplayWidthMM(awt_display, screen)); |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: getYResolution |
| * Signature: ()I |
| */ |
| JNIEXPORT jdouble JNICALL |
| Java_sun_awt_X11GraphicsConfig_getYResolution( |
| JNIEnv *env, jobject this, jint screen) |
| { |
| #ifdef HEADLESS |
| return (jdouble)0; |
| #else |
| return ((DisplayHeight(awt_display, screen) * 25.4) / |
| DisplayHeightMM(awt_display, screen)); |
| #endif /* !HEADLESS */ |
| } |
| |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: getNumColors |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL |
| Java_sun_awt_X11GraphicsConfig_getNumColors( |
| JNIEnv *env, jobject this) |
| { |
| #ifdef HEADLESS |
| return (jint)0; |
| #else |
| AwtGraphicsConfigData *adata; |
| |
| adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this, |
| x11GraphicsConfigIDs.aData); |
| |
| return adata->awt_num_colors; |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: init |
| * Signature: (I)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsConfig_init( |
| JNIEnv *env, jobject this, jint visualNum, jint screen) |
| { |
| #ifndef HEADLESS |
| AwtGraphicsConfigData *adata = NULL; |
| AwtScreenData asd = x11Screens[screen]; |
| int i, n; |
| int depth; |
| XImage * tempImage; |
| |
| /* If haven't gotten all of the configs yet, do it now. */ |
| if (asd.numConfigs == 0) { |
| getAllConfigs (env, screen, &asd); |
| } |
| |
| /* Check the graphicsConfig for this visual */ |
| for (i = 0; i < asd.numConfigs; i++) { |
| AwtGraphicsConfigDataPtr agcPtr = asd.configs[i]; |
| if ((jint)agcPtr->awt_visInfo.visualid == visualNum) { |
| adata = agcPtr; |
| break; |
| } |
| } |
| |
| /* If didn't find the visual, throw an exception... */ |
| if (adata == (AwtGraphicsConfigData *) NULL) { |
| JNU_ThrowIllegalArgumentException(env, "Unknown Visual Specified"); |
| return; |
| } |
| |
| /* adata->awt_cmap initialization has been deferred to |
| * makeColorModel call |
| */ |
| |
| JNU_SetLongFieldFromPtr(env, this, x11GraphicsConfigIDs.aData, adata); |
| |
| depth = adata->awt_visInfo.depth; |
| tempImage = XCreateImage(awt_display, |
| adata->awt_visInfo.visual, |
| depth, ZPixmap, 0, NULL, 1, 1, 32, 0); |
| adata->pixelStride = (tempImage->bits_per_pixel + 7) / 8; |
| (*env)->SetIntField(env, this, x11GraphicsConfigIDs.bitsPerPixel, |
| (jint)tempImage->bits_per_pixel); |
| XDestroyImage(tempImage); |
| #endif /* !HEADLESS */ |
| } |
| |
| |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: makeColorModel |
| * Signature: ()Ljava/awt/image/ColorModel |
| */ |
| JNIEXPORT jobject JNICALL |
| Java_sun_awt_X11GraphicsConfig_makeColorModel( |
| JNIEnv *env, jobject this) |
| { |
| #ifdef HEADLESS |
| return NULL; |
| #else |
| AwtGraphicsConfigData *adata; |
| jobject colorModel; |
| |
| /* |
| * If awt is not locked yet, return null since the toolkit is not |
| * initialized yet. |
| */ |
| if (!awtLockInited) { |
| return NULL; |
| } |
| |
| AWT_LOCK (); |
| |
| adata = (AwtGraphicsConfigData *) JNU_GetLongFieldAsPtr(env, this, |
| x11GraphicsConfigIDs.aData); |
| |
| /* If colormap entry of adata is NULL, need to create it now */ |
| if (adata->awt_cmap == (Colormap) NULL) { |
| awtJNI_CreateColorData (env, adata, 1); |
| } |
| |
| /* Make Color Model object for this GraphicsConfiguration */ |
| colorModel = (*env)->ExceptionCheck(env) |
| ? NULL : awtJNI_GetColorModel (env, adata); |
| |
| AWT_UNLOCK (); |
| |
| return colorModel; |
| #endif /* !HEADLESS */ |
| } |
| |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: getBounds |
| * Signature: ()Ljava/awt/Rectangle |
| */ |
| JNIEXPORT jobject JNICALL |
| Java_sun_awt_X11GraphicsConfig_pGetBounds(JNIEnv *env, jobject this, jint screen) |
| { |
| #ifdef HEADLESS |
| return NULL; |
| #else |
| jclass clazz; |
| jmethodID mid; |
| jobject bounds = NULL; |
| AwtGraphicsConfigDataPtr adata; |
| |
| adata = (AwtGraphicsConfigDataPtr) |
| JNU_GetLongFieldAsPtr(env, this, x11GraphicsConfigIDs.aData); |
| |
| clazz = (*env)->FindClass(env, "java/awt/Rectangle"); |
| CHECK_NULL_RETURN(clazz, NULL); |
| mid = (*env)->GetMethodID(env, clazz, "<init>", "(IIII)V"); |
| if (mid != NULL) { |
| if (usingXinerama) { |
| if (0 <= screen && screen < awt_numScreens) { |
| bounds = (*env)->NewObject(env, clazz, mid, fbrects[screen].x, |
| fbrects[screen].y, |
| fbrects[screen].width, |
| fbrects[screen].height); |
| } else { |
| jclass exceptionClass = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); |
| if (exceptionClass != NULL) { |
| (*env)->ThrowNew(env, exceptionClass, "Illegal screen index"); |
| } |
| } |
| } else { |
| XWindowAttributes xwa; |
| memset(&xwa, 0, sizeof(xwa)); |
| |
| AWT_LOCK (); |
| XGetWindowAttributes(awt_display, |
| RootWindow(awt_display, adata->awt_visInfo.screen), |
| &xwa); |
| AWT_UNLOCK (); |
| |
| bounds = (*env)->NewObject(env, clazz, mid, 0, 0, |
| xwa.width, xwa.height); |
| } |
| |
| if ((*env)->ExceptionOccurred(env)) { |
| return NULL; |
| } |
| } |
| return bounds; |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: createBackBuffer |
| * Signature: (JI)J |
| */ |
| JNIEXPORT jlong JNICALL |
| Java_sun_awt_X11GraphicsConfig_createBackBuffer |
| (JNIEnv *env, jobject this, jlong window, jint swapAction) |
| { |
| int32_t v1, v2; |
| XdbeBackBuffer ret = (unsigned long) 0; |
| Window w = (Window)window; |
| AWT_LOCK(); |
| if (!XdbeQueryExtension(awt_display, &v1, &v2)) { |
| JNU_ThrowByName(env, "java/lang/Exception", |
| "Could not query double-buffer extension"); |
| AWT_UNLOCK(); |
| return (jlong)0; |
| } |
| ret = XdbeAllocateBackBufferName(awt_display, w, |
| (XdbeSwapAction)swapAction); |
| AWT_FLUSH_UNLOCK(); |
| return (jlong)ret; |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: destroyBackBuffer |
| * Signature: (J)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsConfig_destroyBackBuffer |
| (JNIEnv *env, jobject this, jlong backBuffer) |
| { |
| AWT_LOCK(); |
| XdbeDeallocateBackBufferName(awt_display, (XdbeBackBuffer)backBuffer); |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: swapBuffers |
| * Signature: (JI)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsConfig_swapBuffers |
| (JNIEnv *env, jobject this, |
| jlong window, jint swapAction) |
| { |
| XdbeSwapInfo swapInfo; |
| |
| AWT_LOCK(); |
| |
| XdbeBeginIdiom(awt_display); |
| swapInfo.swap_window = (Window)window; |
| swapInfo.swap_action = (XdbeSwapAction)swapAction; |
| if (!XdbeSwapBuffers(awt_display, &swapInfo, 1)) { |
| JNU_ThrowInternalError(env, "Could not swap buffers"); |
| } |
| XdbeEndIdiom(awt_display); |
| |
| AWT_FLUSH_UNLOCK(); |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsConfig |
| * Method: isTranslucencyCapable |
| * Signature: (J)V |
| */ |
| JNIEXPORT jboolean JNICALL |
| Java_sun_awt_X11GraphicsConfig_isTranslucencyCapable |
| (JNIEnv *env, jobject this, jlong configData) |
| { |
| #ifdef HEADLESS |
| return JNI_FALSE; |
| #else |
| AwtGraphicsConfigDataPtr aData = (AwtGraphicsConfigDataPtr)jlong_to_ptr(configData); |
| if (aData == NULL) { |
| return JNI_FALSE; |
| } |
| return aData->isTranslucencySupported ? JNI_TRUE : JNI_FALSE; |
| #endif |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: isDBESupported |
| * Signature: ()Z |
| */ |
| JNIEXPORT jboolean JNICALL |
| Java_sun_awt_X11GraphicsDevice_isDBESupported(JNIEnv *env, jobject this) |
| { |
| #ifdef HEADLESS |
| return JNI_FALSE; |
| #else |
| int opcode = 0, firstEvent = 0, firstError = 0; |
| jboolean ret; |
| |
| AWT_LOCK(); |
| ret = (jboolean)XQueryExtension(awt_display, "DOUBLE-BUFFER", |
| &opcode, &firstEvent, &firstError); |
| AWT_FLUSH_UNLOCK(); |
| return ret; |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: getDoubleBufferVisuals |
| * Signature: (I)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsDevice_getDoubleBufferVisuals(JNIEnv *env, |
| jobject this, jint screen) |
| { |
| #ifndef HEADLESS |
| jclass clazz; |
| jmethodID midAddVisual; |
| Window rootWindow; |
| int i, n = 1; |
| XdbeScreenVisualInfo* visScreenInfo; |
| int xinawareScreen; |
| |
| if (usingXinerama) { |
| xinawareScreen = 0; |
| } |
| else { |
| xinawareScreen = screen; |
| } |
| |
| clazz = (*env)->GetObjectClass(env, this); |
| midAddVisual = (*env)->GetMethodID(env, clazz, "addDoubleBufferVisual", |
| "(I)V"); |
| CHECK_NULL(midAddVisual); |
| AWT_LOCK(); |
| rootWindow = RootWindow(awt_display, xinawareScreen); |
| visScreenInfo = XdbeGetVisualInfo(awt_display, &rootWindow, &n); |
| if (visScreenInfo == NULL) { |
| JNU_ThrowInternalError(env, "Could not get visual info"); |
| AWT_UNLOCK(); |
| return; |
| } |
| AWT_FLUSH_UNLOCK(); |
| for (i = 0; i < visScreenInfo->count; i++) { |
| XdbeVisualInfo* visInfo = visScreenInfo->visinfo; |
| (*env)->CallVoidMethod(env, this, midAddVisual, (visInfo[i]).visual); |
| if ((*env)->ExceptionCheck(env)) { |
| break; |
| } |
| } |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsEnvironment |
| * Method: pRunningXinerama |
| * Signature: ()Z |
| */ |
| JNIEXPORT jboolean JNICALL |
| Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama(JNIEnv *env, |
| jobject this) |
| { |
| #ifdef HEADLESS |
| return JNI_FALSE; |
| #else |
| return usingXinerama ? JNI_TRUE : JNI_FALSE; |
| #endif /* HEADLESS */ |
| } |
| |
| /* |
| * Can return NULL. |
| * |
| * Class: sun_awt_X11GraphicsEnvironment |
| * Method: getXineramaCenterPoint |
| * Signature: ()Ljava/awt/Point |
| */ |
| JNIEXPORT jobject JNICALL |
| Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint(JNIEnv *env, |
| jobject this) |
| { |
| jobject point = NULL; |
| #ifndef HEADLESS /* return NULL in HEADLESS, Linux */ |
| #if !defined(__linux__) && !defined(MACOSX) |
| int x,y; |
| |
| AWT_LOCK(); |
| DASSERT(usingXinerama); |
| if (XineramaSolarisCenterFunc != NULL) { |
| (XineramaSolarisCenterFunc)(awt_display, 0, &x, &y); |
| point = JNU_NewObjectByName(env, "java/awt/Point","(II)V", x, y); |
| DASSERT(point); |
| } else { |
| DTRACE_PRINTLN("unable to call XineramaSolarisCenterFunc: symbol is null"); |
| } |
| AWT_FLUSH_UNLOCK(); |
| #endif /* __linux __ || MACOSX */ |
| #endif /* HEADLESS */ |
| return point; |
| } |
| |
| |
| /** |
| * Begin DisplayMode/FullScreen support |
| */ |
| |
| #ifndef HEADLESS |
| |
| #define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI |
| #define REFRESH_RATE_UNKNOWN java_awt_DisplayMode_REFRESH_RATE_UNKNOWN |
| |
| typedef Status |
| (*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp); |
| typedef XRRScreenConfiguration* |
| (*XRRGetScreenInfoType)(Display *dpy, Drawable root); |
| typedef void |
| (*XRRFreeScreenConfigInfoType)(XRRScreenConfiguration *config); |
| typedef short* |
| (*XRRConfigRatesType)(XRRScreenConfiguration *config, |
| int sizeID, int *nrates); |
| typedef short |
| (*XRRConfigCurrentRateType)(XRRScreenConfiguration *config); |
| typedef XRRScreenSize* |
| (*XRRConfigSizesType)(XRRScreenConfiguration *config, |
| int *nsizes); |
| typedef SizeID |
| (*XRRConfigCurrentConfigurationType)(XRRScreenConfiguration *config, |
| Rotation *rotation); |
| typedef Status |
| (*XRRSetScreenConfigAndRateType)(Display *dpy, |
| XRRScreenConfiguration *config, |
| Drawable draw, |
| int size_index, |
| Rotation rotation, |
| short rate, |
| Time timestamp); |
| typedef Rotation |
| (*XRRConfigRotationsType)(XRRScreenConfiguration *config, |
| Rotation *current_rotation); |
| |
| typedef XRRScreenResources* (*XRRGetScreenResourcesType)(Display *dpy, |
| Window window); |
| |
| typedef void (*XRRFreeScreenResourcesType)(XRRScreenResources *resources); |
| |
| typedef XRROutputInfo * (*XRRGetOutputInfoType)(Display *dpy, |
| XRRScreenResources *resources, RROutput output); |
| |
| typedef void (*XRRFreeOutputInfoType)(XRROutputInfo *outputInfo); |
| |
| static XRRQueryVersionType awt_XRRQueryVersion; |
| static XRRGetScreenInfoType awt_XRRGetScreenInfo; |
| static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo; |
| static XRRConfigRatesType awt_XRRConfigRates; |
| static XRRConfigCurrentRateType awt_XRRConfigCurrentRate; |
| static XRRConfigSizesType awt_XRRConfigSizes; |
| static XRRConfigCurrentConfigurationType awt_XRRConfigCurrentConfiguration; |
| static XRRSetScreenConfigAndRateType awt_XRRSetScreenConfigAndRate; |
| static XRRConfigRotationsType awt_XRRConfigRotations; |
| static XRRGetScreenResourcesType awt_XRRGetScreenResources; |
| static XRRFreeScreenResourcesType awt_XRRFreeScreenResources; |
| static XRRGetOutputInfoType awt_XRRGetOutputInfo; |
| static XRRFreeOutputInfoType awt_XRRFreeOutputInfo; |
| |
| #define LOAD_XRANDR_FUNC(f) \ |
| do { \ |
| awt_##f = (f##Type)dlsym(pLibRandR, #f); \ |
| if (awt_##f == NULL) { \ |
| J2dRlsTraceLn1(J2D_TRACE_ERROR, \ |
| "X11GD_InitXrandrFuncs: Could not load %s", #f); \ |
| dlclose(pLibRandR); \ |
| return JNI_FALSE; \ |
| } \ |
| } while (0) |
| |
| static jboolean |
| X11GD_InitXrandrFuncs(JNIEnv *env) |
| { |
| int rr_maj_ver = 0, rr_min_ver = 0; |
| |
| void *pLibRandR = dlopen(VERSIONED_JNI_LIB_NAME("Xrandr", "2"), |
| RTLD_LAZY | RTLD_LOCAL); |
| if (pLibRandR == NULL) { |
| pLibRandR = dlopen(JNI_LIB_NAME("Xrandr"), RTLD_LAZY | RTLD_LOCAL); |
| } |
| if (pLibRandR == NULL) { |
| J2dRlsTraceLn(J2D_TRACE_ERROR, |
| "X11GD_InitXrandrFuncs: Could not open libXrandr.so.2"); |
| return JNI_FALSE; |
| } |
| |
| LOAD_XRANDR_FUNC(XRRQueryVersion); |
| |
| if (!(*awt_XRRQueryVersion)(awt_display, &rr_maj_ver, &rr_min_ver)) { |
| J2dRlsTraceLn(J2D_TRACE_ERROR, |
| "X11GD_InitXrandrFuncs: XRRQueryVersion returned an error status"); |
| dlclose(pLibRandR); |
| return JNI_FALSE; |
| } |
| |
| if (usingXinerama) { |
| /* |
| * We can proceed as long as this is RANDR 1.2 or above. |
| * As of Xorg server 1.3 onwards the Xinerama backend may actually be |
| * a fake one provided by RANDR itself. See Java bug 6636469 for info. |
| */ |
| if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) { |
| J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. " |
| "Xinerama is active and Xrandr version is %d.%d", |
| rr_maj_ver, rr_min_ver); |
| dlclose(pLibRandR); |
| return JNI_FALSE; |
| } |
| |
| /* |
| * REMIND: Fullscreen mode doesn't work quite right with multi-monitor |
| * setups and RANDR 1.2. |
| */ |
| if ((rr_maj_ver == 1 && rr_min_ver <= 2) && awt_numScreens > 1) { |
| J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. " |
| "Multiple screens in use"); |
| dlclose(pLibRandR); |
| return JNI_FALSE; |
| } |
| } |
| |
| LOAD_XRANDR_FUNC(XRRGetScreenInfo); |
| LOAD_XRANDR_FUNC(XRRFreeScreenConfigInfo); |
| LOAD_XRANDR_FUNC(XRRConfigRates); |
| LOAD_XRANDR_FUNC(XRRConfigCurrentRate); |
| LOAD_XRANDR_FUNC(XRRConfigSizes); |
| LOAD_XRANDR_FUNC(XRRConfigCurrentConfiguration); |
| LOAD_XRANDR_FUNC(XRRSetScreenConfigAndRate); |
| LOAD_XRANDR_FUNC(XRRConfigRotations); |
| LOAD_XRANDR_FUNC(XRRGetScreenResources); |
| LOAD_XRANDR_FUNC(XRRFreeScreenResources); |
| LOAD_XRANDR_FUNC(XRRGetOutputInfo); |
| LOAD_XRANDR_FUNC(XRRFreeOutputInfo); |
| |
| return JNI_TRUE; |
| } |
| |
| static jobject |
| X11GD_CreateDisplayMode(JNIEnv *env, jint width, jint height, |
| jint bitDepth, jint refreshRate) |
| { |
| jclass displayModeClass; |
| jmethodID cid; |
| jint validRefreshRate = refreshRate; |
| |
| displayModeClass = (*env)->FindClass(env, "java/awt/DisplayMode"); |
| CHECK_NULL_RETURN(displayModeClass, NULL); |
| if (JNU_IsNull(env, displayModeClass)) { |
| JNU_ThrowInternalError(env, |
| "Could not get display mode class"); |
| return NULL; |
| } |
| |
| cid = (*env)->GetMethodID(env, displayModeClass, "<init>", "(IIII)V"); |
| CHECK_NULL_RETURN(cid, NULL); |
| if (cid == NULL) { |
| JNU_ThrowInternalError(env, |
| "Could not get display mode constructor"); |
| return NULL; |
| } |
| |
| // early versions of xrandr may report "empty" rates (6880694) |
| if (validRefreshRate <= 0) { |
| validRefreshRate = REFRESH_RATE_UNKNOWN; |
| } |
| |
| return (*env)->NewObject(env, displayModeClass, cid, |
| width, height, bitDepth, validRefreshRate); |
| } |
| |
| static void |
| X11GD_AddDisplayMode(JNIEnv *env, jobject arrayList, |
| jint width, jint height, |
| jint bitDepth, jint refreshRate) |
| { |
| jobject displayMode = X11GD_CreateDisplayMode(env, width, height, |
| bitDepth, refreshRate); |
| if (!JNU_IsNull(env, displayMode)) { |
| jclass arrayListClass; |
| jmethodID mid; |
| arrayListClass = (*env)->GetObjectClass(env, arrayList); |
| if (JNU_IsNull(env, arrayListClass)) { |
| JNU_ThrowInternalError(env, |
| "Could not get class java.util.ArrayList"); |
| return; |
| } |
| mid = (*env)->GetMethodID(env, arrayListClass, "add", |
| "(Ljava/lang/Object;)Z"); |
| CHECK_NULL(mid); |
| if (mid == NULL) { |
| JNU_ThrowInternalError(env, |
| "Could not get method java.util.ArrayList.add()"); |
| return; |
| } |
| (*env)->CallObjectMethod(env, arrayList, mid, displayMode); |
| (*env)->DeleteLocalRef(env, displayMode); |
| } |
| } |
| |
| static void |
| X11GD_SetFullscreenMode(Window win, jboolean enabled) |
| { |
| Atom wmState = XInternAtom(awt_display, "_NET_WM_STATE", False); |
| Atom wmStateFs = XInternAtom(awt_display, |
| "_NET_WM_STATE_FULLSCREEN", False); |
| XWindowAttributes attr; |
| XEvent event; |
| |
| if (wmState == None || wmStateFs == None |
| || !XGetWindowAttributes(awt_display, win, &attr)) { |
| return; |
| } |
| |
| memset(&event, 0, sizeof(event)); |
| event.xclient.type = ClientMessage; |
| event.xclient.message_type = wmState; |
| event.xclient.display = awt_display; |
| event.xclient.window = win; |
| event.xclient.format = 32; |
| event.xclient.data.l[0] = enabled ? 1 : 0; // 1==add, 0==remove |
| event.xclient.data.l[1] = wmStateFs; |
| |
| XSendEvent(awt_display, attr.root, False, |
| SubstructureRedirectMask | SubstructureNotifyMask, |
| &event); |
| XSync(awt_display, False); |
| } |
| #endif /* !HEADLESS */ |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: initXrandrExtension |
| * Signature: ()Z |
| */ |
| JNIEXPORT jboolean JNICALL |
| Java_sun_awt_X11GraphicsDevice_initXrandrExtension |
| (JNIEnv *env, jclass x11gd) |
| { |
| #ifdef HEADLESS |
| return JNI_FALSE; |
| #else |
| int opcode = 0, firstEvent = 0, firstError = 0; |
| jboolean ret; |
| |
| AWT_LOCK(); |
| ret = (jboolean)XQueryExtension(awt_display, "RANDR", |
| &opcode, &firstEvent, &firstError); |
| if (ret) { |
| ret = X11GD_InitXrandrFuncs(env); |
| } |
| AWT_FLUSH_UNLOCK(); |
| |
| return ret; |
| #endif /* HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: getCurrentDisplayMode |
| * Signature: (I)Ljava/awt/DisplayMode; |
| */ |
| JNIEXPORT jobject JNICALL |
| Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode |
| (JNIEnv* env, jclass x11gd, jint screen) |
| { |
| #ifdef HEADLESS |
| return NULL; |
| #else |
| XRRScreenConfiguration *config; |
| jobject displayMode = NULL; |
| |
| AWT_LOCK(); |
| |
| if (screen < ScreenCount(awt_display)) { |
| |
| config = awt_XRRGetScreenInfo(awt_display, |
| RootWindow(awt_display, screen)); |
| if (config != NULL) { |
| Rotation rotation; |
| short curRate; |
| SizeID curSizeIndex; |
| XRRScreenSize *sizes; |
| int nsizes; |
| |
| curSizeIndex = awt_XRRConfigCurrentConfiguration(config, &rotation); |
| sizes = awt_XRRConfigSizes(config, &nsizes); |
| curRate = awt_XRRConfigCurrentRate(config); |
| |
| if ((sizes != NULL) && |
| (curSizeIndex < nsizes)) |
| { |
| XRRScreenSize curSize = sizes[curSizeIndex]; |
| displayMode = X11GD_CreateDisplayMode(env, |
| curSize.width, |
| curSize.height, |
| BIT_DEPTH_MULTI, |
| curRate); |
| } |
| |
| awt_XRRFreeScreenConfigInfo(config); |
| } |
| } |
| |
| AWT_FLUSH_UNLOCK(); |
| |
| return displayMode; |
| #endif /* HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: enumDisplayModes |
| * Signature: (ILjava/util/ArrayList;)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsDevice_enumDisplayModes |
| (JNIEnv* env, jclass x11gd, |
| jint screen, jobject arrayList) |
| { |
| #ifndef HEADLESS |
| |
| AWT_LOCK(); |
| |
| if (usingXinerama && XScreenCount(awt_display) > 0) { |
| XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, |
| RootWindow(awt_display, 0)); |
| if (res) { |
| if (res->noutput > screen) { |
| XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display, |
| res, res->outputs[screen]); |
| if (output_info) { |
| int i; |
| for (i = 0; i < res->nmode; i++) { |
| RRMode m = output_info->modes[i]; |
| int j; |
| XRRModeInfo *mode; |
| for (j = 0; j < res->nmode; j++) { |
| mode = &res->modes[j]; |
| if (mode->id == m) { |
| float rate = 0; |
| if (mode->hTotal && mode->vTotal) { |
| rate = ((float)mode->dotClock / |
| ((float)mode->hTotal * |
| (float)mode->vTotal)); |
| } |
| X11GD_AddDisplayMode(env, arrayList, |
| mode->width, mode->height, |
| BIT_DEPTH_MULTI, (int)(rate +.2)); |
| break; |
| } |
| } |
| } |
| awt_XRRFreeOutputInfo(output_info); |
| } |
| } |
| awt_XRRFreeScreenResources(res); |
| } |
| } else { |
| XRRScreenConfiguration *config; |
| |
| config = awt_XRRGetScreenInfo(awt_display, |
| RootWindow(awt_display, screen)); |
| if (config != NULL) { |
| int nsizes, i, j; |
| XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes); |
| |
| if (sizes != NULL) { |
| for (i = 0; i < nsizes; i++) { |
| int nrates; |
| XRRScreenSize size = sizes[i]; |
| short *rates = awt_XRRConfigRates(config, i, &nrates); |
| |
| for (j = 0; j < nrates; j++) { |
| X11GD_AddDisplayMode(env, arrayList, |
| size.width, |
| size.height, |
| BIT_DEPTH_MULTI, |
| rates[j]); |
| if ((*env)->ExceptionCheck(env)) { |
| break; |
| } |
| } |
| } |
| } |
| |
| awt_XRRFreeScreenConfigInfo(config); |
| } |
| } |
| |
| AWT_FLUSH_UNLOCK(); |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: configDisplayMode |
| * Signature: (IIII)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsDevice_configDisplayMode |
| (JNIEnv* env, jclass x11gd, |
| jint screen, jint width, jint height, jint refreshRate) |
| { |
| #ifndef HEADLESS |
| jboolean success = JNI_FALSE; |
| XRRScreenConfiguration *config; |
| Drawable root; |
| Rotation currentRotation = RR_Rotate_0; |
| |
| AWT_LOCK(); |
| |
| root = RootWindow(awt_display, screen); |
| config = awt_XRRGetScreenInfo(awt_display, root); |
| if (config != NULL) { |
| jboolean foundConfig = JNI_FALSE; |
| int chosenSizeIndex = -1; |
| short chosenRate = -1; |
| int nsizes; |
| XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes); |
| awt_XRRConfigRotations(config, ¤tRotation); |
| |
| if (sizes != NULL) { |
| int i, j; |
| |
| /* find the size index that matches the requested dimensions */ |
| for (i = 0; i < nsizes; i++) { |
| XRRScreenSize size = sizes[i]; |
| |
| if ((size.width == width) && (size.height == height)) { |
| /* we've found our size index... */ |
| int nrates; |
| short *rates = awt_XRRConfigRates(config, i, &nrates); |
| |
| /* now find rate that matches requested refresh rate */ |
| for (j = 0; j < nrates; j++) { |
| if (rates[j] == refreshRate) { |
| /* we've found our rate; break out of the loop */ |
| chosenSizeIndex = i; |
| chosenRate = rates[j]; |
| foundConfig = JNI_TRUE; |
| break; |
| } |
| } |
| |
| break; |
| } |
| } |
| } |
| |
| if (foundConfig) { |
| Status status = |
| awt_XRRSetScreenConfigAndRate(awt_display, config, root, |
| chosenSizeIndex, |
| currentRotation, |
| chosenRate, |
| CurrentTime); |
| |
| /* issue XSync to ensure immediate mode change */ |
| XSync(awt_display, False); |
| |
| if (status == RRSetConfigSuccess) { |
| success = JNI_TRUE; |
| } |
| } |
| |
| awt_XRRFreeScreenConfigInfo(config); |
| } |
| |
| AWT_FLUSH_UNLOCK(); |
| |
| if (!success && !(*env)->ExceptionCheck(env)) { |
| JNU_ThrowInternalError(env, "Could not set display mode"); |
| } |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: enterFullScreenExclusive |
| * Signature: (J)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsDevice_enterFullScreenExclusive |
| (JNIEnv* env, jclass x11gd, |
| jlong window) |
| { |
| #ifndef HEADLESS |
| Window win = (Window)window; |
| |
| AWT_LOCK(); |
| XSync(awt_display, False); /* ensures window is visible first */ |
| X11GD_SetFullscreenMode(win, JNI_TRUE); |
| AWT_UNLOCK(); |
| #endif /* !HEADLESS */ |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: exitFullScreenExclusive |
| * Signature: (J)V |
| */ |
| JNIEXPORT void JNICALL |
| Java_sun_awt_X11GraphicsDevice_exitFullScreenExclusive |
| (JNIEnv* env, jclass x11gd, |
| jlong window) |
| { |
| #ifndef HEADLESS |
| Window win = (Window)window; |
| |
| AWT_LOCK(); |
| X11GD_SetFullscreenMode(win, JNI_FALSE); |
| AWT_UNLOCK(); |
| #endif /* !HEADLESS */ |
| } |
| |
| /** |
| * End DisplayMode/FullScreen support |
| */ |
| |
| static char *get_output_screen_name(JNIEnv *env, int screen) { |
| if (!awt_XRRGetScreenResources || !awt_XRRGetOutputInfo) { |
| return NULL; |
| } |
| char *name = NULL; |
| AWT_LOCK(); |
| int scr = 0, out = 0; |
| if (usingXinerama && XScreenCount(awt_display) > 0) { |
| out = screen; |
| } else { |
| scr = screen; |
| } |
| |
| XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, |
| RootWindow(awt_display, scr)); |
| if (res) { |
| if (res->noutput > out) { |
| XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display, |
| res, res->outputs[out]); |
| if (output_info) { |
| if (output_info->name) { |
| name = strdup(output_info->name); |
| } |
| awt_XRRFreeOutputInfo(output_info); |
| } |
| } |
| awt_XRRFreeScreenResources(res); |
| } |
| AWT_UNLOCK(); |
| return name; |
| } |
| |
| /* |
| * Class: sun_awt_X11GraphicsDevice |
| * Method: getNativeScaleFactor |
| * Signature: (I)D |
| */ |
| JNIEXPORT jdouble JNICALL |
| Java_sun_awt_X11GraphicsDevice_getNativeScaleFactor |
| (JNIEnv *env, jobject this, jint screen) { |
| char *name = get_output_screen_name(env, screen); |
| double scale = getNativeScaleFactor(name); |
| if (name) { |
| free(name); |
| } |
| return scale; |
| } |