8167486: Device.getDisplayMode() doesn't report refresh rate on Linux in case of dual screen
authorssadetsky
Mon, 17 Oct 2016 10:14:38 +0300 (2016-10-17)
changeset 41793 7b9c71553d63
parent 41792 8b032394d44e
child 41794 e30c6574b042
8167486: Device.getDisplayMode() doesn't report refresh rate on Linux in case of dual screen Reviewed-by: serb
jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java
jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h
jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
jdk/test/java/awt/FullScreen/CurrentDisplayModeTest/CurrentDisplayModeTest.java
--- a/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java	Mon Oct 17 09:58:37 2016 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java	Mon Oct 17 10:14:38 2016 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -142,6 +142,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean equals(Object dm) {
         if (dm instanceof DisplayMode) {
             return equals((DisplayMode)dm);
@@ -153,9 +154,20 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public int hashCode() {
         return getWidth() + getHeight() + getBitDepth() * 7
             + getRefreshRate() * 13;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return getWidth() + "x" + getHeight() + "x" +
+               (getBitDepth() > 0 ? getBitDepth() + "bpp": "[Multi depth]")
+               + "@" + (getRefreshRate() > 0 ? getRefreshRate() + "Hz" :
+               "[Unknown refresh rate]");
+    }
 }
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h	Mon Oct 17 09:58:37 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h	Mon Oct 17 10:14:38 2016 +0300
@@ -118,6 +118,19 @@
     RRMode          *modes;
 } XRROutputInfo;
 
+typedef struct {
+    Time            timestamp;
+    int             x, y;
+    unsigned int    width, height;
+    RRMode          mode;
+    Rotation        rotation;
+    int             noutput;
+    RROutput        *outputs;
+    Rotation        rotations;
+    int             npossible;
+    RROutput        *possible;
+} XRRCrtcInfo;
+
 XRRScreenResources *XRRGetScreenResources (Display *dpy, Window window);
 
 void XRRFreeScreenResources (XRRScreenResources *resources);
@@ -126,6 +139,11 @@
                                                                RROutput output);
 void XRRFreeOutputInfo (XRROutputInfo *outputInfo);
 
+XRRCrtcInfo *XRRGetCrtcInfo (Display *dpy, XRRScreenResources *resources,
+                                                                   RRCrtc crtc);
+void XRRFreeCrtcInfo (XRRCrtcInfo *crtcInfo);
+
+
 /* internal representation is private to the library */
 typedef struct _XRRScreenConfiguration XRRScreenConfiguration;
 
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c	Mon Oct 17 09:58:37 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c	Mon Oct 17 10:14:38 2016 +0300
@@ -1667,6 +1667,11 @@
 
 typedef void (*XRRFreeOutputInfoType)(XRROutputInfo *outputInfo);
 
+typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,
+                                    XRRScreenResources *resources, RRCrtc crtc);
+
+typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo);
+
 static XRRQueryVersionType               awt_XRRQueryVersion;
 static XRRGetScreenInfoType              awt_XRRGetScreenInfo;
 static XRRFreeScreenConfigInfoType       awt_XRRFreeScreenConfigInfo;
@@ -1680,6 +1685,8 @@
 static XRRFreeScreenResourcesType        awt_XRRFreeScreenResources;
 static XRRGetOutputInfoType              awt_XRRGetOutputInfo;
 static XRRFreeOutputInfoType             awt_XRRFreeOutputInfo;
+static XRRGetCrtcInfoType                awt_XRRGetCrtcInfo;
+static XRRFreeCrtcInfoType               awt_XRRFreeCrtcInfo;
 
 #define LOAD_XRANDR_FUNC(f) \
     do { \
@@ -1755,6 +1762,8 @@
     LOAD_XRANDR_FUNC(XRRFreeScreenResources);
     LOAD_XRANDR_FUNC(XRRGetOutputInfo);
     LOAD_XRANDR_FUNC(XRRFreeOutputInfo);
+    LOAD_XRANDR_FUNC(XRRGetCrtcInfo);
+    LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);
 
     return JNI_TRUE;
 }
@@ -1895,7 +1904,49 @@
 
     AWT_LOCK();
 
-    if (screen < ScreenCount(awt_display)) {
+    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) {
+                    if (output_info->crtc) {
+                        XRRCrtcInfo *crtc_info =
+                                    awt_XRRGetCrtcInfo (awt_display, res,
+                                                        output_info->crtc);
+                        if (crtc_info) {
+                            if (crtc_info->mode) {
+                                int i;
+                                for (i = 0; i < res->nmode; i++) {
+                                    XRRModeInfo *mode = &res->modes[i];
+                                    if (mode->id == crtc_info->mode) {
+                                        float rate = 0;
+                                        if (mode->hTotal && mode->vTotal) {
+                                             rate = ((float)mode->dotClock /
+                                                    ((float)mode->hTotal *
+                                                    (float)mode->vTotal));
+                                        }
+                                        displayMode = X11GD_CreateDisplayMode(
+                                                           env,
+                                                           mode->width,
+                                                           mode->height,
+                                                           BIT_DEPTH_MULTI,
+                                                           (int)(rate +.2));
+                                        break;
+                                    }
+                                }
+                            }
+                            awt_XRRFreeCrtcInfo(crtc_info);
+                        }
+                    }
+                    awt_XRRFreeOutputInfo(output_info);
+                }
+            }
+            awt_XRRFreeScreenResources(res);
+        }
+    } else {
 
         config = awt_XRRGetScreenInfo(awt_display,
                                       RootWindow(awt_display, screen));
@@ -1954,7 +2005,7 @@
                                                      res, res->outputs[screen]);
                 if (output_info) {
                     int i;
-                    for (i = 0; i < res->nmode; i++) {
+                    for (i = 0; i < output_info->nmode; i++) {
                         RRMode m = output_info->modes[i];
                         int j;
                         XRRModeInfo *mode;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FullScreen/CurrentDisplayModeTest/CurrentDisplayModeTest.java	Mon Oct 17 10:14:38 2016 +0300
@@ -0,0 +1,52 @@
+/*
+ * 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 Device.getDisplayMode() doesn't report refresh rate on Linux in case
+ *          of dual screen
+ * @run main CurrentDisplayModeTest
+ */
+
+import java.awt.*;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class CurrentDisplayModeTest {
+    public static void main(String[] args) {
+        GraphicsDevice[] screenDevices = GraphicsEnvironment.
+                               getLocalGraphicsEnvironment().getScreenDevices();
+        for (GraphicsDevice screenDevice : screenDevices) {
+            DisplayMode currentMode = screenDevice.getDisplayMode();
+            System.out.println("current mode " + currentMode);
+            Set<DisplayMode> set = new HashSet<>(
+                                 Arrays.asList(screenDevice.getDisplayModes()));
+            if (!set.contains(currentMode)) {
+                throw new RuntimeException("Mode " + currentMode +
+                        " is not found in the modes list " + set);
+            }
+        }
+    }
+}