mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-15 21:05:11 +00:00
8354415: [Ubuntu25.04] api/java_awt/GraphicsDevice/indexTGF.html#SetDisplayMode - setDisplayMode_REFRESH_RATE_UNKNOWN fails: Height is different on vnc
Reviewed-by: honkar, kizune
This commit is contained in:
parent
40d159d4a9
commit
18c2e40de7
@ -333,7 +333,7 @@ public final class X11GraphicsDevice extends GraphicsDevice
|
||||
|
||||
private static native void enterFullScreenExclusive(long window);
|
||||
private static native void exitFullScreenExclusive(long window);
|
||||
private static native boolean initXrandrExtension();
|
||||
private static native boolean initXrandrExtension(boolean useOldConfigDisplayMode);
|
||||
private static native DisplayMode getCurrentDisplayMode(int screen);
|
||||
private static native void enumDisplayModes(int screen,
|
||||
ArrayList<DisplayMode> modes);
|
||||
@ -350,10 +350,11 @@ public final class X11GraphicsDevice extends GraphicsDevice
|
||||
*/
|
||||
private static synchronized boolean isXrandrExtensionSupported() {
|
||||
if (xrandrExtSupported == null) {
|
||||
xrandrExtSupported =
|
||||
Boolean.valueOf(initXrandrExtension());
|
||||
boolean useOldConfigDisplayMode =
|
||||
Boolean.getBoolean("awt.x11useOldConfigDisplayMode");
|
||||
xrandrExtSupported = initXrandrExtension(useOldConfigDisplayMode);
|
||||
}
|
||||
return xrandrExtSupported.booleanValue();
|
||||
return xrandrExtSupported;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -62,4 +62,11 @@ struct X11GraphicsConfigIDs {
|
||||
jfieldID bitsPerPixel;
|
||||
};
|
||||
|
||||
#define MAX_DISPLAY_MODES 256
|
||||
typedef struct {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
jint refresh;
|
||||
} DisplayMode;
|
||||
|
||||
#endif /* _AWT_GRAPHICSENV_H_ */
|
||||
|
||||
@ -55,6 +55,7 @@
|
||||
#include "gdefs.h"
|
||||
#include <dlfcn.h>
|
||||
#include "Trace.h"
|
||||
#include <math.h>
|
||||
|
||||
int awt_numScreens; /* Xinerama-aware number of screens */
|
||||
|
||||
@ -76,6 +77,8 @@ jmethodID awtNotifyMID = NULL;
|
||||
jmethodID awtNotifyAllMID = NULL;
|
||||
jboolean awtLockInited = JNI_FALSE;
|
||||
|
||||
static Bool useNewConfigDisplayMode = True;
|
||||
|
||||
/** Convenience macro for loading the lock-related method IDs. */
|
||||
#define GET_STATIC_METHOD(klass, method_id, method_name, method_sig) \
|
||||
do { \
|
||||
@ -1505,6 +1508,20 @@ typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,
|
||||
|
||||
typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo);
|
||||
|
||||
typedef void (*XRRSetScreenSizeType)(Display *dpy, Window window,
|
||||
int width, int height,
|
||||
int mmWidth, int mmHeight);
|
||||
|
||||
typedef Status (*XRRSetCrtcConfigType)(Display *dpy,
|
||||
XRRScreenResources *resources,
|
||||
RRCrtc crtc,
|
||||
Time timestamp,
|
||||
int x, int y,
|
||||
RRMode mode,
|
||||
Rotation rotation,
|
||||
RROutput *outputs,
|
||||
int noutputs);
|
||||
|
||||
static XRRQueryVersionType awt_XRRQueryVersion;
|
||||
static XRRGetScreenInfoType awt_XRRGetScreenInfo;
|
||||
static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo;
|
||||
@ -1520,6 +1537,8 @@ static XRRGetOutputInfoType awt_XRRGetOutputInfo;
|
||||
static XRRFreeOutputInfoType awt_XRRFreeOutputInfo;
|
||||
static XRRGetCrtcInfoType awt_XRRGetCrtcInfo;
|
||||
static XRRFreeCrtcInfoType awt_XRRFreeCrtcInfo;
|
||||
static XRRSetScreenSizeType awt_XRRSetScreenSize;
|
||||
static XRRSetCrtcConfigType awt_XRRSetCrtcConfig;
|
||||
|
||||
#define LOAD_XRANDR_FUNC(f) \
|
||||
do { \
|
||||
@ -1597,6 +1616,8 @@ X11GD_InitXrandrFuncs(JNIEnv *env)
|
||||
LOAD_XRANDR_FUNC(XRRFreeOutputInfo);
|
||||
LOAD_XRANDR_FUNC(XRRGetCrtcInfo);
|
||||
LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);
|
||||
LOAD_XRANDR_FUNC(XRRSetScreenSize);
|
||||
LOAD_XRANDR_FUNC(XRRSetCrtcConfig);
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
@ -1697,11 +1718,11 @@ X11GD_SetFullscreenMode(Window win, jboolean enabled)
|
||||
/*
|
||||
* Class: sun_awt_X11GraphicsDevice
|
||||
* Method: initXrandrExtension
|
||||
* Signature: ()Z
|
||||
* Signature: (Z)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_awt_X11GraphicsDevice_initXrandrExtension
|
||||
(JNIEnv *env, jclass x11gd)
|
||||
(JNIEnv *env, jclass x11gd, jboolean useOldConfigDisplayMode)
|
||||
{
|
||||
#if defined(NO_XRANDR)
|
||||
return JNI_FALSE;
|
||||
@ -1717,10 +1738,304 @@ Java_sun_awt_X11GraphicsDevice_initXrandrExtension
|
||||
}
|
||||
AWT_FLUSH_UNLOCK();
|
||||
|
||||
useNewConfigDisplayMode = !useOldConfigDisplayMode;
|
||||
|
||||
return ret;
|
||||
#endif /* NO_XRANDR */
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// display mode change via XRRSetCrtcConfig
|
||||
// ---------------------------------------------------
|
||||
|
||||
static jint refreshRateFromModeInfo(const XRRModeInfo *modeInfo) {
|
||||
if (!modeInfo->hTotal || !modeInfo->vTotal) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double vTotal = modeInfo->vTotal;
|
||||
|
||||
if (modeInfo->modeFlags & RR_Interlace) {
|
||||
vTotal /= 2;
|
||||
}
|
||||
|
||||
if (modeInfo->modeFlags & RR_DoubleScan) {
|
||||
vTotal *= 2;
|
||||
}
|
||||
|
||||
return (jint) round((double) modeInfo->dotClock / (vTotal * (double) modeInfo->hTotal));
|
||||
}
|
||||
|
||||
static inline Bool isLandscapeOrientation(XRRCrtcInfo* info) {
|
||||
if (!info) {
|
||||
return True;
|
||||
}
|
||||
return info->rotation == RR_Rotate_0 || info->rotation == RR_Rotate_180;
|
||||
}
|
||||
|
||||
static Bool xrrGetInfoForScreen(XRRScreenResources *res,
|
||||
int screen,
|
||||
XRRCrtcInfo **outCrtcInfo,
|
||||
XRROutputInfo **outOutputInfo) {
|
||||
if (!res) {
|
||||
return False;
|
||||
}
|
||||
|
||||
int screenX = 0;
|
||||
int screenY = 0;
|
||||
|
||||
if (usingXinerama) {
|
||||
int nscreens = 0;
|
||||
XineramaScreenInfo *screens = XineramaQueryScreens(awt_display, &nscreens);
|
||||
|
||||
if (!screens) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (screen >= nscreens) {
|
||||
XFree(screens);
|
||||
return False;
|
||||
}
|
||||
|
||||
XineramaScreenInfo xScreenInfo = screens[screen];
|
||||
|
||||
screenX = xScreenInfo.x_org;
|
||||
screenY= xScreenInfo.y_org;
|
||||
|
||||
XFree(screens);
|
||||
}
|
||||
|
||||
for (int i = 0; i < res->noutput; ++i) {
|
||||
XRROutputInfo *output = awt_XRRGetOutputInfo(awt_display, res, res->outputs[i]);
|
||||
if (!output) {
|
||||
continue;
|
||||
}
|
||||
if (output->connection == RR_Connected && output->crtc) {
|
||||
// output is connected and has an active mode
|
||||
XRRCrtcInfo *crtcInfo = awt_XRRGetCrtcInfo(awt_display, res, output->crtc);
|
||||
if (crtcInfo) {
|
||||
if (crtcInfo->mode != None
|
||||
&& crtcInfo->x == screenX
|
||||
&& crtcInfo->y == screenY) {
|
||||
if (outCrtcInfo) {
|
||||
*outCrtcInfo = crtcInfo;
|
||||
} else {
|
||||
awt_XRRFreeCrtcInfo(crtcInfo);
|
||||
}
|
||||
if (outOutputInfo) {
|
||||
*outOutputInfo = output;
|
||||
} else {
|
||||
awt_XRRFreeOutputInfo(output);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
awt_XRRFreeCrtcInfo(crtcInfo);
|
||||
}
|
||||
}
|
||||
awt_XRRFreeOutputInfo(output);
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static jobject xrrGetCurrentDisplayMode(JNIEnv* env, int screen) {
|
||||
XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, DefaultRootWindow(awt_display));
|
||||
if (!res) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XRRCrtcInfo* currentCrtcInfo = NULL;
|
||||
if (!xrrGetInfoForScreen(res, screen, ¤tCrtcInfo, NULL)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!currentCrtcInfo || currentCrtcInfo->mode == None) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (int i = 0; i < res->nmode; ++i) {
|
||||
if (res->modes[i].id == currentCrtcInfo->mode) {
|
||||
XRRModeInfo mode = res->modes[i];
|
||||
DisplayMode dm = {
|
||||
mode.width,
|
||||
mode.height,
|
||||
refreshRateFromModeInfo(&mode)
|
||||
};
|
||||
|
||||
Bool isLandscape = isLandscapeOrientation(currentCrtcInfo);
|
||||
|
||||
jint resultWidth = isLandscape ? (jint) dm.width : (jint) dm.height;
|
||||
jint resultHeight = isLandscape ? (jint) dm.height : (jint) dm.width;
|
||||
|
||||
jobject displayMode = X11GD_CreateDisplayMode(env,
|
||||
resultWidth,
|
||||
resultHeight,
|
||||
BIT_DEPTH_MULTI,
|
||||
dm.refresh);
|
||||
|
||||
awt_XRRFreeCrtcInfo(currentCrtcInfo);
|
||||
awt_XRRFreeScreenResources(res);
|
||||
|
||||
return displayMode;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (currentCrtcInfo) {
|
||||
awt_XRRFreeCrtcInfo(currentCrtcInfo);
|
||||
}
|
||||
awt_XRRFreeScreenResources(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Bool isUniqueDisplayMode(DisplayMode seen[], int count, unsigned int width, unsigned int height, int refresh) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (seen[i].width == width &&
|
||||
seen[i].height == height &&
|
||||
seen[i].refresh == refresh) {
|
||||
return False;
|
||||
}
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
static void xrrEnumDisplayModes(JNIEnv *env, jobject arrayList, jint screen) {
|
||||
XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, DefaultRootWindow(awt_display));
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
|
||||
XRRCrtcInfo *crtcInfo = NULL;
|
||||
XRROutputInfo *outputInfo = NULL;
|
||||
if (!xrrGetInfoForScreen(res, screen, &crtcInfo, &outputInfo)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
DisplayMode seenModes[MAX_DISPLAY_MODES];
|
||||
int seenCount = 0;
|
||||
|
||||
Bool isLandscape = isLandscapeOrientation(crtcInfo);
|
||||
|
||||
for (int i = 0; i < outputInfo->nmode; ++i) {
|
||||
RRMode mode_id = outputInfo->modes[i];
|
||||
|
||||
for (int j = 0; j < res->nmode; ++j) {
|
||||
if (res->modes[j].id == mode_id) {
|
||||
XRRModeInfo mode = res->modes[j];
|
||||
jint rr = refreshRateFromModeInfo(&mode);
|
||||
|
||||
// The refresh rate is stored as an integer in Java, so we need to round the double value.
|
||||
// Because of this rounding, duplicate modes may appear. We only keep the first one encountered.
|
||||
if (isUniqueDisplayMode(seenModes, seenCount, mode.width, mode.height, rr)) {
|
||||
seenModes[seenCount++] = (DisplayMode) {
|
||||
mode.width,
|
||||
mode.height,
|
||||
rr
|
||||
};
|
||||
X11GD_AddDisplayMode(env, arrayList,
|
||||
isLandscape ? (jint) mode.width : (jint) mode.height,
|
||||
isLandscape ? (jint) mode.height : (jint) mode.width,
|
||||
BIT_DEPTH_MULTI,
|
||||
rr);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (outputInfo) {
|
||||
awt_XRRFreeOutputInfo(outputInfo);
|
||||
}
|
||||
if (crtcInfo) {
|
||||
awt_XRRFreeCrtcInfo(crtcInfo);
|
||||
}
|
||||
awt_XRRFreeScreenResources(res);
|
||||
}
|
||||
|
||||
static void xrrChangeDisplayMode(jint screen, jint width, jint height, jint refreshRate) {
|
||||
Drawable root = DefaultRootWindow(awt_display);
|
||||
|
||||
|
||||
XRRScreenResources *res = awt_XRRGetScreenResources(awt_display, root);
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
|
||||
XRRCrtcInfo *crtcInfo = NULL;
|
||||
XRROutputInfo *outputInfo = NULL;
|
||||
|
||||
if (!xrrGetInfoForScreen(res, screen, &crtcInfo, &outputInfo)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
RRMode new_mode = None;
|
||||
|
||||
Bool isLandscape = isLandscapeOrientation(crtcInfo);
|
||||
|
||||
for (int i = 0; i < res->nmode; ++i) {
|
||||
XRRModeInfo mode = res->modes[i];
|
||||
jint rr = refreshRateFromModeInfo(&mode);
|
||||
|
||||
Bool matchW = (isLandscape ? mode.width : mode.height) == (unsigned int) width;
|
||||
Bool matchH = (isLandscape ? mode.height : mode.width) == (unsigned int) height;
|
||||
|
||||
if (matchW && matchH && rr == refreshRate) {
|
||||
for (int j = 0; j < outputInfo->nmode; ++j) {
|
||||
if (mode.id == outputInfo->modes[j]) {
|
||||
// belongs to our output
|
||||
new_mode = mode.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (new_mode != None) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_mode == None) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
awt_XRRSetCrtcConfig (awt_display, res, outputInfo->crtc, CurrentTime,
|
||||
0, 0, None, RR_Rotate_0, NULL, 0);
|
||||
|
||||
int resultMmWidth = outputInfo->mm_width
|
||||
? (int) outputInfo->mm_width
|
||||
: DisplayWidthMM(awt_display, DefaultScreen(awt_display));
|
||||
|
||||
int resultMmHeight = outputInfo->mm_height
|
||||
? (int) outputInfo->mm_height
|
||||
: XDisplayHeightMM(awt_display, DefaultScreen(awt_display));
|
||||
|
||||
awt_XRRSetScreenSize(awt_display, root,
|
||||
width, height,
|
||||
resultMmWidth, resultMmHeight);
|
||||
|
||||
Status s = awt_XRRSetCrtcConfig(awt_display, res, outputInfo->crtc,
|
||||
CurrentTime,
|
||||
crtcInfo->x, crtcInfo->y,
|
||||
new_mode, crtcInfo->rotation,
|
||||
crtcInfo->outputs, crtcInfo->noutput);
|
||||
|
||||
cleanup:
|
||||
if (crtcInfo) {
|
||||
awt_XRRFreeCrtcInfo(crtcInfo);
|
||||
}
|
||||
if (outputInfo) {
|
||||
awt_XRRFreeOutputInfo(outputInfo);
|
||||
}
|
||||
awt_XRRFreeScreenResources(res);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
// display mode change via XRRSetCrtcConfig
|
||||
// ---------------------------------------------------
|
||||
|
||||
/*
|
||||
* Class: sun_awt_X11GraphicsDevice
|
||||
* Method: getCurrentDisplayMode
|
||||
@ -1733,9 +2048,17 @@ Java_sun_awt_X11GraphicsDevice_getCurrentDisplayMode
|
||||
#if defined(NO_XRANDR)
|
||||
return NULL;
|
||||
#else
|
||||
XRRScreenConfiguration *config;
|
||||
jobject displayMode = NULL;
|
||||
|
||||
if (useNewConfigDisplayMode) {
|
||||
AWT_LOCK();
|
||||
displayMode = xrrGetCurrentDisplayMode(env, screen);
|
||||
AWT_FLUSH_UNLOCK();
|
||||
return displayMode;
|
||||
}
|
||||
|
||||
XRRScreenConfiguration *config;
|
||||
|
||||
AWT_LOCK();
|
||||
|
||||
if (screen < ScreenCount(awt_display)) {
|
||||
@ -1786,7 +2109,12 @@ Java_sun_awt_X11GraphicsDevice_enumDisplayModes
|
||||
{
|
||||
#if !defined(NO_XRANDR)
|
||||
|
||||
AWT_LOCK();
|
||||
if (useNewConfigDisplayMode) {
|
||||
AWT_LOCK();
|
||||
xrrEnumDisplayModes(env, arrayList, screen);
|
||||
AWT_FLUSH_UNLOCK();
|
||||
return;
|
||||
}
|
||||
|
||||
if (XScreenCount(awt_display) > 0) {
|
||||
|
||||
@ -1836,6 +2164,15 @@ Java_sun_awt_X11GraphicsDevice_configDisplayMode
|
||||
jint screen, jint width, jint height, jint refreshRate)
|
||||
{
|
||||
#if !defined(NO_XRANDR)
|
||||
if (useNewConfigDisplayMode) {
|
||||
AWT_LOCK();
|
||||
XGrabServer(awt_display);
|
||||
xrrChangeDisplayMode(screen, width, height, refreshRate);
|
||||
XUngrabServer(awt_display);
|
||||
AWT_FLUSH_UNLOCK();
|
||||
return;
|
||||
}
|
||||
|
||||
jboolean success = JNI_FALSE;
|
||||
XRRScreenConfiguration *config;
|
||||
Drawable root;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user