From 442c804d23038e9e0016317dccb0352179b605bb Mon Sep 17 00:00:00 2001 From: serb Date: Wed, 1 May 2013 12:19:25 +0400 Subject: [PATCH] 8009012: [macosx] DisplayChangedListener is not implemented in LWWindowPeer/CGraphicsEnvironment Reviewed-by: anthony, bae --- .../classes/sun/awt/CGraphicsDevice.java | 50 +++++++++--- .../classes/sun/awt/CGraphicsEnvironment.java | 79 +++++++++++-------- .../classes/sun/lwawt/LWWindowPeer.java | 31 +++++++- .../sun/lwawt/macosx/CPlatformWindow.java | 6 +- src/macosx/native/sun/awt/CGraphicsEnv.m | 7 +- .../native/sun/java2d/opengl/CGLLayer.m | 6 +- 6 files changed, 125 insertions(+), 54 deletions(-) diff --git a/src/macosx/classes/sun/awt/CGraphicsDevice.java b/src/macosx/classes/sun/awt/CGraphicsDevice.java index 16ae8a82d..a3dc7e4cd 100644 --- a/src/macosx/classes/sun/awt/CGraphicsDevice.java +++ b/src/macosx/classes/sun/awt/CGraphicsDevice.java @@ -35,10 +35,18 @@ import java.util.Objects; 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 @@ public final class CGraphicsDevice extends GraphicsDevice { // 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 @@ public final class CGraphicsDevice extends GraphicsDevice { */ @Override public String getIDstring() { - return "Display " + this.displayID; + return "Display " + displayID; } /** @@ -104,15 +112,37 @@ public final class CGraphicsDevice extends GraphicsDevice { } 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 @@ public final class CGraphicsDevice extends GraphicsDevice { 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); diff --git a/src/macosx/classes/sun/awt/CGraphicsEnvironment.java b/src/macosx/classes/sun/awt/CGraphicsEnvironment.java index ab435a93f..a2319e675 100644 --- a/src/macosx/classes/sun/awt/CGraphicsEnvironment.java +++ b/src/macosx/classes/sun/awt/CGraphicsEnvironment.java @@ -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 @@ public class CGraphicsEnvironment extends SunGraphicsEnvironment { 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 @@ public class CGraphicsEnvironment extends SunGraphicsEnvironment { } /** - * 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 @@ public class CGraphicsEnvironment extends SunGraphicsEnvironment { private native void deregisterDisplayReconfiguration(long context); /** Available CoreGraphics displays. */ - private final Map devices = new HashMap(); + private final Map devices = new HashMap<>(5); /** Reference to the display reconfiguration callback context. */ private final long displayReconfigContext; @@ -118,11 +121,18 @@ public class CGraphicsEnvironment extends SunGraphicsEnvironment { /** * 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 @@ public class CGraphicsEnvironment extends SunGraphicsEnvironment { } /** - * (Re)create all CGraphicsDevices - * - * @return + * (Re)create all CGraphicsDevices, reuses a devices if it is possible. */ - private synchronized void initDevices() { - devices.clear(); - - 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); - - final int[] displayIDs = getDisplayIDs(); + private void initDevices() { + synchronized (this) { + final Map old = new HashMap<>(devices); + devices.clear(); + + 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. + if (!old.containsKey(mainID)) { + old.put(mainID, new CGraphicsDevice(mainID)); + } - 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 @@ public class CGraphicsEnvironment extends SunGraphicsEnvironment { 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(); diff --git a/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 19f6e48f7..5ffaae70f 100644 --- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -41,7 +41,7 @@ import sun.util.logging.PlatformLogger; public class LWWindowPeer extends LWContainerPeer - implements WindowPeer, FramePeer, DialogPeer, FullScreenCapable + implements FramePeer, DialogPeer, FullScreenCapable, DisplayChangedListener { public static enum PeerType { SIMPLEWINDOW, @@ -189,6 +189,7 @@ public class LWWindowPeer if (getSurfaceData() == null) { replaceSurfaceData(false); } + activateDisplayListener(); } // Just a helper method @@ -205,6 +206,7 @@ public class LWWindowPeer @Override protected void disposeImpl() { + deactivateDisplayListener(); SurfaceData oldData = getSurfaceData(); synchronized (surfaceDataLock){ surfaceData = null; @@ -875,6 +877,18 @@ public class LWWindowPeer // ---- 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 @@ public class LWWindowPeer graphicsDevice = newGraphicsDevice; } - // TODO: DisplayChangedListener stuff final GraphicsConfiguration newGC = newGraphicsDevice.getDefaultConfiguration(); if (!setGraphicsConfig(newGC)) return false; @@ -949,6 +962,20 @@ public class LWWindowPeer 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. */ diff --git a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index a8062c789..b2f264f95 100644 --- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -32,6 +32,7 @@ import java.awt.peer.WindowPeer; import java.beans.*; import java.lang.reflect.InvocationTargetException; import java.util.List; +import java.util.Objects; import javax.swing.*; @@ -916,9 +917,12 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo 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(); } } diff --git a/src/macosx/native/sun/awt/CGraphicsEnv.m b/src/macosx/native/sun/awt/CGraphicsEnv.m index da018a2de..8f8a53c31 100644 --- a/src/macosx/native/sun/awt/CGraphicsEnv.m +++ b/src/macosx/native/sun/awt/CGraphicsEnv.m @@ -124,10 +124,11 @@ static void displaycb_handle 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); }); } diff --git a/src/macosx/native/sun/java2d/opengl/CGLLayer.m b/src/macosx/native/sun/java2d/opengl/CGLLayer.m index 000684ee9..e0074eb4e 100644 --- a/src/macosx/native/sun/java2d/opengl/CGLLayer.m +++ b/src/macosx/native/sun/java2d/opengl/CGLLayer.m @@ -216,7 +216,11 @@ Java_sun_java2d_opengl_CGLLayer_nativeSetScale { 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); -- GitLab