8022810: Cannot list all the available display modes on Ubuntu linux in case of two screen devices
Reviewed-by: alexsch, serb
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h Tue Jul 05 09:48:49 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h Tue Jul 05 12:37:36 2016 +0300
@@ -5,8 +5,8 @@
/*
* $XFree86: xc/lib/Xrandr/Xrandr.h,v 1.9 2002/09/29 23:39:44 keithp Exp $
*
- * Copyright © 2000 Compaq Computer Corporation, Inc.
- * Copyright © 2002 Hewlett-Packard Company, Inc.
+ * Copyright © 2000 Compaq Computer Corporation, Inc.
+ * Copyright © 2002 Hewlett-Packard Company, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -66,6 +66,65 @@
int mheight;
} XRRScreenChangeNotifyEvent;
+typedef XID RROutput;
+typedef XID RRCrtc;
+typedef XID RRMode;
+
+typedef unsigned long XRRModeFlags;
+
+typedef struct {
+ RRMode id;
+ unsigned int width;
+ unsigned int height;
+ unsigned long dotClock;
+ unsigned int hSyncStart;
+ unsigned int hSyncEnd;
+ unsigned int hTotal;
+ unsigned int hSkew;
+ unsigned int vSyncStart;
+ unsigned int vSyncEnd;
+ unsigned int vTotal;
+ char *name;
+ unsigned int nameLength;
+ XRRModeFlags modeFlags;
+} XRRModeInfo;
+
+typedef struct {
+ Time timestamp;
+ Time configTimestamp;
+ int ncrtc;
+ RRCrtc *crtcs;
+ int noutput;
+ RROutput *outputs;
+ int nmode;
+ XRRModeInfo *modes;
+} XRRScreenResources;
+
+typedef struct {
+ Time timestamp;
+ RRCrtc crtc;
+ char *name;
+ int nameLen;
+ unsigned long mm_width;
+ unsigned long mm_height;
+ Connection connection;
+ SubpixelOrder subpixel_order;
+ int ncrtc;
+ RRCrtc *crtcs;
+ int nclone;
+ RROutput *clones;
+ int nmode;
+ int npreferred;
+ RRMode *modes;
+} XRROutputInfo;
+
+XRRScreenResources *XRRGetScreenResources (Display *dpy, Window window);
+
+void XRRFreeScreenResources (XRRScreenResources *resources);
+
+XRROutputInfo * XRRGetOutputInfo (Display *dpy, XRRScreenResources *resources,
+ RROutput output);
+void XRRFreeOutputInfo (XRROutputInfo *outputInfo);
/* internal representation is private to the library */
typedef struct _XRRScreenConfiguration XRRScreenConfiguration;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Tue Jul 05 09:48:49 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c Tue Jul 05 12:37:36 2016 +0300
@@ -1657,6 +1657,16 @@
(*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;
@@ -1666,6 +1676,10 @@
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 { \
@@ -1737,6 +1751,10 @@
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;
}
@@ -1924,36 +1942,73 @@
jint screen, jobject arrayList)
{
#ifndef HEADLESS
- XRRScreenConfiguration *config;
AWT_LOCK();
- config = awt_XRRGetScreenInfo(awt_display,
- RootWindow(awt_display, screen));
- if (config != NULL) {
- int nsizes, i, j;
- XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
+ 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;
- if (sizes != NULL) {
- for (i = 0; i < nsizes; i++) {
- int nrates;
- XRRScreenSize size = sizes[i];
- short *rates = awt_XRRConfigRates(config, i, &nrates);
+ config = awt_XRRGetScreenInfo(awt_display,
+ RootWindow(awt_display, screen));
+ if (config != NULL) {
+ int nsizes, i, j;
+ XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
- for (j = 0; j < nrates; j++) {
- X11GD_AddDisplayMode(env, arrayList,
- size.width,
- size.height,
- BIT_DEPTH_MULTI,
- rates[j]);
- if ((*env)->ExceptionCheck(env)) {
- break;
+ 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_XRRFreeScreenConfigInfo(config);
}
AWT_FLUSH_UNLOCK();
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/randr.h Tue Jul 05 09:48:49 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/randr.h Tue Jul 05 12:37:36 2016 +0300
@@ -5,8 +5,8 @@
/*
* $XFree86: xc/include/extensions/randr.h,v 1.4 2001/11/24 07:24:58 keithp Exp $
*
- * Copyright © 2000, Compaq Computer Corporation,
- * Copyright © 2002, Hewlett Packard, Inc.
+ * Copyright © 2000, Compaq Computer Corporation,
+ * Copyright © 2002, Hewlett Packard, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -31,6 +31,7 @@
#ifndef _RANDR_H_
#define _RANDR_H_
+typedef unsigned short Connection;
typedef unsigned short Rotation;
typedef unsigned short SizeID;
typedef unsigned short SubpixelOrder;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/GraphicsDevice/DisplayModes/CompareToXrandrTest.java Tue Jul 05 12:37:36 2016 +0300
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8022810
+ * @summary Cannot list all the available display modes on Ubuntu linux in case
+ * of two screen devices
+ * @run main CompareToXrandrTest
+ */
+
+import java.awt.GraphicsEnvironment;
+import java.awt.GraphicsDevice;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class CompareToXrandrTest {
+
+ public static void main(String[] args) throws Exception {
+ if (!new File("/usr/bin/xrandr").exists()) {
+ System.out.println("No xrandr tool to compare");
+ return;
+ }
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ Runtime.getRuntime().exec("/usr/bin/xrandr").getInputStream()));
+ reader.readLine();
+ reader.readLine();
+ Pattern pattern = Pattern.compile("^\\s*(\\d+x\\d+)");
+
+ for (GraphicsDevice d : GraphicsEnvironment
+ .getLocalGraphicsEnvironment().getScreenDevices()) {
+
+ Set<String> xrandrModes = reader.lines().map(pattern::matcher)
+ .takeWhile(Matcher::find).map(m -> m.group(1))
+ .collect(Collectors.toSet());
+
+ Set<String> javaModes = Arrays.stream(d.getDisplayModes())
+ .map(m -> m.getWidth() + "x" + m.getHeight())
+ .collect(Collectors.toSet());
+
+ if (!xrandrModes.equals(javaModes)) {
+ throw new RuntimeException("Failed");
+ } else {
+ System.out.println("Device " + d + ": " + javaModes.size() +
+ " modes found.");
+ }
+ }
+ }
+}