8009012: [macosx] DisplayChangedListener is not implemented in LWWindowPeer/CGraphicsEnvironment
Reviewed-by: anthony, bae
--- a/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java Tue Apr 30 17:27:48 2013 +0400
+++ b/jdk/src/macosx/classes/sun/awt/CGraphicsDevice.java Wed May 01 12:19:25 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/jdk/src/macosx/classes/sun/awt/CGraphicsEnvironment.java Tue Apr 30 17:27:48 2013 +0400
+++ b/jdk/src/macosx/classes/sun/awt/CGraphicsEnvironment.java Wed May 01 12:19:25 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() { }
@@ -78,8 +80,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).
*/
@@ -91,7 +94,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;
@@ -118,11 +121,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
@@ -135,31 +145,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
@@ -167,7 +176,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/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Tue Apr 30 17:27:48 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Wed May 01 12:19:25 2013 +0400
@@ -41,7 +41,7 @@
public class LWWindowPeer
extends LWContainerPeer<Window, JComponent>
- implements WindowPeer, FramePeer, DialogPeer, FullScreenCapable
+ implements FramePeer, DialogPeer, FullScreenCapable, DisplayChangedListener
{
public static enum PeerType {
SIMPLEWINDOW,
@@ -189,6 +189,7 @@
if (getSurfaceData() == null) {
replaceSurfaceData(false);
}
+ activateDisplayListener();
}
// Just a helper method
@@ -205,6 +206,7 @@
@Override
protected void disposeImpl() {
+ deactivateDisplayListener();
SurfaceData oldData = getSurfaceData();
synchronized (surfaceDataLock){
surfaceData = null;
@@ -875,6 +877,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(
@@ -936,7 +950,6 @@
graphicsDevice = newGraphicsDevice;
}
- // TODO: DisplayChangedListener stuff
final GraphicsConfiguration newGC = newGraphicsDevice.getDefaultConfiguration();
if (!setGraphicsConfig(newGC)) return false;
@@ -949,6 +962,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/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Tue Apr 30 17:27:48 2013 +0400
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Wed May 01 12:19:25 2013 +0400
@@ -32,6 +32,7 @@
import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
+import java.util.Objects;
import javax.swing.*;
@@ -916,9 +917,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/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m Tue Apr 30 17:27:48 2013 +0400
+++ b/jdk/src/macosx/native/sun/awt/CGraphicsEnv.m Wed May 01 12:19:25 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/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m Tue Apr 30 17:27:48 2013 +0400
+++ b/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m Wed May 01 12:19:25 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);