JBR-5594 Pass display configuration info from AppKit to EDT

This commit is contained in:
Nikita Gubarkov
2025-11-04 16:16:40 +01:00
committed by jbrbot
parent b284fad1b4
commit 0a3bb8842e
5 changed files with 106 additions and 58 deletions

View File

@@ -27,6 +27,7 @@ package com.apple.eawt;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.desktop.AboutEvent;
import java.awt.desktop.AboutHandler;
@@ -65,8 +66,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import sun.awt.AppContext;
import sun.awt.CGraphicsDevice;
import sun.awt.SunToolkit;
import sun.java2d.SunGraphicsEnvironment;
import sun.util.logging.PlatformLogger;
final class _AppEventHandler {
@@ -275,9 +276,14 @@ final class _AppEventHandler {
logger.fine("NOTIFY_SCREEN_CHANGE_PARAMETERS");
}
if (AppContext.getAppContext() != null) {
EventQueue.invokeLater(
() -> ((SunGraphicsEnvironment) GraphicsEnvironment.
getLocalGraphicsEnvironment()).displayParametersChanged());
CGraphicsDevice.DisplayConfiguration displayConfiguration = CGraphicsDevice.DisplayConfiguration.get();
EventQueue.invokeLater(() -> {
for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
if (gd instanceof CGraphicsDevice) {
((CGraphicsDevice) gd).updateDisplayParameters(displayConfiguration);
}
}
});
}
break;
default:

View File

@@ -34,18 +34,21 @@ import java.awt.Window;
import java.awt.geom.Rectangle2D;
import java.awt.peer.WindowPeer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.MacOSFlags;
import sun.java2d.metal.MTLGraphicsConfig;
import sun.java2d.opengl.CGLGraphicsConfig;
import sun.lwawt.macosx.CThreading;
import sun.util.logging.PlatformLogger;
import static java.awt.peer.ComponentPeer.SET_BOUNDS;
public final class CGraphicsDevice extends GraphicsDevice
implements DisplayChangedListener, DisplayParametersChangedListener {
implements DisplayChangedListener {
private static final PlatformLogger logger = PlatformLogger.getLogger(CGraphicsDevice.class.getName());
/**
@@ -192,20 +195,33 @@ public final class CGraphicsDevice extends GraphicsDevice
return s == scale && xr == xResolution && yr == yResolution && m == isMirroring && b.equals(bounds);
}
public void displayParametersChanged() {
Insets newScreenInsets = nativeGetScreenInsets(displayID);
if (!newScreenInsets.equals(screenInsets)) {
public void updateDisplayParameters(DisplayConfiguration config) {
Descriptor desc = config.getDescriptor(displayID);
if (desc == null) return;
if (!desc.screenInsets.equals(screenInsets)) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Screen insets for display(" + displayID + ") changed " +
"[top=" + screenInsets.top + ",left=" + screenInsets.left +
",bottom=" + screenInsets.bottom + ",right=" + screenInsets.right +
"]->[top=" + newScreenInsets.top + ",left=" + newScreenInsets.left +
",bottom=" + newScreenInsets.bottom + ",right=" + newScreenInsets.right +
"]->[top=" + desc.screenInsets.top + ",left=" + desc.screenInsets.left +
",bottom=" + desc.screenInsets.bottom + ",right=" + desc.screenInsets.right +
"]");
}
screenInsets = newScreenInsets;
screenInsets = desc.screenInsets;
}
int newScale = 1;
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
double debugScale = SunGraphicsEnvironment.getDebugScale();
newScale = (int) (debugScale >= 1 ? Math.round(debugScale) : (int) desc.scale);
}
if (newScale != scale) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Scale for display(" + displayID + ") changed " + scale + "->" + newScale);
}
scale = newScale;
}
}
@Override
public void paletteChanged() {
// devices do not need to react to this event.
@@ -386,4 +402,36 @@ public final class CGraphicsDevice extends GraphicsDevice
private static native Insets nativeGetScreenInsets(int displayID);
private static native Rectangle2D nativeGetBounds(int displayID);
private static native void nativeGetDisplayConfiguration(DisplayConfiguration config);
public static final class DisplayConfiguration {
private final Map<Integer, Descriptor> map = new HashMap<>();
private void addDescriptor(int displayID, int top, int left, int bottom, int right, double scale) {
map.put(displayID, new Descriptor(new Insets(top, left, bottom, right), scale));
}
public Descriptor getDescriptor(int displayID) {
return map.get(displayID);
}
public static DisplayConfiguration get() {
try {
return CThreading.executeOnAppKit(() -> {
DisplayConfiguration config = new DisplayConfiguration();
nativeGetDisplayConfiguration(config);
return config;
});
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
private static final class Descriptor {
private final Insets screenInsets;
private final double scale;
private Descriptor(Insets screenInsets, double scale) {
this.screenInsets = screenInsets;
this.scale = scale;
}
}
}

View File

@@ -585,3 +585,43 @@ JNI_COCOA_ENTER(env);
JNI_COCOA_EXIT(env);
return ret;
}
/*
* Class: sun_awt_CGraphicsDevice
* Method: nativeGetDisplayConfiguration
* Signature: (Lsun/awt/CGraphicsDevice$DisplayConfiguration;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetDisplayConfiguration
(JNIEnv *env, jclass class, jobject config) {
AWT_ASSERT_APPKIT_THREAD;
JNI_COCOA_ENTER(env);
DECLARE_CLASS(jc_DisplayConfiguration, "sun/awt/CGraphicsDevice$DisplayConfiguration");
DECLARE_METHOD(jc_DisplayConfiguration_addDescriptor, jc_DisplayConfiguration, "addDescriptor", "(IIIIID)V");
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
NSDictionary *screenInfo = [screen deviceDescription];
NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"];
jint displayID = [screenID unsignedIntValue];
jdouble scale = 1.0;
if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
scale = [screen backingScaleFactor];
}
NSRect frame = [screen frame];
NSRect visibleFrame = [screen visibleFrame];
// Convert between Cocoa's coordinate system and Java.
jint bottom = visibleFrame.origin.y - frame.origin.y;
jint top = frame.size.height - visibleFrame.size.height - bottom;
jint left = visibleFrame.origin.x - frame.origin.x;
jint right = frame.size.width - visibleFrame.size.width - left;
(*env)->CallVoidMethod(env, config, jc_DisplayConfiguration_addDescriptor,
displayID, top, left, bottom, right, scale);
CHECK_EXCEPTION();
}
JNI_COCOA_EXIT(env);
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, JetBrains s.r.o.. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.awt;
import java.util.EventListener;
public interface DisplayParametersChangedListener extends EventListener {
/**
* Invoked when the display parameters changed.
*/
public void displayParametersChanged();
}

View File

@@ -44,7 +44,6 @@ import java.util.Locale;
import java.util.TreeMap;
import sun.awt.DisplayChangedListener;
import sun.awt.DisplayParametersChangedListener;
import sun.awt.SunDisplayChanger;
import sun.font.FontManager;
import sun.font.FontManagerFactory;
@@ -60,7 +59,7 @@ import sun.java2d.pipe.Region;
* @see GraphicsConfiguration
*/
public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
implements DisplayChangedListener, DisplayParametersChangedListener {
implements DisplayChangedListener {
/** Establish the default font to be used by SG2D. */
private final Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
@@ -276,15 +275,6 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
displayChanger.notifyListeners();
}
@Override
public void displayParametersChanged() {
for (GraphicsDevice gd : getScreenDevices()) {
if (gd instanceof DisplayParametersChangedListener) {
((DisplayParametersChangedListener) gd).displayParametersChanged();
}
}
}
/**
* Part of the DisplayChangedListener interface:
* propagate this event to listeners