changeset 6090:a13d508c69a8

8009012: [macosx] DisplayChangedListener is not implemented in LWWindowPeer/CGraphicsEnvironment Reviewed-by: anthony, bae
author serb
date Mon, 20 May 2013 15:35:37 +0400
parents 23a5c142b13f
children 0bb10924802a
files src/macosx/classes/sun/awt/CGraphicsDevice.java src/macosx/classes/sun/awt/CGraphicsEnvironment.java src/macosx/classes/sun/lwawt/LWWindowPeer.java src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java src/macosx/native/sun/awt/CGraphicsEnv.m src/macosx/native/sun/java2d/opengl/CGLLayer.m
diffstat 6 files changed, 123 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/src/macosx/classes/sun/awt/CGraphicsDevice.java	Mon May 06 14:17:59 2013 -0700
+++ b/src/macosx/classes/sun/awt/CGraphicsDevice.java	Mon May 20 15:35:37 2013 +0400
@@ -35,10 +35,18 @@
 
 import sun.java2d.opengl.CGLGraphicsConfig;
 
-public final class CGraphicsDevice extends GraphicsDevice {
+public final class CGraphicsDevice extends GraphicsDevice
+        implements DisplayChangedListener {
 
-    // CoreGraphics display ID
-    private final int displayID;
+    /**
+     * CoreGraphics display ID. This identifier can become non-valid at any time
+     * therefore methods, which is using this id should be ready to it.
+     */
+    private volatile int displayID;
+    private volatile Insets screenInsets;
+    private volatile double xResolution;
+    private volatile double yResolution;
+    private volatile int scale;
 
     // Array of all GraphicsConfig instances for this device
     private final GraphicsConfiguration[] configs;
@@ -51,7 +59,7 @@
     // Save/restore DisplayMode for the Full Screen mode
     private DisplayMode originalMode;
 
-    public CGraphicsDevice(int displayID) {
+    public CGraphicsDevice(final int displayID) {
         this.displayID = displayID;
         configs = new GraphicsConfiguration[] {
             CGLGraphicsConfig.getConfig(this, 0)
@@ -89,7 +97,7 @@
      */
     @Override
     public String getIDstring() {
-        return "Display " + this.displayID;
+        return "Display " + displayID;
     }
 
     /**
@@ -104,15 +112,37 @@
     }
 
     public double getXResolution() {
-        return nativeGetXResolution(displayID);
+        return xResolution;
     }
 
     public double getYResolution() {
-        return nativeGetYResolution(displayID);
+        return yResolution;
     }
 
     public Insets getScreenInsets() {
-        return nativeGetScreenInsets(displayID);
+        return screenInsets;
+    }
+
+    public int getScaleFactor() {
+        return scale;
+    }
+
+    public void invalidate(final int defaultDisplayID) {
+        displayID = defaultDisplayID;
+    }
+
+    @Override
+    public void displayChanged() {
+        xResolution = nativeGetXResolution(displayID);
+        yResolution = nativeGetYResolution(displayID);
+        screenInsets = nativeGetScreenInsets(displayID);
+        scale = (int) nativeGetScaleFactor(displayID);
+        //TODO configs/fullscreenWindow/modes?
+    }
+
+    @Override
+    public void paletteChanged() {
+        // devices do not need to react to this event.
     }
 
     /**
@@ -219,10 +249,6 @@
         return nativeGetDisplayModes(displayID);
     }
 
-    public int getScaleFactor() {
-        return (int) nativeGetScaleFactor(displayID);
-    }
-
     private static native double nativeGetScaleFactor(int displayID);
 
     private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate);
--- a/src/macosx/classes/sun/awt/CGraphicsEnvironment.java	Mon May 06 14:17:59 2013 -0700
+++ b/src/macosx/classes/sun/awt/CGraphicsEnvironment.java	Mon May 20 15:35:37 2013 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, 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
@@ -26,19 +26,20 @@
 package sun.awt;
 
 import java.awt.*;
-import java.awt.print.*;
 import java.util.*;
 
 import sun.java2d.*;
 
 /**
- * This is an implementation of a GraphicsEnvironment object for the default local GraphicsEnvironment used by the Java
- * Runtime Environment for Mac OS X GUI environments.
+ * This is an implementation of a GraphicsEnvironment object for the default
+ * local GraphicsEnvironment used by the Java Runtime Environment for Mac OS X
+ * GUI environments.
  *
  * @see GraphicsDevice
  * @see GraphicsConfiguration
  */
-public class CGraphicsEnvironment extends SunGraphicsEnvironment {
+public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
+
     // Global initialization of the Cocoa runtime.
     private static native void initCocoa();
 
@@ -53,7 +54,8 @@
     private static native int getMainDisplayID();
 
     /**
-     * Noop function that just acts as an entry point for someone to force a static initialization of this class.
+     * Noop function that just acts as an entry point for someone to force a
+     * static initialization of this class.
      */
     public static void init() { }
 
@@ -72,8 +74,9 @@
     }
 
     /**
-     * Register the instance with CGDisplayRegisterReconfigurationCallback()
-     * The registration uses a weak global reference -- if our instance is garbage collected, the reference will be dropped.
+     * Register the instance with CGDisplayRegisterReconfigurationCallback().
+     * The registration uses a weak global reference -- if our instance is
+     * garbage collected, the reference will be dropped.
      *
      * @return Return the registration context (a pointer).
      */
@@ -85,7 +88,7 @@
     private native void deregisterDisplayReconfiguration(long context);
 
     /** Available CoreGraphics displays. */
-    private final Map<Integer, CGraphicsDevice> devices = new HashMap<Integer, CGraphicsDevice>();
+    private final Map<Integer, CGraphicsDevice> devices = new HashMap<>(5);
 
     /** Reference to the display reconfiguration callback context. */
     private final long displayReconfigContext;
@@ -112,11 +115,18 @@
     /**
      * Called by the CoreGraphics Display Reconfiguration Callback.
      *
-     * @param displayId
-     *            CoreGraphics displayId
+     * @param displayId CoreGraphics displayId
+     * @param removed   true if displayId was removed, false otherwise.
      */
-    void _displayReconfiguration(long displayId) {
-        displayChanged();
+    void _displayReconfiguration(final int displayId, final boolean removed) {
+        synchronized (this) {
+            if (removed && devices.containsKey(displayId)) {
+                final CGraphicsDevice gd = devices.remove(displayId);
+                gd.invalidate(getMainDisplayID());
+                gd.displayChanged();
+            }
+        }
+        initDevices();
     }
 
     @Override
@@ -129,31 +139,30 @@
     }
 
     /**
-     * (Re)create all CGraphicsDevices
-     *
-     * @return
+     * (Re)create all CGraphicsDevices, reuses a devices if it is possible.
      */
-    private synchronized void initDevices() {
-        devices.clear();
+    private void initDevices() {
+        synchronized (this) {
+            final Map<Integer, CGraphicsDevice> old = new HashMap<>(devices);
+            devices.clear();
 
-        int mainID = getMainDisplayID();
+            int mainID = getMainDisplayID();
 
-        // initialization of the graphics device may change
-        // list of displays on hybrid systems via an activation
-        // of discrete video.
-        // So, we initialize the main display first, and then
-        // retrieve actual list of displays.
-        CGraphicsDevice mainDevice = new CGraphicsDevice(mainID);
+            // initialization of the graphics device may change
+            // list of displays on hybrid systems via an activation
+            // of discrete video.
+            // So, we initialize the main display first, and then
+            // retrieve actual list of displays.
+            if (!old.containsKey(mainID)) {
+                old.put(mainID, new CGraphicsDevice(mainID));
+            }
 
-        final int[] displayIDs = getDisplayIDs();
-
-        for (int displayID : displayIDs) {
-            if (displayID != mainID) {
-                devices.put(displayID, new CGraphicsDevice(displayID));
-            } else {
-                devices.put(mainID, mainDevice);
+            for (final int id : getDisplayIDs()) {
+                devices.put(id, old.containsKey(id) ? old.get(id)
+                                                    : new CGraphicsDevice(id));
             }
         }
+        displayChanged();
     }
 
     @Override
@@ -161,7 +170,7 @@
         final int mainDisplayID = getMainDisplayID();
         CGraphicsDevice d = devices.get(mainDisplayID);
         if (d == null) {
-            // we do not exepct that this may happen, the only responce
+            // we do not expect that this may happen, the only response
             // is to re-initialize the list of devices
             initDevices();
 
--- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Mon May 06 14:17:59 2013 -0700
+++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Mon May 20 15:35:37 2013 +0400
@@ -42,7 +42,7 @@
 
 public class LWWindowPeer
     extends LWContainerPeer<Window, JComponent>
-    implements WindowPeer, FramePeer, DialogPeer, FullScreenCapable
+    implements FramePeer, DialogPeer, FullScreenCapable, DisplayChangedListener
 {
     public static enum PeerType {
         SIMPLEWINDOW,
@@ -194,6 +194,7 @@
         if (getSurfaceData() == null) {
             replaceSurfaceData(false);
         }
+        activateDisplayListener();
     }
 
     // Just a helper method
@@ -215,6 +216,7 @@
 
     @Override
     protected void disposeImpl() {
+        deactivateDisplayListener();
         SurfaceData oldData = getSurfaceData();
         synchronized (surfaceDataLock){
             surfaceData = null;
@@ -920,6 +922,18 @@
 
     // ---- UTILITY METHODS ---- //
 
+    private void activateDisplayListener() {
+        final GraphicsEnvironment ge =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+        ((SunGraphicsEnvironment) ge).addDisplayChangedListener(this);
+    }
+
+    private void deactivateDisplayListener() {
+        final GraphicsEnvironment ge =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+        ((SunGraphicsEnvironment) ge).removeDisplayChangedListener(this);
+    }
+
     private void postWindowStateChangedEvent(int newWindowState) {
         if (getTarget() instanceof Frame) {
             AWTAccessor.getFrameAccessor().setExtendedState(
@@ -981,7 +995,6 @@
             graphicsDevice = newGraphicsDevice;
         }
 
-        // TODO: DisplayChangedListener stuff
         final GraphicsConfiguration newGC = newGraphicsDevice.getDefaultConfiguration();
 
         if (!setGraphicsConfig(newGC)) return false;
@@ -994,6 +1007,20 @@
         return true;
     }
 
+    @Override
+    public final void displayChanged() {
+        updateGraphicsDevice();
+        // Replace surface unconditionally, because internal state of the
+        // GraphicsDevice could be changed.
+        replaceSurfaceData();
+        repaintPeer();
+    }
+
+    @Override
+    public final void paletteChanged() {
+        // components do not need to react to this event.
+    }
+
     /*
      * May be called by delegate to provide SD to Java2D code.
      */
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Mon May 06 14:17:59 2013 -0700
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Mon May 20 15:35:37 2013 +0400
@@ -33,6 +33,7 @@
 import java.beans.*;
 import java.lang.reflect.InvocationTargetException;
 import java.util.List;
+import java.util.Objects;
 
 import javax.swing.*;
 
@@ -925,9 +926,12 @@
 
         final Rectangle oldB = nativeBounds;
         nativeBounds = new Rectangle(x, y, width, height);
+        final GraphicsConfiguration oldGC = peer.getGraphicsConfiguration();
         peer.notifyReshape(x, y, width, height);
+        final GraphicsConfiguration newGC = peer.getGraphicsConfiguration();
+        // System-dependent appearance optimization.
         if ((byUser && !oldB.getSize().equals(nativeBounds.getSize()))
-            || isFullScreenAnimationOn) {
+            || isFullScreenAnimationOn || !Objects.equals(newGC, oldGC)) {
             flushBuffers();
         }
     }
--- a/src/macosx/native/sun/awt/CGraphicsEnv.m	Mon May 06 14:17:59 2013 -0700
+++ b/src/macosx/native/sun/awt/CGraphicsEnv.m	Mon May 20 15:35:37 2013 +0400
@@ -124,10 +124,11 @@
 
         jobject graphicsEnv = [wrapper jObjectWithEnv:env];
         if (graphicsEnv == NULL) return; // ref already GC'd
-
         static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");
-        static JNF_MEMBER_CACHE(jm_displayReconfiguration, jc_CGraphicsEnvironment, "_displayReconfiguration", "(J)V");
-        JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration);
+        static JNF_MEMBER_CACHE(jm_displayReconfiguration, jc_CGraphicsEnvironment, "_displayReconfiguration", "(IZ)V");
+        JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration,
+                            (jint) display, 
+                            (jboolean) flags & kCGDisplayRemoveFlag);
     });
 }
 
--- a/src/macosx/native/sun/java2d/opengl/CGLLayer.m	Mon May 06 14:17:59 2013 -0700
+++ b/src/macosx/native/sun/java2d/opengl/CGLLayer.m	Mon May 20 15:35:37 2013 +0400
@@ -216,7 +216,11 @@
 {
     JNF_COCOA_ENTER(env);
     CGLLayer *layer = jlong_to_ptr(layerPtr);
-    [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
+    // We always call all setXX methods asynchronously, exception is only in 
+    // this method where we need to change native texture size and layer's scale
+    // in one call on appkit, otherwise we'll get window's contents blinking, 
+    // during screen-2-screen moving.
+    [ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){
         layer.contentsScale = scale;
     }];
     JNF_COCOA_EXIT(env);