mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-09 21:19:38 +00:00
8382201: Transparent Window is Opaque w/o Volatile Buffering
Reviewed-by: prr, jdv
This commit is contained in:
parent
c2074e46a4
commit
ebb3d6888e
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, 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
|
||||
@ -51,6 +51,7 @@ import java.awt.Image;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.Window;
|
||||
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
@ -236,7 +237,11 @@ public final class MTLGraphicsConfig extends CGraphicsConfig
|
||||
public Image createAcceleratedImage(Component target,
|
||||
int width, int height)
|
||||
{
|
||||
ColorModel model = getColorModel(Transparency.OPAQUE);
|
||||
int transparency = Transparency.OPAQUE;
|
||||
if (target instanceof Window window && !window.isOpaque()) {
|
||||
transparency = Transparency.TRANSLUCENT;
|
||||
}
|
||||
ColorModel model = getColorModel(transparency);
|
||||
WritableRaster wr = model.createCompatibleWritableRaster(width, height);
|
||||
return new OffScreenImage(target, model, wr,
|
||||
model.isAlphaPremultiplied());
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2026, 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
|
||||
@ -34,6 +34,7 @@ import java.awt.Image;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.Window;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
@ -255,7 +256,11 @@ public final class CGLGraphicsConfig extends CGraphicsConfig
|
||||
public Image createAcceleratedImage(Component target,
|
||||
int width, int height)
|
||||
{
|
||||
ColorModel model = getColorModel(Transparency.OPAQUE);
|
||||
int transparency = Transparency.OPAQUE;
|
||||
if (target instanceof Window window && !window.isOpaque()) {
|
||||
transparency = Transparency.TRANSLUCENT;
|
||||
}
|
||||
ColorModel model = getColorModel(transparency);
|
||||
WritableRaster wr = model.createCompatibleWritableRaster(width, height);
|
||||
return new OffScreenImage(target, model, wr,
|
||||
model.isAlphaPremultiplied());
|
||||
|
||||
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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 8382201
|
||||
* @key headful
|
||||
* @summary This tests window translucency when
|
||||
* `swing.volatileImageBufferEnabled=false`
|
||||
* @requires os.family == "mac"
|
||||
* @run main/othervm -Dsun.java2d.opengl=false TranslucentDialogTest
|
||||
* @run main/othervm -Dsun.java2d.opengl=true TranslucentDialogTest
|
||||
*/
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.plaf.PanelUI;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Robot;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
|
||||
public class TranslucentDialogTest {
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("swing.volatileImageBufferEnabled", "false");
|
||||
TranslucentDialogTest test = new TranslucentDialogTest();
|
||||
test.run();
|
||||
}
|
||||
|
||||
static class Sample {
|
||||
final int x, y;
|
||||
Color before, after;
|
||||
|
||||
Sample(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
void assignBeforeColor(Robot robot) {
|
||||
before = robot.getPixelColor(x, y);
|
||||
}
|
||||
|
||||
void assignAfterColor(Robot robot) {
|
||||
after = robot.getPixelColor(x, y);
|
||||
}
|
||||
|
||||
boolean isIdentical(int tolerance) {
|
||||
int dRed = Math.abs(before.getRed() - after.getRed());
|
||||
int dGreen = Math.abs(before.getGreen() - after.getGreen());
|
||||
int dBlue = Math.abs(before.getBlue() - after.getBlue());
|
||||
return dRed < tolerance && dGreen < tolerance && dBlue < tolerance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Sample[ x = " + x + ", y = " + y + ", " +
|
||||
"before = 0x" + Integer.toHexString(
|
||||
before.getRGB()) +
|
||||
" after = 0x" + Integer.toHexString(
|
||||
after.getRGB());
|
||||
}
|
||||
}
|
||||
|
||||
JDialog translucentDialog;
|
||||
Sample transparentPixel, translucentPixel;
|
||||
Robot robot;
|
||||
|
||||
private void run() {
|
||||
try {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
translucentDialog = createDialog();
|
||||
translucentDialog.pack();
|
||||
translucentDialog.setLocationRelativeTo(null);
|
||||
transparentPixel = new Sample(translucentDialog.getX() + 4,
|
||||
translucentDialog.getY() + 4);
|
||||
translucentPixel = new Sample(translucentDialog.getX() +
|
||||
translucentDialog.getWidth()/2,
|
||||
translucentDialog.getY() +
|
||||
translucentDialog.getHeight()/2);
|
||||
try {
|
||||
robot = new Robot();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
transparentPixel.assignBeforeColor(robot);
|
||||
translucentPixel.assignBeforeColor(robot);
|
||||
int gray = (transparentPixel.before.getRed() +
|
||||
transparentPixel.before.getGreen() +
|
||||
transparentPixel.before.getBlue()) / 3;
|
||||
if (gray > 128) {
|
||||
System.out.println("using transparent black");
|
||||
translucentDialog.setBackground(new Color(0,0,0,0));
|
||||
} else {
|
||||
System.out.println("using transparent white");
|
||||
translucentDialog.setBackground(
|
||||
new Color(255, 255, 255, 0));
|
||||
}
|
||||
translucentDialog.setVisible(true);
|
||||
});
|
||||
|
||||
robot.waitForIdle();
|
||||
robot.delay(50);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
transparentPixel.assignAfterColor(robot);
|
||||
translucentPixel.assignAfterColor(robot);
|
||||
});
|
||||
|
||||
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
transparentPixel = translucentPixel = null;
|
||||
}
|
||||
|
||||
System.out.println("transparent pixel (border): " + transparentPixel);
|
||||
System.out.println("translucent pixel (center): " + translucentPixel);
|
||||
|
||||
if (!transparentPixel.isIdentical(10)) {
|
||||
// this is the main problem with JDK-8382201
|
||||
throw new RuntimeException("the border pixel wasn't supposed to change");
|
||||
}
|
||||
if (translucentPixel.isIdentical(10)) {
|
||||
// if this fails: this test isn't capturing pixels correctly.
|
||||
throw new RuntimeException("the center pixel was supposed to change");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
translucentDialog.dispose();
|
||||
});
|
||||
}
|
||||
|
||||
private static JDialog createDialog() {
|
||||
JDialog d = new JDialog();
|
||||
d.getRootPane().putClientProperty("Window.shadow", "false");
|
||||
JLabel instructions = new JLabel(
|
||||
"This test passes if this window is translucent");
|
||||
instructions.setBorder(new EmptyBorder(10,10,10,10));
|
||||
instructions.setOpaque(false);
|
||||
|
||||
d.setUndecorated(true);
|
||||
JPanel p = new JPanel();
|
||||
p.setOpaque(false);
|
||||
p.setBorder(new EmptyBorder(10,10,10,10));
|
||||
p.setUI(new PanelUI() {
|
||||
@Override
|
||||
public void paint(Graphics g, JComponent c) {
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
g2.setColor(new Color(220, 180, 0, 200));
|
||||
g2.fill(new RoundRectangle2D.Double(5, 5, c.getWidth() - 10,
|
||||
c.getHeight() - 10,20,20));
|
||||
}
|
||||
});
|
||||
p.add(instructions);
|
||||
d.getContentPane().add(p);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user