mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-07 09:01:42 +01:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5438a83c83 | ||
|
|
230ef3a2b0 | ||
|
|
616b476674 |
@@ -89,7 +89,7 @@ AC_DEFUN_ONCE([LIB_SETUP_VULKAN],
|
||||
if (test "x${with_vulkan_shader_compiler}" = x || test "x${with_vulkan_shader_compiler}" = xglslc); then
|
||||
UTIL_LOOKUP_PROGS(GLSLC, glslc)
|
||||
SHADER_COMPILER="$GLSLC"
|
||||
VULKAN_SHADER_COMPILER="glslc --target-env=vulkan1.2 -mfmt=num"
|
||||
VULKAN_SHADER_COMPILER="glslc --target-env=vulkan1.2 -mfmt=num -o"
|
||||
fi
|
||||
|
||||
# Check glslangValidator
|
||||
@@ -97,8 +97,7 @@ AC_DEFUN_ONCE([LIB_SETUP_VULKAN],
|
||||
test "x$SHADER_COMPILER" = x; then
|
||||
UTIL_LOOKUP_PROGS(GLSLANG, glslangValidator)
|
||||
SHADER_COMPILER="$GLSLANG"
|
||||
# Newer glslangValidator could use -P\"\#extension GL_GOOGLE_include_directive: require\"
|
||||
VULKAN_SHADER_COMPILER="glslangValidator --target-env vulkan1.2 -x"
|
||||
VULKAN_SHADER_COMPILER="glslangValidator --target-env vulkan1.2 -x -o"
|
||||
fi
|
||||
|
||||
if test "x$SHADER_COMPILER" = x; then
|
||||
|
||||
@@ -35,7 +35,6 @@ WAYLAND_BASIC_PROTOCOL_FILES := \
|
||||
$(WAYLAND_PROTOCOLS_ROOT)/staging/xdg-activation/xdg-activation-v1.xml \
|
||||
$(WAYLAND_PROTOCOLS_ROOT)/unstable/primary-selection/primary-selection-unstable-v1.xml \
|
||||
$(WAYLAND_PROTOCOLS_ROOT)/unstable/xdg-output/xdg-output-unstable-v1.xml \
|
||||
$(WAYLAND_PROTOCOLS_ROOT)/unstable/relative-pointer/relative-pointer-unstable-v1.xml \
|
||||
$(GTK_SHELL1_PROTOCOL_PATH) \
|
||||
#
|
||||
|
||||
|
||||
@@ -199,7 +199,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \
|
||||
-framework OpenGL, \
|
||||
LIBS_windows := advapi32.lib comctl32.lib comdlg32.lib delayimp.lib \
|
||||
gdi32.lib gdiplus.lib imm32.lib kernel32.lib ole32.lib shell32.lib shlwapi.lib \
|
||||
user32.lib uuid.lib winmm.lib winspool.lib dwmapi.lib $(A11Y_NVDA_ANNOUNCING_LIBS) oleacc.lib, \
|
||||
user32.lib uuid.lib winmm.lib winspool.lib dwmapi.lib $(A11Y_NVDA_ANNOUNCING_LIBS), \
|
||||
VERSIONINFO_RESOURCE := $(LIBAWT_VERSIONINFO_RESOURCE), \
|
||||
EXTRA_RCFLAGS := $(LIBAWT_RCFLAGS), \
|
||||
STATIC_LIB_EXCLUDE_OBJS := $(LIBAWT_STATIC_EXCLUDE_OBJS), \
|
||||
@@ -220,7 +220,7 @@ endif
|
||||
# Compile Vulkan shaders
|
||||
define compile-spirv
|
||||
$(call MakeTargetDir)
|
||||
$(VULKAN_SHADER_COMPILER) -D$(call uppercase,$(patsubst .%,STAGE_%,$(suffix $<))) -o '$(call DecodeSpace, $@)' '$(call DecodeSpace, $<)'
|
||||
$(VULKAN_SHADER_COMPILER) '$(call DecodeSpace, $@)' '$(call DecodeSpace, $<)'
|
||||
endef
|
||||
spirv-name = $(strip $1).h
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import sun.lwawt.macosx.CFLayer;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Window;
|
||||
|
||||
@@ -50,13 +51,12 @@ public class MTLLayer extends CFLayer {
|
||||
private static native void nativeSetOpaque(long layerPtr, boolean opaque);
|
||||
|
||||
private int scale = 1;
|
||||
private final boolean perfCountersEnabled;
|
||||
|
||||
public MTLLayer(LWWindowPeer peer) {
|
||||
super(0, true);
|
||||
|
||||
Window target = (peer != null) ? peer.getTarget() : null;
|
||||
this.perfCountersEnabled = (target != null) && AWTAccessor.getWindowAccessor().countersEnabled(target);
|
||||
boolean perfCountersEnabled = (target != null) && AWTAccessor.getWindowAccessor().countersEnabled(target);
|
||||
|
||||
setPtr(nativeCreateLayer(perfCountersEnabled));
|
||||
this.peer = peer;
|
||||
@@ -150,29 +150,11 @@ public class MTLLayer extends CFLayer {
|
||||
}
|
||||
}
|
||||
|
||||
private final static String[] STAT_NAMES = new String[]{
|
||||
"java2d.native.mtlLayer.drawInMTLContext", // type = 0
|
||||
"java2d.native.mtlLayer.nextDrawable" // type = 1
|
||||
};
|
||||
|
||||
private void addStat(int type, double value) {
|
||||
// Called from the native code when this layer has been presented on screen
|
||||
if (perfCountersEnabled && (peer != null)) {
|
||||
final Component target = peer.getTarget();
|
||||
if (target instanceof Window window) {
|
||||
AWTAccessor.getWindowAccessor().addStat(window,
|
||||
((type >= 0) && (type < STAT_NAMES.length)) ? STAT_NAMES[type] : "undefined", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void countNewFrame() {
|
||||
// Called from the native code when this layer has been presented on screen
|
||||
if (perfCountersEnabled && (peer != null)) {
|
||||
final Component target = peer.getTarget();
|
||||
if (target instanceof Window window) {
|
||||
AWTAccessor.getWindowAccessor().incrementCounter(window, "java2d.native.frames");
|
||||
}
|
||||
Component target = peer.getTarget();
|
||||
if (target instanceof Window window) {
|
||||
AWTAccessor.getWindowAccessor().bumpCounter(window, "java2d.native.frames");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,11 +162,9 @@ public class MTLLayer extends CFLayer {
|
||||
// Called from the native code when an attempt was made to present this layer
|
||||
// on screen, but that attempt was not successful. This can happen, for example,
|
||||
// when those attempts are too frequent.
|
||||
if (perfCountersEnabled && (peer != null)) {
|
||||
final Component target = peer.getTarget();
|
||||
if (target instanceof Window window) {
|
||||
AWTAccessor.getWindowAccessor().incrementCounter(window, "java2d.native.framesDropped");
|
||||
}
|
||||
Component target = peer.getTarget();
|
||||
if (target instanceof Window window) {
|
||||
AWTAccessor.getWindowAccessor().bumpCounter(window, "java2d.native.framesDropped");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,8 +71,6 @@
|
||||
- (void) stopRedraw:(MTLContext*)mtlc displayID:(jint)displayID force:(BOOL)force;
|
||||
- (void) flushBuffer;
|
||||
- (void) commitCommandBuffer:(MTLContext*)mtlc wait:(BOOL)waitUntilCompleted display:(BOOL)updateDisplay;
|
||||
|
||||
- (void) addStatCallback:(int)type value:(double)value;
|
||||
- (void) countFramePresentedCallback;
|
||||
- (void) countFrameDroppedCallback;
|
||||
@end
|
||||
|
||||
@@ -226,33 +226,29 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
|
||||
}
|
||||
|
||||
// Acquire CAMetalDrawable without blocking:
|
||||
const CFTimeInterval beforeDrawableTime = CACurrentMediaTime();
|
||||
const CFTimeInterval beforeDrawableTime = (TRACE_DISPLAY) ? CACurrentMediaTime() : 0.0;
|
||||
const id<CAMetalDrawable> mtlDrawable = [self nextDrawable];
|
||||
if (mtlDrawable == nil) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: nextDrawable is null");
|
||||
return;
|
||||
}
|
||||
const CFTimeInterval nextDrawableTime = CACurrentMediaTime();
|
||||
const CFTimeInterval nextDrawableLatency = (nextDrawableTime - beforeDrawableTime);
|
||||
const CFTimeInterval nextDrawableTime = (TRACE_DISPLAY) ? CACurrentMediaTime() : 0.0;
|
||||
|
||||
// rolling mean weight (lerp):
|
||||
static const NSTimeInterval a = 0.25;
|
||||
|
||||
if (nextDrawableLatency > 0.0) {
|
||||
if (self.perfCountersEnabled) {
|
||||
[self addStatCallback:1 value:1000.0 * nextDrawableLatency]; // See MTLLayer.STAT_NAMES[1]
|
||||
}
|
||||
#if TRACE_DISPLAY_ON
|
||||
const CFTimeInterval nextDrawableLatency = (nextDrawableTime - beforeDrawableTime);
|
||||
if (nextDrawableLatency > 0.0) {
|
||||
self.avgNextDrawableTime = nextDrawableLatency * a + self.avgNextDrawableTime * (1.0 - a);
|
||||
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"[%.6lf] MTLLayer_blitTexture: drawable(%d) presented"
|
||||
" - nextDrawableLatency = %.3lf ms - average = %.3lf ms",
|
||||
CACurrentMediaTime(), mtlDrawable.drawableID,
|
||||
1000.0 * nextDrawableLatency, 1000.0 * self.avgNextDrawableTime
|
||||
);
|
||||
#endif
|
||||
}
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"[%.6lf] MTLLayer_blitTexture: drawable(%d) presented"
|
||||
" - nextDrawableLatency = %.3lf ms - average = %.3lf ms",
|
||||
CACurrentMediaTime(), mtlDrawable.drawableID,
|
||||
1000.0 * nextDrawableLatency, 1000.0 * self.avgNextDrawableTime
|
||||
);
|
||||
#endif
|
||||
// Keep Fence from now:
|
||||
releaseFence = NO;
|
||||
|
||||
@@ -393,17 +389,8 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
|
||||
return;
|
||||
}
|
||||
|
||||
const CFTimeInterval beforeMethod = CACurrentMediaTime();
|
||||
|
||||
(*env)->CallVoidMethod(env, javaLayerLocalRef, jm_drawInMTLContext);
|
||||
CHECK_EXCEPTION();
|
||||
|
||||
const CFTimeInterval drawInMTLContextLatency = (CACurrentMediaTime() - beforeMethod);
|
||||
if (drawInMTLContextLatency > 0.0) {
|
||||
if (self.perfCountersEnabled) {
|
||||
[self addStatCallback:0 value:1000.0 * drawInMTLContextLatency]; // See MTLLayer.STAT_NAMES[0]
|
||||
}
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, javaLayerLocalRef);
|
||||
}
|
||||
|
||||
@@ -529,20 +516,6 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
|
||||
}
|
||||
}
|
||||
|
||||
- (void) addStatCallback:(int)type value:(double)value {
|
||||
// attach the current thread to the JVM if necessary, and get an env
|
||||
JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
|
||||
GET_MTL_LAYER_CLASS();
|
||||
DECLARE_METHOD(jm_addStatFrame, jc_JavaLayer, "addStat", "(ID)V");
|
||||
|
||||
jobject javaLayerLocalRef = (*env)->NewLocalRef(env, self.javaLayer);
|
||||
if (javaLayerLocalRef != NULL) {
|
||||
(*env)->CallVoidMethod(env, javaLayerLocalRef, jm_addStatFrame, (jint)type, (jdouble)value);
|
||||
CHECK_EXCEPTION();
|
||||
(*env)->DeleteLocalRef(env, javaLayerLocalRef);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) countFrameDroppedCallback {
|
||||
// attach the current thread to the JVM if necessary, and get an env
|
||||
JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
|
||||
|
||||
@@ -53,14 +53,10 @@ import java.awt.event.TextEvent;
|
||||
import java.awt.im.InputContext;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.awt.image.BufferStrategy;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.ImageProducer;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.peer.ContainerPeer;
|
||||
import java.awt.peer.LightweightPeer;
|
||||
@@ -93,7 +89,6 @@ import javax.accessibility.AccessibleStateSet;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JRootPane;
|
||||
|
||||
import com.jetbrains.exported.JBRApi;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.ComponentFactory;
|
||||
@@ -104,7 +99,6 @@ import sun.awt.EmbeddedFrame;
|
||||
import sun.awt.RequestFocusController;
|
||||
import sun.awt.SubRegionShowable;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.SurfacePixelGrabber;
|
||||
import sun.awt.dnd.SunDropTargetEvent;
|
||||
import sun.awt.im.CompositionArea;
|
||||
import sun.awt.image.VSyncedBSManager;
|
||||
@@ -10565,79 +10559,4 @@ public abstract class Component implements ImageObserver, MenuContainer,
|
||||
}
|
||||
return p.updateCustomTitleBarHitTest(allowNativeActions);
|
||||
}
|
||||
|
||||
@JBRApi.Provides("Screenshoter#getWindowBackbufferArea")
|
||||
private static BufferedImage getWindowBackbufferArea(Window window, int x, int y, int width, int height) {
|
||||
Objects.requireNonNull(window);
|
||||
|
||||
if (x < 0 || y < 0) {
|
||||
throw new IllegalArgumentException("Negative coordinates are not allowed");
|
||||
}
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new IllegalArgumentException("The size must be positive");
|
||||
}
|
||||
|
||||
Image fullBackbuffer = window.getBackBuffer();
|
||||
if (fullBackbuffer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var bufferWidth = fullBackbuffer.getWidth(null);
|
||||
var bufferHeight = fullBackbuffer.getHeight(null);
|
||||
if (x >= width) {
|
||||
throw new IllegalArgumentException(String.format("x coordinate (%d) is out of bounds (%d)", x, bufferWidth));
|
||||
}
|
||||
|
||||
if (y >= height) {
|
||||
throw new IllegalArgumentException(String.format("y coordinate (%d) is out of bounds (%d)", y, bufferHeight));
|
||||
}
|
||||
|
||||
if ((long) x + width > bufferWidth) {
|
||||
width = bufferWidth - x;
|
||||
}
|
||||
|
||||
if ((long) y + height > bufferHeight) {
|
||||
height = bufferHeight - y;
|
||||
}
|
||||
|
||||
if (fullBackbuffer instanceof BufferedImage bufferedImage) {
|
||||
return bufferedImage.getSubimage(x, y, width, height);
|
||||
} else {
|
||||
ColorModel colorModel = window.getGraphicsConfiguration().getColorModel();
|
||||
SampleModel sampleModel = colorModel.createCompatibleSampleModel(width, height);
|
||||
WritableRaster raster = Raster.createWritableRaster(sampleModel, null);
|
||||
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
|
||||
image.getGraphics().drawImage(fullBackbuffer,
|
||||
0, 0, width, height,
|
||||
x, y, x + width, y + height,
|
||||
null);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
@JBRApi.Provides("Screenshoter#getWindowSurfaceArea")
|
||||
private static BufferedImage getWindowSurfaceArea(Window window, int x, int y, int width, int height) {
|
||||
Objects.requireNonNull(window);
|
||||
|
||||
if (x < 0 || y < 0) {
|
||||
throw new IllegalArgumentException("Negative coordinates are not allowed");
|
||||
}
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new IllegalArgumentException("The size must be positive");
|
||||
}
|
||||
|
||||
ComponentPeer peer = window.peer;
|
||||
if (peer == null || !window.isVisible()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (peer instanceof SurfacePixelGrabber spg) {
|
||||
// TODO: translate coordinates, maybe?
|
||||
return spg.getClientAreaSnapshot(x, y, width, height);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.awt.event.WindowFocusListener;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.awt.event.WindowStateListener;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.im.InputContext;
|
||||
import java.awt.image.BufferStrategy;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
@@ -43,7 +44,6 @@ import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OptionalDataException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Native;
|
||||
@@ -53,15 +53,12 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EventListener;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@@ -72,14 +69,11 @@ import javax.accessibility.AccessibleState;
|
||||
import javax.accessibility.AccessibleStateSet;
|
||||
|
||||
import com.jetbrains.exported.JBRApi;
|
||||
import jdk.internal.misc.InnocuousThread;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.DebugSettings;
|
||||
import sun.awt.SunToolkit;
|
||||
import sun.awt.util.IdentityArrayList;
|
||||
import sun.awt.util.ThreadGroupUtils;
|
||||
import sun.java2d.marlin.stats.StatDouble;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
@@ -1159,51 +1153,45 @@ public class Window extends Container implements Accessible {
|
||||
}
|
||||
|
||||
void doDispose() {
|
||||
final class DisposeAction implements Runnable {
|
||||
public void run() {
|
||||
final Window window = Window.this;
|
||||
|
||||
// dump stats if needed:
|
||||
AWTAccessor.getWindowAccessor().dumpStats(window, true, null);
|
||||
|
||||
disposing = true;
|
||||
try {
|
||||
// Check if this window is the fullscreen window for the
|
||||
// device. Exit the fullscreen mode prior to disposing
|
||||
// of the window if that's the case.
|
||||
GraphicsDevice gd = getGraphicsConfiguration().getDevice();
|
||||
if (gd.getFullScreenWindow() == window) {
|
||||
gd.setFullScreenWindow(null);
|
||||
}
|
||||
|
||||
Object[] ownedWindowArray;
|
||||
synchronized(ownedWindowList) {
|
||||
ownedWindowArray = new Object[ownedWindowList.size()];
|
||||
ownedWindowList.copyInto(ownedWindowArray);
|
||||
}
|
||||
for (int i = 0; i < ownedWindowArray.length; i++) {
|
||||
Window child = (Window) (((WeakReference)
|
||||
(ownedWindowArray[i])).get());
|
||||
if (child != null) {
|
||||
child.disposeImpl();
|
||||
}
|
||||
}
|
||||
hide();
|
||||
beforeFirstShow = true;
|
||||
removeNotify();
|
||||
synchronized (inputContextLock) {
|
||||
if (inputContext != null) {
|
||||
inputContext.dispose();
|
||||
inputContext = null;
|
||||
}
|
||||
}
|
||||
clearCurrentFocusCycleRootOnHide();
|
||||
} finally {
|
||||
disposing = false;
|
||||
class DisposeAction implements Runnable {
|
||||
public void run() {
|
||||
disposing = true;
|
||||
try {
|
||||
// Check if this window is the fullscreen window for the
|
||||
// device. Exit the fullscreen mode prior to disposing
|
||||
// of the window if that's the case.
|
||||
GraphicsDevice gd = getGraphicsConfiguration().getDevice();
|
||||
if (gd.getFullScreenWindow() == Window.this) {
|
||||
gd.setFullScreenWindow(null);
|
||||
}
|
||||
|
||||
Object[] ownedWindowArray;
|
||||
synchronized(ownedWindowList) {
|
||||
ownedWindowArray = new Object[ownedWindowList.size()];
|
||||
ownedWindowList.copyInto(ownedWindowArray);
|
||||
}
|
||||
for (int i = 0; i < ownedWindowArray.length; i++) {
|
||||
Window child = (Window) (((WeakReference)
|
||||
(ownedWindowArray[i])).get());
|
||||
if (child != null) {
|
||||
child.disposeImpl();
|
||||
}
|
||||
}
|
||||
hide();
|
||||
beforeFirstShow = true;
|
||||
removeNotify();
|
||||
synchronized (inputContextLock) {
|
||||
if (inputContext != null) {
|
||||
inputContext.dispose();
|
||||
inputContext = null;
|
||||
}
|
||||
}
|
||||
clearCurrentFocusCycleRootOnHide();
|
||||
} finally {
|
||||
disposing = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
boolean fireWindowClosedEvent = isDisplayable();
|
||||
DisposeAction action = new DisposeAction();
|
||||
if (EventQueue.isDispatchThread()) {
|
||||
@@ -3962,7 +3950,6 @@ public class Window extends Container implements Accessible {
|
||||
private float getHeight() { return height; }
|
||||
private void setHeight(float height) {
|
||||
if (height <= 0.0f) throw new IllegalArgumentException("TitleBar height must be positive");
|
||||
if (this.height == height) return;
|
||||
this.height = height;
|
||||
notifyUpdate();
|
||||
}
|
||||
@@ -3971,17 +3958,13 @@ public class Window extends Container implements Accessible {
|
||||
}
|
||||
private void putProperties(Map<String, ?> m) {
|
||||
if (properties == null) properties = new HashMap<>();
|
||||
boolean needsUpdate = false;
|
||||
for (Map.Entry<String, ?> e : m.entrySet()) {
|
||||
Object old = properties.put(e.getKey(), e.getValue());
|
||||
if (!needsUpdate && !Objects.equals(old, e.getValue())) needsUpdate = true;
|
||||
}
|
||||
if (needsUpdate) notifyUpdate();
|
||||
properties.putAll(m);
|
||||
notifyUpdate();
|
||||
}
|
||||
private void putProperty(String key, Object value) {
|
||||
if (properties == null) properties = new HashMap<>();
|
||||
Object old = properties.put(key, value);
|
||||
if (!Objects.equals(old, value)) notifyUpdate();
|
||||
properties.put(key, value);
|
||||
notifyUpdate();
|
||||
}
|
||||
private float getLeftInset() { return insets[0]; }
|
||||
private float getRightInset() { return insets[1]; }
|
||||
@@ -4176,36 +4159,8 @@ public class Window extends Container implements Accessible {
|
||||
return value;
|
||||
}
|
||||
|
||||
private final static String STATS_ALL_SUFFIX = ".all";
|
||||
private final static String SYSTEM_PROPERTY_COUNTERS;
|
||||
|
||||
private final static boolean USE_COUNTERS;
|
||||
private final static boolean TRACE_ALL_COUNTERS;
|
||||
private final static boolean TRACE_STD_ERR;
|
||||
|
||||
private final static int TRACE_CAPACITY;
|
||||
|
||||
private final static boolean TRACE_COUNTERS = true;
|
||||
private final static boolean DUMP_STATS = true;
|
||||
|
||||
// thread dump interval (ms)
|
||||
static final long DUMP_INTERVAL = 10 * 1000L;
|
||||
|
||||
private static PrintStream getTraceStdStream() {
|
||||
// get live std stream:
|
||||
return TRACE_STD_ERR ? System.err : System.out;
|
||||
}
|
||||
|
||||
static {
|
||||
SYSTEM_PROPERTY_COUNTERS = System.getProperty("awt.window.counters");
|
||||
USE_COUNTERS = (SYSTEM_PROPERTY_COUNTERS != null);
|
||||
|
||||
TRACE_ALL_COUNTERS = USE_COUNTERS && (Objects.equals(SYSTEM_PROPERTY_COUNTERS, "")
|
||||
|| Objects.equals(SYSTEM_PROPERTY_COUNTERS, "stderr")
|
||||
|| Objects.equals(SYSTEM_PROPERTY_COUNTERS, "stdout"));
|
||||
|
||||
TRACE_STD_ERR = USE_COUNTERS && SYSTEM_PROPERTY_COUNTERS.contains("stderr");
|
||||
TRACE_CAPACITY = USE_COUNTERS ? 8 : 0;
|
||||
String counters = System.getProperty("awt.window.counters");
|
||||
|
||||
AWTAccessor.setWindowAccessor(new AWTAccessor.WindowAccessor() {
|
||||
public void updateWindow(Window window) {
|
||||
@@ -4242,206 +4197,100 @@ public class Window extends Container implements Accessible {
|
||||
|
||||
public boolean countersEnabled(Window w) {
|
||||
// May want to selectively enable or disable counters per window
|
||||
return USE_COUNTERS;
|
||||
return counters != null;
|
||||
}
|
||||
|
||||
private final static long NANO_IN_SEC = java.util.concurrent.TimeUnit.SECONDS.toNanos(1);
|
||||
public void bumpCounter(Window w, String counterName) {
|
||||
Objects.requireNonNull(w);
|
||||
Objects.requireNonNull(counterName);
|
||||
|
||||
public void incrementCounter(final Window w, final String counterName) {
|
||||
if (USE_COUNTERS) {
|
||||
Objects.requireNonNull(w);
|
||||
Objects.requireNonNull(counterName);
|
||||
|
||||
final long curTimeNanos = System.nanoTime();
|
||||
// use try-catch to avoid throwing runtime exception to native JNI callers!
|
||||
try {
|
||||
PerfCounter newCounter, prevCounter;
|
||||
synchronized (w.perfCounters) {
|
||||
newCounter = w.perfCounters.compute(counterName, (_, v) ->
|
||||
v == null
|
||||
? new PerfCounter(curTimeNanos, 1L)
|
||||
: new PerfCounter(curTimeNanos, v.value + 1));
|
||||
PerfCounter newCounter;
|
||||
long curTimeNanos = System.nanoTime();
|
||||
synchronized (w.perfCounters) {
|
||||
newCounter = w.perfCounters.compute(counterName, (k, v) ->
|
||||
v == null
|
||||
? new PerfCounter(curTimeNanos, 1L)
|
||||
: new PerfCounter(curTimeNanos, v.value + 1));
|
||||
}
|
||||
PerfCounter prevCounter;
|
||||
synchronized (w.perfCountersPrev) {
|
||||
prevCounter = w.perfCountersPrev.putIfAbsent(counterName, newCounter);
|
||||
}
|
||||
if (prevCounter != null) {
|
||||
long nanosInSecond = java.util.concurrent.TimeUnit.SECONDS.toNanos(1);
|
||||
long timeDeltaNanos = curTimeNanos - prevCounter.updateTimeNanos;
|
||||
if (timeDeltaNanos > nanosInSecond) {
|
||||
long valPerSecond = (long) ((double) (newCounter.value - prevCounter.value)
|
||||
* nanosInSecond / timeDeltaNanos);
|
||||
boolean traceAllCounters = Objects.equals(counters, "")
|
||||
|| Objects.equals(counters, "stdout")
|
||||
|| Objects.equals(counters, "stderr");
|
||||
boolean traceEnabled = traceAllCounters || (counters != null && counters.contains(counterName));
|
||||
if (traceEnabled) {
|
||||
if (counters.contains("stderr")) {
|
||||
System.err.println(counterName + " per second: " + valPerSecond);
|
||||
} else {
|
||||
System.out.println(counterName + " per second: " + valPerSecond);
|
||||
}
|
||||
}
|
||||
if (perfLog.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
perfLog.fine(counterName + " per second: " + valPerSecond);
|
||||
}
|
||||
synchronized (w.perfCountersPrev) {
|
||||
prevCounter = w.perfCountersPrev.putIfAbsent(counterName, newCounter);
|
||||
}
|
||||
if (prevCounter != null) {
|
||||
final long timeDeltaNanos = curTimeNanos - prevCounter.updateTimeNanos;
|
||||
if (timeDeltaNanos > NANO_IN_SEC) {
|
||||
final double valPerSecond = (double) (newCounter.value - prevCounter.value)
|
||||
* NANO_IN_SEC / timeDeltaNanos;
|
||||
|
||||
synchronized (w.perfCountersPrev) {
|
||||
w.perfCountersPrev.put(counterName, newCounter);
|
||||
}
|
||||
addStat(w, counterName, valPerSecond);
|
||||
if (TRACE_COUNTERS) {
|
||||
dumpCounter(counterName, valPerSecond);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException re) {
|
||||
perfLog.severe("incrementCounter: failed", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addStat(final Window w, final String statName, final double value) {
|
||||
if (USE_COUNTERS && Double.isFinite(value)) {
|
||||
Objects.requireNonNull(w);
|
||||
Objects.requireNonNull(statName);
|
||||
|
||||
// use try-catch to avoid throwing runtime exception to native JNI callers!
|
||||
try {
|
||||
synchronized (w.perfStats) {
|
||||
StatDouble stat = w.perfStats.computeIfAbsent(statName, StatDouble::new);
|
||||
stat.add(value);
|
||||
stat = w.perfStats.computeIfAbsent(statName + STATS_ALL_SUFFIX, StatDouble::new);
|
||||
stat.add(value);
|
||||
}
|
||||
} catch (RuntimeException re) {
|
||||
perfLog.severe("addStat: failed", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long getCounter(final Window w, final String counterName) {
|
||||
if (USE_COUNTERS) {
|
||||
Objects.requireNonNull(w);
|
||||
Objects.requireNonNull(counterName);
|
||||
|
||||
synchronized (w.perfCounters) {
|
||||
PerfCounter counter = w.perfCounters.get(counterName);
|
||||
return counter != null ? counter.value : -1L;
|
||||
}
|
||||
}
|
||||
return -1L;
|
||||
}
|
||||
|
||||
public double getCounterPerSecond(final Window w, final String counterName) {
|
||||
if (USE_COUNTERS) {
|
||||
Objects.requireNonNull(w);
|
||||
Objects.requireNonNull(counterName);
|
||||
|
||||
PerfCounter newCounter, prevCounter;
|
||||
synchronized (w.perfCounters) {
|
||||
newCounter = w.perfCounters.get(counterName);
|
||||
}
|
||||
synchronized (w.perfCountersPrev) {
|
||||
prevCounter = w.perfCountersPrev.get(counterName);
|
||||
}
|
||||
|
||||
if (newCounter != null && prevCounter != null) {
|
||||
final long timeDeltaNanos = newCounter.updateTimeNanos - prevCounter.updateTimeNanos;
|
||||
// Note that this time delta will usually be above one second.
|
||||
if (timeDeltaNanos > 0L) {
|
||||
return (double) (newCounter.value - prevCounter.value) * NANO_IN_SEC / timeDeltaNanos;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
public void dumpStats(final Window w, final boolean reset, StringBuilder sb) {
|
||||
if (USE_COUNTERS) {
|
||||
synchronized (w.perfStats) {
|
||||
boolean header = false;
|
||||
|
||||
for (final StatDouble stat : w.perfStats.values()) {
|
||||
if (stat.shouldLog()) {
|
||||
final boolean traceEnabled = TRACE_ALL_COUNTERS || SYSTEM_PROPERTY_COUNTERS.contains(stat.name);
|
||||
if (!header) {
|
||||
header = true;
|
||||
doLog(String.format("* Window['%s'@%s]:",
|
||||
(w instanceof Frame ? ((Frame) w).getTitle() : ""),
|
||||
Integer.toHexString(System.identityHashCode(w))),
|
||||
traceEnabled);
|
||||
}
|
||||
// format:
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder(128);
|
||||
}
|
||||
sb.setLength(0);
|
||||
sb.append(" - ");
|
||||
stat.toString(sb);
|
||||
doLog(sb.toString(), traceEnabled);
|
||||
|
||||
if (reset && !stat.name.endsWith(STATS_ALL_SUFFIX)) {
|
||||
stat.reset();
|
||||
} else {
|
||||
stat.updateLastLogCount();
|
||||
}
|
||||
}
|
||||
w.perfCountersPrev.put(counterName, newCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addWindowListener(Window w, WindowListener listener) {
|
||||
w.addWindowListener(listener);
|
||||
}
|
||||
public long getCounter(Window w, String counterName) {
|
||||
Objects.requireNonNull(w);
|
||||
Objects.requireNonNull(counterName);
|
||||
|
||||
private static void dumpCounter(final String counterName, final double valPerSecond) {
|
||||
if (USE_COUNTERS) {
|
||||
doLog(String.format("%s per second: %.2f", counterName, valPerSecond),
|
||||
TRACE_ALL_COUNTERS || SYSTEM_PROPERTY_COUNTERS.contains(counterName));
|
||||
synchronized (w.perfCounters) {
|
||||
PerfCounter counter = w.perfCounters.get(counterName);
|
||||
return counter != null ? counter.value : -1L;
|
||||
}
|
||||
}
|
||||
|
||||
private static void doLog(final String msg, final boolean traceEnabled) {
|
||||
if (traceEnabled) {
|
||||
getTraceStdStream().println(msg);
|
||||
public long getCounterPerSecond(Window w, String counterName) {
|
||||
Objects.requireNonNull(w);
|
||||
Objects.requireNonNull(counterName);
|
||||
|
||||
PerfCounter newCounter;
|
||||
PerfCounter prevCounter;
|
||||
|
||||
synchronized (w.perfCounters) {
|
||||
newCounter = w.perfCounters.get(counterName);
|
||||
}
|
||||
if (perfLog.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
perfLog.fine(msg);
|
||||
|
||||
synchronized (w.perfCountersPrev) {
|
||||
prevCounter = w.perfCountersPrev.get(counterName);
|
||||
}
|
||||
|
||||
if (newCounter != null && prevCounter != null) {
|
||||
long timeDeltaNanos = newCounter.updateTimeNanos - prevCounter.updateTimeNanos;
|
||||
// Note that this time delta will usually be above one second.
|
||||
if (timeDeltaNanos > 0) {
|
||||
long nanosInSecond = java.util.concurrent.TimeUnit.SECONDS.toNanos(1);
|
||||
long valPerSecond = (long) ((double) (newCounter.value - prevCounter.value)
|
||||
* nanosInSecond / timeDeltaNanos);
|
||||
return valPerSecond;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}); // WindowAccessor
|
||||
|
||||
if (USE_COUNTERS) {
|
||||
final Runnable dumper = new Runnable() {
|
||||
private final static StringBuilder sb = new StringBuilder(128);
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
getTraceStdStream().printf("--- WindowStats dump at: %s ---\n", new java.util.Date());
|
||||
|
||||
final AWTAccessor.WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
|
||||
|
||||
for (Window window : Window.getWindows()) {
|
||||
// dump stats if needed:
|
||||
windowAccessor.dumpStats(window, true, sb);
|
||||
}
|
||||
getTraceStdStream().println("-----");
|
||||
}
|
||||
};
|
||||
final Thread hook = InnocuousThread.newSystemThread("WindowStatsHook", dumper);
|
||||
hook.setDaemon(true);
|
||||
hook.setContextClassLoader(null);
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
|
||||
if (DUMP_STATS) {
|
||||
final Timer statTimer = new Timer("WindowStats", true);
|
||||
statTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
dumper.run();
|
||||
}
|
||||
}, DUMP_INTERVAL, DUMP_INTERVAL);
|
||||
}
|
||||
}
|
||||
} // static
|
||||
|
||||
// a window doesn't need to be updated in the Z-order.
|
||||
@Override
|
||||
void updateZOrder() {}
|
||||
|
||||
private record PerfCounter(long updateTimeNanos, long value) {}
|
||||
private record PerfCounter(Long updateTimeNanos, Long value) {}
|
||||
|
||||
private transient final HashMap<String, PerfCounter> perfCounters = (USE_COUNTERS) ? new HashMap<>(TRACE_CAPACITY) : null;
|
||||
private transient final HashMap<String, PerfCounter> perfCountersPrev = (USE_COUNTERS) ? new HashMap<>(TRACE_CAPACITY) : null;
|
||||
private transient final LinkedHashMap<String, StatDouble> perfStats = (USE_COUNTERS) ? new LinkedHashMap<>(TRACE_CAPACITY) : null;
|
||||
private transient final Map<String, PerfCounter> perfCounters = new HashMap<>(4);
|
||||
private transient final Map<String, PerfCounter> perfCountersPrev = new HashMap<>(4);
|
||||
|
||||
} // class Window
|
||||
|
||||
|
||||
@@ -27,7 +27,10 @@ package javax.swing;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.awt.peer.WindowPeer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.applet.*;
|
||||
@@ -40,12 +43,14 @@ import sun.java2d.SunGraphicsEnvironment;
|
||||
|
||||
import com.sun.java.swing.SwingUtilities3;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.swing.SwingAccessor;
|
||||
import sun.swing.SwingUtilities2;
|
||||
import sun.swing.SwingUtilities2.RepaintListener;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This class manages repaint requests, allowing the number
|
||||
@@ -750,7 +755,7 @@ public class RepaintManager
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.forEach(w -> AWTAccessor.getWindowAccessor()
|
||||
.incrementCounter(w, "swing.RepaintManager.updateWindows"));
|
||||
.bumpCounter(w, "swing.RepaintManager.updateWindows"));
|
||||
|
||||
if (Toolkit.getDefaultToolkit() instanceof SunToolkit sunToolkit &&
|
||||
sunToolkit.needUpdateWindow()) {
|
||||
@@ -769,14 +774,14 @@ public class RepaintManager
|
||||
|
||||
for (Window window : windows) {
|
||||
AWTAccessor.getWindowAccessor().updateWindow(window);
|
||||
AWTAccessor.getWindowAccessor().incrementCounter(window, "swing.RepaintManager.updateWindows");
|
||||
AWTAccessor.getWindowAccessor().bumpCounter(window, "swing.RepaintManager.updateWindows");
|
||||
}
|
||||
} else {
|
||||
dirtyComponents.keySet().stream()
|
||||
.map(c -> c instanceof Window w ? w : SwingUtilities.getWindowAncestor(c))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(w -> AWTAccessor.getWindowAccessor()
|
||||
.incrementCounter(w, "swing.RepaintManager.updateWindows"));
|
||||
.bumpCounter(w, "swing.RepaintManager.updateWindows"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -748,27 +748,6 @@ public class BasicTreeUI extends TreeUI
|
||||
return bounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* A potentially faster version of {@link #getPathBounds(JTree, TreePath)}
|
||||
* which calculates only {@code y} and {@code height}
|
||||
* of the bounding {@code Rectangle}
|
||||
*/
|
||||
private Rectangle getVerticalPathBounds(TreePath path) {
|
||||
if (tree == null || treeState == null) {
|
||||
return null;
|
||||
}
|
||||
int rowHeight = treeState.getRowHeight();
|
||||
if (rowHeight <= 0) {
|
||||
return getPathBounds(tree, path);
|
||||
}
|
||||
int row = treeState.getRowForPath(path);
|
||||
if (row < 0) {
|
||||
return null;
|
||||
}
|
||||
return new Rectangle(0, tree.getInsets().top + row * rowHeight,
|
||||
0, rowHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path for passed in row. If row is not visible
|
||||
* null is returned.
|
||||
@@ -4402,21 +4381,17 @@ public class BasicTreeUI extends TreeUI
|
||||
updateSize();
|
||||
}
|
||||
else if (treeState.isExpanded(parentPath)) {
|
||||
TreePath minPath = null;
|
||||
Rectangle minBounds = null;
|
||||
if (tree.isShowing()) {
|
||||
// Changed nodes are visible
|
||||
// Find the minimum index, we only need paint from there
|
||||
// down.
|
||||
int minIndex = indices[0];
|
||||
for (int i = indices.length - 1; i > 0; i--) {
|
||||
minIndex = Math.min(indices[i], minIndex);
|
||||
}
|
||||
Object minChild = treeModel.getChild(
|
||||
parentPath.getLastPathComponent(), minIndex);
|
||||
minPath = parentPath.pathByAddingChild(minChild);
|
||||
minBounds = getVerticalPathBounds(minPath);
|
||||
// Changed nodes are visible
|
||||
// Find the minimum index, we only need paint from there
|
||||
// down.
|
||||
int minIndex = indices[0];
|
||||
for (int i = indices.length - 1; i > 0; i--) {
|
||||
minIndex = Math.min(indices[i], minIndex);
|
||||
}
|
||||
Object minChild = treeModel.getChild(
|
||||
parentPath.getLastPathComponent(), minIndex);
|
||||
TreePath minPath = parentPath.pathByAddingChild(minChild);
|
||||
Rectangle minBounds = getPathBounds(tree, minPath);
|
||||
|
||||
// Forward to the treestate
|
||||
treeState.treeNodesChanged(e);
|
||||
@@ -4424,19 +4399,20 @@ public class BasicTreeUI extends TreeUI
|
||||
// Mark preferred size as bogus.
|
||||
updateSize0();
|
||||
|
||||
if (minBounds != null) {
|
||||
// And repaint
|
||||
Rectangle newMinBounds = getVerticalPathBounds(minPath);
|
||||
if (newMinBounds != null) {
|
||||
if (indices.length == 1 &&
|
||||
newMinBounds.height == minBounds.height) {
|
||||
tree.repaint(0, minBounds.y, tree.getWidth(),
|
||||
minBounds.height);
|
||||
} else {
|
||||
tree.repaint(0, minBounds.y, tree.getWidth(),
|
||||
tree.getHeight() - minBounds.y);
|
||||
}
|
||||
}
|
||||
// And repaint
|
||||
Rectangle newMinBounds = getPathBounds(tree, minPath);
|
||||
if (minBounds == null || newMinBounds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (indices.length == 1 &&
|
||||
newMinBounds.height == minBounds.height) {
|
||||
tree.repaint(0, minBounds.y, tree.getWidth(),
|
||||
minBounds.height);
|
||||
}
|
||||
else {
|
||||
tree.repaint(0, minBounds.y, tree.getWidth(),
|
||||
tree.getHeight() - minBounds.y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -37,7 +37,7 @@ import java.awt.event.InputEvent;
|
||||
import java.awt.event.InvocationEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.image.BufferStrategy;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
|
||||
@@ -329,17 +329,10 @@ public final class AWTAccessor {
|
||||
*/
|
||||
Window[] getOwnedWindows(Window w);
|
||||
|
||||
/* JBR Window counters API */
|
||||
boolean countersEnabled(Window w);
|
||||
void incrementCounter(Window w, String counterName);
|
||||
void addStat(Window w, String statName, double value);
|
||||
|
||||
void bumpCounter(Window w, String counterName);
|
||||
long getCounter(Window w, String counterName);
|
||||
double getCounterPerSecond(Window w, String counterName);
|
||||
|
||||
void dumpStats(Window w, boolean reset, StringBuilder sb);
|
||||
|
||||
void addWindowListener(Window w, WindowListener listener);
|
||||
long getCounterPerSecond(Window w, String counterName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,7 +50,6 @@ import java.awt.KeyboardFocusManager;
|
||||
import java.awt.Label;
|
||||
import java.awt.MenuComponent;
|
||||
import java.awt.Panel;
|
||||
import java.awt.Point;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.ScrollPane;
|
||||
import java.awt.Scrollbar;
|
||||
@@ -91,7 +90,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import com.jetbrains.exported.JBRApi;
|
||||
import sun.awt.im.InputContext;
|
||||
import sun.awt.image.ByteArrayImageSource;
|
||||
import sun.awt.image.FileImageSource;
|
||||
@@ -2086,23 +2084,6 @@ public abstract class SunToolkit extends Toolkit
|
||||
return AWTAccessor.getAWTEventAccessor().isSystemGenerated(e);
|
||||
}
|
||||
|
||||
@JBRApi.Service
|
||||
@JBRApi.Provides("RelativePointerMovement")
|
||||
public interface RelativePointerMovementInfoProvider {
|
||||
private static RelativePointerMovementInfoProvider create() {
|
||||
var tk = Toolkit.getDefaultToolkit();
|
||||
if (tk instanceof ComponentFactory cf) {
|
||||
var mouseInfoPeer = cf.getMouseInfoPeer();
|
||||
if (mouseInfoPeer instanceof RelativePointerMovementInfoProvider p){
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
throw new JBRApi.ServiceNotAvailableException("Service not supported for toolkit " + tk.getClass().getName());
|
||||
}
|
||||
|
||||
Point getAccumulatedMouseDeltaAndReset();
|
||||
}
|
||||
} // class SunToolkit
|
||||
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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.awt.image.BufferedImage;
|
||||
|
||||
public interface SurfacePixelGrabber {
|
||||
BufferedImage getClientAreaSnapshot(int x, int y, int width, int height);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2021, 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
|
||||
@@ -144,9 +144,7 @@ final class Curve {
|
||||
// finds points where the first and second derivative are
|
||||
// perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where
|
||||
// * is a dot product). Unfortunately, we have to solve a cubic.
|
||||
private int perpendiculardfddf(final double[] pts, final int off,
|
||||
final double A, final double B)
|
||||
{
|
||||
private int perpendiculardfddf(final double[] pts, final int off) {
|
||||
assert pts.length >= off + 4;
|
||||
|
||||
// these are the coefficients of some multiple of g(t) (not g(t),
|
||||
@@ -157,7 +155,7 @@ final class Curve {
|
||||
final double c = 2.0d * (dax * cx + day * cy) + dbx * dbx + dby * dby;
|
||||
final double d = dbx * cx + dby * cy;
|
||||
|
||||
return Helpers.cubicRootsInAB(a, b, c, d, pts, off, A, B);
|
||||
return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0.0d, 1.0d);
|
||||
}
|
||||
|
||||
// Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
|
||||
@@ -173,43 +171,35 @@ final class Curve {
|
||||
// at most 4 sub-intervals of (0,1). ROC has asymptotes at inflection
|
||||
// points, so roc-w can have at least 6 roots. This shouldn't be a
|
||||
// problem for what we're trying to do (draw a nice looking curve).
|
||||
int rootsOfROCMinusW(final double[] roots, final int off, final double w2,
|
||||
final double A, final double B)
|
||||
{
|
||||
int rootsOfROCMinusW(final double[] roots, final int off, final double w2, final double err) {
|
||||
// no OOB exception, because by now off<=6, and roots.length >= 10
|
||||
assert off <= 6 && roots.length >= 10;
|
||||
|
||||
int ret = off;
|
||||
final int end = off + perpendiculardfddf(roots, off, A, B);
|
||||
Helpers.isort(roots, off, end);
|
||||
final int end = off + perpendiculardfddf(roots, off);
|
||||
roots[end] = 1.0d; // always check interval end points
|
||||
|
||||
double t0 = 0.0d;
|
||||
double ft0 = eliminateInf(ROCsq(t0) - w2);
|
||||
double t1, ft1;
|
||||
double t0 = 0.0d, ft0 = ROCsq(t0) - w2;
|
||||
|
||||
for (int i = off; i <= end; i++) {
|
||||
t1 = roots[i];
|
||||
ft1 = eliminateInf(ROCsq(t1) - w2);
|
||||
double t1 = roots[i], ft1 = ROCsq(t1) - w2;
|
||||
if (ft0 == 0.0d) {
|
||||
roots[ret++] = t0;
|
||||
} else if (ft1 * ft0 < 0.0d) { // have opposite signs
|
||||
// (ROC(t)^2 == w^2) == (ROC(t) == w) is true because
|
||||
// ROC(t) >= 0 for all t.
|
||||
roots[ret++] = falsePositionROCsqMinusX(t0, t1, ft0, ft1, w2, A); // A = err
|
||||
roots[ret++] = falsePositionROCsqMinusX(t0, t1, w2, err);
|
||||
}
|
||||
t0 = t1;
|
||||
ft0 = ft1;
|
||||
}
|
||||
|
||||
return ret - off;
|
||||
}
|
||||
|
||||
private final static double MAX_ROC_SQ = 1e20;
|
||||
|
||||
private static double eliminateInf(final double x2) {
|
||||
// limit the value of x to avoid numerical problems (smaller step):
|
||||
// must handle NaN and +Infinity:
|
||||
return (x2 <= MAX_ROC_SQ) ? x2 : MAX_ROC_SQ;
|
||||
private static double eliminateInf(final double x) {
|
||||
return (x == Double.POSITIVE_INFINITY ? Double.MAX_VALUE :
|
||||
(x == Double.NEGATIVE_INFINITY ? Double.MIN_VALUE : x));
|
||||
}
|
||||
|
||||
// A slight modification of the false position algorithm on wikipedia.
|
||||
@@ -220,18 +210,17 @@ final class Curve {
|
||||
// and turn out. Same goes for the newton's method
|
||||
// algorithm in Helpers.java
|
||||
private double falsePositionROCsqMinusX(final double t0, final double t1,
|
||||
final double ft0, final double ft1,
|
||||
final double w2, final double err)
|
||||
{
|
||||
final int iterLimit = 100;
|
||||
int side = 0;
|
||||
double s = t0, fs = eliminateInf(ft0);
|
||||
double t = t1, ft = eliminateInf(ft1);
|
||||
double t = t1, ft = eliminateInf(ROCsq(t) - w2);
|
||||
double s = t0, fs = eliminateInf(ROCsq(s) - w2);
|
||||
double r = s, fr;
|
||||
|
||||
for (int i = 0; i < iterLimit && Math.abs(t - s) > err; i++) {
|
||||
for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) {
|
||||
r = (fs * t - ft * s) / (fs - ft);
|
||||
fr = eliminateInf(ROCsq(r) - w2);
|
||||
fr = ROCsq(r) - w2;
|
||||
if (sameSign(fr, ft)) {
|
||||
ft = fr; t = r;
|
||||
if (side < 0) {
|
||||
@@ -252,7 +241,7 @@ final class Curve {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (Math.abs(ft) <= Math.abs(fs)) ? t : s;
|
||||
return r;
|
||||
}
|
||||
|
||||
private static boolean sameSign(final double x, final double y) {
|
||||
@@ -267,9 +256,9 @@ final class Curve {
|
||||
final double dy = t * (t * day + dby) + cy;
|
||||
final double ddx = 2.0d * dax * t + dbx;
|
||||
final double ddy = 2.0d * day * t + dby;
|
||||
final double dx2dy2 = dx * dx + dy * dy; // positive
|
||||
final double dxddyddxdy = dx * ddy - dy * ddx;
|
||||
// may return +Infinity if dxddyddxdy = 0 or NaN if 0/0:
|
||||
return (dx2dy2 * dx2dy2 * dx2dy2) / (dxddyddxdy * dxddyddxdy); // both positive
|
||||
final double dx2dy2 = dx * dx + dy * dy;
|
||||
final double ddx2ddy2 = ddx * ddx + ddy * ddy;
|
||||
final double ddxdxddydy = ddx * dx + ddy * dy;
|
||||
return dx2dy2 * ((dx2dy2 * dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy * ddxdxddydy));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2024, 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
|
||||
@@ -564,7 +564,7 @@ public final class DMarlinRenderingEngine extends RenderingEngine
|
||||
}
|
||||
|
||||
private static boolean nearZero(final double num) {
|
||||
return Math.abs(num) < 2.0d * Helpers.ulp(num);
|
||||
return Math.abs(num) < 2.0d * Math.ulp(num);
|
||||
}
|
||||
|
||||
abstract static class NormalizingPathIterator implements PathIterator {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2022, 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
|
||||
@@ -31,19 +31,12 @@ import sun.java2d.marlin.stats.StatLong;
|
||||
|
||||
final class Helpers implements MarlinConst {
|
||||
|
||||
private final static double T_ERR = 1e-4;
|
||||
private final static double T_A = T_ERR;
|
||||
private final static double T_B = 1.0 - T_ERR;
|
||||
|
||||
private static final double EPS = 1e-9d;
|
||||
|
||||
private Helpers() {
|
||||
throw new Error("This is a non instantiable class");
|
||||
}
|
||||
|
||||
/** use lower precision like former Pisces and Marlin (float-precision) */
|
||||
static double ulp(final double value) { return Math.ulp((float)value); }
|
||||
|
||||
static boolean within(final double x, final double y) {
|
||||
return within(x, y, EPS);
|
||||
}
|
||||
@@ -329,10 +322,10 @@ final class Helpers implements MarlinConst {
|
||||
|
||||
// now we must subdivide at points where one of the offset curves will have
|
||||
// a cusp. This happens at ts where the radius of curvature is equal to w.
|
||||
ret += c.rootsOfROCMinusW(ts, ret, w2, T_A, T_B);
|
||||
ret += c.rootsOfROCMinusW(ts, ret, w2, 0.0001d);
|
||||
|
||||
ret = filterOutNotInAB(ts, 0, ret, T_A, T_B);
|
||||
isort(ts, 0, ret);
|
||||
ret = filterOutNotInAB(ts, 0, ret, 0.0001d, 0.9999d);
|
||||
isort(ts, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -361,7 +354,7 @@ final class Helpers implements MarlinConst {
|
||||
if ((outCodeOR & OUTCODE_BOTTOM) != 0) {
|
||||
ret += curve.yPoints(ts, ret, clipRect[1]);
|
||||
}
|
||||
isort(ts, 0, ret);
|
||||
isort(ts, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -381,11 +374,11 @@ final class Helpers implements MarlinConst {
|
||||
}
|
||||
}
|
||||
|
||||
static void isort(final double[] a, final int off, final int len) {
|
||||
for (int i = off + 1, j; i < len; i++) {
|
||||
static void isort(final double[] a, final int len) {
|
||||
for (int i = 1, j; i < len; i++) {
|
||||
final double ai = a[i];
|
||||
j = i - 1;
|
||||
for (; j >= off && a[j] > ai; j--) {
|
||||
for (; j >= 0 && a[j] > ai; j--) {
|
||||
a[j + 1] = a[j];
|
||||
}
|
||||
a[j + 1] = ai;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, 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
|
||||
@@ -28,8 +28,6 @@ package sun.java2d.marlin;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import jdk.internal.misc.InnocuousThread;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
import sun.java2d.marlin.ArrayCacheConst.CacheStats;
|
||||
import static sun.java2d.marlin.MarlinUtils.logInfo;
|
||||
@@ -385,13 +383,21 @@ public final class RendererStats implements MarlinConst {
|
||||
= new ConcurrentLinkedQueue<>();
|
||||
|
||||
private RendererStatsHolder() {
|
||||
final Thread hook = InnocuousThread.newSystemThread("MarlinStatsHook", () -> dump());
|
||||
hook.setDaemon(true);
|
||||
final Thread hook = new Thread(
|
||||
MarlinUtils.getRootThreadGroup(),
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dump();
|
||||
}
|
||||
},
|
||||
"MarlinStatsHook"
|
||||
);
|
||||
hook.setContextClassLoader(null);
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
|
||||
if (USE_DUMP_THREAD) {
|
||||
final Timer statTimer = new Timer("RendererStats", true);
|
||||
final Timer statTimer = new Timer("RendererStats");
|
||||
statTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2023, 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
|
||||
@@ -886,8 +886,8 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst {
|
||||
|
||||
// if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
|
||||
// in which case ignore if p1 == p2
|
||||
final boolean p1eqp2 = Helpers.withinD(dx1, dy1, 6.0d * Helpers.ulp(y2));
|
||||
final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Helpers.ulp(y4));
|
||||
final boolean p1eqp2 = Helpers.withinD(dx1, dy1, 6.0d * Math.ulp(y2));
|
||||
final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Math.ulp(y4));
|
||||
|
||||
if (p1eqp2 && p3eqp4) {
|
||||
return getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
|
||||
@@ -905,7 +905,7 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst {
|
||||
final double l1sq = dx1 * dx1 + dy1 * dy1;
|
||||
final double l4sq = dx4 * dx4 + dy4 * dy4;
|
||||
|
||||
if (Helpers.within(dotsq, l1sq * l4sq, 4.0d * Helpers.ulp(dotsq))) {
|
||||
if (Helpers.within(dotsq, l1sq * l4sq, 4.0d * Math.ulp(dotsq))) {
|
||||
return getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
|
||||
}
|
||||
|
||||
@@ -1078,8 +1078,8 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst {
|
||||
// equal if they're very close to each other.
|
||||
|
||||
// if p1 == p2 or p2 == p3: draw line from p1->p3
|
||||
final boolean p1eqp2 = Helpers.withinD(dx12, dy12, 6.0d * Helpers.ulp(y2));
|
||||
final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Helpers.ulp(y3));
|
||||
final boolean p1eqp2 = Helpers.withinD(dx12, dy12, 6.0d * Math.ulp(y2));
|
||||
final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Math.ulp(y3));
|
||||
|
||||
if (p1eqp2 || p2eqp3) {
|
||||
return getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
|
||||
@@ -1091,7 +1091,7 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst {
|
||||
final double l1sq = dx12 * dx12 + dy12 * dy12;
|
||||
final double l3sq = dx23 * dx23 + dy23 * dy23;
|
||||
|
||||
if (Helpers.within(dotsq, l1sq * l3sq, 4.0d * Helpers.ulp(dotsq))) {
|
||||
if (Helpers.within(dotsq, l1sq * l3sq, 4.0d * Math.ulp(dotsq))) {
|
||||
return getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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
|
||||
@@ -27,7 +27,7 @@ package sun.java2d.marlin;
|
||||
|
||||
public final class Version {
|
||||
|
||||
private static final String VERSION = "marlin-0.9.4.9-Unsafe-OpenJDK";
|
||||
private static final String VERSION = "marlin-0.9.4.7-Unsafe-OpenJDK";
|
||||
|
||||
public static String getVersion() {
|
||||
return VERSION;
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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.java2d.marlin.stats;
|
||||
|
||||
import static sun.java2d.marlin.stats.StatLong.trimTo3Digits;
|
||||
|
||||
/**
|
||||
* Statistics on double values
|
||||
*/
|
||||
public final class StatDouble {
|
||||
// rolling mean weight (lerp):
|
||||
private final static double EMA_ALPHA = 0.25;
|
||||
private final static double EMA_ONE_MINUS_ALPHA = 1.0 - EMA_ALPHA;
|
||||
|
||||
public final String name;
|
||||
private long count, lastLogCount;
|
||||
private double min, max, mean, ema_mean = 0.0, squaredError;
|
||||
|
||||
public StatDouble(final String name) {
|
||||
this.name = name;
|
||||
reset();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
count = 0L;
|
||||
lastLogCount = 0L;
|
||||
min = Double.POSITIVE_INFINITY;
|
||||
max = Double.NEGATIVE_INFINITY;
|
||||
mean = 0.0;
|
||||
// skip ema_mean = 0.0;
|
||||
squaredError = 0.0;
|
||||
}
|
||||
|
||||
public void add(final double val) {
|
||||
count++;
|
||||
if (val < min) {
|
||||
min = val;
|
||||
}
|
||||
if (val > max) {
|
||||
max = val;
|
||||
}
|
||||
// Exponential smoothing (EMA):
|
||||
ema_mean = EMA_ALPHA * val + EMA_ONE_MINUS_ALPHA * ema_mean;
|
||||
// Welford's algorithm:
|
||||
final double oldMean = mean;
|
||||
mean += (val - mean) / count;
|
||||
squaredError += (val - mean) * (val - oldMean);
|
||||
}
|
||||
|
||||
public boolean shouldLog() {
|
||||
return (count > lastLogCount);
|
||||
}
|
||||
|
||||
public void updateLastLogCount() {
|
||||
this.lastLogCount = this.count;
|
||||
}
|
||||
|
||||
public long count() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public double min() {
|
||||
return (count != 0L) ? min : Double.NaN;
|
||||
}
|
||||
|
||||
public double max() {
|
||||
return (count != 0L) ? max : Double.NaN;
|
||||
}
|
||||
|
||||
public double mean() {
|
||||
return (count != 0L) ? mean : Double.NaN;
|
||||
}
|
||||
|
||||
public double ema() {
|
||||
return (count != 0L) ? ema_mean : Double.NaN;
|
||||
}
|
||||
|
||||
public double variance() {
|
||||
return (count != 0L) ? (squaredError / (count - 1L)) : Double.NaN;
|
||||
}
|
||||
|
||||
public double stddev() {
|
||||
return (count != 0L) ? Math.sqrt(variance()) : Double.NaN;
|
||||
}
|
||||
|
||||
public double total() {
|
||||
return (count != 0L) ? (mean() * count) : Double.NaN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(new StringBuilder(128)).toString();
|
||||
}
|
||||
|
||||
public StringBuilder toString(final StringBuilder sb) {
|
||||
sb.append(name).append('[').append(count);
|
||||
sb.append("] sum: ").append(trimTo3Digits(total()));
|
||||
sb.append(" avg: ").append(trimTo3Digits(mean()));
|
||||
sb.append(" stddev: ").append(trimTo3Digits(stddev()));
|
||||
sb.append(" ema: ").append(trimTo3Digits(ema()));
|
||||
sb.append(" [").append(trimTo3Digits(min())).append(" - ").append(trimTo3Digits(max())).append("]");
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import sun.util.logging.PlatformLogger;
|
||||
import java.awt.Toolkit;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class VKEnv {
|
||||
@@ -48,7 +49,7 @@ public final class VKEnv {
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static final boolean accelsd = vulkan && "true".equalsIgnoreCase(AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan.accelsd", "true")));
|
||||
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan.accelsd", "")));
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static final int deviceNumber = !vulkan ? 0 : AccessController.doPrivileged(
|
||||
@@ -108,20 +109,16 @@ public final class VKEnv {
|
||||
state = newState;
|
||||
|
||||
if (Options.verbose || log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
StringBuilder msg = new StringBuilder("Vulkan rendering enabled: ");
|
||||
String message;
|
||||
if (isVulkanEnabled()) {
|
||||
msg.append("YES")
|
||||
.append("\n Presentation enabled: ").append(isPresentationEnabled() ? "YES" : "NO")
|
||||
.append("\n Accelerated surface data enabled: ").append(isSurfaceDataAccelerated() ? "YES" : "NO")
|
||||
.append("\n Devices:");
|
||||
for (int i = 0; i < devices.length; i++) {
|
||||
VKGPU d = devices[i];
|
||||
msg.append(d == defaultDevice ? "\n *" : "\n ").append(i).append(": ").append(d.getName());
|
||||
}
|
||||
message = "Vulkan rendering enabled: YES" +
|
||||
"\n presentation enabled: " + (isPresentationEnabled() ? "YES" : "NO") +
|
||||
"\n accelerated surface data enabled: " + (isSurfaceDataAccelerated() ? "YES" : "NO") +
|
||||
"\n devices:" + Stream.of(devices).map(d -> (d == defaultDevice ?
|
||||
"\n *" : "\n ") + d.getName()).collect(Collectors.joining());
|
||||
} else {
|
||||
msg.append("NO");
|
||||
message = "Vulkan rendering enabled: NO";
|
||||
}
|
||||
String message = msg.toString();
|
||||
if (Options.verbose) {
|
||||
System.err.println(message);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.CONFIGURE_SURFACE;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.DISPOSE_SURFACE;
|
||||
import sun.java2d.pipe.BufferedContext;
|
||||
import sun.java2d.pipe.ParallelogramPipe;
|
||||
import sun.java2d.pipe.PixelToParallelogramConverter;
|
||||
@@ -44,6 +43,7 @@ import sun.java2d.pipe.RenderBuffer;
|
||||
import sun.java2d.pipe.TextPipe;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
@@ -137,29 +137,7 @@ public abstract class VKSurfaceData extends SurfaceData
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the native resources associated with the given VKSurfaceData
|
||||
* (referenced by the pData parameter). This method is invoked from
|
||||
* the native Dispose() method from the Disposer thread when the
|
||||
* Java-level VKSurfaceData object is about to go away.
|
||||
*/
|
||||
static void dispose(long pData) {
|
||||
VKRenderQueue rq = VKRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(12, 4);
|
||||
buf.putInt(DISPOSE_SURFACE);
|
||||
buf.putLong(pData);
|
||||
|
||||
// this call is expected to complete synchronously, so flush now
|
||||
rq.flushNow();
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage getSnapshot(int x, int y, int width, int height) {
|
||||
protected BufferedImage getSnapshot(int x, int y, int width, int height) {
|
||||
BufferedImage image = getFormat().createCompatibleImage(width, height, getTransparency());
|
||||
SurfaceData sd = SurfaceData.getPrimarySurfaceData(image);
|
||||
Blit blit = Blit.getFromCache(getSurfaceType(), CompositeType.SrcNoEa, sd.getSurfaceType());
|
||||
|
||||
20
src/java.desktop/share/glsl/vulkan/alpha_type.glsl
Normal file
20
src/java.desktop/share/glsl/vulkan/alpha_type.glsl
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
#define ALPHA_TYPE_PRE_MULTIPLIED 0U
|
||||
#define ALPHA_TYPE_STRAIGHT 1U
|
||||
|
||||
vec4 convertAlpha(vec4 color, uint inType, uint outType) {
|
||||
if (inType == ALPHA_TYPE_STRAIGHT && outType == ALPHA_TYPE_PRE_MULTIPLIED) {
|
||||
return vec4(color.rgb * color.a, color.a);
|
||||
} else if (inType == ALPHA_TYPE_PRE_MULTIPLIED && outType == ALPHA_TYPE_STRAIGHT && color.a > 0.0) {
|
||||
return vec4(color.rgb / color.a, color.a);
|
||||
} else return color;
|
||||
}
|
||||
|
||||
#ifdef ALPHA_TYPE_SPEC_INDEX
|
||||
layout (constant_id = ALPHA_TYPE_SPEC_INDEX ) const uint const_InAlphaType = ALPHA_TYPE_PRE_MULTIPLIED;
|
||||
layout (constant_id = ALPHA_TYPE_SPEC_INDEX+1) const uint const_OutAlphaType = ALPHA_TYPE_PRE_MULTIPLIED;
|
||||
|
||||
vec4 convertAlpha(vec4 color) {
|
||||
return convertAlpha(color, const_InAlphaType, const_OutAlphaType);
|
||||
}
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#include "common.glsl"
|
||||
DEFAULT_PUSH_CONSTANTS();
|
||||
#define ALPHA_TYPE_SPEC_INDEX 0
|
||||
#include "alpha_type.glsl"
|
||||
|
||||
layout(set = 0, binding = 0) uniform texture2D u_Texture;
|
||||
layout(set = 1, binding = 0) uniform sampler u_Sampler;
|
||||
@@ -9,5 +9,5 @@ layout(location = 0) in vec2 in_TexCoord;
|
||||
layout(location = 0) out vec4 out_Color;
|
||||
|
||||
void main() {
|
||||
out_Color = APPLY_COMPOSITE(convertAlpha(texture(sampler2D(u_Texture, u_Sampler), in_TexCoord)));
|
||||
out_Color = convertAlpha(texture(sampler2D(u_Texture, u_Sampler), in_TexCoord));
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#include "common.glsl"
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat2x3 transform;
|
||||
} push;
|
||||
|
||||
layout(location = 0) in vec2 in_Position;
|
||||
layout(location = 1) in vec2 in_TexCoord;
|
||||
layout(location = 0) out vec2 out_TexCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = transformToDeviceSpace(in_Position);
|
||||
gl_Position = vec4(vec3(in_Position, 1.0)*push.transform, 0.0, 1.0);
|
||||
out_TexCoord = in_TexCoord;
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#include "common.glsl"
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat2x3 transform;
|
||||
} push;
|
||||
|
||||
layout(location = 0) in ivec2 in_Position;
|
||||
|
||||
void main() {
|
||||
gl_Position = transformToDeviceSpace(in_Position);
|
||||
gl_Position = vec4(vec3(in_Position, 1)*push.transform, 0.0, 1.0);
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#include "common.glsl"
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat2x3 transform;
|
||||
} push;
|
||||
|
||||
layout(location = 0) in vec2 in_Position;
|
||||
layout(location = 1) in uint in_Color;
|
||||
layout(location = 1) in vec4 in_Color;
|
||||
layout(location = 0) out flat vec4 out_Color;
|
||||
|
||||
void main() {
|
||||
gl_Position = transformToDeviceSpace(in_Position);
|
||||
out_Color = convertAlpha(decodeColor(in_Color)); // No need to APPLY_COMPOSITE - it was already done on the host.
|
||||
gl_Position = vec4(vec3(in_Position, 1)*push.transform, 0.0, 1.0);
|
||||
out_Color = in_Color;
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
|
||||
// Shader specialization.
|
||||
#define SHADER_MOD_XOR 1U // Xor composite mode
|
||||
#define SHADER_MOD_MASK 2U // MASK_FILL / MASK_BLIT
|
||||
|
||||
layout (constant_id = 0) const uint const_InAlphaType = 0;
|
||||
layout (constant_id = 1) const uint const_OutAlphaType = 0;
|
||||
layout (constant_id = 2) const uint const_ShaderVariant = 0;
|
||||
layout (constant_id = 3) const uint const_ShaderModifier = 0;
|
||||
|
||||
// Host structs.
|
||||
struct VKTransform {
|
||||
float m00, m01, m02;
|
||||
float m10, m11, m12;
|
||||
};
|
||||
struct VKCompositeConstants {
|
||||
uint xorColor;
|
||||
float extraAlpha;
|
||||
};
|
||||
|
||||
// Vertex shader transformation support.
|
||||
#ifdef STAGE_VERT
|
||||
layout(push_constant) uniform PushConstants { VKTransform transform; } push;
|
||||
|
||||
vec4 transformToDeviceSpace(vec2 v) {
|
||||
return vec4(vec3(v, 1.0) * mat2x3(push.transform.m00, push.transform.m01, push.transform.m02, push.transform.m10, push.transform.m11, push.transform.m12), 0.0, 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fragment shader push constant support.
|
||||
#ifdef STAGE_FRAG
|
||||
#define PUSH_CONSTANTS_IMPL(STATEMENT) \
|
||||
layout(push_constant) uniform PushConstants { VKTransform _; VKCompositeConstants push_composite; STATEMENT }
|
||||
#define DEFAULT_PUSH_CONSTANTS() PUSH_CONSTANTS_IMPL(STAGE_FRAG)
|
||||
#define PUSH_CONSTANTS(TYPE) PUSH_CONSTANTS_IMPL(TYPE push;)
|
||||
#endif
|
||||
|
||||
// Color conversion support.
|
||||
#define ALPHA_TYPE_PRE_MULTIPLIED 0U
|
||||
#define ALPHA_TYPE_STRAIGHT 1U
|
||||
|
||||
vec4 convertAlpha(vec4 color, uint inType, uint outType) {
|
||||
if (inType == ALPHA_TYPE_STRAIGHT && outType == ALPHA_TYPE_PRE_MULTIPLIED) {
|
||||
return vec4(color.rgb * color.a, color.a);
|
||||
} else if (inType == ALPHA_TYPE_PRE_MULTIPLIED && outType == ALPHA_TYPE_STRAIGHT && color.a > 0.0) {
|
||||
return vec4(color.rgb / color.a, color.a);
|
||||
} else return color;
|
||||
}
|
||||
|
||||
vec4 convertAlpha(vec4 color) {
|
||||
return convertAlpha(color, const_InAlphaType, const_OutAlphaType);
|
||||
}
|
||||
|
||||
// When applying alpha to a color, straight alpha only multiplies alpha,
|
||||
// and pre-multiplied multiplies the whole color. Use this for convenience.
|
||||
vec4 alphaMask(float alpha, uint alphaType) {
|
||||
return alphaType == ALPHA_TYPE_PRE_MULTIPLIED ? vec4(alpha) : vec4(1.0, 1.0, 1.0, alpha);
|
||||
}
|
||||
|
||||
// Decode color from uint-packed ARGB components.
|
||||
vec4 decodeColor(uint srgb) {
|
||||
return vec4((uvec4(srgb) >> uvec4(16, 8, 0, 24)) & 0xFFU) / 255.0;
|
||||
}
|
||||
|
||||
#ifdef STAGE_FRAG
|
||||
// Before outputting the color, some post-processing is needed:
|
||||
// - For alpha composite, apply extra alpha.
|
||||
// - For XOR composite, apply xor.
|
||||
vec4 applyComposite(vec4 color, VKCompositeConstants composite) {
|
||||
if ((const_ShaderModifier & SHADER_MOD_XOR) != 0) {
|
||||
uvec4 xor = uvec4(composite.xorColor) >> uvec4(16, 8, 0, 24);
|
||||
xor = (uvec4(color * 255.0) ^ xor) & 0xFFU;
|
||||
return vec4(xor) / 255.0;
|
||||
} else return color * alphaMask(composite.extraAlpha, const_OutAlphaType);
|
||||
}
|
||||
#define APPLY_COMPOSITE(COLOR) applyComposite(COLOR, push_composite)
|
||||
|
||||
// MASK_FILL / MASK_BLIT support.
|
||||
int calculateMaskIndex(vec2 localCoord, ivec4 originOffsetAndScanline) {
|
||||
ivec2 maskPos = ivec2(localCoord - vec2(originOffsetAndScanline.xy));
|
||||
int offset = originOffsetAndScanline.z;
|
||||
int scanline = originOffsetAndScanline.w;
|
||||
return offset + scanline * maskPos.y + min(scanline, maskPos.x);
|
||||
}
|
||||
vec4 applyMaskOp(vec4 color, float mask) {
|
||||
if ((const_ShaderModifier & SHADER_MOD_XOR) != 0) return color * float(mask > 0.0);
|
||||
else return color * alphaMask(mask, const_OutAlphaType);
|
||||
}
|
||||
#define APPLY_MASK(COLOR) applyMaskOp(COLOR, imageLoad(u_Mask, calculateMaskIndex(gl_FragCoord.xy, in_OriginOffsetAndScanline)).r)
|
||||
|
||||
// Generic shader support.
|
||||
#define GENERIC_INOUT() \
|
||||
layout(location = 0) out vec4 out_Color; \
|
||||
layout(location = 0) in vec2 in_Position; \
|
||||
layout(location = 1) in flat uint in_Data; \
|
||||
layout(location = 2) in flat ivec4 in_OriginOffsetAndScanline; \
|
||||
layout(origin_upper_left) in vec4 gl_FragCoord; \
|
||||
layout(set = 0, binding = 0, r8) uniform readonly restrict imageBuffer u_Mask
|
||||
|
||||
// Generic color output - handles composite and mask automatically.
|
||||
#define OUTPUT(COLOR) out_Color = COLOR; out_Color = APPLY_COMPOSITE(out_Color); \
|
||||
if ((const_ShaderModifier & SHADER_MOD_MASK) != 0) out_Color = APPLY_MASK(out_Color)
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#include "common.glsl"
|
||||
|
||||
#define SHADER_VARIANT_GRADIENT_CLAMP 0
|
||||
#define SHADER_VARIANT_GRADIENT_CYCLE 1
|
||||
|
||||
struct VKGradientPaintConstants {
|
||||
vec4 c0, c1;
|
||||
vec3 p;
|
||||
};
|
||||
PUSH_CONSTANTS(VKGradientPaintConstants);
|
||||
GENERIC_INOUT();
|
||||
|
||||
void main() {
|
||||
float t = dot(vec3(in_Position, 1.0), push.p);
|
||||
t = const_ShaderVariant == SHADER_VARIANT_GRADIENT_CYCLE ?
|
||||
abs(mod(t + 1.0, 2.0) - 1.0) : // Cycle
|
||||
clamp(t, 0.0, 1.0); // Clamp
|
||||
OUTPUT(convertAlpha(mix(push.c0, push.c1, t)));
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#include "common.glsl"
|
||||
|
||||
layout(location = 0) in ivec4 in_PositionOffsetAndScanline;
|
||||
layout(location = 1) in uint in_Data;
|
||||
|
||||
layout(location = 0) out vec2 out_Position;
|
||||
layout(location = 1) out uint out_Data;
|
||||
|
||||
// This starts with "Origin" and not "Position" intentionally.
|
||||
// When drawing, vertices are ordered in a such way, that provoking vertex is always the top-left one.
|
||||
// This gives us an easy way to calculate offset within the rectangle without additional inputs.
|
||||
layout(location = 2) out flat ivec4 out_OriginOffsetAndScanline;
|
||||
|
||||
void main() {
|
||||
out_Position = in_PositionOffsetAndScanline.xy;
|
||||
out_Data = in_Data;
|
||||
out_OriginOffsetAndScanline = in_PositionOffsetAndScanline;
|
||||
gl_Position = transformToDeviceSpace(in_PositionOffsetAndScanline.xy);
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#include "common.glsl"
|
||||
|
||||
layout(set = 0, binding = 0, r8) uniform readonly restrict imageBuffer u_Mask;
|
||||
|
||||
@@ -12,5 +10,9 @@ layout(location = 1) in flat vec4 in_Color;
|
||||
layout(location = 0) out vec4 out_Color;
|
||||
|
||||
void main() {
|
||||
out_Color = APPLY_MASK(in_Color);
|
||||
ivec2 maskPos = ivec2(gl_FragCoord.xy - vec2(in_OriginOffsetAndScanline.xy));
|
||||
int offset = in_OriginOffsetAndScanline.z;
|
||||
int scanline = in_OriginOffsetAndScanline.w;
|
||||
int maskIndex = offset + scanline * maskPos.y + min(scanline, maskPos.x);
|
||||
out_Color = in_Color * imageLoad(u_Mask, maskIndex).r;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#include "common.glsl"
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
mat2x3 transform;
|
||||
} push;
|
||||
|
||||
layout(location = 0) in ivec4 in_PositionOffsetAndScanline;
|
||||
layout(location = 1) in uint in_Color;
|
||||
layout(location = 1) in vec4 in_Color;
|
||||
|
||||
// This starts with "Origin" and not "Position" intentionally.
|
||||
// When drawing, vertices are ordered in a such way, that provoking vertex is always the top-left one.
|
||||
@@ -12,7 +14,7 @@ layout(location = 0) out flat ivec4 out_OriginOffsetAndScanline;
|
||||
layout(location = 1) out flat vec4 out_Color;
|
||||
|
||||
void main() {
|
||||
gl_Position = transformToDeviceSpace(in_PositionOffsetAndScanline.xy);
|
||||
gl_Position = vec4(vec3(in_PositionOffsetAndScanline.xy, 1)*push.transform, 0.0, 1.0);
|
||||
out_OriginOffsetAndScanline = in_PositionOffsetAndScanline;
|
||||
out_Color = convertAlpha(decodeColor(in_Color));
|
||||
out_Color = in_Color;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#include "common.glsl"
|
||||
|
||||
layout(location = 0) in vec2 in_Position;
|
||||
layout(location = 1) in uint in_Data;
|
||||
layout(location = 0) out vec2 out_Position;
|
||||
layout(location = 1) out uint out_Data;
|
||||
layout(location = 2) out flat ivec4 _; // Unused output
|
||||
|
||||
void main() {
|
||||
out_Position = in_Position;
|
||||
out_Data = in_Data;
|
||||
gl_Position = transformToDeviceSpace(in_Position);
|
||||
}
|
||||
@@ -113,7 +113,7 @@ void VKBlitLoops_IsoBlit(VKSDOps* srcOps, jint filter,
|
||||
VK_COMPONENT_SWIZZLE_ONE);
|
||||
VKPackedSwizzle swizzle = srcOpaque ? OPAQUE_SWIZZLE : 0;
|
||||
|
||||
if (!VKRenderer_Validate(SHADER_BLIT, NO_SHADER_VARIANT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
|
||||
if (!VKRenderer_Validate(SHADER_BLIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
|
||||
VKRenderer_DrawImage(srcOps->image, srcOps->image->format, swizzle, filter, SAMPLER_WRAP_BORDER,
|
||||
(float)sx1, (float)sy1, (float)sx2, (float)sy2, (float)dx1, (float)dy1, (float)dx2, (float)dy2);
|
||||
VKRenderer_AddSurfaceDependency(srcOps, context->surface);
|
||||
@@ -165,12 +165,11 @@ void VKBlitLoops_Blit(JNIEnv *env, SurfaceDataOps* src, jshort srctype, jint fil
|
||||
|
||||
// Need to validate render pass early, as image may not yet be configured.
|
||||
AlphaType alphaType = getSrcAlphaType(srctype);
|
||||
if (!VKRenderer_Validate(SHADER_BLIT, NO_SHADER_VARIANT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
|
||||
if (!VKRenderer_Validate(SHADER_BLIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
|
||||
|
||||
VKDevice* device = context->surface->device;
|
||||
BlitSrcType type = decodeSrcType(device, srctype);
|
||||
VKTexturePoolHandle* imageHandle =
|
||||
VKTexturePool_GetTexture(VKRenderer_GetTexturePool(device->renderer), sw, sh, type.format);
|
||||
VKTexturePoolHandle* imageHandle = VKTexturePool_GetTexture(device->texturePool, sw, sh, type.format);
|
||||
VKImage* image = VKTexturePoolHandle_GetTexture(imageHandle);
|
||||
|
||||
VkDeviceSize dataSize = sh * sw * srcInfo.pixelStride;
|
||||
|
||||
@@ -56,7 +56,7 @@ VKComposites VKComposites_Create() {
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT },
|
||||
{ .logicOpEnable = VK_TRUE,
|
||||
.logicOp = VK_LOGIC_OP_XOR }, ALPHA_TYPE_STRAIGHT });
|
||||
.logicOp = VK_LOGIC_OP_XOR }, ALPHA_TYPE_PRE_MULTIPLIED });
|
||||
|
||||
// NAME | SRC_COLOR | DST_COLOR | SRC_ALPHA | DST_ALPHA ||
|
||||
ALPHA_BLEND( CLEAR , ZERO , ZERO , ZERO , ZERO );
|
||||
@@ -138,6 +138,7 @@ void VKComposites_AddState(VKComposites* composites, VKCompositeMode mode, VKCom
|
||||
state.blendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
state.blendState.pNext = NULL;
|
||||
state.blendState.attachmentCount = 1;
|
||||
state.outAlphaType = ALPHA_TYPE_PRE_MULTIPLIED;
|
||||
MAP_AT(composites->map, (VKCompositeDescriptor) { mode, VK_FALSE }) = state;
|
||||
|
||||
// Using pre-multiplied alpha is necessary for correct blending,
|
||||
|
||||
@@ -272,6 +272,7 @@ void VKDevice_CheckAndAdd(VKEnv* vk, VkPhysicalDevice physicalDevice) {
|
||||
void VKDevice_Reset(VKDevice* device) {
|
||||
if (device == NULL) return;
|
||||
VKRenderer_Destroy(device->renderer);
|
||||
VKTexturePool_Dispose(device->texturePool);
|
||||
VKAllocator_Destroy(device->allocator);
|
||||
ARRAY_FREE(device->enabledExtensions);
|
||||
ARRAY_FREE(device->enabledLayers);
|
||||
@@ -391,4 +392,11 @@ Java_sun_java2d_vulkan_VKGPU_init(JNIEnv *env, jclass jClass, jlong jDevice) {
|
||||
JNU_ThrowByName(env, "java/lang/RuntimeException", "Vulkan: Cannot create renderer");
|
||||
return;
|
||||
}
|
||||
|
||||
device->texturePool = VKTexturePool_InitWithDevice(device);
|
||||
if (!device->texturePool) {
|
||||
VKDevice_Reset(device);
|
||||
JNU_ThrowByName(env, "java/lang/RuntimeException", "Vulkan: Cannot create texture pool");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ struct VKDevice {
|
||||
|
||||
VKAllocator* allocator;
|
||||
VKRenderer* renderer;
|
||||
VKTexturePool* texturePool;
|
||||
|
||||
DEVICE_FUNCTION_TABLE(DECL_PFN)
|
||||
SWAPCHAIN_DEVICE_FUNCTION_TABLE(DECL_PFN)
|
||||
|
||||
@@ -49,7 +49,6 @@ static size_t pipelineDescriptorHash(const void* ptr) {
|
||||
hash(&h, d->inAlphaType);
|
||||
hash(&h, d->composite);
|
||||
hash(&h, d->shader);
|
||||
hash(&h, d->shaderVariant);
|
||||
hash(&h, d->topology);
|
||||
return (size_t) h;
|
||||
}
|
||||
@@ -60,7 +59,6 @@ static bool pipelineDescriptorEquals(const void* ap, const void* bp) {
|
||||
a->inAlphaType == b->inAlphaType &&
|
||||
a->composite == b->composite &&
|
||||
a->shader == b->shader &&
|
||||
a->shaderVariant == b->shaderVariant &&
|
||||
a->topology == b->topology;
|
||||
}
|
||||
|
||||
@@ -146,20 +144,12 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
|
||||
VkPipelineShaderStageCreateInfo createInfos[2]; // vert + frag
|
||||
} ShaderStages;
|
||||
ShaderStages stages[count];
|
||||
typedef struct {
|
||||
uint32_t inAlphaType, outAlphaType, shaderVariant, shaderModifier;
|
||||
} SpecializationData;
|
||||
const VkSpecializationMapEntry SPECIALIZATION_ENTRIES[] = {
|
||||
{ 0, 0, 4 },
|
||||
{ 1, 4, 4 },
|
||||
{ 2, 8, 4 },
|
||||
{ 3, 12, 4 }
|
||||
};
|
||||
typedef struct {
|
||||
VkSpecializationInfo info;
|
||||
SpecializationData data;
|
||||
VkSpecializationMapEntry entries[2];
|
||||
uint64_t data[1];
|
||||
} Specialization;
|
||||
Specialization specializations[count];
|
||||
Specialization specializations[count][2];
|
||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStates[count];
|
||||
VkPipelineDepthStencilStateCreateInfo depthStencilStates[count];
|
||||
VkPipelineDynamicStateCreateInfo dynamicStates[count];
|
||||
@@ -173,19 +163,14 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
|
||||
// - pStages (but stageCount is set to 2)
|
||||
// - pVertexInputState
|
||||
// - createInfo.layout
|
||||
specializations[i] = (Specialization) {
|
||||
.info = {
|
||||
.mapEntryCount = SARRAY_COUNT_OF(SPECIALIZATION_ENTRIES),
|
||||
.pMapEntries = SPECIALIZATION_ENTRIES,
|
||||
.dataSize = sizeof(SpecializationData),
|
||||
.pData = &specializations[i].data
|
||||
},
|
||||
.data = {
|
||||
descriptors[i].inAlphaType, pipelineInfos[i].outAlphaType, (uint32_t) descriptors[i].shaderVariant,
|
||||
(descriptors[i].composite == LOGIC_COMPOSITE_XOR ? 1 : 0) |
|
||||
(descriptors[i].shader & SHADER_MASK ? 2 : 0)
|
||||
}
|
||||
};
|
||||
for (uint32_t j = 0; j < SARRAY_COUNT_OF(specializations[i]); j++) {
|
||||
specializations[i][j].info = (VkSpecializationInfo) {
|
||||
.mapEntryCount = 0,
|
||||
.pMapEntries = specializations[i][j].entries,
|
||||
.dataSize = 0,
|
||||
.pData = specializations[i][j].data
|
||||
};
|
||||
}
|
||||
inputAssemblyStates[i] = (VkPipelineInputAssemblyStateCreateInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||
.topology = descriptors[i].topology
|
||||
@@ -249,38 +234,37 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
|
||||
}
|
||||
|
||||
// Setup input states.
|
||||
MAKE_INPUT_STATE(PRIMITIVE, VKVertex, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32_UINT);
|
||||
MAKE_INPUT_STATE(MASK_FILL, VKMaskFillVertex, VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32_UINT);
|
||||
MAKE_INPUT_STATE(COLOR, VKColorVertex, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT);
|
||||
MAKE_INPUT_STATE(MASK_FILL_COLOR, VKMaskFillColorVertex, VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SFLOAT);
|
||||
MAKE_INPUT_STATE(BLIT, VKTxVertex, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32_SFLOAT);
|
||||
MAKE_INPUT_STATE(CLIP, VKIntVertex, VK_FORMAT_R32G32_SINT);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
// Setup shader-specific pipeline parameters.
|
||||
switch ((int) descriptors[i].shader) {
|
||||
switch (descriptors[i].shader) {
|
||||
case SHADER_COLOR:
|
||||
createInfos[i].pVertexInputState = &INPUT_STATE_PRIMITIVE;
|
||||
createInfos[i].layout = pipelineContext->commonPipelineLayout;
|
||||
createInfos[i].pVertexInputState = &INPUT_STATE_COLOR;
|
||||
createInfos[i].layout = pipelineContext->colorPipelineLayout;
|
||||
stages[i] = (ShaderStages) {{ shaders->color_vert, shaders->color_frag }};
|
||||
break;
|
||||
case SHADER_COLOR | SHADER_MASK:
|
||||
createInfos[i].pVertexInputState = &INPUT_STATE_MASK_FILL;
|
||||
case SHADER_MASK_FILL_COLOR:
|
||||
createInfos[i].pVertexInputState = &INPUT_STATE_MASK_FILL_COLOR;
|
||||
createInfos[i].layout = pipelineContext->maskFillPipelineLayout;
|
||||
stages[i] = (ShaderStages) {{ shaders->mask_fill_color_vert, shaders->mask_fill_color_frag }};
|
||||
break;
|
||||
case SHADER_GRADIENT:
|
||||
createInfos[i].pVertexInputState = &INPUT_STATE_PRIMITIVE;
|
||||
createInfos[i].layout = pipelineContext->maskFillPipelineLayout;
|
||||
stages[i] = (ShaderStages) {{ shaders->primitive_vert, shaders->gradient_frag }};
|
||||
break;
|
||||
case SHADER_GRADIENT | SHADER_MASK:
|
||||
createInfos[i].pVertexInputState = &INPUT_STATE_MASK_FILL;
|
||||
createInfos[i].layout = pipelineContext->maskFillPipelineLayout;
|
||||
stages[i] = (ShaderStages) {{ shaders->mask_fill_vert, shaders->gradient_frag }};
|
||||
break;
|
||||
case SHADER_BLIT:
|
||||
createInfos[i].pVertexInputState = &INPUT_STATE_BLIT;
|
||||
createInfos[i].layout = pipelineContext->texturePipelineLayout;
|
||||
stages[i] = (ShaderStages) {{ shaders->blit_vert, shaders->blit_frag }};
|
||||
// Alpha conversion specialization.
|
||||
uint32_t* spec = (uint32_t*) specializations[i][1].data;
|
||||
spec[0] = descriptors[i].inAlphaType;
|
||||
spec[1] = pipelineInfos[i].outAlphaType;
|
||||
specializations[i][1].info.dataSize = 8;
|
||||
specializations[i][1].entries[0] = (VkSpecializationMapEntry) { 0, 0, 4 };
|
||||
specializations[i][1].entries[1] = (VkSpecializationMapEntry) { 1, 4, 4 };
|
||||
specializations[i][1].info.mapEntryCount = 2;
|
||||
stages[i].createInfos[1].pSpecializationInfo = &specializations[i][1].info;
|
||||
break;
|
||||
case SHADER_CLIP:
|
||||
createInfos[i].pVertexInputState = &INPUT_STATE_CLIP;
|
||||
@@ -306,9 +290,6 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
|
||||
default:
|
||||
VK_FATAL_ERROR("Cannot create pipeline, unknown shader requested!");
|
||||
}
|
||||
for (uint32_t j = 0; j < createInfos[i].stageCount; j++) {
|
||||
stages[i].createInfos[j].pSpecializationInfo = &specializations[i].info;
|
||||
}
|
||||
assert(createInfos[i].pDynamicState->dynamicStateCount <= MAX_DYNAMIC_STATES);
|
||||
J2dRlsTraceLn(J2D_TRACE_INFO, "VKPipelines_CreatePipelines: stencilMode=%d, dstOpaque=%d, composite=%d, shader=%d, topology=%d",
|
||||
descriptors[i].stencilMode, descriptors[i].dstOpaque, descriptors[i].composite, descriptors[i].shader, descriptors[i].topology);
|
||||
@@ -322,7 +303,6 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
|
||||
J2dRlsTraceLn(J2D_TRACE_INFO, "VKPipelines_CreatePipelines: created %d pipelines", count);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
pipelineInfos[i].pipeline = pipelines[i];
|
||||
pipelineInfos[i].layout = createInfos[i].layout;
|
||||
MAP_AT(renderPassContext->pipelines, descriptors[i]) = pipelineInfos[i];
|
||||
}
|
||||
return pipelineInfos[0];
|
||||
@@ -423,49 +403,21 @@ static VkResult VKPipelines_InitPipelineLayouts(VKDevice* device, VKPipelineCont
|
||||
assert(device != NULL && pipelines != NULL);
|
||||
VkResult result;
|
||||
|
||||
// We want all our pipelines to have the same push constant ranges to ensure a common state is compatible between pipelines.
|
||||
VkPushConstantRange pushConstantRanges[] = {{
|
||||
// We want all our pipelines to have same push constant range to ensure common state is compatible between pipelines.
|
||||
VkPushConstantRange pushConstantRange = {
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.offset = 0,
|
||||
.size = sizeof(VKTransform)
|
||||
}, {
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.offset = PUSH_CONSTANTS_OFFSET,
|
||||
.size = PUSH_CONSTANTS_SIZE
|
||||
}};
|
||||
|
||||
// Common pipeline.
|
||||
};
|
||||
VkPipelineLayoutCreateInfo createInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = 0,
|
||||
.pushConstantRangeCount = SARRAY_COUNT_OF(pushConstantRanges),
|
||||
.pPushConstantRanges = pushConstantRanges
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &pushConstantRange
|
||||
};
|
||||
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->commonPipelineLayout);
|
||||
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->colorPipelineLayout);
|
||||
VK_IF_ERROR(result) return result;
|
||||
|
||||
// Mask fill pipeline.
|
||||
VkDescriptorSetLayoutBinding maskBufferLayoutBinding = {
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.pImmutableSamplers = NULL
|
||||
};
|
||||
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.bindingCount = 1,
|
||||
.pBindings = &maskBufferLayoutBinding
|
||||
};
|
||||
result = device->vkCreateDescriptorSetLayout(device->handle, &descriptorSetLayoutCreateInfo, NULL, &pipelines->maskFillDescriptorSetLayout);
|
||||
VK_IF_ERROR(result) return result;
|
||||
|
||||
createInfo.setLayoutCount = 1;
|
||||
createInfo.pSetLayouts = &pipelines->maskFillDescriptorSetLayout;
|
||||
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->maskFillPipelineLayout);
|
||||
VK_IF_ERROR(result) return result;
|
||||
|
||||
// Texture pipeline.
|
||||
VkDescriptorSetLayoutBinding textureLayoutBinding = {
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
@@ -485,11 +437,31 @@ static VkResult VKPipelines_InitPipelineLayouts(VKDevice* device, VKPipelineCont
|
||||
pipelines->textureDescriptorSetLayout,
|
||||
pipelines->samplers.descriptorSetLayout
|
||||
};
|
||||
createInfo.setLayoutCount = SARRAY_COUNT_OF(textureDescriptorSetLayouts);
|
||||
createInfo.setLayoutCount = 2;
|
||||
createInfo.pSetLayouts = textureDescriptorSetLayouts;
|
||||
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->texturePipelineLayout);
|
||||
VK_IF_ERROR(result) return result;
|
||||
|
||||
VkDescriptorSetLayoutBinding maskBufferLayoutBinding = {
|
||||
.binding = 0,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.pImmutableSamplers = NULL
|
||||
};
|
||||
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.bindingCount = 1,
|
||||
.pBindings = &maskBufferLayoutBinding
|
||||
};
|
||||
result = device->vkCreateDescriptorSetLayout(device->handle, &descriptorSetLayoutCreateInfo, NULL, &pipelines->maskFillDescriptorSetLayout);
|
||||
VK_IF_ERROR(result) return result;
|
||||
|
||||
createInfo.setLayoutCount = 1;
|
||||
createInfo.pSetLayouts = &pipelines->maskFillDescriptorSetLayout;
|
||||
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->maskFillPipelineLayout);
|
||||
VK_IF_ERROR(result) return result;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -532,7 +504,7 @@ void VKPipelines_DestroyContext(VKPipelineContext* pipelineContext) {
|
||||
|
||||
VKPipelines_DestroyShaders(device, pipelineContext->shaders);
|
||||
|
||||
device->vkDestroyPipelineLayout(device->handle, pipelineContext->commonPipelineLayout, NULL);
|
||||
device->vkDestroyPipelineLayout(device->handle, pipelineContext->colorPipelineLayout, NULL);
|
||||
device->vkDestroyPipelineLayout(device->handle, pipelineContext->texturePipelineLayout, NULL);
|
||||
device->vkDestroyDescriptorSetLayout(device->handle, pipelineContext->textureDescriptorSetLayout, NULL);
|
||||
device->vkDestroyPipelineLayout(device->handle, pipelineContext->maskFillPipelineLayout, NULL);
|
||||
|
||||
@@ -36,26 +36,13 @@
|
||||
* Shader programs.
|
||||
*/
|
||||
typedef enum {
|
||||
// Base shaders.
|
||||
SHADER_COLOR,
|
||||
SHADER_GRADIENT,
|
||||
SHADER_MASK_FILL_COLOR,
|
||||
SHADER_BLIT,
|
||||
SHADER_CLIP,
|
||||
NO_SHADER = 0x7FFFFFFF,
|
||||
// Mask modifier bit (MASK_FILL & MASK_BLIT).
|
||||
SHADER_MASK = ~NO_SHADER
|
||||
NO_SHADER = 0x7FFFFFFF
|
||||
} VKShader;
|
||||
|
||||
/**
|
||||
* Shader variant.
|
||||
* It is used to specialize shader behavior, and its meaning varies with each particular shader.
|
||||
*/
|
||||
typedef enum {
|
||||
SHADER_VARIANT_GRADIENT_CLAMP = 0,
|
||||
SHADER_VARIANT_GRADIENT_CYCLE = 1,
|
||||
NO_SHADER_VARIANT = 0x7FFFFFFF
|
||||
} VKShaderVariant;
|
||||
|
||||
typedef enum {
|
||||
STENCIL_MODE_NONE = 0, // No stencil attachment.
|
||||
STENCIL_MODE_OFF = 1, // Has stencil attachment, stencil test disabled.
|
||||
@@ -72,14 +59,12 @@ typedef struct {
|
||||
AlphaType inAlphaType : 1;
|
||||
VKCompositeMode composite;
|
||||
VKShader shader;
|
||||
VKShaderVariant shaderVariant;
|
||||
VkPrimitiveTopology topology;
|
||||
} VKPipelineDescriptor;
|
||||
|
||||
typedef struct {
|
||||
VkPipeline pipeline;
|
||||
VkPipelineLayout layout;
|
||||
AlphaType outAlphaType;
|
||||
VkPipeline pipeline;
|
||||
AlphaType outAlphaType;
|
||||
} VKPipelineInfo;
|
||||
|
||||
/**
|
||||
@@ -87,7 +72,7 @@ typedef struct {
|
||||
*/
|
||||
struct VKPipelineContext {
|
||||
VKDevice* device;
|
||||
VkPipelineLayout commonPipelineLayout;
|
||||
VkPipelineLayout colorPipelineLayout;
|
||||
VkDescriptorSetLayout textureDescriptorSetLayout;
|
||||
VkPipelineLayout texturePipelineLayout;
|
||||
VkDescriptorSetLayout maskFillDescriptorSetLayout;
|
||||
@@ -108,42 +93,14 @@ struct VKRenderPassContext {
|
||||
MAP(VKPipelineDescriptor, VKPipelineInfo) pipelines;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned int xorColor;
|
||||
float extraAlpha;
|
||||
} VKCompositeConstants;
|
||||
|
||||
typedef struct {
|
||||
RGBA c0, c1;
|
||||
float p0, p1, p3;
|
||||
} VKGradientPaintConstants;
|
||||
|
||||
typedef union {
|
||||
// The minimum guaranteed size of push constants is 128 bytes.
|
||||
alignas(32) // The maximum alignment for built-in glsl types is 32 bytes (dvec4).
|
||||
char data[(128 - sizeof(VKTransform) - sizeof(VKCompositeConstants)) / 32 * 32];
|
||||
VKGradientPaintConstants gradientPaint;
|
||||
} VKShaderConstants;
|
||||
#define MAX_SHADER_CONSTANTS_SIZE 96 // We expect 96 bytes
|
||||
typedef char VKShaderConstantsCheckOffset[sizeof(VKShaderConstants) == MAX_SHADER_CONSTANTS_SIZE ? 1 : -1]; // Verify.
|
||||
|
||||
typedef struct {
|
||||
VKTransform transform;
|
||||
VKCompositeConstants composite;
|
||||
VKShaderConstants shader;
|
||||
} VKPushConstants;
|
||||
typedef char VKPushConstantsCheckSize[sizeof(VKPushConstants) <= 128 ? 1 : -1]; // We should not exceed 128 bytes.
|
||||
static const uint32_t PUSH_CONSTANTS_OFFSET = (uintptr_t) &((VKPushConstants*) NULL)->composite;
|
||||
static const uint32_t PUSH_CONSTANTS_SIZE = sizeof(VKPushConstants) - PUSH_CONSTANTS_OFFSET;
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} VKIntVertex;
|
||||
|
||||
typedef struct {
|
||||
float x, y;
|
||||
unsigned int data;
|
||||
} VKVertex;
|
||||
RGBA color;
|
||||
} VKColorVertex;
|
||||
|
||||
typedef struct {
|
||||
float px, py;
|
||||
@@ -152,8 +109,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int x, y, maskOffset, maskScanline;
|
||||
unsigned int data;
|
||||
} VKMaskFillVertex;
|
||||
RGBA color;
|
||||
} VKMaskFillColorVertex;
|
||||
|
||||
VKPipelineContext* VKPipelines_CreateContext(VKDevice* device);
|
||||
void VKPipelines_DestroyContext(VKPipelineContext* pipelines);
|
||||
|
||||
@@ -93,21 +93,6 @@
|
||||
#define OFFSET_XFORM sun_java2d_vulkan_VKBlitLoops_OFFSET_XFORM
|
||||
#define OFFSET_ISOBLIT sun_java2d_vulkan_VKBlitLoops_OFFSET_ISOBLIT
|
||||
|
||||
static void applyXor() {
|
||||
if (VKRenderer_GetContext()->shader == SHADER_COLOR) {
|
||||
VKRenderer_GetContext()->vertexData ^= VKRenderer_GetContext()->constants.composite.xorColor;
|
||||
}
|
||||
}
|
||||
|
||||
static void setComposite(VKCompositeMode comp, unsigned int xorColor, float extraAlpha) {
|
||||
VKRenderer_GetContext()->composite = comp;
|
||||
if (VKRenderer_GetContext()->constants.composite.xorColor != xorColor ||
|
||||
VKRenderer_GetContext()->constants.composite.extraAlpha != extraAlpha) {
|
||||
VKRenderer_GetContext()->constants.composite = (VKCompositeConstants) { xorColor, extraAlpha };
|
||||
VKRenderer_GetContext()->constantsModCount++;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
(JNIEnv *env, jobject oglrq, jlong buf, jint limit)
|
||||
{
|
||||
@@ -491,26 +476,30 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
jint flags = NEXT_INT(b);
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: SET_ALPHA_COMPOSITE(%d, %f, %d)", rule, extraAlpha, flags);
|
||||
applyXor();
|
||||
setComposite((VKCompositeMode) rule, 0, extraAlpha);
|
||||
VKRenderer_GetContext()->renderColor = VKRenderer_GetContext()->color;
|
||||
VKRenderer_GetContext()->composite = (VKCompositeMode) rule;
|
||||
VKRenderer_GetContext()->extraAlpha = extraAlpha;
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE:
|
||||
{
|
||||
jint xorPixel = NEXT_INT(b);
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: SET_XOR_COMPOSITE(0x%08x)", xorPixel);
|
||||
applyXor();
|
||||
setComposite(LOGIC_COMPOSITE_XOR, xorPixel, -1.0f);
|
||||
applyXor();
|
||||
"VKRenderQueue_flushBuffer: SET_XOR_COMPOSITE");
|
||||
VKRenderer_GetContext()->renderColor = VKUtil_DecodeJavaColor(xorPixel, ALPHA_TYPE_STRAIGHT);
|
||||
// TODO Fix XOR mode!
|
||||
// VKRenderer_GetContext()->renderColor.a = 0.0f; // Alpha is left unchanged in XOR mode.
|
||||
VKRenderer_GetContext()->composite = LOGIC_COMPOSITE_XOR;
|
||||
VKRenderer_GetContext()->extraAlpha = 1.0f;
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE:
|
||||
{
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: RESET_COMPOSITE");
|
||||
applyXor();
|
||||
setComposite(ALPHA_COMPOSITE_SRC, 0, 1.0f);
|
||||
VKRenderer_GetContext()->renderColor = VKRenderer_GetContext()->color;
|
||||
VKRenderer_GetContext()->composite = ALPHA_COMPOSITE_SRC;
|
||||
VKRenderer_GetContext()->extraAlpha = 1.0f;
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_TRANSFORM:
|
||||
@@ -533,8 +522,8 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
};
|
||||
|
||||
VKRenderingContext* context = VKRenderer_GetContext();
|
||||
if (VK_IS_NEQ_TRANSFORM(&context->constants.transform, &transform)) {
|
||||
context->constants.transform = transform;
|
||||
if (VK_IS_NEQ_TRANSFORM(&context->transform, &transform)) {
|
||||
context->transform = transform;
|
||||
context->transformModCount++;
|
||||
}
|
||||
}
|
||||
@@ -544,8 +533,8 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: RESET_TRANSFORM");
|
||||
VKRenderingContext* context = VKRenderer_GetContext();
|
||||
if (VK_IS_NEQ_TRANSFORM(&context->constants.transform, &VK_ID_TRANSFORM)) {
|
||||
context->constants.transform = VK_ID_TRANSFORM;
|
||||
if (VK_IS_NEQ_TRANSFORM(&context->transform, &VK_ID_TRANSFORM)) {
|
||||
context->transform = VK_ID_TRANSFORM;
|
||||
context->transformModCount++;
|
||||
}
|
||||
}
|
||||
@@ -579,10 +568,9 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_DISPOSE_SURFACE:
|
||||
{
|
||||
VKSDOps* surface = NEXT_VK_SURFACE(b);
|
||||
jlong pData = NEXT_LONG(b);
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: DISPOSE_SURFACE");
|
||||
VKSD_ResetSurface(surface);
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_DISPOSE_CONFIG:
|
||||
@@ -655,34 +643,31 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
|
||||
{
|
||||
VKRenderer_GetContext()->inAlphaType = ALPHA_TYPE_STRAIGHT;
|
||||
VKRenderer_GetContext()->shader = SHADER_COLOR;
|
||||
VKRenderer_GetContext()->shaderVariant = NO_SHADER_VARIANT;
|
||||
VKRenderer_GetContext()->vertexData = NEXT_INT(b);
|
||||
applyXor();
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE, "VKRenderQueue_flushBuffer: SET_COLOR(0x%08x)", VKRenderer_GetContext()->vertexData);
|
||||
jint javaColor = NEXT_INT(b);
|
||||
VKRenderer_GetContext()->color = VKUtil_DecodeJavaColor(javaColor, ALPHA_TYPE_STRAIGHT);
|
||||
if (COMPOSITE_GROUP(VKRenderer_GetContext()->composite) == ALPHA_COMPOSITE_GROUP) {
|
||||
VKRenderer_GetContext()->renderColor = VKRenderer_GetContext()->color;
|
||||
}
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE, "VKRenderQueue_flushBuffer: SET_COLOR(0x%08x)", javaColor);
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, // Print color values with straight alpha for convenience.
|
||||
" srgb={%.3f, %.3f, %.3f, %.3f}",
|
||||
VKUtil_GetRGBA(VKRenderer_GetContext()->color, ALPHA_TYPE_STRAIGHT).r,
|
||||
VKUtil_GetRGBA(VKRenderer_GetContext()->color, ALPHA_TYPE_STRAIGHT).g,
|
||||
VKUtil_GetRGBA(VKRenderer_GetContext()->color, ALPHA_TYPE_STRAIGHT).b,
|
||||
VKUtil_GetRGBA(VKRenderer_GetContext()->color, ALPHA_TYPE_STRAIGHT).a);
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT:
|
||||
{
|
||||
jboolean useMask = NEXT_BOOLEAN(b); // Unused.
|
||||
jboolean cyclic = NEXT_BOOLEAN(b);
|
||||
jdouble p0 = NEXT_DOUBLE(b);
|
||||
jdouble p1 = NEXT_DOUBLE(b);
|
||||
jdouble p3 = NEXT_DOUBLE(b);
|
||||
jint pixel1 = NEXT_INT(b);
|
||||
jint pixel2 = NEXT_INT(b);
|
||||
jboolean useMask= NEXT_BOOLEAN(b);
|
||||
jboolean cyclic = NEXT_BOOLEAN(b);
|
||||
jdouble p0 = NEXT_DOUBLE(b);
|
||||
jdouble p1 = NEXT_DOUBLE(b);
|
||||
jdouble p3 = NEXT_DOUBLE(b);
|
||||
jint pixel1 = NEXT_INT(b);
|
||||
jint pixel2 = NEXT_INT(b);
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: SET_GRADIENT_PAINT");
|
||||
VKRenderer_GetContext()->inAlphaType = ALPHA_TYPE_PRE_MULTIPLIED;
|
||||
VKRenderer_GetContext()->shader = SHADER_GRADIENT;
|
||||
VKRenderer_GetContext()->shaderVariant = cyclic ? SHADER_VARIANT_GRADIENT_CYCLE : SHADER_VARIANT_GRADIENT_CLAMP;
|
||||
VKRenderer_GetContext()->constants.shader.gradientPaint = (VKGradientPaintConstants) {
|
||||
VKUtil_GetRGBA(VKUtil_DecodeJavaColor(pixel1, ALPHA_TYPE_PRE_MULTIPLIED), ALPHA_TYPE_PRE_MULTIPLIED),
|
||||
VKUtil_GetRGBA(VKUtil_DecodeJavaColor(pixel2, ALPHA_TYPE_PRE_MULTIPLIED), ALPHA_TYPE_PRE_MULTIPLIED),
|
||||
p0*2.0, p1*2.0, p3*2.0-0.5
|
||||
};
|
||||
VKRenderer_GetContext()->constantsModCount++;
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_LINEAR_GRADIENT_PAINT:
|
||||
|
||||
@@ -94,7 +94,6 @@ typedef struct {
|
||||
struct VKRenderer {
|
||||
VKDevice* device;
|
||||
VKPipelineContext* pipelineContext;
|
||||
VKTexturePool* texturePool;
|
||||
|
||||
POOL(VkCommandBuffer, commandBufferPool);
|
||||
POOL(VkCommandBuffer, secondaryCommandBufferPool);
|
||||
@@ -164,7 +163,6 @@ struct VKRenderPass {
|
||||
BufferWritingState maskFillBufferWriting;
|
||||
|
||||
VKPipelineDescriptor state;
|
||||
uint64_t constantsModCount; // Just a tag to detect when constants were changed.
|
||||
uint64_t transformModCount; // Just a tag to detect when transform was changed.
|
||||
uint64_t clipModCount; // Just a tag to detect when clip was changed.
|
||||
VkBool32 pendingFlush : 1;
|
||||
@@ -177,17 +175,12 @@ struct VKRenderPass {
|
||||
// which is only called from queue flusher thread, no need for synchronization.
|
||||
static VKRenderingContext context = {
|
||||
.surface = NULL,
|
||||
.composite = ALPHA_COMPOSITE_SRC_OVER,
|
||||
.inAlphaType = ALPHA_TYPE_UNKNOWN,
|
||||
.shader = NO_SHADER,
|
||||
.shaderVariant = NO_SHADER_VARIANT,
|
||||
.vertexData = 0,
|
||||
.constantsModCount = 1,
|
||||
.transform = VK_ID_TRANSFORM,
|
||||
.transformModCount = 1,
|
||||
.constants = {
|
||||
.transform = VK_ID_TRANSFORM,
|
||||
.composite = { 0, 1.0f }
|
||||
},
|
||||
.color = {},
|
||||
.renderColor = {},
|
||||
.composite = ALPHA_COMPOSITE_SRC_OVER,
|
||||
.extraAlpha = 1.0f,
|
||||
.clipModCount = 1,
|
||||
.clipRect = NO_CLIP,
|
||||
.clipSpanVertices = NULL
|
||||
@@ -200,9 +193,6 @@ VKRenderingContext *VKRenderer_GetContext() {
|
||||
return &context;
|
||||
}
|
||||
|
||||
VKTexturePool *VKRenderer_GetTexturePool(VKRenderer* renderer) {
|
||||
return renderer->texturePool;
|
||||
}
|
||||
/**
|
||||
* Helper function for POOL_TAKE macro.
|
||||
*/
|
||||
@@ -227,7 +217,7 @@ static VkBool32 VKRenderer_CheckPoolDrain(void* pool, void* entry) {
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
#define VERTEX_BUFFER_SIZE (128 * 1024) // 128KiB - enough to draw 1820 quads (6 verts) with VKVertex.
|
||||
#define VERTEX_BUFFER_SIZE (128 * 1024) // 128KiB - enough to draw 910 quads (6 verts) with VKColorVertex.
|
||||
#define VERTEX_BUFFER_PAGE_SIZE (1 * 1024 * 1024) // 1MiB - fits 8 buffers.
|
||||
static void VKRenderer_FindVertexBufferMemoryType(VKMemoryRequirements* requirements) {
|
||||
VKAllocator_FindMemoryType(requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
|
||||
@@ -378,12 +368,6 @@ VKRenderer* VKRenderer_Create(VKDevice* device) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderer->texturePool = VKTexturePool_InitWithDevice(device);
|
||||
if (!renderer->texturePool) {
|
||||
VKRenderer_Destroy(renderer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create command pool
|
||||
// TODO we currently have single command pool with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
|
||||
// we may need to consider having multiple pools to avoid resetting buffers one-by-one
|
||||
@@ -454,9 +438,6 @@ void VKRenderer_Destroy(VKRenderer* renderer) {
|
||||
device->vkDestroyDescriptorPool(device->handle, renderer->descriptorPools[i], NULL);
|
||||
}
|
||||
ARRAY_FREE(renderer->descriptorPools);
|
||||
|
||||
VKTexturePool_Dispose(renderer->texturePool);
|
||||
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(renderer->imageDescriptorPools); i++) {
|
||||
device->vkDestroyDescriptorPool(device->handle, renderer->imageDescriptorPools[i], NULL);
|
||||
}
|
||||
@@ -603,47 +584,33 @@ inline void VKRenderer_FlushDraw(VKSDOps* surface) {
|
||||
static void VKRenderer_ResetDrawing(VKSDOps* surface) {
|
||||
assert(surface != NULL && surface->renderPass != NULL);
|
||||
VKRenderer* renderer = surface->device->renderer;
|
||||
VKRenderPass* renderPass = surface->renderPass;
|
||||
renderPass->state.composite = NO_COMPOSITE;
|
||||
renderPass->state.shader = NO_SHADER;
|
||||
renderPass->constantsModCount = 0;
|
||||
renderPass->transformModCount = 0;
|
||||
renderPass->firstVertex = 0;
|
||||
renderPass->vertexCount = 0;
|
||||
renderPass->vertexBufferWriting = (BufferWritingState) { NULL, 0, VK_FALSE };
|
||||
renderPass->maskFillBufferWriting = (BufferWritingState) { NULL, 0, VK_FALSE };
|
||||
if (ARRAY_SIZE(renderPass->flushRanges) > 0) {
|
||||
surface->renderPass->state.composite = NO_COMPOSITE;
|
||||
surface->renderPass->state.shader = NO_SHADER;
|
||||
surface->renderPass->transformModCount = 0;
|
||||
surface->renderPass->firstVertex = 0;
|
||||
surface->renderPass->vertexCount = 0;
|
||||
surface->renderPass->vertexBufferWriting = (BufferWritingState) {NULL, 0, VK_FALSE};
|
||||
surface->renderPass->maskFillBufferWriting = (BufferWritingState) {NULL, 0, VK_FALSE};
|
||||
if (ARRAY_SIZE(surface->renderPass->flushRanges) > 0) {
|
||||
VK_IF_ERROR(surface->device->vkFlushMappedMemoryRanges(surface->device->handle,
|
||||
ARRAY_SIZE(renderPass->flushRanges), renderPass->flushRanges)) {}
|
||||
ARRAY_RESIZE(renderPass->flushRanges, 0);
|
||||
ARRAY_SIZE(surface->renderPass->flushRanges), surface->renderPass->flushRanges)) {}
|
||||
ARRAY_RESIZE(surface->renderPass->flushRanges, 0);
|
||||
}
|
||||
size_t vertexBufferCount = ARRAY_SIZE(renderPass->vertexBuffers);
|
||||
size_t maskFillBufferCount = ARRAY_SIZE(renderPass->maskFillBuffers);
|
||||
size_t cleanupQueueCount = ARRAY_SIZE(renderPass->cleanupQueue);
|
||||
size_t vertexBufferCount = ARRAY_SIZE(surface->renderPass->vertexBuffers);
|
||||
size_t maskFillBufferCount = ARRAY_SIZE(surface->renderPass->maskFillBuffers);
|
||||
size_t cleanupQueueCount = ARRAY_SIZE(surface->renderPass->cleanupQueue);
|
||||
for (uint32_t i = 0; i < vertexBufferCount; i++) {
|
||||
POOL_RETURN(renderer, vertexBufferPool, renderPass->vertexBuffers[i]);
|
||||
POOL_RETURN(surface->device->renderer, vertexBufferPool, surface->renderPass->vertexBuffers[i]);
|
||||
}
|
||||
for (uint32_t i = 0; i < maskFillBufferCount; i++) {
|
||||
POOL_RETURN(renderer, maskFillBufferPool, renderPass->maskFillBuffers[i]);
|
||||
POOL_RETURN(surface->device->renderer, maskFillBufferPool, surface->renderPass->maskFillBuffers[i]);
|
||||
}
|
||||
for (uint32_t i = 0; i < cleanupQueueCount; i++) {
|
||||
POOL_RETURN(renderer, cleanupQueue, renderPass->cleanupQueue[i]);
|
||||
POOL_RETURN(surface->device->renderer, cleanupQueue, surface->renderPass->cleanupQueue[i]);
|
||||
}
|
||||
ARRAY_RESIZE(renderPass->vertexBuffers, 0);
|
||||
ARRAY_RESIZE(renderPass->maskFillBuffers, 0);
|
||||
ARRAY_RESIZE(renderPass->cleanupQueue, 0);
|
||||
|
||||
// Update dependencies on used surfaces.
|
||||
for (uint32_t i = 0, surfaces = (uint32_t) ARRAY_SIZE(renderPass->usedSurfaces); i < surfaces; i++) {
|
||||
VKSDOps* usedSurface = renderPass->usedSurfaces[i];
|
||||
uint32_t newSize = 0, oldSize = (uint32_t) ARRAY_SIZE(usedSurface->dependentSurfaces);
|
||||
for (uint32_t j = 0; j < oldSize; j++) {
|
||||
VKSDOps* s = usedSurface->dependentSurfaces[j];
|
||||
if (s != surface) usedSurface->dependentSurfaces[newSize++] = s;
|
||||
}
|
||||
if (newSize != oldSize) ARRAY_RESIZE(usedSurface->dependentSurfaces, newSize);
|
||||
}
|
||||
ARRAY_RESIZE(renderPass->usedSurfaces, 0);
|
||||
ARRAY_RESIZE(surface->renderPass->vertexBuffers, 0);
|
||||
ARRAY_RESIZE(surface->renderPass->maskFillBuffers, 0);
|
||||
ARRAY_RESIZE(surface->renderPass->cleanupQueue, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -731,7 +698,6 @@ static VkBool32 VKRenderer_InitRenderPass(VKSDOps* surface) {
|
||||
.composite = NO_COMPOSITE,
|
||||
.shader = NO_SHADER
|
||||
},
|
||||
.constantsModCount = 0,
|
||||
.transformModCount = 0,
|
||||
.clipModCount = 0,
|
||||
.pendingFlush = VK_FALSE,
|
||||
@@ -898,11 +864,19 @@ VkBool32 VKRenderer_FlushRenderPass(VKSDOps* surface) {
|
||||
VKRenderer* renderer = device->renderer;
|
||||
VkCommandBuffer cb = VKRenderer_Record(renderer);
|
||||
|
||||
// Update timestamps on used surfaces.
|
||||
// Update dependencies on used surfaces.
|
||||
surface->lastTimestamp = renderer->writeTimestamp;
|
||||
for (uint32_t i = 0, surfaces = (uint32_t) ARRAY_SIZE(surface->renderPass->usedSurfaces); i < surfaces; i++) {
|
||||
surface->renderPass->usedSurfaces[i]->lastTimestamp = renderer->writeTimestamp;
|
||||
VKSDOps* usedSurface = surface->renderPass->usedSurfaces[i];
|
||||
usedSurface->lastTimestamp = renderer->writeTimestamp;
|
||||
uint32_t newSize = 0, oldSize = (uint32_t) ARRAY_SIZE(usedSurface->dependentSurfaces);
|
||||
for (uint32_t j = 0; j < oldSize; j++) {
|
||||
VKSDOps* s = usedSurface->dependentSurfaces[j];
|
||||
if (s != surface) usedSurface->dependentSurfaces[newSize++] = s;
|
||||
}
|
||||
if (newSize != oldSize) ARRAY_RESIZE(usedSurface->dependentSurfaces, newSize);
|
||||
}
|
||||
ARRAY_RESIZE(surface->renderPass->usedSurfaces, 0);
|
||||
|
||||
// Insert barriers to prepare surface for rendering.
|
||||
VkImageMemoryBarrier barriers[2];
|
||||
@@ -1135,7 +1109,7 @@ static uint32_t VKRenderer_AllocateVertices(uint32_t primitives, uint32_t vertic
|
||||
* This function can invalidate drawing state, always call it before VK_DRAW.
|
||||
*/
|
||||
static BufferWritingState VKRenderer_AllocateMaskFillBytes(uint32_t size) {
|
||||
// assert(size > 0); // size can be 0 when binding the buffer without allocating any data.
|
||||
assert(size > 0);
|
||||
assert(size <= MASK_FILL_BUFFER_SIZE);
|
||||
VKSDOps* surface = VKRenderer_GetContext()->surface;
|
||||
BufferWritingState state = VKRenderer_AllocateBufferData(
|
||||
@@ -1171,35 +1145,16 @@ static void VKRenderer_ValidateTransform() {
|
||||
0.0f, 2.0f / (float) surface->image->extent.height, -1.0f
|
||||
};
|
||||
// Combine it with user transform.
|
||||
VKUtil_ConcatenateTransform(&transform, &context->constants.transform);
|
||||
VKUtil_ConcatenateTransform(&transform, &context->transform);
|
||||
// Push the transform into shader.
|
||||
surface->device->vkCmdPushConstants(
|
||||
renderPass->commandBuffer,
|
||||
surface->device->renderer->pipelineContext->commonPipelineLayout,
|
||||
surface->device->renderer->pipelineContext->colorPipelineLayout, // TODO what if our pipeline layout differs?
|
||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VKTransform), &transform
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void VKRenderer_ValidateConstants() {
|
||||
VKRenderingContext* context = VKRenderer_GetContext();
|
||||
assert(context->surface != NULL);
|
||||
VKSDOps* surface = context->surface;
|
||||
VKRenderPass* renderPass = surface->renderPass;
|
||||
// Update constants, ignoring clip and color shaders.
|
||||
if (renderPass->constantsModCount != context->constantsModCount &&
|
||||
renderPass->state.shader != SHADER_CLIP && renderPass->state.shader != SHADER_COLOR) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "VKRenderer_ValidateConstants: updating constants");
|
||||
VKRenderer_FlushDraw(surface);
|
||||
renderPass->constantsModCount = context->constantsModCount;
|
||||
surface->device->vkCmdPushConstants(
|
||||
renderPass->commandBuffer,
|
||||
surface->device->renderer->pipelineContext->commonPipelineLayout,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, PUSH_CONSTANTS_OFFSET, PUSH_CONSTANTS_SIZE, &context->constants.composite
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup stencil attachment according to the context clip state.
|
||||
* If there is a clip shape, attachment is cleared with "fail" value and then
|
||||
@@ -1236,7 +1191,6 @@ static void VKRenderer_SetupStencil() {
|
||||
.inAlphaType = ALPHA_TYPE_UNKNOWN,
|
||||
.composite = NO_COMPOSITE,
|
||||
.shader = SHADER_CLIP,
|
||||
.shaderVariant = NO_SHADER_VARIANT,
|
||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
|
||||
}).pipeline);
|
||||
// Reset vertex buffer binding.
|
||||
@@ -1281,7 +1235,7 @@ void VKRenderer_RecordBarriers(VKRenderer* renderer,
|
||||
/**
|
||||
* Setup pipeline for drawing. Returns FALSE if surface is not yet ready for drawing.
|
||||
*/
|
||||
VkBool32 VKRenderer_Validate(VKShader shader, VKShaderVariant shaderVariant, VkPrimitiveTopology topology, AlphaType inAlphaType) {
|
||||
VkBool32 VKRenderer_Validate(VKShader shader, VkPrimitiveTopology topology, AlphaType inAlphaType) {
|
||||
assert(context.surface != NULL);
|
||||
VKSDOps* surface = context.surface;
|
||||
|
||||
@@ -1323,18 +1277,10 @@ VkBool32 VKRenderer_Validate(VKShader shader, VKShaderVariant shaderVariant, VkP
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "VKRenderer_Validate: updating clip");
|
||||
surface->device->vkCmdSetScissor(renderPass->commandBuffer, 0, 1, &context.clipRect);
|
||||
if (clipChanged) {
|
||||
VKStencilMode stencilMode = STENCIL_MODE_NONE;
|
||||
if (ARRAY_SIZE(context.clipSpanVertices) > 0) {
|
||||
VKRenderer_SetupStencil();
|
||||
stencilMode = STENCIL_MODE_ON;
|
||||
} else if (surface->stencil != NULL) {
|
||||
stencilMode = STENCIL_MODE_OFF;
|
||||
}
|
||||
// Reset the pipeline when changing stencil mode.
|
||||
if (renderPass->state.stencilMode != stencilMode) {
|
||||
renderPass->state.shader = NO_SHADER;
|
||||
}
|
||||
renderPass->state.stencilMode = stencilMode;
|
||||
renderPass->state.stencilMode = STENCIL_MODE_ON;
|
||||
} else renderPass->state.stencilMode = surface->stencil != NULL ? STENCIL_MODE_OFF : STENCIL_MODE_NONE;
|
||||
}
|
||||
}
|
||||
// Validate current composite.
|
||||
@@ -1350,7 +1296,6 @@ VkBool32 VKRenderer_Validate(VKShader shader, VKShaderVariant shaderVariant, VkP
|
||||
|
||||
// Validate current pipeline.
|
||||
if (renderPass->state.shader != shader ||
|
||||
renderPass->state.shaderVariant != shaderVariant ||
|
||||
renderPass->state.topology != topology ||
|
||||
renderPass->state.inAlphaType != inAlphaType) {
|
||||
J2dTraceLn(J2D_TRACE_VERBOSE, "VKRenderer_Validate: updating pipeline, old=%d, new=%d",
|
||||
@@ -1358,7 +1303,6 @@ VkBool32 VKRenderer_Validate(VKShader shader, VKShaderVariant shaderVariant, VkP
|
||||
VKRenderer_FlushDraw(surface);
|
||||
VkCommandBuffer cb = renderPass->commandBuffer;
|
||||
renderPass->state.shader = shader;
|
||||
renderPass->state.shaderVariant = shaderVariant;
|
||||
renderPass->state.topology = topology;
|
||||
renderPass->state.inAlphaType = inAlphaType;
|
||||
VKPipelineInfo pipelineInfo = VKPipelines_GetPipelineInfo(renderPass->context, renderPass->state);
|
||||
@@ -1366,26 +1310,10 @@ VkBool32 VKRenderer_Validate(VKShader shader, VKShaderVariant shaderVariant, VkP
|
||||
surface->device->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineInfo.pipeline);
|
||||
renderPass->vertexBufferWriting.bound = VK_FALSE;
|
||||
renderPass->maskFillBufferWriting.bound = VK_FALSE;
|
||||
|
||||
// If pipeline uses mask fill layout, but the shader is not actually a MASK one, that must be a generic-layout pipeline.
|
||||
// In that case, we need to bind a mask buffer, even if we won't ever use it.
|
||||
// We could use VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT or nullDescriptor, but those require
|
||||
// optional features or extensions, so don't bother for now...
|
||||
// TODO this is ugly, do something with it.
|
||||
if (pipelineInfo.layout == surface->device->renderer->pipelineContext->maskFillPipelineLayout && !(shader & SHADER_MASK)) {
|
||||
VKRenderer_AllocateMaskFillBytes(0);
|
||||
}
|
||||
}
|
||||
|
||||
VKRenderer_ValidateConstants();
|
||||
return VK_TRUE;
|
||||
}
|
||||
|
||||
static VkBool32 VKRenderer_ValidatePaint(VKShader shaderModifier, VkBool32 fill) {
|
||||
return VKRenderer_Validate(context.shader | shaderModifier, context.shaderVariant,
|
||||
fill ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST : VK_PRIMITIVE_TOPOLOGY_LINE_LIST, context.inAlphaType);
|
||||
}
|
||||
|
||||
// Drawing operations.
|
||||
|
||||
void VKRenderer_RenderRect(VkBool32 fill, jint x, jint y, jint w, jint h) {
|
||||
@@ -1396,9 +1324,12 @@ void VKRenderer_RenderRect(VkBool32 fill, jint x, jint y, jint w, jint h) {
|
||||
void VKRenderer_RenderParallelogram(VkBool32 fill,
|
||||
jfloat x11, jfloat y11,
|
||||
jfloat dx21, jfloat dy21,
|
||||
jfloat dx12, jfloat dy12) {
|
||||
if (!VKRenderer_ValidatePaint(0, fill)) return; // Not ready.
|
||||
|
||||
jfloat dx12, jfloat dy12)
|
||||
{
|
||||
if (!VKRenderer_Validate(SHADER_COLOR,
|
||||
fill ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
|
||||
: VK_PRIMITIVE_TOPOLOGY_LINE_LIST, ALPHA_TYPE_UNKNOWN)) return; // Not ready.
|
||||
RGBA c = VKRenderer_GetRGBA(context.surface, context.renderColor);
|
||||
/* dx21
|
||||
* (p1)---------(p2) | (p1)------
|
||||
* |\ \ | | \ dy21
|
||||
@@ -1409,12 +1340,12 @@ void VKRenderer_RenderParallelogram(VkBool32 fill,
|
||||
* dy21 \ |
|
||||
* -----(p3)
|
||||
*/
|
||||
VKVertex p1 = {x11, y11, context.vertexData};
|
||||
VKVertex p2 = {x11 + dx21, y11 + dy21, context.vertexData};
|
||||
VKVertex p3 = {x11 + dx21 + dx12, y11 + dy21 + dy12, context.vertexData};
|
||||
VKVertex p4 = {x11 + dx12, y11 + dy12, context.vertexData};
|
||||
VKColorVertex p1 = {x11, y11, c};
|
||||
VKColorVertex p2 = {x11 + dx21, y11 + dy21, c};
|
||||
VKColorVertex p3 = {x11 + dx21 + dx12, y11 + dy21 + dy12, c};
|
||||
VKColorVertex p4 = {x11 + dx12, y11 + dy12, c};
|
||||
|
||||
VKVertex* vs;
|
||||
VKColorVertex* vs;
|
||||
VK_DRAW(vs, 1, fill ? 6 : 8);
|
||||
uint32_t i = 0;
|
||||
vs[i++] = p1;
|
||||
@@ -1431,18 +1362,19 @@ void VKRenderer_RenderParallelogram(VkBool32 fill,
|
||||
|
||||
void VKRenderer_FillSpans(jint spanCount, jint *spans) {
|
||||
if (spanCount == 0) return;
|
||||
if (!VKRenderer_ValidatePaint(0, VK_TRUE)) return; // Not ready.
|
||||
if (!VKRenderer_Validate(SHADER_COLOR, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, ALPHA_TYPE_UNKNOWN)) return; // Not ready.
|
||||
RGBA c = VKRenderer_GetRGBA(context.surface, context.renderColor);
|
||||
|
||||
jfloat x1 = (float)*(spans++);
|
||||
jfloat y1 = (float)*(spans++);
|
||||
jfloat x2 = (float)*(spans++);
|
||||
jfloat y2 = (float)*(spans++);
|
||||
VKVertex p1 = {x1, y1, context.vertexData};
|
||||
VKVertex p2 = {x2, y1, context.vertexData};
|
||||
VKVertex p3 = {x2, y2, context.vertexData};
|
||||
VKVertex p4 = {x1, y2, context.vertexData};
|
||||
VKColorVertex p1 = {x1, y1, c};
|
||||
VKColorVertex p2 = {x2, y1, c};
|
||||
VKColorVertex p3 = {x2, y2, c};
|
||||
VKColorVertex p4 = {x1, y2, c};
|
||||
|
||||
VKVertex* vs;
|
||||
VKColorVertex* vs;
|
||||
VK_DRAW(vs, 1, 6);
|
||||
vs[0] = p1; vs[1] = p2; vs[2] = p3; vs[3] = p3; vs[4] = p4; vs[5] = p1;
|
||||
|
||||
@@ -1459,8 +1391,8 @@ void VKRenderer_FillSpans(jint spanCount, jint *spans) {
|
||||
|
||||
void VKRenderer_MaskFill(jint x, jint y, jint w, jint h,
|
||||
jint maskoff, jint maskscan, jint masklen, uint8_t *mask) {
|
||||
if (!VKRenderer_ValidatePaint(SHADER_MASK, VK_TRUE)) return; // Not ready.
|
||||
|
||||
if (!VKRenderer_Validate(SHADER_MASK_FILL_COLOR,
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, ALPHA_TYPE_UNKNOWN)) return; // Not ready.
|
||||
// maskoff is the offset from the beginning of mask,
|
||||
// it's the same as x and y offset within a tile (maskoff % maskscan, maskoff / maskscan).
|
||||
// maskscan is the number of bytes in a row/
|
||||
@@ -1478,13 +1410,14 @@ void VKRenderer_MaskFill(jint x, jint y, jint w, jint h,
|
||||
*((char *)maskState.data) = (char)0xFF;
|
||||
}
|
||||
|
||||
VKMaskFillVertex* vs;
|
||||
VKMaskFillColorVertex* vs;
|
||||
VK_DRAW(vs, 1, 6);
|
||||
RGBA c = VKRenderer_GetRGBA(context.surface, context.renderColor);
|
||||
int offset = (int) maskState.offset;
|
||||
VKMaskFillVertex p1 = {x, y, offset, maskscan, context.vertexData};
|
||||
VKMaskFillVertex p2 = {x + w, y, offset, maskscan, context.vertexData};
|
||||
VKMaskFillVertex p3 = {x + w, y + h, offset, maskscan, context.vertexData};
|
||||
VKMaskFillVertex p4 = {x, y + h, offset, maskscan, context.vertexData};
|
||||
VKMaskFillColorVertex p1 = {x, y, offset, maskscan, c};
|
||||
VKMaskFillColorVertex p2 = {x + w, y, offset, maskscan, c};
|
||||
VKMaskFillColorVertex p3 = {x + w, y + h, offset, maskscan, c};
|
||||
VKMaskFillColorVertex p4 = {x, y + h, offset, maskscan, c};
|
||||
// Always keep p1 as provoking vertex for correct origin calculation in vertex shader.
|
||||
vs[0] = p1; vs[1] = p3; vs[2] = p2;
|
||||
vs[3] = p1; vs[4] = p3; vs[5] = p4;
|
||||
|
||||
@@ -29,22 +29,27 @@
|
||||
|
||||
#include "VKTypes.h"
|
||||
#include "VKPipelines.h"
|
||||
#include "VKTexturePool.h"
|
||||
|
||||
#define NO_CLIP ((VkRect2D) {{0, 0}, {0x7FFFFFFFU, 0x7FFFFFFFU}})
|
||||
|
||||
struct VKRenderingContext {
|
||||
VKSDOps* surface;
|
||||
|
||||
VKCompositeMode composite;
|
||||
AlphaType inAlphaType;
|
||||
VKShader shader;
|
||||
VKShaderVariant shaderVariant;
|
||||
unsigned int vertexData;
|
||||
VKPushConstants constants;
|
||||
uint64_t constantsModCount;
|
||||
VKTransform transform;
|
||||
uint64_t transformModCount;
|
||||
|
||||
// We keep this color separately from renderColor,
|
||||
// because we need consistent state when switching between XOR and alpha
|
||||
// composite modes. This variable holds last value set by SET_COLOR, while
|
||||
// renderColor holds color, currently used for drawing, which may have
|
||||
// also been provided by SET_XOR_COMPOSITE.
|
||||
Color color;
|
||||
Color renderColor;
|
||||
VKCompositeMode composite;
|
||||
|
||||
// Extra alpha is not used when painting with plain color,
|
||||
// in this case color.a already includes it.
|
||||
float extraAlpha;
|
||||
uint64_t clipModCount; // Used to track changes to the clip.
|
||||
VkRect2D clipRect;
|
||||
ARRAY(VKIntVertex) clipSpanVertices;
|
||||
@@ -57,7 +62,7 @@ VKRenderer* VKRenderer_Create(VKDevice* device);
|
||||
/**
|
||||
* Setup pipeline for drawing. Returns FALSE if the surface is not yet ready for drawing.
|
||||
*/
|
||||
VkBool32 VKRenderer_Validate(VKShader shader, VKShaderVariant shaderVariant, VkPrimitiveTopology topology, AlphaType inAlphaType);
|
||||
VkBool32 VKRenderer_Validate(VKShader shader, VkPrimitiveTopology topology, AlphaType inAlphaType);
|
||||
|
||||
/**
|
||||
* Record commands into the primary command buffer (outside of a render pass).
|
||||
@@ -142,6 +147,5 @@ void VKRenderer_DrawImage(VKImage* image, VkFormat format,
|
||||
float dx1, float dy1, float dx2, float dy2);
|
||||
|
||||
VKRenderingContext* VKRenderer_GetContext();
|
||||
VKTexturePool* VKRenderer_GetTexturePool(VKRenderer* );
|
||||
|
||||
#endif //VKRenderer_h_Included
|
||||
|
||||
@@ -292,7 +292,7 @@ VkBool32 VKSD_ConfigureWindowSurface(VKWinSDOps* vkwinsdo) {
|
||||
}
|
||||
|
||||
static void VKSD_OnDispose(JNIEnv* env, SurfaceDataOps* ops) {
|
||||
JNU_CallStaticMethodByName(env, NULL, "sun/java2d/vulkan/VKSurfaceData", "dispose", "(J)V", ptr_to_jlong(ops));
|
||||
VKSD_ResetSurface((VKSDOps*) ops);
|
||||
}
|
||||
|
||||
JNIEXPORT VKSDOps* VKSD_CreateSurface(JNIEnv* env, jobject vksd, jint type, jint format, jint backgroundRGB,
|
||||
|
||||
@@ -62,7 +62,7 @@ typedef uint16_t VKPackedSwizzle;
|
||||
*/
|
||||
typedef struct {
|
||||
float m00, m01, m02;
|
||||
float m10, m11, m12;
|
||||
float m10 __attribute__((aligned(16))), m11, m12;
|
||||
} VKTransform;
|
||||
|
||||
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VKMemory);
|
||||
|
||||
@@ -40,44 +40,35 @@ import java.awt.RenderingHints;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
|
||||
public class DefaultFrameDecoration extends FullFrameDecorationHelper {
|
||||
private static final int BORDER_SIZE = 1;
|
||||
private static final int HEIGHT = 28 + BORDER_SIZE;
|
||||
private static final int HEIGHT = 30;
|
||||
private static final int BUTTON_ICON_SIZE = 4;
|
||||
private static final int BUTTON_SIZE = 16;
|
||||
private static final int BUTTONS_RIGHT_PADDING = 7;
|
||||
private static final int BUTTONS_PADDING = 8;
|
||||
private static final int BUTTON_CIRCLE_RADIUS = 10;
|
||||
private static final Font FONT = new Font(Font.DIALOG, Font.BOLD, 12);
|
||||
private static final Color ACTIVE_BACKGROUND = new Color(0xedeeef);
|
||||
private static final Color ACTIVE_BACKGROUND_DARK = new Color(0x31363b);
|
||||
private static final Color INACTIVE_BACKGROUND = new Color(0xdcddde);
|
||||
private static final Color INACTIVE_BACKGROUND_DARK = new Color(0x292d31);
|
||||
private static final Color ACTIVE_BACKGROUND = new Color(0xebebeb);
|
||||
private static final Color ACTIVE_BACKGROUND_DARK = new Color(0x222222);
|
||||
private static final Color INACTIVE_BACKGROUND = new Color(0xfafafa);
|
||||
private static final Color INACTIVE_BACKGROUND_DARK = new Color(0x2c2c2c);
|
||||
private static final Color ICON_BACKGROUND = ACTIVE_BACKGROUND;
|
||||
private static final Color ICON_BACKGROUND_DARK = ACTIVE_BACKGROUND_DARK;
|
||||
private static final Color ICON_HOVERED_BACKGROUND = new Color(0x232629);
|
||||
private static final Color ICON_HOVERED_BACKGROUND_DARK = new Color(0xfcfcfc);
|
||||
private static final Color ICON_HOVERED_FOREGROUND = new Color(0xcacdcf);
|
||||
private static final Color ICON_HOVERED_FOREGROUND_DARK = new Color(0x43484c);
|
||||
private static final Color ICON_PRESSED_BACKGROUND = new Color(0xa6a8ab);
|
||||
private static final Color ICON_PRESSED_BACKGROUND_DARK = new Color(0x6e7175);
|
||||
private static final Color CLOSE_ICON_PRESSED_BACKGROUND = new Color(0x6d2229);
|
||||
private static final Color CLOSE_ICON_PRESSED_BACKGROUND_DARK = new Color(0x6d2229);
|
||||
private static final Color CLOSE_ICON_HOVERED_BACKGROUND = new Color(0xff98a2);
|
||||
private static final Color CLOSE_ICON_HOVERED_INACTIVE_BACKGROUND = new Color(0xda4453);
|
||||
private static final Color CLOSE_ICON_HOVERED_INACTIVE_BACKGROUND_DARK = new Color(0xda4453);
|
||||
private static final Color CLOSE_ICON_HOVERED_BACKGROUND_DARK = new Color(0xff98a2);
|
||||
private static final Color ACTIVE_FOREGROUND = new Color(0x2d3033);
|
||||
private static final Color ACTIVE_FOREGROUND_DARK = new Color(0xf1f1f1);
|
||||
private static final Color INACTIVE_FOREGROUND = ACTIVE_FOREGROUND;
|
||||
private static final Color INACTIVE_FOREGROUND_DARK = ACTIVE_FOREGROUND_DARK;
|
||||
private static final Color ICON_HOVERED_BACKGROUND = new Color(0xd1d1d1);
|
||||
private static final Color ICON_HOVERED_BACKGROUND_DARK = new Color(0x373737);
|
||||
private static final Color ICON_PRESSED_BACKGROUND = new Color(0xc0c0c0);
|
||||
private static final Color ICON_PRESSED_BACKGROUND_DARK = new Color(0x565656);
|
||||
private static final Color ACTIVE_FOREGROUND = Color.darkGray;
|
||||
private static final Color ACTIVE_FOREGROUND_DARK = new Color(0xf7f7f7);
|
||||
private static final Color INACTIVE_FOREGROUND = Color.gray;
|
||||
private static final Color INACTIVE_FOREGROUND_DARK = new Color(0xb5b5b5);
|
||||
|
||||
private static final Color ACTIVE_BACKGROUND_TOP = new Color(0xa9abac);
|
||||
private static final Color ACTIVE_BACKGROUND_TOP_DARK = new Color(0x4c565f);
|
||||
private static final Color INACTIVE_BACKGROUND_TOP = new Color(0xb7b8b9);
|
||||
private static final Color INACTIVE_BACKGROUND_TOP_DARK = new Color(0x424952);
|
||||
private static final Color ACTIVE_BORDER = ACTIVE_BACKGROUND_TOP;
|
||||
private static final Color ACTIVE_BORDER_DARK = ACTIVE_BACKGROUND_TOP_DARK;
|
||||
private static final Color INACTIVE_BORDER = INACTIVE_BACKGROUND_TOP;
|
||||
private static final Color INACTIVE_BORDER_DARK = INACTIVE_BACKGROUND_TOP_DARK;
|
||||
private static final Color ACTIVE_BACKGROUND_TOP = new Color(0xfbfbfb);
|
||||
private static final Color ACTIVE_BACKGROUND_TOP_DARK = new Color(0x313131);
|
||||
private static final Color INACTIVE_BACKGROUND_TOP = new Color(0xfefefe);
|
||||
private static final Color INACTIVE_BACKGROUND_TOP_DARK = new Color(0x3a3a3a);
|
||||
private static final Color ACTIVE_BORDER = new Color(0x9e9e9e);
|
||||
private static final Color ACTIVE_BORDER_DARK = new Color(0x080808);
|
||||
private static final Color INACTIVE_BORDER = new Color(0xbcbcbc);
|
||||
private static final Color INACTIVE_BORDER_DARK = new Color(0x121212);
|
||||
|
||||
private static final int BORDER_SIZE = 1;
|
||||
private static final int SIGNIFICANT_DRAG_DISTANCE = 4;
|
||||
|
||||
public DefaultFrameDecoration(WLDecoratedPeer peer, boolean showMinimize, boolean showMaximize) {
|
||||
@@ -105,31 +96,64 @@ public class DefaultFrameDecoration extends FullFrameDecorationHelper {
|
||||
return new Dimension(getButtonSpaceWidth(), HEIGHT);
|
||||
}
|
||||
|
||||
private Point getCloseButtonCenter() {
|
||||
int width = peer.getWidth();
|
||||
return width >= HEIGHT ? new Point(width - HEIGHT / 2, HEIGHT / 2) : null;
|
||||
}
|
||||
|
||||
private Point getMaximizeButtonCenter() {
|
||||
if (!hasMaximizeButton()) return null;
|
||||
int width = peer.getWidth();
|
||||
return width >= 2 * HEIGHT ? new Point(width - HEIGHT * 3 / 2, HEIGHT / 2) : null;
|
||||
}
|
||||
|
||||
private Point getMinimizeButtonCenter() {
|
||||
if (!hasMinimizeButton()) return null;
|
||||
int width = peer.getWidth();
|
||||
int buttonSpaceWidth = getButtonSpaceWidth();
|
||||
return width >= buttonSpaceWidth ? new Point(width - buttonSpaceWidth + HEIGHT / 2, HEIGHT / 2) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rectangle getCloseButtonBounds() {
|
||||
int x = peer.getWidth() - BUTTON_SIZE - BUTTONS_RIGHT_PADDING - BORDER_SIZE;
|
||||
int y = (int) Math.floor((HEIGHT - BUTTON_SIZE + 1f) / 2);
|
||||
return new Rectangle(x, y, BUTTON_SIZE, BUTTON_SIZE);
|
||||
int width = peer.getWidth();
|
||||
if (width >= HEIGHT) {
|
||||
return new Rectangle(width - HEIGHT / 2 - BUTTON_CIRCLE_RADIUS,
|
||||
HEIGHT / 2 - BUTTON_CIRCLE_RADIUS,
|
||||
BUTTON_CIRCLE_RADIUS * 2,
|
||||
BUTTON_CIRCLE_RADIUS * 2);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rectangle getMaximizeButtonBounds() {
|
||||
if (!hasMaximizeButton()) return null;
|
||||
|
||||
int x = peer.getWidth() - BUTTON_SIZE * 2 - BUTTONS_RIGHT_PADDING
|
||||
- BUTTONS_PADDING - BORDER_SIZE;
|
||||
int y = (int) Math.floor((HEIGHT - BUTTON_SIZE + 1f) / 2);
|
||||
return x > 0 ? new Rectangle(x, y, BUTTON_SIZE, BUTTON_SIZE) : null;
|
||||
int width = peer.getWidth();
|
||||
if (width >= 2 * HEIGHT) {
|
||||
return new Rectangle(width - HEIGHT * 3 / 2 - BUTTON_CIRCLE_RADIUS,
|
||||
HEIGHT / 2 - BUTTON_CIRCLE_RADIUS,
|
||||
BUTTON_CIRCLE_RADIUS * 2,
|
||||
BUTTON_CIRCLE_RADIUS * 2);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rectangle getMinimizeButtonBounds() {
|
||||
if (!hasMinimizeButton()) return null;
|
||||
|
||||
int x = peer.getWidth() - BUTTON_SIZE * 3 - BUTTONS_RIGHT_PADDING
|
||||
- BUTTONS_PADDING * 2 - BORDER_SIZE;
|
||||
int y = (int) Math.floor((HEIGHT - BUTTON_SIZE + 1f) / 2);
|
||||
return x > 0 ? new Rectangle(x, y, BUTTON_SIZE, BUTTON_SIZE) : null;
|
||||
int width = peer.getWidth();
|
||||
int buttonSpaceWidth = getButtonSpaceWidth();
|
||||
if (width >= buttonSpaceWidth) {
|
||||
return new Rectangle(width - buttonSpaceWidth + HEIGHT / 2 - BUTTON_CIRCLE_RADIUS,
|
||||
HEIGHT / 2 - BUTTON_CIRCLE_RADIUS,
|
||||
BUTTON_CIRCLE_RADIUS * 2,
|
||||
BUTTON_CIRCLE_RADIUS * 2);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -146,7 +170,7 @@ public class DefaultFrameDecoration extends FullFrameDecorationHelper {
|
||||
final int numButtons = 1
|
||||
+ (hasMaximizeButton() ? 1 : 0)
|
||||
+ (hasMinimizeButton() ? 1 : 0);
|
||||
return numButtons * BUTTON_SIZE + (numButtons - 1) * BUTTONS_PADDING + BUTTONS_RIGHT_PADDING;
|
||||
return numButtons * HEIGHT;
|
||||
}
|
||||
|
||||
private Color getBackgroundColor(boolean isActive) {
|
||||
@@ -193,33 +217,13 @@ public class DefaultFrameDecoration extends FullFrameDecorationHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private Color getButtonForeground(boolean isHovered) {
|
||||
if (isHovered) {
|
||||
return isDarkTheme() ? ICON_HOVERED_FOREGROUND_DARK : ICON_HOVERED_FOREGROUND;
|
||||
} else {
|
||||
return isDarkTheme() ? ACTIVE_FOREGROUND_DARK : ACTIVE_FOREGROUND;
|
||||
}
|
||||
}
|
||||
|
||||
private Color getClosePressedBackground() {
|
||||
return isDarkTheme() ? CLOSE_ICON_PRESSED_BACKGROUND_DARK : CLOSE_ICON_PRESSED_BACKGROUND;
|
||||
}
|
||||
|
||||
private Color getCloseHoveredBackground(boolean isActive) {
|
||||
if (isActive) {
|
||||
return isDarkTheme() ? CLOSE_ICON_HOVERED_BACKGROUND_DARK : CLOSE_ICON_HOVERED_BACKGROUND;
|
||||
} else {
|
||||
return isDarkTheme() ? CLOSE_ICON_HOVERED_INACTIVE_BACKGROUND_DARK : CLOSE_ICON_HOVERED_INACTIVE_BACKGROUND;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintBorder(Graphics2D g2d) {
|
||||
int width = peer.getWidth();
|
||||
int height = peer.getHeight();
|
||||
g2d.setColor(getBorderColor(isActive()));
|
||||
g2d.setStroke(new BasicStroke(BORDER_SIZE));
|
||||
g2d.drawRect(0, 0, width, height);
|
||||
g2d.drawRect(0, 0, width - BORDER_SIZE, height - BORDER_SIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -246,11 +250,17 @@ public class DefaultFrameDecoration extends FullFrameDecorationHelper {
|
||||
// The title bar
|
||||
g.fillRoundRect(0, 0, width, HEIGHT + radius + 1, radius, radius);
|
||||
|
||||
// The top bevel of the title bar
|
||||
g.setColor(getBackgroundTopColor(active));
|
||||
g.drawLine(radius / 2, 1, width - radius / 2, 1);
|
||||
g.drawArc(1, 1, (radius - 1), (radius - 1), 90, 60);
|
||||
g.drawArc(width - radius, 1, (radius - 1), (radius - 1), 45, 45);
|
||||
|
||||
// The border
|
||||
var oldStroke = g.getStroke();
|
||||
g.setColor(getBorderColor(active));
|
||||
g.setStroke(new BasicStroke(BORDER_SIZE));
|
||||
g.drawRoundRect(0, 0, width, HEIGHT + radius + 1, radius, radius);
|
||||
g.drawRoundRect(0, 0, width - BORDER_SIZE, HEIGHT + radius + 1, radius, radius);
|
||||
g.setStroke(oldStroke);
|
||||
g.drawLine(0, HEIGHT - 1, width, HEIGHT - 1);
|
||||
} else {
|
||||
@@ -260,35 +270,32 @@ public class DefaultFrameDecoration extends FullFrameDecorationHelper {
|
||||
|
||||
// The top bevel of the title bar
|
||||
g.setColor(getBackgroundTopColor(active));
|
||||
g.drawLine(BORDER_SIZE, BORDER_SIZE, width, BORDER_SIZE);
|
||||
g.drawLine(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, HEIGHT);
|
||||
g.drawLine(BORDER_SIZE, BORDER_SIZE, width - BORDER_SIZE, BORDER_SIZE);
|
||||
g.drawLine(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, HEIGHT - BORDER_SIZE);
|
||||
|
||||
// The border
|
||||
var oldStroke = g.getStroke();
|
||||
g.setColor(getBorderColor(active));
|
||||
g.setStroke(new BasicStroke(BORDER_SIZE));
|
||||
g.drawRect(0, 0, width, HEIGHT);
|
||||
g.drawRect(0, 0, width - BORDER_SIZE, HEIGHT - BORDER_SIZE);
|
||||
g.setStroke(oldStroke);
|
||||
}
|
||||
paintTitle(g, title, foregroundColor, width);
|
||||
|
||||
Rectangle closeButtonBounds = getCloseButtonBounds();
|
||||
if (closeButtonBounds != null) {
|
||||
paintCloseButtonBackground(g, closeButtonBounds, closeButton);
|
||||
Color buttonColor = getButtonForeground(closeButton.hovered);
|
||||
paintCloseButton(g, closeButtonBounds, buttonColor);
|
||||
Point closeButtonCenter = getCloseButtonCenter();
|
||||
if (closeButtonCenter != null) {
|
||||
paintButtonBackground(g, closeButtonCenter, closeButton);
|
||||
paintCloseButton(g, closeButtonCenter, foregroundColor);
|
||||
}
|
||||
Rectangle maximizedButtonBounds = getMaximizeButtonBounds();
|
||||
if (maximizedButtonBounds != null) {
|
||||
paintButtonBackground(g, maximizedButtonBounds, maximizeButton);
|
||||
Color buttonColor = getButtonForeground(maximizeButton.hovered);
|
||||
paintMaximizeButton(g, maximizedButtonBounds, buttonColor);
|
||||
Point maximizedButtonCenter = getMaximizeButtonCenter();
|
||||
if (maximizedButtonCenter != null) {
|
||||
paintButtonBackground(g, maximizedButtonCenter, maximizeButton);
|
||||
paintMaximizeButton(g, maximizedButtonCenter, foregroundColor);
|
||||
}
|
||||
Rectangle minimizedButtonBounds = getMinimizeButtonBounds();
|
||||
if (minimizedButtonBounds != null) {
|
||||
paintButtonBackground(g, minimizedButtonBounds, minimizeButton);
|
||||
Color buttonColor = getButtonForeground(minimizeButton.hovered);
|
||||
paintMinimizeButton(g, minimizedButtonBounds, buttonColor);
|
||||
Point minimizedButtonCenter = getMinimizeButtonCenter();
|
||||
if (minimizedButtonCenter != null) {
|
||||
paintButtonBackground(g, minimizedButtonCenter, minimizeButton);
|
||||
paintMinimizeButton(g, minimizedButtonCenter, foregroundColor);
|
||||
}
|
||||
g.setClip(null);
|
||||
}
|
||||
@@ -297,7 +304,7 @@ public class DefaultFrameDecoration extends FullFrameDecorationHelper {
|
||||
g.setColor(foregroundColor);
|
||||
g.setFont(FONT);
|
||||
FontMetrics fm = g.getFontMetrics();
|
||||
int leftMargin = HEIGHT / 2 - BUTTON_SIZE; // same as space between close button and right window edge
|
||||
int leftMargin = HEIGHT / 2 - BUTTON_CIRCLE_RADIUS; // same as space between close button and right window edge
|
||||
int availableWidth = width - getButtonSpaceWidth() - leftMargin;
|
||||
String text = SwingUtilities2.clipStringIfNecessary(null, fm, title, availableWidth);
|
||||
int textWidth = fm.stringWidth(text);
|
||||
@@ -306,60 +313,48 @@ public class DefaultFrameDecoration extends FullFrameDecorationHelper {
|
||||
(HEIGHT - fm.getHeight()) / 2 + fm.getAscent());
|
||||
}
|
||||
|
||||
private void paintCloseButtonBackground(Graphics2D g, Rectangle bounds, ButtonState state) {
|
||||
if (!isActive() && !state.hovered && !state.pressed) return;
|
||||
|
||||
g.setColor(state.pressed ? getClosePressedBackground() :
|
||||
state.hovered ? getCloseHoveredBackground(isActive()) : getIconBackground());
|
||||
g.fill(new Ellipse2D.Float(bounds.x, bounds.y, bounds.width, bounds.height));
|
||||
}
|
||||
|
||||
private void paintButtonBackground(Graphics2D g, Rectangle bounds, ButtonState state) {
|
||||
if (state.hovered || state.pressed) {
|
||||
private void paintButtonBackground(Graphics2D g, Point center, ButtonState state) {
|
||||
if (isActive()) {
|
||||
g.setColor(state.pressed ? getIconPressedBackground() :
|
||||
state.hovered ? getIconHoveredBackground() : getIconBackground());
|
||||
g.fill(new Ellipse2D.Float(bounds.x, bounds.y, bounds.width, bounds.height));
|
||||
g.fill(new Ellipse2D.Float(center.x - BUTTON_CIRCLE_RADIUS + .5f,
|
||||
center.y - BUTTON_CIRCLE_RADIUS + .5f,
|
||||
2 * BUTTON_CIRCLE_RADIUS, 2 * BUTTON_CIRCLE_RADIUS));
|
||||
}
|
||||
}
|
||||
|
||||
private static Point centerOf(Rectangle rect) {
|
||||
return new Point((int) Math.floor(rect.x + rect.width / 2f),
|
||||
(int) Math.floor(rect.y + rect.height / 2f));
|
||||
}
|
||||
|
||||
private void paintCloseButton(Graphics2D g, Rectangle bounds, Color foregroundColor) {
|
||||
private void paintCloseButton(Graphics2D g, Point center, Color foregroundColor) {
|
||||
g.setColor(foregroundColor);
|
||||
Point center = centerOf(bounds);
|
||||
g.drawLine(center.x - BUTTON_ICON_SIZE, center.y - BUTTON_ICON_SIZE,
|
||||
center.x + BUTTON_ICON_SIZE, center.y + BUTTON_ICON_SIZE);
|
||||
g.drawLine(center.x - BUTTON_ICON_SIZE, center.y + BUTTON_ICON_SIZE,
|
||||
center.x + BUTTON_ICON_SIZE, center.y - BUTTON_ICON_SIZE);
|
||||
}
|
||||
|
||||
private void paintMaximizeButton(Graphics2D g, Rectangle bounds, Color foregroundColor) {
|
||||
private void paintMaximizeButton(Graphics2D g, Point center, Color foregroundColor) {
|
||||
g.setColor(foregroundColor);
|
||||
Point center = centerOf(bounds);
|
||||
int size = BUTTON_ICON_SIZE + 1;
|
||||
if (peer.getState() == Frame.MAXIMIZED_BOTH) {
|
||||
g.drawLine(center.x - size, center.y, center.x, center.y - size);
|
||||
g.drawLine(center.x, center.y - size, center.x + size, center.y);
|
||||
g.drawLine(center.x - size, center.y, center.x, center.y + size);
|
||||
g.drawLine(center.x, center.y + size, center.x + size, center.y);
|
||||
g.drawLine(center.x - BUTTON_ICON_SIZE, center.y,
|
||||
center.x, center.y - BUTTON_ICON_SIZE);
|
||||
g.drawLine(center.x, center.y - BUTTON_ICON_SIZE,
|
||||
center.x + BUTTON_ICON_SIZE, center.y);
|
||||
g.drawLine(center.x - BUTTON_ICON_SIZE, center.y,
|
||||
center.x, center.y + BUTTON_ICON_SIZE);
|
||||
g.drawLine(center.x, center.y + BUTTON_ICON_SIZE,
|
||||
center.x + BUTTON_ICON_SIZE, center.y);
|
||||
} else {
|
||||
g.drawLine(center.x - size, (int) (center.y + size / 2f),
|
||||
center.x, (int) (center.y - size / 2f));
|
||||
g.drawLine(center.x, (int) (center.y - size / 2f),
|
||||
center.x + size, (int) (center.y + size / 2f));
|
||||
g.drawLine(center.x - BUTTON_ICON_SIZE, center.y + BUTTON_ICON_SIZE / 2,
|
||||
center.x, center.y - BUTTON_ICON_SIZE / 2);
|
||||
g.drawLine(center.x, center.y - BUTTON_ICON_SIZE / 2,
|
||||
center.x + BUTTON_ICON_SIZE, center.y + BUTTON_ICON_SIZE / 2);
|
||||
}
|
||||
}
|
||||
|
||||
private void paintMinimizeButton(Graphics2D g, Rectangle bounds, Color foregroundColor) {
|
||||
private void paintMinimizeButton(Graphics2D g, Point center, Color foregroundColor) {
|
||||
g.setColor(foregroundColor);
|
||||
Point center = centerOf(bounds);
|
||||
int size = BUTTON_ICON_SIZE + 1;
|
||||
g.drawLine(center.x - size, (int) (center.y - size / 2f),
|
||||
center.x, (int) (center.y + size / 2f));
|
||||
g.drawLine(center.x, (int) (center.y + size / 2f),
|
||||
center.x + size, (int) (center.y - size / 2f));
|
||||
g.drawLine(center.x - BUTTON_ICON_SIZE, center.y - BUTTON_ICON_SIZE / 2,
|
||||
center.x, center.y + BUTTON_ICON_SIZE / 2);
|
||||
g.drawLine(center.x, center.y + BUTTON_ICON_SIZE / 2,
|
||||
center.x + BUTTON_ICON_SIZE, center.y - BUTTON_ICON_SIZE / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +76,8 @@ public class GtkFrameDecoration extends FullFrameDecorationHelper {
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
// Determine buttons' bounds, etc.
|
||||
nativePrePaint(nativePtr, peer.getWidth(), peer.getHeight());
|
||||
if (peer.getWidth() >= titleBarMinWidth && peer.getHeight() >= titleBarHeight) {
|
||||
super.paint(g);
|
||||
}
|
||||
nativePrePaint(nativePtr, peer.getWidth());
|
||||
super.paint(g);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,9 +85,6 @@ public class GtkFrameDecoration extends FullFrameDecorationHelper {
|
||||
int width = peer.getWidth();
|
||||
int height = titleBarHeight;
|
||||
|
||||
assert width >= titleBarMinWidth;
|
||||
assert peer.getHeight() >= titleBarHeight;
|
||||
|
||||
double scale = ((WLGraphicsConfig) peer.getGraphicsConfiguration()).getEffectiveScale();
|
||||
g2d.setBackground(new Color(0, true));
|
||||
g2d.clearRect(0, 0, width, height);
|
||||
@@ -222,5 +217,5 @@ public class GtkFrameDecoration extends FullFrameDecorationHelper {
|
||||
String title, int buttonsState);
|
||||
private native int nativeGetIntProperty(long nativePtr, String name);
|
||||
private native void nativeNotifyConfigured(long nativePtr, boolean active, boolean maximized, boolean fullscreen);
|
||||
private native void nativePrePaint(long nativePtr, int width, int height);
|
||||
private native void nativePrePaint(long nativePtr, int width);
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.wl.focus.WLComponentPeer");
|
||||
private static final PlatformLogger popupLog = PlatformLogger.getLogger("sun.awt.wl.popup.WLComponentPeer");
|
||||
|
||||
protected static final int MINIMUM_WIDTH = 1;
|
||||
protected static final int MINIMUM_HEIGHT = 1;
|
||||
private static final int MINIMUM_WIDTH = 1;
|
||||
private static final int MINIMUM_HEIGHT = 1;
|
||||
|
||||
private final Object stateLock = new Object();
|
||||
|
||||
@@ -135,12 +135,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
log.fine("WLComponentPeer: target=" + target + " with size=" + wlSize);
|
||||
}
|
||||
|
||||
boolean shadowEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.wl.Shadow", "true"));
|
||||
if (shadowEnabled) {
|
||||
shadow = new ShadowImpl(targetIsWlPopup() ? ShadowImage.POPUP_SHADOW_SIZE : ShadowImage.WINDOW_SHADOW_SIZE);
|
||||
} else {
|
||||
shadow = new NilShadow();
|
||||
}
|
||||
shadow = new Shadow(targetIsWlPopup() ? ShadowImage.POPUP_SHADOW_SIZE : ShadowImage.WINDOW_SHADOW_SIZE);
|
||||
// TODO
|
||||
// setup parent window for target
|
||||
}
|
||||
@@ -857,10 +852,8 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
int shadowSize = shadow != null ? (int) Math.ceil(shadow.getSize() * 4) : 0;
|
||||
return shadowSize == 0
|
||||
? new Dimension(MINIMUM_WIDTH, MINIMUM_HEIGHT)
|
||||
: new Dimension(shadowSize, shadowSize);
|
||||
int shadowSize = (int) Math.ceil(shadow.getSize() * 4);
|
||||
return new Dimension(shadowSize, shadowSize);
|
||||
}
|
||||
|
||||
void showWindowMenu(long serial, int x, int y) {
|
||||
@@ -1618,14 +1611,6 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
return new Dimension(javaUnitsToSurfaceSize(d.width), javaUnitsToSurfaceSize(d.height));
|
||||
}
|
||||
|
||||
int javaUnitsToBufferUnits(int value) {
|
||||
return (int) Math.floor(value * effectiveScale);
|
||||
}
|
||||
|
||||
int javaSizeToBufferSize(int value) {
|
||||
return (int) Math.ceil(value * effectiveScale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a point in the device (screen) space into coordinates on this surface
|
||||
*/
|
||||
@@ -1756,12 +1741,9 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
|
||||
private Dimension constrainSize(int width, int height) {
|
||||
Dimension maxBounds = getMaxBufferBounds();
|
||||
Dimension minSize = getMinimumSize();
|
||||
minSize.width = Math.max(MINIMUM_WIDTH, minSize.width);
|
||||
minSize.height = Math.max(MINIMUM_HEIGHT, minSize.height);
|
||||
return new Dimension(
|
||||
Math.max(Math.min(width, maxBounds.width), minSize.width),
|
||||
Math.max(Math.min(height, maxBounds.height), minSize.height));
|
||||
Math.max(Math.min(width, maxBounds.width), MINIMUM_WIDTH),
|
||||
Math.max(Math.min(height, maxBounds.height), MINIMUM_HEIGHT));
|
||||
}
|
||||
|
||||
private Dimension constrainSize(Dimension bounds) {
|
||||
@@ -1830,20 +1812,6 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
return result;
|
||||
}
|
||||
|
||||
private interface Shadow {
|
||||
int getSize();
|
||||
void updateSurfaceSize();
|
||||
void resizeToParentWindow();
|
||||
void createSurface();
|
||||
void commitSurface();
|
||||
void dispose();
|
||||
void hide();
|
||||
void updateSurfaceData();
|
||||
void paint();
|
||||
void commitSurfaceData();
|
||||
void notifyConfigured(boolean active, boolean maximized, boolean fullscreen);
|
||||
}
|
||||
|
||||
private static class ShadowImage {
|
||||
private static final Color activeColor = new Color(0, 0, 0, 0xA0);
|
||||
private static final Color inactiveColor = new Color(0, 0, 0, 0x40);
|
||||
@@ -1948,7 +1916,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
}
|
||||
|
||||
private class ShadowImpl implements WLSurfaceSizeListener, Shadow {
|
||||
private class Shadow implements WLSurfaceSizeListener {
|
||||
private WLSubSurface shadowSurface; // protected by AWT lock
|
||||
private SurfaceData shadowSurfaceData; // protected by AWT lock
|
||||
private boolean needsRepaint = true; // protected by AWT lock
|
||||
@@ -1956,7 +1924,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
private final WLSize shadowWlSize = new WLSize(); // protected by stateLock
|
||||
private boolean isActive; // protected by AWT lock
|
||||
|
||||
public ShadowImpl(int shadowSize) {
|
||||
public Shadow(int shadowSize) {
|
||||
this.shadowSize = shadowSize;
|
||||
shadowWlSize.deriveFromJavaSize(wlSize.getJavaWidth() + shadowSize * 2, wlSize.getJavaHeight() + shadowSize * 2);
|
||||
shadowSurfaceData = ((WLGraphicsConfig) getGraphicsConfiguration()).createSurfaceData(this, shadowWlSize.getPixelWidth(), shadowWlSize.getPixelHeight());
|
||||
@@ -2071,20 +2039,6 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
|
||||
}
|
||||
}
|
||||
|
||||
private static class NilShadow implements Shadow {
|
||||
@Override public int getSize() { return 0; }
|
||||
@Override public void updateSurfaceSize() { }
|
||||
@Override public void resizeToParentWindow() { }
|
||||
@Override public void createSurface() { }
|
||||
@Override public void commitSurface() { }
|
||||
@Override public void dispose() { }
|
||||
@Override public void hide() { }
|
||||
@Override public void updateSurfaceData() { }
|
||||
@Override public void paint() { }
|
||||
@Override public void commitSurfaceData() { }
|
||||
@Override public void notifyConfigured(boolean active, boolean maximized, boolean fullscreen) { }
|
||||
}
|
||||
|
||||
private class WLSize {
|
||||
/**
|
||||
* Represents the full size of the component in "client" units as returned by Component.getSize().
|
||||
|
||||
@@ -88,7 +88,7 @@ public class WLDataDevice {
|
||||
private static native void dispatchDataSourceQueueImpl(long nativePtr);
|
||||
private static native void setSelectionImpl(int protocol, long nativePtr, long dataOfferNativePtr, long serial);
|
||||
private static native void startDragImpl(long nativePtr, long dataOfferNativePtr,
|
||||
long originSurfaceNativePtr, long serial);
|
||||
long originSurfaceNativePtr, long iconNativePtr, long serial);
|
||||
|
||||
public boolean isProtocolSupported(int protocol) {
|
||||
return isProtocolSupportedImpl(nativePtr, protocol);
|
||||
@@ -98,8 +98,8 @@ public class WLDataDevice {
|
||||
setSelectionImpl(protocol, nativePtr, (source == null) ? 0 : source.getNativePtr(), serial);
|
||||
}
|
||||
|
||||
public void startDrag(WLDataSource source, long originSurfaceNativePtr, long serial) {
|
||||
startDragImpl(nativePtr, source.getNativePtr(), originSurfaceNativePtr, serial);
|
||||
public void startDrag(WLDataSource source, long originSurfaceNativePtr, long iconNativePtr, long serial) {
|
||||
startDragImpl(nativePtr, source.getNativePtr(), originSurfaceNativePtr, iconNativePtr, serial);
|
||||
}
|
||||
|
||||
public WLClipboard getSystemClipboard() {
|
||||
|
||||
@@ -25,10 +25,7 @@
|
||||
|
||||
package sun.awt.wl;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class WLDataSource {
|
||||
@@ -47,8 +44,6 @@ public class WLDataSource {
|
||||
|
||||
private static native void setDnDActionsImpl(long nativePtr, int actions);
|
||||
|
||||
private static native void setDnDIconImpl(long nativePtr, int scale, int width, int height, int offsetX, int offsetY, int[] pixels);
|
||||
|
||||
WLDataSource(WLDataDevice dataDevice, int protocol, Transferable data) {
|
||||
var wlDataTransferer = (WLDataTransferer) WLDataTransferer.getInstance();
|
||||
|
||||
@@ -96,31 +91,6 @@ public class WLDataSource {
|
||||
setDnDActionsImpl(nativePtr, actions);
|
||||
}
|
||||
|
||||
public void setDnDIcon(Image image, int scale, int offsetX, int offsetY) {
|
||||
if (nativePtr == 0) {
|
||||
throw new IllegalStateException("Native pointer is null");
|
||||
}
|
||||
|
||||
int width = image.getWidth(null);
|
||||
int height = image.getHeight(null);
|
||||
int[] pixels = new int[width * height];
|
||||
|
||||
if (image instanceof BufferedImage) {
|
||||
// NOTE: no need to ensure that the BufferedImage is TYPE_INT_ARGB,
|
||||
// getRGB() does pixel format conversion automatically
|
||||
((BufferedImage) image).getRGB(0, 0, width, height, pixels, 0, width);
|
||||
} else {
|
||||
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = bufferedImage.createGraphics();
|
||||
g.drawImage(image, 0, 0, null);
|
||||
g.dispose();
|
||||
|
||||
bufferedImage.getRGB(0, 0, width, height, pixels, 0, width);
|
||||
}
|
||||
|
||||
setDnDIconImpl(nativePtr, scale, width, height, offsetX, offsetY, pixels);
|
||||
}
|
||||
|
||||
public synchronized void destroy() {
|
||||
if (nativePtr != 0) {
|
||||
destroyImpl(nativePtr);
|
||||
|
||||
@@ -63,7 +63,7 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
|
||||
d = new DefaultFrameDecoration(this, showMinimize, showMaximize);
|
||||
}
|
||||
} else {
|
||||
if (!WLToolkit.isKDE() && isGTKAvailable()) {
|
||||
if (isGTKAvailable()) {
|
||||
d = new GtkFrameDecoration(this, showMinimize, showMaximize);
|
||||
} else {
|
||||
d = new DefaultFrameDecoration(this, showMinimize, showMaximize);
|
||||
@@ -134,11 +134,10 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
|
||||
@Override
|
||||
public Dimension getMinimumSize() {
|
||||
final Dimension parentMinimumSize = super.getMinimumSize();
|
||||
var d = getDecoration();
|
||||
final Dimension decorMinimumSize = d != null ? d.getMinimumSize() : new Dimension(0, 0);
|
||||
final Dimension decorMinimumSize = getDecoration().getMinimumSize();
|
||||
final Dimension frameMinimumSize
|
||||
= (decorMinimumSize.getWidth() == 0 && decorMinimumSize.getHeight() == 0)
|
||||
? new Dimension(MINIMUM_WIDTH, MINIMUM_HEIGHT)
|
||||
? new Dimension(1, 1)
|
||||
: decorMinimumSize;
|
||||
return new Rectangle(parentMinimumSize)
|
||||
.union(new Rectangle(frameMinimumSize))
|
||||
|
||||
@@ -92,33 +92,21 @@ public class WLDragSourceContextPeer extends SunDragSourceContextPeer {
|
||||
this.dataDevice = dataDevice;
|
||||
}
|
||||
|
||||
private WLComponentPeer getPeer() {
|
||||
private long getComponentWlSurfacePtr() {
|
||||
var comp = getComponent();
|
||||
while (comp != null) {
|
||||
var peer = AWTAccessor.getComponentAccessor().getPeer(comp);
|
||||
if (peer instanceof WLComponentPeer wlPeer) {
|
||||
return wlPeer;
|
||||
return wlPeer.getSurface().getWlSurfacePtr();
|
||||
}
|
||||
comp = comp.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private WLMainSurface getSurface() {
|
||||
WLComponentPeer peer = getPeer();
|
||||
if (peer != null) {
|
||||
return peer.getSurface();
|
||||
}
|
||||
return null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startDrag(Transferable trans, long[] formats, Map<Long, DataFlavor> formatMap) {
|
||||
var mainSurface = getSurface();
|
||||
if (mainSurface == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// formats and formatMap are unused, because WLDataSource already references the same DataTransferer singleton
|
||||
var source = new WLDragSource(trans);
|
||||
|
||||
@@ -127,17 +115,10 @@ public class WLDragSourceContextPeer extends SunDragSourceContextPeer {
|
||||
|
||||
source.setDnDActions(waylandActions);
|
||||
|
||||
var dragImage = getDragImage();
|
||||
if (dragImage != null) {
|
||||
var dragImageOffset = getDragImageOffset();
|
||||
source.setDnDIcon(dragImage,
|
||||
mainSurface.getGraphicsDevice().getDisplayScale(),
|
||||
dragImageOffset.x, dragImageOffset.y);
|
||||
}
|
||||
|
||||
long eventSerial = WLToolkit.getInputState().pointerButtonSerial();
|
||||
|
||||
dataDevice.startDrag(source, mainSurface.getWlSurfacePtr(), eventSerial);
|
||||
var wlSurface = getComponentWlSurfacePtr();
|
||||
dataDevice.startDrag(source, wlSurface, 0, eventSerial);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
package sun.awt.wl;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.peer.FramePeer;
|
||||
import sun.awt.AWTAccessor;
|
||||
@@ -43,12 +42,6 @@ public class WLFramePeer extends WLDecoratedPeer implements FramePeer {
|
||||
super(target, target.isUndecorated(),
|
||||
Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.ICONIFIED),
|
||||
Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH));
|
||||
AWTAccessor.getWindowAccessor().addWindowListener(target, new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
getFrame().removeNotify();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,9 +38,35 @@ import sun.java2d.wl.WLSurfaceSizeListener;
|
||||
|
||||
public abstract class WLGraphicsConfig extends GraphicsConfiguration {
|
||||
private final WLGraphicsDevice device;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int xLogical; // logical (scaled) horizontal location; optional, could be zero
|
||||
private final int yLogical; // logical (scaled) vertical location; optional, could be zero
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final int widthLogical; // logical (scaled) width; optional, could be zero
|
||||
private final int heightLogical;// logical (scaled) height; optional, could be zero
|
||||
private final int displayScale; // as reported by Wayland
|
||||
private final double effectiveScale; // as enforced by Java
|
||||
|
||||
protected WLGraphicsConfig(WLGraphicsDevice device) {
|
||||
protected WLGraphicsConfig(WLGraphicsDevice device, int x, int y, int xLogical, int yLogical,
|
||||
int width, int height, int widthLogical, int heightLogical,
|
||||
int displayScale) {
|
||||
this.device = device;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.xLogical = xLogical;
|
||||
this.yLogical = yLogical;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.widthLogical = widthLogical;
|
||||
this.heightLogical = heightLogical;
|
||||
this.displayScale = displayScale;
|
||||
this.effectiveScale = WLGraphicsEnvironment.effectiveScaleFrom(displayScale);
|
||||
}
|
||||
|
||||
boolean differsFrom(int width, int height, int scale) {
|
||||
return width != this.width || height != this.height || scale != this.displayScale;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,7 +84,7 @@ public abstract class WLGraphicsConfig extends GraphicsConfiguration {
|
||||
|
||||
@Override
|
||||
public AffineTransform getDefaultTransform() {
|
||||
double scale = device.getEffectiveScale();
|
||||
double scale = effectiveScale;
|
||||
return AffineTransform.getScaleInstance(scale, scale);
|
||||
}
|
||||
|
||||
@@ -71,18 +97,20 @@ public abstract class WLGraphicsConfig extends GraphicsConfiguration {
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
return device.getBounds();
|
||||
return (widthLogical > 0 && heightLogical > 0)
|
||||
? new Rectangle(xLogical, yLogical, widthLogical, heightLogical)
|
||||
: new Rectangle(x, y, width, height);
|
||||
}
|
||||
|
||||
public Rectangle getRealBounds() {
|
||||
return device.getRealBounds();
|
||||
return new Rectangle(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the preferred Wayland buffer scale for this display configuration.
|
||||
*/
|
||||
public int getDisplayScale() {
|
||||
return device.getDisplayScale();
|
||||
return displayScale;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +118,7 @@ public abstract class WLGraphicsConfig extends GraphicsConfiguration {
|
||||
* if overridden with the sun.java2d.uiScale system property.
|
||||
*/
|
||||
public double getEffectiveScale() {
|
||||
return device.getEffectiveScale();
|
||||
return effectiveScale;
|
||||
}
|
||||
|
||||
public abstract SurfaceType getSurfaceType();
|
||||
@@ -99,7 +127,6 @@ public abstract class WLGraphicsConfig extends GraphicsConfiguration {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
Rectangle bounds = getBounds();
|
||||
return String.format("%dx%d@(%d, %d) %dx scale", bounds.width, bounds.height, bounds.x, bounds.y, getDisplayScale());
|
||||
return String.format("%dx%d@(%d, %d) %dx scale", width, height, x, y, displayScale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,21 +39,15 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Corresponds to a Wayland output and is identified by its wlID.
|
||||
* Owns all graphics configurations associated with this device.
|
||||
* Encapsulates all the other properties of the output, such as its size
|
||||
* and location in a multi-monitor configuration.
|
||||
* Whenever any of these properties change, they are updated and
|
||||
* the GraphicsConfiguration objects get re-created to let referents know of the change.
|
||||
* Corresponds to Wayland's output and is identified by its wlID and x, y coordinates
|
||||
* in the multi-monitor setup. Whenever those change, this device is re-created.
|
||||
*/
|
||||
public class WLGraphicsDevice extends GraphicsDevice {
|
||||
private static final double MM_IN_INCH = 25.4;
|
||||
|
||||
/**
|
||||
* ID of the corresponding wl_output object received from Wayland.
|
||||
* Only changes when the device gets invalidated.
|
||||
*/
|
||||
private volatile int wlID;
|
||||
private volatile int wlID; // only changes when the device gets invalidated
|
||||
|
||||
/**
|
||||
* Some human-readable name of the device that came from Wayland.
|
||||
@@ -64,142 +58,75 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
/**
|
||||
* The horizontal location of this device in the multi-monitor configuration.
|
||||
*/
|
||||
private volatile int x;
|
||||
private volatile int x; // only changes when the device gets invalidated
|
||||
|
||||
/**
|
||||
* The vertical location of this device in the multi-monitor configuration.
|
||||
*/
|
||||
private volatile int y;
|
||||
private volatile int y; // only changes when the device gets invalidated
|
||||
|
||||
/**
|
||||
* Pixel width, mostly for accounting and reporting.
|
||||
*/
|
||||
private volatile int width;
|
||||
private volatile int xLogical; // logical (scaled) horizontal location; optional, could be zero
|
||||
private volatile int yLogical; // logical (scaled) vertical location; optional, could be zero
|
||||
|
||||
/**
|
||||
* Pixel height, mostly for accounting and reporting.
|
||||
*/
|
||||
private volatile int height;
|
||||
private final int widthMm;
|
||||
private final int heightMm;
|
||||
|
||||
/**
|
||||
* Logical (scaled) width in Java units.
|
||||
*/
|
||||
private volatile int widthLogical;
|
||||
// Configs are always the same in size and scale
|
||||
private volatile GraphicsConfiguration[] configs = null;
|
||||
|
||||
/**
|
||||
* Logical (scaled) height in Java units.
|
||||
*/
|
||||
private volatile int heightLogical;
|
||||
// The default config is an object from the configs array
|
||||
private volatile WLGraphicsConfig defaultConfig = null;
|
||||
|
||||
/**
|
||||
* Width in millimeters.
|
||||
*/
|
||||
private volatile int widthMm;
|
||||
|
||||
/**
|
||||
* Height in millimeters.
|
||||
*/
|
||||
private volatile int heightMm;
|
||||
|
||||
/**
|
||||
* The device's scale factor as reported by Wayland.
|
||||
* Since it is an integer, it's usually higher than the real fraction scale.
|
||||
*/
|
||||
private volatile int displayScale;
|
||||
|
||||
/**
|
||||
* The effective scale factor as determined by Java.
|
||||
*/
|
||||
private volatile double effectiveScale;
|
||||
|
||||
private volatile GraphicsConfiguration[] configs;
|
||||
private volatile WLGraphicsConfig defaultConfig; // A reference to the configs array
|
||||
|
||||
/**
|
||||
* Top-level window peers that consider this device as their primary one
|
||||
* and get their graphics configuration from it
|
||||
*/
|
||||
// Top-level window peers that consider this device as their primary one
|
||||
// and get their graphics configuration from it
|
||||
private final Set<WLComponentPeer> toplevels = new HashSet<>(); // guarded by 'this'
|
||||
|
||||
private WLGraphicsDevice(int id,
|
||||
String name,
|
||||
int x, int y,
|
||||
int width, int height,
|
||||
int widthLogical, int heightLogical,
|
||||
int widthMm, int heightMm,
|
||||
int displayScale) {
|
||||
assert width > 0 && height > 0;
|
||||
assert widthLogical > 0 && heightLogical > 0;
|
||||
assert widthMm > 0 && heightMm > 0;
|
||||
assert displayScale > 0;
|
||||
|
||||
private WLGraphicsDevice(int id, int x, int y, int xLogical, int yLogical, int widthMm, int heightMm) {
|
||||
this.wlID = id;
|
||||
this.name = name;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.widthLogical = widthLogical;
|
||||
this.heightLogical = heightLogical;
|
||||
this.xLogical = xLogical;
|
||||
this.yLogical = yLogical;
|
||||
this.widthMm = widthMm;
|
||||
this.heightMm = heightMm;
|
||||
this.displayScale = displayScale;
|
||||
this.effectiveScale = WLGraphicsEnvironment.effectiveScaleFrom(displayScale);
|
||||
|
||||
makeGC();
|
||||
}
|
||||
|
||||
private void makeGC() {
|
||||
GraphicsConfiguration[] newConfigs;
|
||||
WLGraphicsConfig newDefaultConfig;
|
||||
if (VKEnv.isPresentationEnabled()) {
|
||||
newConfigs = VKEnv.getDevices().flatMap(d -> d.getPresentableGraphicsConfigs().map(
|
||||
gc -> WLVKGraphicsConfig.getConfig(gc, this)))
|
||||
.toArray(WLGraphicsConfig[]::new);
|
||||
newDefaultConfig = (WLGraphicsConfig) newConfigs[0];
|
||||
} else {
|
||||
// TODO: Actually, Wayland may support a lot more shared memory buffer configurations, need to
|
||||
// subscribe to the wl_shm:format event and get the list from there.
|
||||
newDefaultConfig = WLSMGraphicsConfig.getConfig(this, true);
|
||||
newConfigs = new GraphicsConfiguration[2];
|
||||
newConfigs[0] = newDefaultConfig;
|
||||
newConfigs[1] = WLSMGraphicsConfig.getConfig(this, false);
|
||||
int getID() {
|
||||
return wlID;
|
||||
}
|
||||
|
||||
void updateConfiguration(String name, int width, int height, int widthLogical, int heightLogical, int scale) {
|
||||
this.name = name;
|
||||
|
||||
WLGraphicsConfig config = defaultConfig;
|
||||
// Note that all configs are of equal size and scale
|
||||
if (config == null || config.differsFrom(width, height, scale)) {
|
||||
GraphicsConfiguration[] newConfigs;
|
||||
WLGraphicsConfig newDefaultConfig;
|
||||
// It is necessary to create a new object whenever config changes as its
|
||||
// identity is used to detect changes in scale, among other things.
|
||||
if (VKEnv.isPresentationEnabled()) {
|
||||
newConfigs = VKEnv.getDevices().flatMap(d -> d.getPresentableGraphicsConfigs().map(
|
||||
gc -> WLVKGraphicsConfig.getConfig(
|
||||
gc, this, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale)))
|
||||
.toArray(WLGraphicsConfig[]::new);
|
||||
newDefaultConfig = (WLGraphicsConfig) newConfigs[0];
|
||||
} else {
|
||||
// TODO: Actually, Wayland may support a lot more shared memory buffer configurations, need to
|
||||
// subscribe to the wl_shm:format event and get the list from there.
|
||||
newDefaultConfig = WLSMGraphicsConfig.getConfig(this, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale, true);
|
||||
newConfigs = new GraphicsConfiguration[2];
|
||||
newConfigs[0] = newDefaultConfig;
|
||||
newConfigs[1] = WLSMGraphicsConfig.getConfig(this, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale, false);
|
||||
}
|
||||
|
||||
configs = newConfigs;
|
||||
defaultConfig = newDefaultConfig;
|
||||
}
|
||||
|
||||
configs = newConfigs;
|
||||
defaultConfig = newDefaultConfig;
|
||||
}
|
||||
|
||||
void updateConfiguration(String name,
|
||||
int x, int y,
|
||||
int width, int height,
|
||||
int widthLogical, int heightLogical,
|
||||
int widthMm, int heightMm,
|
||||
int scale) {
|
||||
assert width > 0 && height > 0;
|
||||
assert widthLogical > 0 && heightLogical > 0;
|
||||
assert widthMm > 0 && heightMm > 0;
|
||||
assert scale > 0;
|
||||
|
||||
this.name = name;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.widthLogical = widthLogical;
|
||||
this.heightLogical = heightLogical;
|
||||
this.widthMm = widthMm;
|
||||
this.heightMm = heightMm;
|
||||
this.displayScale = scale;
|
||||
this.effectiveScale = WLGraphicsEnvironment.effectiveScaleFrom(scale);
|
||||
|
||||
// It is necessary to create new config objects whenever this device changes
|
||||
// as GraphicsConfiguration identity is used to detect changes in scale, among other things.
|
||||
makeGC();
|
||||
|
||||
// It is important that by the time displayChanged() events are delivered,
|
||||
// all the peers on this device had their graphics configuration updated
|
||||
// to refer to the new ones with, perhaps, a different scale or resolution.
|
||||
// to refer to the new ones with, perhaps, different scale or resolution.
|
||||
// This affects various BufferStrategy that use volatile images as their buffers.
|
||||
notifyToplevels();
|
||||
}
|
||||
@@ -209,36 +136,47 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
synchronized (this) {
|
||||
toplevelsCopy.addAll(toplevels);
|
||||
}
|
||||
toplevelsCopy.forEach(WLComponentPeer::checkIfOnNewScreen);
|
||||
int wlOutputID = this.wlID;
|
||||
// NB: each of those peers will likely receive another such notification
|
||||
// from Wayland when it gets the wl_surface::enter event, but the second one
|
||||
// will effectively be a no-op.
|
||||
toplevelsCopy.forEach((peer) -> peer.notifyEnteredOutput(wlOutputID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes all aspects of this device, including its identity to be that of the given
|
||||
* Changes all aspects of this device including its identity to be that of the given
|
||||
* device. Only used for devices that are no longer physically present, but references
|
||||
* to which may still exist in the program.
|
||||
*/
|
||||
void invalidate(WLGraphicsDevice similarDevice) {
|
||||
// Note: It is expected that all the surface this device used to host have already received
|
||||
// the 'leave' event and updated their device/graphics configurations accordingly.
|
||||
this.wlID = similarDevice.wlID;
|
||||
updateConfiguration(similarDevice.name,
|
||||
similarDevice.x,
|
||||
similarDevice.y,
|
||||
similarDevice.width,
|
||||
similarDevice.height,
|
||||
similarDevice.widthLogical,
|
||||
similarDevice.heightLogical,
|
||||
similarDevice.widthMm,
|
||||
similarDevice.heightMm,
|
||||
similarDevice.displayScale);
|
||||
this.x = similarDevice.x;
|
||||
this.y = similarDevice.y;
|
||||
this.xLogical = similarDevice.xLogical;
|
||||
this.yLogical = similarDevice.yLogical;
|
||||
|
||||
int newScale = similarDevice.getDisplayScale();
|
||||
Rectangle newBounds = similarDevice.defaultConfig.getBounds();
|
||||
Rectangle newRealBounds = similarDevice.defaultConfig.getRealBounds();
|
||||
updateConfiguration(similarDevice.name, newRealBounds.width, newRealBounds.height, newBounds.width, newBounds.height, newScale);
|
||||
}
|
||||
|
||||
public static WLGraphicsDevice createWithConfiguration(int id, String name,
|
||||
int x, int y,
|
||||
int x, int y, int xLogical, int yLogical,
|
||||
int width, int height, int widthLogical, int heightLogical,
|
||||
int widthMm, int heightMm,
|
||||
int scale) {
|
||||
return new WLGraphicsDevice(id, name, x, y, width, height, widthLogical, heightLogical, widthMm, heightMm, scale);
|
||||
WLGraphicsDevice device = new WLGraphicsDevice(id, x, y, xLogical, yLogical, widthMm, heightMm);
|
||||
device.updateConfiguration(name, width, height, widthLogical, heightLogical, scale);
|
||||
return device;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the identity of this device with the given attributes
|
||||
* and returns true iff the attributes identify the same device.
|
||||
*/
|
||||
boolean isSameDeviceAs(int wlID, int x, int y, int xLogical, int yLogical) {
|
||||
return this.wlID == wlID && this.x == x && this.y == y && this.xLogical == xLogical && this.yLogical == yLogical;
|
||||
}
|
||||
|
||||
boolean hasSameNameAs(WLGraphicsDevice otherDevice) {
|
||||
@@ -269,8 +207,8 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
public GraphicsConfiguration[] getConfigurations() {
|
||||
// From wayland.xml, wl_output.mode event:
|
||||
// "Non-current modes are deprecated. A compositor can decide to only
|
||||
// advertise the current mode and never send other modes. Clients
|
||||
// should not rely on non-current modes."
|
||||
// advertise the current mode and never send other modes. Clients
|
||||
// should not rely on non-current modes."
|
||||
// So there's always the same set of configs.
|
||||
return configs.clone();
|
||||
}
|
||||
@@ -280,24 +218,8 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
return defaultConfig;
|
||||
}
|
||||
|
||||
int getID() {
|
||||
return wlID;
|
||||
}
|
||||
|
||||
Rectangle getBounds() {
|
||||
return new Rectangle(x, y, widthLogical, heightLogical);
|
||||
}
|
||||
|
||||
Rectangle getRealBounds() {
|
||||
return new Rectangle(x, y, width, height);
|
||||
}
|
||||
|
||||
int getDisplayScale() {
|
||||
return displayScale;
|
||||
}
|
||||
|
||||
double getEffectiveScale() {
|
||||
return effectiveScale;
|
||||
return defaultConfig.getDisplayScale();
|
||||
}
|
||||
|
||||
int getResolution() {
|
||||
@@ -305,6 +227,13 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
return getResolutionX(defaultConfig);
|
||||
}
|
||||
|
||||
double getPhysicalResolution() {
|
||||
Rectangle bounds = defaultConfig.getRealBounds();
|
||||
double daigInPixels = Math.sqrt(bounds.width * bounds.width + bounds.height * bounds.height);
|
||||
double diagInMm = Math.sqrt(widthMm * widthMm + heightMm * heightMm);
|
||||
return daigInPixels * MM_IN_INCH / diagInMm;
|
||||
}
|
||||
|
||||
double getPhysicalScale() {
|
||||
Rectangle bounds = defaultConfig.getRealBounds();
|
||||
double daigInPixels = Math.sqrt(bounds.width * bounds.width + bounds.height * bounds.height);
|
||||
@@ -338,7 +267,7 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
|
||||
boolean fsSupported = isFullScreenSupported();
|
||||
if (fsSupported && old != null) {
|
||||
// enter windowed mode and restore the original display mode
|
||||
// enter windowed mode and restore original display mode
|
||||
exitFullScreenExclusive(old);
|
||||
}
|
||||
|
||||
@@ -382,8 +311,9 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
@Override
|
||||
public String toString() {
|
||||
var config = defaultConfig;
|
||||
return String.format("WLGraphicsDevice: '%s' id=%d at (%d, %d) with %s",
|
||||
name, wlID, x, y, config != null ? config : "<no configs>");
|
||||
return String.format("WLGraphicsDevice: '%s' id=%d at (%d, %d) ((%d, %d) logical) with %s",
|
||||
name, wlID, x, y, xLogical, yLogical,
|
||||
config != null ? config : "<no configs>");
|
||||
}
|
||||
|
||||
public Insets getInsets() {
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
package sun.awt.wl;
|
||||
|
||||
import java.awt.AWTError;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
@@ -55,8 +54,6 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment implements HiD
|
||||
private static final boolean debugScaleEnabled;
|
||||
private final Dimension totalDisplayBounds = new Dimension();
|
||||
|
||||
private final List<WLGraphicsDevice> devices = new ArrayList<>(5);
|
||||
|
||||
@SuppressWarnings("restricted")
|
||||
private static void loadAwt() {
|
||||
System.loadLibrary("awt");
|
||||
@@ -97,30 +94,15 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment implements HiD
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsDevice getDefaultScreenDevice() {
|
||||
synchronized (devices) {
|
||||
if (devices.isEmpty()) {
|
||||
throw new AWTError("no screen devices");
|
||||
}
|
||||
return devices.getFirst();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized GraphicsDevice[] getScreenDevices() {
|
||||
synchronized (devices) {
|
||||
return devices.toArray(new GraphicsDevice[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplayLocal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private final List<WLGraphicsDevice> devices = new ArrayList<>(5);
|
||||
|
||||
private void notifyOutputConfigured(String name, String make, String model, int wlID,
|
||||
int x, int y,
|
||||
int x, int y, int xLogical, int yLogical,
|
||||
int width, int height,
|
||||
int widthLogical, int heightLogical,
|
||||
int widthMm, int heightMm,
|
||||
@@ -128,33 +110,44 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment implements HiD
|
||||
// Called from native code whenever a new output appears or an existing one changes its properties
|
||||
// NB: initially called during WLToolkit.initIDs() on the main thread; later on EDT.
|
||||
if (log.isLoggable(Level.FINE)) {
|
||||
log.fine(String.format("Output configured id=%d at (%d, %d) %dx%d (%dx%d logical) %dx scale",
|
||||
wlID, x, y, width, height, widthLogical, heightLogical, scale));
|
||||
log.fine(String.format("Output configured id=%d at (%d, %d) (%d, %d logical) %dx%d (%dx%d logical) %dx scale",
|
||||
wlID, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale));
|
||||
}
|
||||
|
||||
// Logical size comes from an optional protocol, so take the data from the main one, if absent
|
||||
if (widthLogical == 0) widthLogical = width;
|
||||
if (heightLogical == 0) heightLogical = height;
|
||||
String humanID = deviceNameFrom(name, make, model);
|
||||
|
||||
WLGraphicsDevice gd = deviceWithID(wlID);
|
||||
if (gd != null) {
|
||||
// Some properties of an existing device have changed; update the existing device and
|
||||
// let all the windows it hosts know about the change.
|
||||
gd.updateConfiguration(humanID, x, y, width, height, widthLogical, heightLogical, widthMm, heightMm, scale);
|
||||
} else {
|
||||
WLGraphicsDevice newGD = WLGraphicsDevice.createWithConfiguration(wlID, humanID,
|
||||
x, y, width, height, widthLogical, heightLogical,
|
||||
widthMm, heightMm, scale);
|
||||
synchronized (devices) {
|
||||
devices.add(newGD);
|
||||
String humanID =
|
||||
(name != null ? name + " " : "")
|
||||
+ (make != null ? make + " " : "")
|
||||
+ (model != null ? model : "");
|
||||
synchronized (devices) {
|
||||
boolean newOutput = true;
|
||||
for (int i = 0; i < devices.size(); i++) {
|
||||
final WLGraphicsDevice gd = devices.get(i);
|
||||
if (gd.getID() == wlID) {
|
||||
newOutput = false;
|
||||
if (gd.isSameDeviceAs(wlID, x, y, xLogical, yLogical)) {
|
||||
// These coordinates and the size are not scaled.
|
||||
gd.updateConfiguration(humanID, width, height, widthLogical, heightLogical, scale);
|
||||
} else {
|
||||
final WLGraphicsDevice updatedDevice = WLGraphicsDevice.createWithConfiguration(wlID, humanID,
|
||||
x, y, xLogical, yLogical, width, height, widthLogical, heightLogical,
|
||||
widthMm, heightMm, scale);
|
||||
devices.set(i, updatedDevice);
|
||||
gd.invalidate(updatedDevice);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newOutput) {
|
||||
final WLGraphicsDevice gd = WLGraphicsDevice.createWithConfiguration(wlID, humanID,
|
||||
x, y, xLogical, yLogical, width, height, widthLogical, heightLogical,
|
||||
widthMm, heightMm, scale);
|
||||
devices.add(gd);
|
||||
}
|
||||
if (LogDisplay.ENABLED) {
|
||||
double effectiveScale = effectiveScaleFrom(scale);
|
||||
LogDisplay log = newOutput ? LogDisplay.ADDED : LogDisplay.CHANGED;
|
||||
log.log(wlID, (int) (width / effectiveScale) + "x" + (int) (height / effectiveScale), effectiveScale);
|
||||
}
|
||||
}
|
||||
|
||||
if (LogDisplay.ENABLED) {
|
||||
double effectiveScale = effectiveScaleFrom(scale);
|
||||
LogDisplay log = (gd == null) ? LogDisplay.ADDED : LogDisplay.CHANGED;
|
||||
log.log(wlID, (int) (width / effectiveScale) + "x" + (int) (height / effectiveScale), effectiveScale);
|
||||
}
|
||||
|
||||
updateTotalDisplayBounds();
|
||||
@@ -165,12 +158,6 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment implements HiD
|
||||
}
|
||||
}
|
||||
|
||||
private static String deviceNameFrom(String name, String make, String model) {
|
||||
return (name != null ? name + " " : "")
|
||||
+ (make != null ? make + " " : "")
|
||||
+ (model != null ? model : "");
|
||||
}
|
||||
|
||||
private WLGraphicsDevice getSimilarDevice(WLGraphicsDevice modelDevice) {
|
||||
WLGraphicsDevice similarDevice = devices.isEmpty() ? null : devices.getFirst();
|
||||
for (WLGraphicsDevice device : devices) {
|
||||
@@ -194,33 +181,47 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment implements HiD
|
||||
log.fine(String.format("Output destroyed id=%d", wlID));
|
||||
}
|
||||
// NB: id may *not* be that of any output; if so, just ignore this event.
|
||||
WLGraphicsDevice gd = deviceWithID(wlID);
|
||||
if (gd != null) {
|
||||
if (LogDisplay.ENABLED) {
|
||||
WLGraphicsConfig config = (WLGraphicsConfig) gd.getDefaultConfiguration();
|
||||
Rectangle bounds = config.getBounds();
|
||||
LogDisplay.REMOVED.log(wlID, bounds.width + "x" + bounds.height, config.getEffectiveScale());
|
||||
synchronized (devices) {
|
||||
final Optional<WLGraphicsDevice> deviceOptional = devices.stream()
|
||||
.filter(device -> device.getID() == wlID)
|
||||
.findFirst();
|
||||
if (deviceOptional.isPresent()) {
|
||||
final WLGraphicsDevice destroyedDevice = deviceOptional.get();
|
||||
if (LogDisplay.ENABLED) {
|
||||
WLGraphicsConfig config = (WLGraphicsConfig) destroyedDevice.getDefaultConfiguration();
|
||||
Rectangle bounds = config.getBounds();
|
||||
LogDisplay.REMOVED.log(wlID, bounds.width + "x" + bounds.height, config.getEffectiveScale());
|
||||
}
|
||||
devices.remove(destroyedDevice);
|
||||
final WLGraphicsDevice similarDevice = getSimilarDevice(destroyedDevice);
|
||||
if (similarDevice != null) destroyedDevice.invalidate(similarDevice);
|
||||
}
|
||||
synchronized (devices) {
|
||||
devices.remove(gd);
|
||||
}
|
||||
final WLGraphicsDevice similarDevice = getSimilarDevice(gd);
|
||||
if (similarDevice != null) gd.invalidate(similarDevice);
|
||||
}
|
||||
|
||||
updateTotalDisplayBounds();
|
||||
displayChanged();
|
||||
}
|
||||
|
||||
WLGraphicsDevice deviceWithID(int wlOutputID) {
|
||||
WLGraphicsDevice notifySurfaceEnteredOutput(WLComponentPeer wlComponentPeer, int wlOutputID) {
|
||||
synchronized (devices) {
|
||||
for (WLGraphicsDevice gd : devices) {
|
||||
if (gd.getID() == wlOutputID) {
|
||||
return gd;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
WLGraphicsDevice notifySurfaceLeftOutput(WLComponentPeer wlComponentPeer, int wlOutputID) {
|
||||
synchronized (devices) {
|
||||
for (WLGraphicsDevice gd : devices) {
|
||||
if (gd.getID() == wlOutputID) {
|
||||
return gd;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Dimension getTotalDisplayBounds() {
|
||||
@@ -230,14 +231,16 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment implements HiD
|
||||
}
|
||||
|
||||
private void updateTotalDisplayBounds() {
|
||||
Rectangle virtualBounds = new Rectangle();
|
||||
synchronized (devices) {
|
||||
for (var gd : devices) {
|
||||
virtualBounds = virtualBounds.union(gd.getBounds());
|
||||
Rectangle virtualBounds = new Rectangle();
|
||||
for (GraphicsDevice gd : devices) {
|
||||
for (GraphicsConfiguration gc : gd.getConfigurations()) {
|
||||
virtualBounds = virtualBounds.union(gc.getBounds());
|
||||
}
|
||||
}
|
||||
synchronized (totalDisplayBounds) {
|
||||
totalDisplayBounds.setSize(virtualBounds.getSize());
|
||||
}
|
||||
}
|
||||
synchronized (totalDisplayBounds) {
|
||||
totalDisplayBounds.setSize(virtualBounds.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public class WLMainSurface extends WLSurface {
|
||||
// Called from native code whenever the corresponding wl_surface enters an output (monitor)
|
||||
synchronized (devices) {
|
||||
final WLGraphicsEnvironment ge = (WLGraphicsEnvironment)WLGraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
final WLGraphicsDevice gd = ge.deviceWithID(wlOutputID);
|
||||
final WLGraphicsDevice gd = ge.notifySurfaceEnteredOutput(peer, wlOutputID);
|
||||
if (gd != null) {
|
||||
devices.add(gd);
|
||||
}
|
||||
@@ -81,7 +81,7 @@ public class WLMainSurface extends WLSurface {
|
||||
// Called from native code whenever the corresponding wl_surface leaves an output (monitor)
|
||||
synchronized (devices) {
|
||||
final WLGraphicsEnvironment ge = (WLGraphicsEnvironment)WLGraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
final WLGraphicsDevice gd = ge.deviceWithID(wlOutputID);
|
||||
final WLGraphicsDevice gd = ge.notifySurfaceLeftOutput(peer, wlOutputID);
|
||||
if (gd != null) {
|
||||
devices.remove(gd);
|
||||
}
|
||||
|
||||
@@ -24,16 +24,11 @@
|
||||
*/
|
||||
package sun.awt.wl;
|
||||
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Window;
|
||||
import java.awt.peer.MouseInfoPeer;
|
||||
|
||||
public class WLMouseInfoPeer implements MouseInfoPeer, SunToolkit.RelativePointerMovementInfoProvider {
|
||||
private final Object mouseDeltaLock = new Object();
|
||||
private double mouseDeltaX = 0.0;
|
||||
private double mouseDeltaY = 0.0;
|
||||
public class WLMouseInfoPeer implements MouseInfoPeer {
|
||||
|
||||
@Override
|
||||
public int fillPointWithCoords(Point point) {
|
||||
@@ -60,23 +55,4 @@ public class WLMouseInfoPeer implements MouseInfoPeer, SunToolkit.RelativePointe
|
||||
return HOLDER.instance;
|
||||
}
|
||||
|
||||
void accumulatePointerDelta(double dx, double dy) {
|
||||
synchronized (mouseDeltaLock) {
|
||||
mouseDeltaX += dx;
|
||||
mouseDeltaY += dy;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point getAccumulatedMouseDeltaAndReset() {
|
||||
var p = new Point();
|
||||
synchronized (mouseDeltaLock) {
|
||||
int idx = (int) mouseDeltaX;
|
||||
int idy = (int) mouseDeltaY;
|
||||
p.setLocation(idx, idy);
|
||||
mouseDeltaX = mouseDeltaX - idx;
|
||||
mouseDeltaY = mouseDeltaY - idy;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
||||
@@ -52,8 +52,7 @@ public class WLRoundedCornersManager implements RoundedCornersManager {
|
||||
|
||||
public static int roundCornerRadiusFor(RoundedCornerKind kind) {
|
||||
return switch (kind) {
|
||||
case DEFAULT -> 12;
|
||||
case FULL -> 24;
|
||||
case DEFAULT, FULL -> 24;
|
||||
case NONE -> 0;
|
||||
case SMALL -> 8;
|
||||
};
|
||||
|
||||
@@ -58,16 +58,36 @@ public class WLSMGraphicsConfig extends WLGraphicsConfig
|
||||
private final ColorModel colorModel;
|
||||
private final SurfaceType surfaceType;
|
||||
|
||||
private WLSMGraphicsConfig(WLGraphicsDevice device, boolean translucencyCapable) {
|
||||
super(device);
|
||||
private WLSMGraphicsConfig(WLGraphicsDevice device,
|
||||
int x,
|
||||
int y,
|
||||
int xLogical,
|
||||
int yLogical,
|
||||
int width,
|
||||
int height,
|
||||
int widthLogical,
|
||||
int heightLogical,
|
||||
int scale,
|
||||
boolean translucencyCapable) {
|
||||
super(device, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale);
|
||||
this.translucencyCapable = translucencyCapable;
|
||||
this.colorModel = colorModelFor(translucencyCapable ? Transparency.TRANSLUCENT : Transparency.OPAQUE);
|
||||
// Note: GNOME Shell definitely expects alpha values to be pre-multiplied
|
||||
this.surfaceType = translucencyCapable ? SurfaceType.IntArgbPre : SurfaceType.IntRgb;
|
||||
}
|
||||
|
||||
public static WLSMGraphicsConfig getConfig(WLGraphicsDevice device, boolean translucencyCapable) {
|
||||
var newConfig = new WLSMGraphicsConfig(device, translucencyCapable);
|
||||
public static WLSMGraphicsConfig getConfig(WLGraphicsDevice device,
|
||||
int x,
|
||||
int y,
|
||||
int xLogical,
|
||||
int yLogical,
|
||||
int width,
|
||||
int height,
|
||||
int widthLogical,
|
||||
int heightLogical,
|
||||
int scale,
|
||||
boolean translucencyCapable) {
|
||||
var newConfig = new WLSMGraphicsConfig(device, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale, translucencyCapable);
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine("New shared memory config " + newConfig);
|
||||
}
|
||||
|
||||
@@ -86,7 +86,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
@@ -139,8 +138,6 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
|
||||
private static Boolean sunAwtDisableGtkFileDialogs = null;
|
||||
|
||||
private static final boolean isKDE;
|
||||
|
||||
private static native void initIDs(long displayPtr);
|
||||
|
||||
static {
|
||||
@@ -150,8 +147,6 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
VKEnv.init(display);
|
||||
initIDs(display);
|
||||
}
|
||||
String desktop = System.getenv("XDG_CURRENT_DESKTOP");
|
||||
isKDE = desktop != null && desktop.toLowerCase().contains("kde");
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@@ -295,10 +290,6 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
private static WLInputState inputState = WLInputState.initialState();
|
||||
private static WLKeyboard keyboard;
|
||||
|
||||
private static void dispatchRelativePointerEvent(double dx, double dy) {
|
||||
WLMouseInfoPeer.getInstance().accumulatePointerDelta(dx, dy);
|
||||
}
|
||||
|
||||
private static void dispatchPointerEvent(WLPointerEvent e) {
|
||||
// Invoked from the native code
|
||||
assert EventQueue.isDispatchThread();
|
||||
@@ -954,28 +945,17 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
|
||||
@Override
|
||||
public void grab(Window w) {
|
||||
// There is no input grab in Wayland for client applications, only
|
||||
// the compositor can control grabs. But we need UngrabEvent
|
||||
// for popup/tooltip management, so we do input grab accounting here
|
||||
// and in ungrab() below.
|
||||
Objects.requireNonNull(w);
|
||||
|
||||
var peer = AWTAccessor.getComponentAccessor().getPeer(w);
|
||||
if (peer instanceof WLWindowPeer windowPeer) {
|
||||
windowPeer.grab();
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine("Not implemented: WLToolkit.grab()");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ungrab(Window w) {
|
||||
Objects.requireNonNull(w);
|
||||
|
||||
var peer = AWTAccessor.getComponentAccessor().getPeer(w);
|
||||
if (peer instanceof WLWindowPeer windowPeer) {
|
||||
windowPeer.ungrab(false);
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine("Not implemented: WLToolkit.ungrab()");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the java.awt.Desktop class is supported on the current
|
||||
* desktop.
|
||||
@@ -1096,7 +1076,4 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
return WLCursorManager.getInstance();
|
||||
}
|
||||
|
||||
public static boolean isKDE() {
|
||||
return isKDE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,15 +25,10 @@
|
||||
package sun.awt.wl;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.SurfacePixelGrabber;
|
||||
import sun.awt.UngrabEvent;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.vulkan.VKSurfaceData;
|
||||
import sun.java2d.wl.WLSMSurfaceData;
|
||||
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.RootPaneContainer;
|
||||
import java.awt.AWTEvent;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
@@ -41,21 +36,18 @@ import java.awt.Dialog;
|
||||
import java.awt.Font;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.SystemColor;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.peer.ComponentPeer;
|
||||
import java.awt.peer.WindowPeer;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class WLWindowPeer extends WLComponentPeer implements WindowPeer, SurfacePixelGrabber {
|
||||
public class WLWindowPeer extends WLComponentPeer implements WindowPeer {
|
||||
private static Font defaultFont;
|
||||
private Dialog blocker;
|
||||
private static WLWindowPeer grabbingWindow; // fake, kept for UngrabEvent only
|
||||
|
||||
// If this window gets focus from Wayland, we need to transfer focus synthFocusOwner, if any
|
||||
private WeakReference<Component> synthFocusOwner = new WeakReference<>(null);
|
||||
@@ -102,8 +94,6 @@ public class WLWindowPeer extends WLComponentPeer implements WindowPeer, Surface
|
||||
|
||||
@Override
|
||||
protected void wlSetVisible(boolean v) {
|
||||
if (!v) ungrab(true);
|
||||
|
||||
if (v && targetIsWlPopup() && shouldBeFocusedOnShowing()) {
|
||||
requestWindowFocus();
|
||||
}
|
||||
@@ -207,7 +197,6 @@ public class WLWindowPeer extends WLComponentPeer implements WindowPeer, Surface
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ungrab(true);
|
||||
resetCornerMasks();
|
||||
super.dispose();
|
||||
}
|
||||
@@ -247,91 +236,6 @@ public class WLWindowPeer extends WLComponentPeer implements WindowPeer, Surface
|
||||
synthFocusOwner = new WeakReference<>(c);
|
||||
}
|
||||
|
||||
public void grab() {
|
||||
if (grabbingWindow != null && !isGrabbing()) {
|
||||
grabbingWindow.ungrab(false);
|
||||
}
|
||||
grabbingWindow = this;
|
||||
}
|
||||
|
||||
public void ungrab(boolean externalUngrab) {
|
||||
if (isGrabbing()) {
|
||||
grabbingWindow = null;
|
||||
if (externalUngrab) {
|
||||
WLToolkit.postEvent(new UngrabEvent(getTarget()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isGrabbing() {
|
||||
return this == grabbingWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleJavaWindowFocusEvent(AWTEvent e) {
|
||||
if (e.getID() == WindowEvent.WINDOW_LOST_FOCUS) {
|
||||
ungrab(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getClientAreaSnapshot(int x, int y, int width, int height) {
|
||||
// Move the coordinate system to the client area
|
||||
Insets insets = getInsets();
|
||||
x += insets.left;
|
||||
y += insets.top;
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
return null;
|
||||
}
|
||||
if (x < 0 || y < 0) {
|
||||
// Shouldn't happen, but better avoid accessing surface data outside the range
|
||||
throw new IllegalArgumentException("Negative coordinates are not allowed");
|
||||
}
|
||||
if (x >= getWidth()) {
|
||||
throw new IllegalArgumentException(String.format("x coordinate (%d) is out of bounds (%d)", x, getWidth()));
|
||||
}
|
||||
if (y >= getHeight()) {
|
||||
throw new IllegalArgumentException(String.format("y coordinate (%d) is out of bounds (%d)", y, getHeight()));
|
||||
}
|
||||
if ((long) x + width > getWidth()) {
|
||||
width = getWidth() - x;
|
||||
}
|
||||
if ((long) y + height > getHeight()) {
|
||||
height = getHeight() - y;
|
||||
}
|
||||
|
||||
// At this point the coordinates and size are in Java units;
|
||||
// need to convert them into pixels.
|
||||
Rectangle bounds = new Rectangle(
|
||||
javaUnitsToBufferUnits(x),
|
||||
javaUnitsToBufferUnits(y),
|
||||
javaSizeToBufferSize(width),
|
||||
javaSizeToBufferSize(height)
|
||||
);
|
||||
Rectangle bufferBounds = getBufferBounds();
|
||||
if (bounds.x >= bufferBounds.width) {
|
||||
bounds.x = bufferBounds.width - 1;
|
||||
}
|
||||
if (bounds.y >= bufferBounds.height) {
|
||||
bounds.y = bufferBounds.height - 1;
|
||||
}
|
||||
if (bounds.x + bounds.width > bufferBounds.width) {
|
||||
bounds.width = bufferBounds.width - bounds.x;
|
||||
}
|
||||
if (bounds.y + bounds.height > bufferBounds.height) {
|
||||
bounds.height = bufferBounds.height - bounds.y;
|
||||
}
|
||||
|
||||
if (surfaceData instanceof VKSurfaceData vksd) {
|
||||
return vksd.getSnapshot(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
} else if (surfaceData instanceof WLSMSurfaceData smsd) {
|
||||
return smsd.getSnapshot(bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean canPaintRoundedCorners() {
|
||||
int roundedCornerSize = WLRoundedCornersManager.roundCornerRadiusFor(roundedCornerKind);
|
||||
// Note: You would normally get a transparency-capable color model when using
|
||||
|
||||
@@ -47,8 +47,11 @@ public final class WLVKGraphicsConfig extends WLGraphicsConfig
|
||||
|
||||
private final VKGraphicsConfig offscreenConfig;
|
||||
|
||||
public WLVKGraphicsConfig(VKGraphicsConfig offscreenConfig, WLGraphicsDevice device) {
|
||||
super(device);
|
||||
public WLVKGraphicsConfig(VKGraphicsConfig offscreenConfig, WLGraphicsDevice device,
|
||||
int x, int y, int xLogical, int yLogical,
|
||||
int width, int height, int widthLogical, int heightLogical,
|
||||
int scale) {
|
||||
super(device, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale);
|
||||
this.offscreenConfig = offscreenConfig;
|
||||
}
|
||||
|
||||
@@ -62,8 +65,11 @@ public final class WLVKGraphicsConfig extends WLGraphicsConfig
|
||||
return getEffectiveScale();
|
||||
}
|
||||
|
||||
public static WLVKGraphicsConfig getConfig(VKGraphicsConfig offscreenConfig, WLGraphicsDevice device) {
|
||||
return new WLVKGraphicsConfig(offscreenConfig, device);
|
||||
public static WLVKGraphicsConfig getConfig(VKGraphicsConfig offscreenConfig, WLGraphicsDevice device,
|
||||
int x, int y, int xLogical, int yLogical,
|
||||
int width, int height, int widthLogical, int heightLogical,
|
||||
int scale) {
|
||||
return new WLVKGraphicsConfig(offscreenConfig, device, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,25 +26,19 @@
|
||||
|
||||
package sun.java2d.wl;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Window;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.util.Objects;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.wl.WLComponentPeer;
|
||||
import sun.awt.wl.WLGraphicsConfig;
|
||||
import sun.awt.wl.WLSMGraphicsConfig;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
@@ -130,20 +124,16 @@ public class WLSMSurfaceData extends SurfaceData implements WLSurfaceDataExt, WL
|
||||
return gc;
|
||||
}
|
||||
|
||||
public BufferedImage getSnapshot(int x, int y, int width, int height) {
|
||||
ColorModel colorModel = getColorModel();
|
||||
SampleModel sampleModel = colorModel.createCompatibleSampleModel(width, height);
|
||||
WritableRaster raster = Raster.createWritableRaster(sampleModel, null);
|
||||
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
|
||||
SurfaceData sd = SurfaceData.getPrimarySurfaceData(image);
|
||||
Blit blit = Blit.getFromCache(getSurfaceType(), CompositeType.SrcNoEa, sd.getSurfaceType());
|
||||
blit.Blit(this, sd, AlphaComposite.Src, null, x, y, 0, 0, width, height);
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Raster getRaster(int x, int y, int w, int h) {
|
||||
return getSnapshot(x, y, w, h).getRaster().createTranslatedChild(x, y);
|
||||
// Can do something like the following:
|
||||
// Raster r = getColorModel().createCompatibleWritableRaster(w, h);
|
||||
// copy surface data to this raster
|
||||
// save a reference to this raster
|
||||
// return r;
|
||||
// then in flush() check if raster was modified and take pixels from there
|
||||
// This is obviously suboptimal and shouldn't be used in performance-critical situations.
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -199,7 +189,7 @@ public class WLSMSurfaceData extends SurfaceData implements WLSurfaceDataExt, WL
|
||||
private void countNewFrame() {
|
||||
// Called from the native code when this surface data has been sent to the Wayland server
|
||||
if (target instanceof Window window) {
|
||||
AWTAccessor.getWindowAccessor().incrementCounter(window, "java2d.native.frames");
|
||||
AWTAccessor.getWindowAccessor().bumpCounter(window, "java2d.native.frames");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +198,7 @@ public class WLSMSurfaceData extends SurfaceData implements WLSurfaceDataExt, WL
|
||||
// the Wayland server, but that attempt was not successful. This can happen, for example,
|
||||
// when those attempts are too frequent.
|
||||
if (target instanceof Window window) {
|
||||
AWTAccessor.getWindowAccessor().incrementCounter(window, "java2d.native.framesDropped");
|
||||
AWTAccessor.getWindowAccessor().bumpCounter(window, "java2d.native.framesDropped");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -643,19 +643,8 @@ JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativePaintTitleBar
|
||||
jint pixel_width = ceil(width * scale);
|
||||
jint pixel_height = ceil(height * scale);
|
||||
|
||||
jboolean is_copy = JNI_FALSE;
|
||||
const char *title_c_str = "";
|
||||
if (title) {
|
||||
title_c_str = JNU_GetStringPlatformChars(env, title, &is_copy);
|
||||
if (!title_c_str)
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char *buffer = (*env)->GetPrimitiveArrayCritical(env, dest, 0);
|
||||
if (!buffer) {
|
||||
if (is_copy) {
|
||||
JNU_ReleaseStringPlatformChars(env, title, title_c_str);
|
||||
}
|
||||
JNU_ThrowOutOfMemoryError(env, "Could not get image buffer");
|
||||
return;
|
||||
}
|
||||
@@ -671,25 +660,31 @@ JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativePaintTitleBar
|
||||
|
||||
cairo_t *cr = p_cairo_create(surface);
|
||||
|
||||
jboolean is_copy = JNI_FALSE;
|
||||
const char *title_c_str = "";
|
||||
if (title) {
|
||||
title_c_str = JNU_GetStringPlatformChars(env, title, &is_copy);
|
||||
if (!title_c_str)
|
||||
return;
|
||||
}
|
||||
draw_title_bar(decor, surface, cr, width, height, scale, title_c_str, buttonsState);
|
||||
|
||||
if (is_copy) {
|
||||
JNU_ReleaseStringPlatformChars(env, title, title_c_str);
|
||||
}
|
||||
|
||||
// Make sure pixels have been flush into the underlying buffer
|
||||
p_cairo_surface_flush(surface);
|
||||
|
||||
p_gdk_threads_leave();
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, dest, buffer, 0);
|
||||
|
||||
if (is_copy) {
|
||||
JNU_ReleaseStringPlatformChars(env, title, title_c_str);
|
||||
}
|
||||
|
||||
p_cairo_destroy(cr);
|
||||
p_cairo_surface_destroy(surface);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativePrePaint(JNIEnv *env, jobject obj,
|
||||
jlong ptr, jint width, jint height) {
|
||||
jlong ptr, jint width) {
|
||||
assert (ptr != 0);
|
||||
GtkFrameDecorationDescr* decor = jlong_to_ptr(ptr);
|
||||
|
||||
@@ -719,12 +714,6 @@ JNIEXPORT void JNICALL Java_sun_awt_wl_GtkFrameDecoration_nativePrePaint(JNIEnv
|
||||
(*env)->SetIntField(env, obj, TitleBarHeightFID, pref_height);
|
||||
(*env)->SetIntField(env, obj, TitleBarMinWidthFID, min_width);
|
||||
|
||||
if (width < min_width || height < pref_height) {
|
||||
// Avoid gtk warnings in case of insufficient space
|
||||
p_gdk_threads_leave();
|
||||
return;
|
||||
}
|
||||
|
||||
GtkAllocation ha = {0, 0, width, pref_height};
|
||||
p_gtk_widget_size_allocate(decor->titlebar, &ha);
|
||||
|
||||
|
||||
@@ -72,9 +72,6 @@ struct DataSource
|
||||
struct wl_data_source *wlDataSource;
|
||||
struct zwp_primary_selection_source_v1 *zwpPrimarySelectionSource;
|
||||
};
|
||||
|
||||
struct wl_surface* dragIcon;
|
||||
struct wl_buffer* dragIconBuffer;
|
||||
};
|
||||
|
||||
// native part of WLDataOffer, remains alive until WLDataOffer.destroy() is called
|
||||
@@ -345,18 +342,22 @@ DataOffer_create(struct DataDevice *dataDevice, enum DataTransferProtocol protoc
|
||||
}
|
||||
|
||||
offer->javaObject = globalRef;
|
||||
offer->protocol = protocol;
|
||||
|
||||
if (protocol == DATA_TRANSFER_PROTOCOL_WAYLAND) {
|
||||
struct wl_data_offer *wlDataOffer = waylandObject;
|
||||
offer->wlDataOffer = wlDataOffer;
|
||||
|
||||
wl_data_offer_add_listener(wlDataOffer, &wlDataOfferListener, offer);
|
||||
|
||||
offer->wlDataOffer = wlDataOffer;
|
||||
offer->protocol = DATA_TRANSFER_PROTOCOL_WAYLAND;
|
||||
}
|
||||
|
||||
if (protocol == DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION) {
|
||||
struct zwp_primary_selection_offer_v1 *zwpPrimarySelectionOffer = waylandObject;
|
||||
offer->zwpPrimarySelectionOffer = zwpPrimarySelectionOffer;
|
||||
|
||||
zwp_primary_selection_offer_v1_add_listener(zwpPrimarySelectionOffer, &zwpPrimarySelectionOfferListener, offer);
|
||||
offer->zwpPrimarySelectionOffer = zwpPrimarySelectionOffer;
|
||||
offer->protocol = DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION;
|
||||
}
|
||||
|
||||
return offer;
|
||||
@@ -936,7 +937,7 @@ Java_sun_awt_wl_WLDataDevice_setSelectionImpl(JNIEnv *env,
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLDataDevice_startDragImpl(JNIEnv *env, jclass clazz, jlong dataDeviceNativePtr,
|
||||
jlong dataSourceNativePtr, jlong wlSurfacePtr,
|
||||
jlong serial)
|
||||
jlong iconPtr, jlong serial)
|
||||
{
|
||||
struct DataDevice *dataDevice = jlong_to_ptr(dataDeviceNativePtr);
|
||||
assert(dataDevice != NULL);
|
||||
@@ -945,10 +946,7 @@ Java_sun_awt_wl_WLDataDevice_startDragImpl(JNIEnv *env, jclass clazz, jlong data
|
||||
assert(source != NULL);
|
||||
|
||||
wl_data_device_start_drag(dataDevice->wlDataDevice, source->wlDataSource, jlong_to_ptr(wlSurfacePtr),
|
||||
source->dragIcon, serial);
|
||||
if (source->dragIcon != NULL) {
|
||||
wl_surface_commit(source->dragIcon);
|
||||
}
|
||||
jlong_to_ptr(iconPtr), serial);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
@@ -980,53 +978,36 @@ Java_sun_awt_wl_WLDataSource_initNative(JNIEnv *env, jobject javaObject, jlong d
|
||||
protocol = DATA_TRANSFER_PROTOCOL_WAYLAND;
|
||||
}
|
||||
|
||||
dataSource->protocol = protocol;
|
||||
|
||||
if (protocol == DATA_TRANSFER_PROTOCOL_WAYLAND) {
|
||||
// To avoid race conditions when setting the dispatch queue,
|
||||
// it's necessary to do this dance with wl_proxy_create_wrapper.
|
||||
// See the docs for wl_proxy_create_wrapper for more details
|
||||
|
||||
struct wl_data_device_manager* dmWrapper = wl_proxy_create_wrapper(wl_ddm);
|
||||
struct wl_data_source *wlDataSource = NULL;
|
||||
|
||||
if (dmWrapper != NULL) {
|
||||
wl_proxy_set_queue((struct wl_proxy *) dmWrapper, dataDevice->dataSourceQueue);
|
||||
wlDataSource = wl_data_device_manager_create_data_source(dmWrapper);
|
||||
wl_proxy_wrapper_destroy(dmWrapper);
|
||||
}
|
||||
|
||||
struct wl_data_source *wlDataSource = wl_data_device_manager_create_data_source(wl_ddm);
|
||||
if (wlDataSource == NULL) {
|
||||
free(dataSource);
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "Wayland error creating wl_data_source proxy");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dataSource->wlDataSource = wlDataSource;
|
||||
|
||||
wl_proxy_set_queue((struct wl_proxy *) wlDataSource, dataDevice->dataSourceQueue);
|
||||
wl_data_source_add_listener(wlDataSource, &wl_data_source_listener, dataSource);
|
||||
|
||||
dataSource->protocol = DATA_TRANSFER_PROTOCOL_WAYLAND;
|
||||
dataSource->wlDataSource = wlDataSource;
|
||||
}
|
||||
|
||||
if (protocol == DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION) {
|
||||
struct zwp_primary_selection_device_manager_v1 *dmWrapper = wl_proxy_create_wrapper(zwp_selection_dm);
|
||||
struct zwp_primary_selection_source_v1 *zwpPrimarySelectionSource = NULL;
|
||||
|
||||
if (dmWrapper != NULL) {
|
||||
wl_proxy_set_queue((struct wl_proxy *) dmWrapper, dataDevice->dataSourceQueue);
|
||||
zwpPrimarySelectionSource = zwp_primary_selection_device_manager_v1_create_source(dmWrapper);
|
||||
wl_proxy_wrapper_destroy(dmWrapper);
|
||||
}
|
||||
|
||||
struct zwp_primary_selection_source_v1 *zwpPrimarySelectionSource =
|
||||
zwp_primary_selection_device_manager_v1_create_source(zwp_selection_dm);
|
||||
if (zwpPrimarySelectionSource == NULL) {
|
||||
free(dataSource);
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "Wayland error creating zwp_primary_selection_source_v1 proxy");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dataSource->zwpPrimarySelectionSource = zwpPrimarySelectionSource;
|
||||
|
||||
wl_proxy_set_queue((struct wl_proxy *) zwpPrimarySelectionSource, dataDevice->dataSourceQueue);
|
||||
zwp_primary_selection_source_v1_add_listener(zwpPrimarySelectionSource,
|
||||
&zwp_primary_selection_source_v1_listener, dataSource);
|
||||
|
||||
dataSource->protocol = DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION;
|
||||
dataSource->zwpPrimarySelectionSource = zwpPrimarySelectionSource;
|
||||
}
|
||||
|
||||
return ptr_to_jlong(dataSource);
|
||||
@@ -1064,14 +1045,6 @@ Java_sun_awt_wl_WLDataSource_destroyImpl(JNIEnv *env, jclass clazz, jlong native
|
||||
zwp_primary_selection_source_v1_destroy(source->zwpPrimarySelectionSource);
|
||||
}
|
||||
|
||||
if (source->dragIconBuffer) {
|
||||
wl_buffer_destroy(source->dragIconBuffer);
|
||||
}
|
||||
|
||||
if (source->dragIcon) {
|
||||
wl_surface_destroy(source->dragIcon);
|
||||
}
|
||||
|
||||
free(source);
|
||||
}
|
||||
|
||||
@@ -1085,70 +1058,6 @@ Java_sun_awt_wl_WLDataSource_setDnDActionsImpl(JNIEnv *env,
|
||||
DataSource_setDnDActions(source, actions);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_sun_awt_wl_WLDataSource_setDnDIconImpl
|
||||
(JNIEnv * env, jclass clazz, jlong nativePtr, jint scale,
|
||||
jint width, jint height, jint offsetX, jint offsetY, jintArray pixels)
|
||||
{
|
||||
struct DataSource *source = jlong_to_ptr(nativePtr);
|
||||
|
||||
size_t pixelCount = (size_t)((*env)->GetArrayLength(env, pixels));
|
||||
size_t byteSize = pixelCount * 4U;
|
||||
if (byteSize >= INT32_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
jint *shmPixels = NULL;
|
||||
struct wl_shm_pool *pool = CreateShmPool(byteSize, "WLDataSource_DragIcon", (void**)&shmPixels, NULL);
|
||||
if (!pool) {
|
||||
return;
|
||||
}
|
||||
|
||||
(*env)->GetIntArrayRegion(env, pixels, 0, pixelCount, shmPixels);
|
||||
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
// Wayland requires little-endian data
|
||||
for (size_t i = 0; i < pixelCount; i++) {
|
||||
uint32_t value = (uint32_t)shmPixels[i];
|
||||
shmPixels[i] = (jint)((value & 0xFFU) << 24 |
|
||||
(value & 0xFF00U) << 8 |
|
||||
(value & 0xFF0000U) >> 8 |
|
||||
(value & 0xFF000000U) >> 24 & 0xFFU);
|
||||
}
|
||||
#endif
|
||||
|
||||
source->dragIconBuffer = wl_shm_pool_create_buffer(pool, 0, width, height, width * 4, WL_SHM_FORMAT_ARGB8888);
|
||||
wl_shm_pool_destroy(pool);
|
||||
if (!source->dragIconBuffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
source->dragIcon = wl_compositor_create_surface(wl_compositor);
|
||||
if (!source->dragIcon) {
|
||||
wl_buffer_destroy(source->dragIconBuffer);
|
||||
source->dragIconBuffer = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
#if WL_SURFACE_OFFSET_SINCE_VERSION >= 5
|
||||
int wl_compositor_version = wl_compositor_get_version(wl_compositor);
|
||||
if (wl_compositor_version >= 5) {
|
||||
wl_surface_attach(source->dragIcon, source->dragIconBuffer, 0, 0);
|
||||
wl_surface_offset(source->dragIcon, offsetX, offsetY);
|
||||
} else {
|
||||
wl_surface_attach(source->dragIcon, source->dragIconBuffer, offsetX, offsetY);
|
||||
}
|
||||
#else
|
||||
wl_surface_attach(source->dragIcon, source->dragIconBuffer, offsetX, offsetY);
|
||||
#endif
|
||||
|
||||
if (scale >= 1) {
|
||||
wl_surface_set_buffer_scale(source->dragIcon, scale);
|
||||
}
|
||||
|
||||
wl_surface_damage_buffer(source->dragIcon, 0, 0, width, height);
|
||||
|
||||
// NOTE: we still need to commit the surface, this is done immediately after start_drag
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_awt_wl_WLDataOffer_destroyImpl(JNIEnv *env, jclass clazz, jlong nativePtr)
|
||||
{
|
||||
|
||||
@@ -43,6 +43,8 @@ typedef struct WLOutput {
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t x_logical;
|
||||
int32_t y_logical;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t width_logical;
|
||||
@@ -57,8 +59,6 @@ typedef struct WLOutput {
|
||||
char * make;
|
||||
char * model;
|
||||
char * name;
|
||||
|
||||
bool offset_known; // whether x and y were set by xdg_output
|
||||
} WLOutput;
|
||||
|
||||
static jclass geClass;
|
||||
@@ -83,13 +83,10 @@ wl_output_geometry(
|
||||
{
|
||||
WLOutput *output = data;
|
||||
|
||||
if (!output->offset_known) {
|
||||
// Ubuntu 22.04 has a bug that prevent Mutter from sending out updates to (x, y) in this
|
||||
// geometry event. So we prefer to learn offset from xdg_output that will override
|
||||
// (x, y) from this event.
|
||||
output->x = x;
|
||||
output->y = y;
|
||||
}
|
||||
// TODO: there's also a recommended, but unstable interface xdg_output;
|
||||
// we may want to switch to that one day.
|
||||
output->x = x;
|
||||
output->y = y;
|
||||
output->subpixel = subpixel;
|
||||
output->transform = transform;
|
||||
output->width_mm = physical_width;
|
||||
@@ -164,6 +161,8 @@ NotifyOutputConfigured(WLOutput* output)
|
||||
output->id,
|
||||
output->x,
|
||||
output->y,
|
||||
output->x_logical,
|
||||
output->y_logical,
|
||||
output->width,
|
||||
output->height,
|
||||
output->width_logical,
|
||||
@@ -174,8 +173,6 @@ NotifyOutputConfigured(WLOutput* output)
|
||||
(jint)output->transform,
|
||||
(jint)output->scale);
|
||||
JNU_CHECK_EXCEPTION(env);
|
||||
|
||||
output->offset_known = false;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -221,12 +218,8 @@ static void
|
||||
zxdg_output_logical_position(void *data, struct zxdg_output_v1 *zxdg_output_v1, int32_t x, int32_t y)
|
||||
{
|
||||
WLOutput * output = data;
|
||||
output->x = x;
|
||||
output->y = y;
|
||||
|
||||
// Prevent the geometry event from overriding these values with potentially incorrect ones;
|
||||
// see wl_output_geometry().
|
||||
output->offset_known = true;
|
||||
output->x_logical = x;
|
||||
output->y_logical = y;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -264,7 +257,7 @@ WLGraphicsEnvironment_initIDs
|
||||
CHECK_NULL_RETURN(
|
||||
notifyOutputConfiguredMID = (*env)->GetMethodID(env, clazz,
|
||||
"notifyOutputConfigured",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIIIIIII)V"),
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIIIIIIIII)V"),
|
||||
JNI_FALSE);
|
||||
CHECK_NULL_RETURN(
|
||||
notifyOutputDestroyedMID = (*env)->GetMethodID(env, clazz,
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "relative-pointer-unstable-v1.h"
|
||||
#ifdef HEADLESS
|
||||
#error This file should not be included in headless library
|
||||
#endif
|
||||
@@ -81,7 +80,6 @@ struct gtk_shell1* gtk_shell1 = NULL;
|
||||
#endif
|
||||
struct wl_keyboard *wl_keyboard; // optional, check for NULL before use
|
||||
struct wl_pointer *wl_pointer; // optional, check for NULL before use
|
||||
struct zwp_relative_pointer_manager_v1* relative_pointer_manager; // optional, check for NULL before use
|
||||
|
||||
#define MAX_CURSOR_SCALE 100
|
||||
struct wl_cursor_theme *cursor_themes[MAX_CURSOR_SCALE] = {NULL};
|
||||
@@ -130,7 +128,6 @@ static jmethodID dispatchKeyboardKeyEventMID;
|
||||
static jmethodID dispatchKeyboardModifiersEventMID;
|
||||
static jmethodID dispatchKeyboardEnterEventMID;
|
||||
static jmethodID dispatchKeyboardLeaveEventMID;
|
||||
static jmethodID dispatchRelativePointerEventMID;
|
||||
|
||||
JNIEnv *getEnv() {
|
||||
JNIEnv *env;
|
||||
@@ -467,31 +464,6 @@ static const struct wl_keyboard_listener wl_keyboard_listener = {
|
||||
.key = wl_keyboard_key
|
||||
};
|
||||
|
||||
static void
|
||||
wl_relative_motion(void *data,
|
||||
struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1,
|
||||
uint32_t utime_hi,
|
||||
uint32_t utime_lo,
|
||||
wl_fixed_t dx,
|
||||
wl_fixed_t dy,
|
||||
wl_fixed_t dx_unaccel,
|
||||
wl_fixed_t dy_unaccel)
|
||||
{
|
||||
double ddx = wl_fixed_to_double(dx);
|
||||
double ddy = wl_fixed_to_double(dy);
|
||||
JNIEnv* env = getEnv();
|
||||
|
||||
(*env)->CallStaticVoidMethod(env,
|
||||
tkClass,
|
||||
dispatchRelativePointerEventMID,
|
||||
ddx, ddy);
|
||||
JNU_CHECK_EXCEPTION(env);
|
||||
}
|
||||
|
||||
static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
|
||||
.relative_motion = wl_relative_motion
|
||||
};
|
||||
|
||||
static void
|
||||
wl_seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities)
|
||||
{
|
||||
@@ -502,14 +474,6 @@ wl_seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities)
|
||||
wl_pointer = wl_seat_get_pointer(wl_seat);
|
||||
if (wl_pointer != NULL) {
|
||||
wl_pointer_add_listener(wl_pointer, &wl_pointer_listener, NULL);
|
||||
if (relative_pointer_manager != NULL) {
|
||||
struct zwp_relative_pointer_v1* rptr
|
||||
= zwp_relative_pointer_manager_v1_get_relative_pointer(relative_pointer_manager,
|
||||
wl_pointer);
|
||||
if (rptr != NULL) {
|
||||
zwp_relative_pointer_v1_add_listener(rptr, &relative_pointer_listener, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!has_pointer && wl_pointer != NULL) {
|
||||
wl_pointer_release(wl_pointer);
|
||||
@@ -572,12 +536,7 @@ registry_global(void *data, struct wl_registry *wl_registry,
|
||||
if (strcmp(interface, wl_shm_interface.name) == 0) {
|
||||
wl_shm = wl_registry_bind( wl_registry, name, &wl_shm_interface, 1);
|
||||
} else if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
||||
#if WL_SURFACE_OFFSET_SINCE_VERSION >= 5
|
||||
uint32_t chosen_version = (version >= 5) ? 5 : 4;
|
||||
#else
|
||||
uint32_t chosen_version = 4;
|
||||
#endif
|
||||
wl_compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, chosen_version);
|
||||
wl_compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 4);
|
||||
} else if (strcmp(interface, wl_subcompositor_interface.name) == 0) {
|
||||
wl_subcompositor = wl_registry_bind(wl_registry, name, &wl_subcompositor_interface, 1);
|
||||
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
|
||||
@@ -601,9 +560,6 @@ registry_global(void *data, struct wl_registry *wl_registry,
|
||||
} else if (strcmp(interface, xdg_activation_v1_interface.name) == 0) {
|
||||
xdg_activation_v1 = wl_registry_bind(wl_registry, name, &xdg_activation_v1_interface, 1);
|
||||
}
|
||||
else if (strcmp(interface, zwp_relative_pointer_manager_v1_interface.name) == 0) {
|
||||
relative_pointer_manager = wl_registry_bind(wl_registry, name, &zwp_relative_pointer_manager_v1_interface, 1);
|
||||
}
|
||||
#ifdef HAVE_GTK_SHELL1
|
||||
else if (strcmp(interface, gtk_shell1_interface.name) == 0) {
|
||||
gtk_shell1 = wl_registry_bind(wl_registry, name, >k_shell1_interface, 1);
|
||||
@@ -754,10 +710,6 @@ initJavaRefs(JNIEnv *env, jclass clazz)
|
||||
"dispatchKeyboardModifiersEvent",
|
||||
"(J)V"),
|
||||
JNI_FALSE);
|
||||
CHECK_NULL_RETURN(dispatchRelativePointerEventMID = (*env)->GetStaticMethodID(env, tkClass,
|
||||
"dispatchRelativePointerEvent",
|
||||
"(DD)V"),
|
||||
JNI_FALSE);
|
||||
|
||||
jclass wlgeClass = (*env)->FindClass(env, "sun/awt/wl/WLGraphicsEnvironment");
|
||||
CHECK_NULL_RETURN(wlgeClass, JNI_FALSE);
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
#include "xdg-output-unstable-v1.h"
|
||||
#include "primary-selection-unstable-v1.h"
|
||||
#include "viewporter.h"
|
||||
#include "relative-pointer-unstable-v1.h"
|
||||
|
||||
#include "jvm_md.h"
|
||||
#include "jni_util.h"
|
||||
|
||||
@@ -68,7 +66,7 @@ extern struct wl_cursor_theme *wl_cursor_theme;
|
||||
extern struct wl_data_device_manager *wl_ddm;
|
||||
extern struct zwp_primary_selection_device_manager_v1 *zwp_selection_dm; // optional, check for NULL before use
|
||||
extern struct zxdg_output_manager_v1 *zxdg_output_manager_v1; // optional, check for NULL before use
|
||||
extern struct zwp_relative_pointer_manager_v1* relative_pointer_manager;
|
||||
|
||||
JNIEnv *getEnv();
|
||||
|
||||
int wlFlushToServer(JNIEnv* env);
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 JetBrains s.r.o.
|
||||
* 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.windows;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.CaretEvent;
|
||||
import javax.swing.event.CaretListener;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import java.awt.*;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Provides caret tracking support for assistive tools that don't work with Java Access Bridge.
|
||||
* Specifically, it's targeted for the built-in Windows Magnifier.
|
||||
* This class listens to caret change events of the currently focused JTextComponent
|
||||
* and forwards them to the native code, which then sends them as Win32 IAccessible events.
|
||||
* <p>
|
||||
* A typical high-level scenario of the interaction with the magnifier:
|
||||
* <ol>
|
||||
* <li>Magnifier sends a WM_GETOBJECT window message to get accessible content of the window.</li>
|
||||
* <li>The message is handled in AwtComponent native class (awt_Component.cpp),
|
||||
* which calls {@link #startCaretNotifier}.</li>
|
||||
* <li>We start listening for keyboard focus change events.</li>
|
||||
* <li>If at some point focus gets to a {@link JTextComponent}, we subscribe to its caret events.</li>
|
||||
* <li>When the caret changes, we need to move the magnifier viewport to the new caret location.
|
||||
* To achieve this, we create a Win32 IAccessible object for the caret (see AccessibleCaret.cpp)
|
||||
* and send an event that its location was changed (EVENT_OBJECT_LOCATIONCHANGE).</li>
|
||||
* <li>Magnifier receives this event and sends the WM_GETOBJECT message with the OBJID_CARET argument
|
||||
* to get the caret object and its location property. After that, it moves the viewport to the returned location.
|
||||
* </li>
|
||||
* <li>When the {@link JTextComponent} loses focus, we stop listening to caret events
|
||||
* and release the IAccessible caret object.</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
* <p>
|
||||
* The feature is enabled by default
|
||||
* and can be toggled by setting the sun.awt.windows.use.native.caret.accessibility.events property.
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("unused") // Used from the native side through JNI.
|
||||
class AccessibleCaretLocationNotifier implements PropertyChangeListener, CaretListener {
|
||||
private volatile static AccessibleCaretLocationNotifier caretNotifier;
|
||||
private static final boolean nativeCaretEventsEnabled =
|
||||
Boolean.parseBoolean(System.getProperty("sun.awt.windows.use.native.caret.accessibility.events", "true"));
|
||||
|
||||
private WeakReference<JTextComponent> currentFocusedComponent;
|
||||
private long currentHwnd;
|
||||
|
||||
@SuppressWarnings("unused") // Called from the native through JNI.
|
||||
public static void startCaretNotifier(long hwnd) {
|
||||
if (nativeCaretEventsEnabled && caretNotifier == null) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (caretNotifier == null) {
|
||||
caretNotifier = new AccessibleCaretLocationNotifier(hwnd);
|
||||
KeyboardFocusManager cfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
cfm.addPropertyChangeListener("focusOwner", caretNotifier);
|
||||
if (cfm.getFocusOwner() instanceof JTextComponent textComponent) {
|
||||
caretNotifier.propertyChange(new PropertyChangeEvent(caretNotifier, "focusOwner", null, textComponent));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public AccessibleCaretLocationNotifier(long hwnd) {
|
||||
currentHwnd = hwnd;
|
||||
}
|
||||
|
||||
private static native void updateNativeCaretLocation(long hwnd, int x, int y, int width, int height);
|
||||
private static native void releaseNativeCaret(long hwnd);
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent e) {
|
||||
Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow();
|
||||
if (w != null) {
|
||||
WWindowPeer wp = AWTAccessor.getComponentAccessor().getPeer(w);
|
||||
if (wp != null) {
|
||||
long hwnd = wp.getHWnd();
|
||||
if (currentHwnd != hwnd) {
|
||||
currentHwnd = hwnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object newFocusedComponent = e.getNewValue();
|
||||
if (currentFocusedComponent != null) {
|
||||
JTextComponent currentComponentStrong = currentFocusedComponent.get();
|
||||
if (currentComponentStrong != null && newFocusedComponent != currentComponentStrong) {
|
||||
currentComponentStrong.removeCaretListener(this);
|
||||
currentFocusedComponent.clear();
|
||||
currentFocusedComponent = null;
|
||||
releaseNativeCaret(currentHwnd);
|
||||
}
|
||||
}
|
||||
|
||||
if (newFocusedComponent instanceof JTextComponent textComponent) {
|
||||
currentFocusedComponent = new WeakReference<>(textComponent);
|
||||
textComponent.addCaretListener(this);
|
||||
// Trigger the caret event when the text component receives focus to notify about the initial caret location
|
||||
caretUpdate(new CaretEvent(textComponent) {
|
||||
// Dot and mark won't be used, so we can set any values.
|
||||
@Override
|
||||
public int getDot() { return 0; }
|
||||
|
||||
@Override
|
||||
public int getMark() { return 0; }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void caretUpdate(CaretEvent e) {
|
||||
if (!(e.getSource() instanceof JTextComponent textComponent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (!textComponent.isShowing()) return;
|
||||
InputMethodRequests imr = textComponent.getInputMethodRequests();
|
||||
if (imr == null) return;
|
||||
Rectangle caretRectangle = imr.getTextLocation(null);
|
||||
if (caretRectangle == null) return;
|
||||
caretRectangle.width = 1;
|
||||
|
||||
Container parent = textComponent.getParent();
|
||||
if (parent != null && parent.isShowing()) {
|
||||
// Make sure we don't go outside of parent bounds, which can happen in the case of scrollable components.
|
||||
Rectangle parentBounds = parent.getBounds();
|
||||
parentBounds.setLocation(parent.getLocationOnScreen());
|
||||
|
||||
if (!parentBounds.contains(caretRectangle)) {
|
||||
caretRectangle = parentBounds.intersection(caretRectangle);
|
||||
if (caretRectangle.isEmpty()) return;
|
||||
}
|
||||
}
|
||||
|
||||
caretRectangle = SunGraphicsEnvironment.toDeviceSpaceAbs(caretRectangle);
|
||||
|
||||
updateNativeCaretLocation(AccessibleCaretLocationNotifier.this.currentHwnd,
|
||||
(int) caretRectangle.getX(), (int) caretRectangle.getY(),
|
||||
(int) caretRectangle.getWidth(), (int) caretRectangle.getHeight());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -831,11 +831,11 @@ public class D3DSurfaceData extends SurfaceData implements AccelSurface {
|
||||
if (sd.getPeer().getTarget() instanceof Window window) {
|
||||
switch (D3DRenderQueue.getFramePresentedStatus()) {
|
||||
case 1:
|
||||
AWTAccessor.getWindowAccessor().incrementCounter(window, "java2d.native.framesPresentRequested");
|
||||
AWTAccessor.getWindowAccessor().bumpCounter(window, "java2d.native.framesPresentRequested");
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
AWTAccessor.getWindowAccessor().incrementCounter(window, "java2d.native.framesPresentFailed");
|
||||
AWTAccessor.getWindowAccessor().bumpCounter(window, "java2d.native.framesPresentFailed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,317 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "AccessibleCaret.h"
|
||||
#include "debug_assert.h" // DASSERT
|
||||
#include "sun_awt_windows_AccessibleCaretLocationNotifier.h"
|
||||
|
||||
#include <atomic> // std::atomic
|
||||
|
||||
|
||||
/**
|
||||
* This class implements Win32 IAccessible interface in a similar way to the system text caret.
|
||||
*/
|
||||
|
||||
static std::atomic<AccessibleCaret *> GLOBAL_INSTANCE{nullptr};
|
||||
|
||||
AccessibleCaret* AccessibleCaret::getInstanceIfPresent() noexcept {
|
||||
return GLOBAL_INSTANCE.load();
|
||||
}
|
||||
|
||||
AccessibleCaret* AccessibleCaret::getOrCreateInstance() {
|
||||
bool unused;
|
||||
return AccessibleCaret::getOrCreateInstance(unused);
|
||||
}
|
||||
|
||||
AccessibleCaret* AccessibleCaret::getOrCreateInstance(bool& instanceIsNew) {
|
||||
instanceIsNew = false;
|
||||
|
||||
AccessibleCaret* result = GLOBAL_INSTANCE.load();
|
||||
|
||||
if (result == nullptr) {
|
||||
AccessibleCaret* newInstance = new AccessibleCaret();
|
||||
|
||||
if (GLOBAL_INSTANCE.compare_exchange_strong(result, newInstance)) {
|
||||
result = newInstance;
|
||||
instanceIsNew = true;
|
||||
} else {
|
||||
DASSERT(result != nullptr);
|
||||
delete newInstance;
|
||||
}
|
||||
}
|
||||
|
||||
DASSERT(result != nullptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AccessibleCaret::releaseInstanceIfPresent() {
|
||||
AccessibleCaret* instance = GLOBAL_INSTANCE.exchange(nullptr);
|
||||
if (instance != nullptr) {
|
||||
instance->Release();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
AccessibleCaret::AccessibleCaret()
|
||||
: m_refCount(1), m_x(0), m_y(0), m_width(0), m_height(0) {
|
||||
InitializeCriticalSection(&m_caretLocationLock);
|
||||
}
|
||||
|
||||
AccessibleCaret::~AccessibleCaret() {
|
||||
DeleteCriticalSection(&m_caretLocationLock);
|
||||
|
||||
// If the destroyed object is being referred by the singleton variable, the latter should be cleared.
|
||||
// This case should never happen, but if it does, it's better not to leave a dangling pointer.
|
||||
AccessibleCaret* self = this;
|
||||
(void)GLOBAL_INSTANCE.compare_exchange_strong(self, nullptr);
|
||||
}
|
||||
|
||||
|
||||
// IUnknown methods
|
||||
IFACEMETHODIMP_(ULONG) AccessibleCaret::AddRef() {
|
||||
return InterlockedIncrement(&m_refCount);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) AccessibleCaret::Release() {
|
||||
ULONG count = InterlockedDecrement(&m_refCount);
|
||||
if (count == 0) {
|
||||
delete this;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::QueryInterface(REFIID riid, void **ppInterface) {
|
||||
if (ppInterface == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (riid == IID_IUnknown || riid == IID_IDispatch || riid == IID_IAccessible) {
|
||||
*ppInterface = static_cast<IAccessible *>(this);
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppInterface = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
// IDispatch methods
|
||||
IFACEMETHODIMP AccessibleCaret::GetTypeInfoCount(UINT *pctinfo) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid,
|
||||
DISPID *rgdispid) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
|
||||
DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo,
|
||||
UINT *puArgErr) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
// IAccessible methods
|
||||
IFACEMETHODIMP AccessibleCaret::get_accParent(IDispatch **ppdispParent) {
|
||||
if (ppdispParent == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppdispParent = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accChildCount(long *pcountChildren) {
|
||||
if (pcountChildren == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
*pcountChildren = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accChild(VARIANT varChild, IDispatch **ppdispChild) {
|
||||
if (ppdispChild == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
*ppdispChild = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accName(VARIANT varChild, BSTR *pszName) {
|
||||
if (pszName == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
*pszName = SysAllocString(L"Edit"); // Same name as the system caret.
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accValue(VARIANT varChild, BSTR *pszValue) {
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accDescription(VARIANT varChild, BSTR *pszDescription) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accRole(VARIANT varChild, VARIANT *pvarRole) {
|
||||
if (pvarRole == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
pvarRole->vt = VT_I4;
|
||||
pvarRole->lVal = ROLE_SYSTEM_CARET;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accState(VARIANT varChild, VARIANT *pvarState) {
|
||||
if (pvarState == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
pvarState->vt = VT_I4;
|
||||
pvarState->lVal = 0; // The state without any flags, corresponds to "normal".
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accHelp(VARIANT varChild, BSTR *pszHelp) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accKeyboardShortcut(VARIANT varChild, BSTR *pszKeyboardShortcut) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accFocus(VARIANT *pvarChild) {
|
||||
if (pvarChild == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
pvarChild->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accSelection(VARIANT *pvarChildren) {
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::accSelect(long flagsSelect, VARIANT varChild) {
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight,
|
||||
VARIANT varChild) {
|
||||
if (pxLeft == nullptr || pyTop == nullptr || pcxWidth == nullptr || pcyHeight == nullptr) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&m_caretLocationLock);
|
||||
*pxLeft = m_x;
|
||||
*pyTop = m_y;
|
||||
*pcxWidth = m_width;
|
||||
*pcyHeight = m_height;
|
||||
LeaveCriticalSection(&m_caretLocationLock);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEndUpAt) {
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::accHitTest(long xLeft, long yTop, VARIANT *pvarChild) {
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::accDoDefaultAction(VARIANT varChild) {
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::put_accName(VARIANT varChild, BSTR szName) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP AccessibleCaret::put_accValue(VARIANT varChild, BSTR szValue) {
|
||||
return DISP_E_MEMBERNOTFOUND;
|
||||
}
|
||||
|
||||
void AccessibleCaret::setLocation(long x, long y, long width, long height) {
|
||||
EnterCriticalSection(&m_caretLocationLock);
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
LeaveCriticalSection(&m_caretLocationLock);
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
/*
|
||||
* Class: sun_awt_windows_AccessibleCaretLocationNotifier
|
||||
* Method: updateNativeCaretLocation
|
||||
* Signature: (JIIII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_awt_windows_AccessibleCaretLocationNotifier_updateNativeCaretLocation(
|
||||
JNIEnv *env, jclass jClass,
|
||||
jlong jHwnd, jint x, jint y, jint width, jint height) {
|
||||
HWND hwnd = reinterpret_cast<HWND>(jHwnd);
|
||||
|
||||
bool caretIsNew = false;
|
||||
AccessibleCaret* caret = AccessibleCaret::getOrCreateInstance(caretIsNew);
|
||||
if (caretIsNew) {
|
||||
// Notify with Object ID "OBJID_CARET".
|
||||
// After that, an assistive tool will send a WM_GETOBJECT message with this ID,
|
||||
// and we can return the caret instance.
|
||||
NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_CARET, CHILDID_SELF);
|
||||
NotifyWinEvent(EVENT_OBJECT_SHOW, hwnd, OBJID_CARET, CHILDID_SELF);
|
||||
}
|
||||
caret->setLocation(x, y, width, height);
|
||||
NotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, hwnd, OBJID_CARET, CHILDID_SELF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_awt_windows_AccessibleCaretLocationNotifier
|
||||
* Method: releaseNativeCaret
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_awt_windows_AccessibleCaretLocationNotifier_releaseNativeCaret(
|
||||
JNIEnv *env, jclass jClass, jlong jHwnd) {
|
||||
if (AccessibleCaret::releaseInstanceIfPresent()) {
|
||||
HWND hwnd = reinterpret_cast<HWND>(jHwnd);
|
||||
NotifyWinEvent(EVENT_OBJECT_HIDE, hwnd, OBJID_CARET, CHILDID_SELF);
|
||||
NotifyWinEvent(EVENT_OBJECT_DESTROY, hwnd, OBJID_CARET, CHILDID_SELF);
|
||||
}
|
||||
}
|
||||
} /* extern "C" */
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ACCESSIBLECARET_H
|
||||
#define ACCESSIBLECARET_H
|
||||
|
||||
#include <oleacc.h>
|
||||
#include <windows.h> // ULONG, CRITICAL_SECTION
|
||||
|
||||
class AccessibleCaret : public IAccessible {
|
||||
public:
|
||||
static AccessibleCaret* getInstanceIfPresent() noexcept;
|
||||
static AccessibleCaret* getOrCreateInstance();
|
||||
static AccessibleCaret* getOrCreateInstance(bool& instanceIsNew);
|
||||
static bool releaseInstanceIfPresent();
|
||||
|
||||
// IUnknown methods.
|
||||
IFACEMETHODIMP_(ULONG) AddRef();
|
||||
IFACEMETHODIMP_(ULONG) Release();
|
||||
IFACEMETHODIMP QueryInterface(REFIID riid, void **ppInterface);
|
||||
|
||||
// IDispatch methods.
|
||||
IFACEMETHODIMP GetTypeInfoCount(UINT *pctinfo);
|
||||
IFACEMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo);
|
||||
IFACEMETHODIMP GetIDsOfNames(REFIID riid, __in_ecount(cNames)
|
||||
OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid);
|
||||
IFACEMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid,
|
||||
WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult,
|
||||
EXCEPINFO *pexcepinfo, UINT *puArgErr);
|
||||
|
||||
// IAccessible methods
|
||||
IFACEMETHODIMP get_accParent(IDispatch **ppdispParent);
|
||||
IFACEMETHODIMP get_accChildCount(long *pcountChildren);
|
||||
IFACEMETHODIMP get_accChild(VARIANT varChild, IDispatch **ppdispChild);
|
||||
IFACEMETHODIMP get_accName(VARIANT varChild, BSTR *pszName);
|
||||
IFACEMETHODIMP get_accValue(VARIANT varChild, BSTR *pszValue);
|
||||
IFACEMETHODIMP get_accDescription(VARIANT varChild, BSTR *pszDescription);
|
||||
IFACEMETHODIMP get_accRole(VARIANT varChild, VARIANT *pvarRole);
|
||||
IFACEMETHODIMP get_accState(VARIANT varChild, VARIANT *pvarState);
|
||||
IFACEMETHODIMP get_accHelp(VARIANT varChild, BSTR *pszHelp);
|
||||
IFACEMETHODIMP get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic);
|
||||
IFACEMETHODIMP get_accKeyboardShortcut(VARIANT varChild, BSTR *pszKeyboardShortcut);
|
||||
IFACEMETHODIMP get_accFocus(VARIANT *pvarChild);
|
||||
IFACEMETHODIMP get_accSelection(VARIANT *pvarChildren);
|
||||
IFACEMETHODIMP get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction);
|
||||
IFACEMETHODIMP accSelect(long flagsSelect, VARIANT varChild);
|
||||
IFACEMETHODIMP accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild);
|
||||
IFACEMETHODIMP accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEndUpAt);
|
||||
IFACEMETHODIMP accHitTest(long xLeft, long yTop, VARIANT *pvarChild);
|
||||
IFACEMETHODIMP accDoDefaultAction(VARIANT varChild);
|
||||
IFACEMETHODIMP put_accName(VARIANT varChild, BSTR szName);
|
||||
IFACEMETHODIMP put_accValue(VARIANT varChild, BSTR szValue);
|
||||
|
||||
void setLocation(long x, long y, long width, long height);
|
||||
|
||||
private:
|
||||
AccessibleCaret();
|
||||
~AccessibleCaret();
|
||||
|
||||
ULONG m_refCount;
|
||||
int m_x, m_y, m_width, m_height;
|
||||
CRITICAL_SECTION m_caretLocationLock;
|
||||
};
|
||||
|
||||
#endif //ACCESSIBLECARET_H
|
||||
@@ -50,7 +50,6 @@
|
||||
#include "awt_Win32GraphicsDevice.h"
|
||||
#include "Hashtable.h"
|
||||
#include "ComCtl32Util.h"
|
||||
#include "AccessibleCaret.h"
|
||||
|
||||
#include <Region.h>
|
||||
|
||||
@@ -2038,32 +2037,6 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) {
|
||||
mr = mrConsume;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_GETOBJECT:
|
||||
{
|
||||
// We've got a WM_GETOBJECT message which was likely sent by an assistive tool.
|
||||
// Therefore, we can start generating native caret accessibility events.
|
||||
DWORD objId = static_cast<DWORD>(static_cast<DWORD_PTR>(lParam));
|
||||
if (objId == OBJID_CLIENT) {
|
||||
JNIEnv *env = (JNIEnv *) JNU_GetEnv(jvm, JNI_VERSION_1_2);
|
||||
if (env != nullptr) {
|
||||
jclass cls = env->FindClass("sun/awt/windows/AccessibleCaretLocationNotifier");
|
||||
if (cls != nullptr) {
|
||||
jmethodID mid = env->GetStaticMethodID(cls, "startCaretNotifier", "(J)V");
|
||||
if (mid != nullptr) {
|
||||
env->CallStaticVoidMethod(cls, mid, reinterpret_cast<jlong>(GetHWnd()));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (objId == OBJID_CARET) {
|
||||
AccessibleCaret *caret = AccessibleCaret::getInstanceIfPresent();
|
||||
if (caret != nullptr) {
|
||||
retValue = LresultFromObject(IID_IAccessible, wParam, caret);
|
||||
mr = mrConsume;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2477,7 +2450,7 @@ void AwtComponent::WmTouchHandler(const TOUCHINPUT& touchInput)
|
||||
const jint scrollModifiers = modifiers & ~java_awt_event_InputEvent_SHIFT_DOWN_MASK;
|
||||
SendMouseWheelEventFromTouch(p, scrollModifiers, sun_awt_event_TouchEvent_TOUCH_UPDATE, deltaY);
|
||||
}
|
||||
|
||||
|
||||
const jint deltaX = ScaleDownX(static_cast<int>(m_lastTouchPoint.x - p.x));
|
||||
if (deltaX != 0) {
|
||||
const jint scrollModifiers = modifiers | java_awt_event_InputEvent_SHIFT_DOWN_MASK;
|
||||
|
||||
@@ -58,7 +58,7 @@ gc/stress/gcold/TestGCOldWithShenandoah.java#aggressive JBR-8563 windows-aarch64
|
||||
|
||||
# :hotspot_runtime
|
||||
|
||||
runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java#coh_no_cds JBR-6616,JBR-9488 windows-aarch64,macosx-26.0
|
||||
runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java#coh_no_cds JBR-6616 windows-aarch64
|
||||
runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java#no_coh_cds JBR-6616 windows-aarch64
|
||||
runtime/ErrorHandling/AccessZeroNKlassHitsProtectionZone.java#no_coh_no_cds JBR-6616 windows-aarch64
|
||||
runtime/ErrorHandling/ErrorFileOverwriteTest.java JBR-8524 windows-aarch64
|
||||
@@ -89,12 +89,9 @@ vmTestbase/jit/misctests/JitBug1/JitBug1.java JBR-8801 linux-aarch64,windows-all
|
||||
vmTestbase/jit/misctests/Pi/Pi.java JBR-8854 linux-aarch64
|
||||
vmTestbase/jit/misctests/t5/t5.java JBR-8854 linux-aarch64
|
||||
vmTestbase/jit/misctests/putfield00802/putfield00802.java JBR-8801 linux-aarch64,windows-all
|
||||
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi001/Multi001.java JBR-8545 windows-aarch64,windows-x64
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi002/TestDescription.java JBR-8927,JBR-8545 windows-aarch64,windows-x64
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi003/TestDescription.java JBR-8927,JBR-8545 windows-aarch64,windows-x64
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi004/TestDescription.java JBR-8927,JBR-8545 windows-aarch64,windows-x64
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java JBR-8927,JBR-8545 windows-aarch64,windows-x64
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi002/TestDescription.java JBR-8743 windows-all
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi003/TestDescription.java JBR-8743 windows-all
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi004/TestDescription.java JBR-8743,JBR-8744 windows-all
|
||||
|
||||
#############################################################################
|
||||
|
||||
|
||||
@@ -209,11 +209,10 @@ containers/docker/TestPids.java 8356277 linux-all
|
||||
runtime/memory/ReserveMemory.java initial_run windows-aarch64
|
||||
runtime/memory/ReadFromNoaccessArea.java initial_run windows-aarch64
|
||||
|
||||
runtime/cds/appcds/ArchiveRelocationTest.java JBR-9420 macosx-26.0
|
||||
runtime/cds/appcds/CommandLineFlagCombo.java JBR-6616 windows-aarch64
|
||||
runtime/cds/appcds/complexURI/ComplexURITest.java JBR-6616 windows-aarch64
|
||||
runtime/cds/appcds/lambdaForm/DefaultClassListLFInvokers.java JBR-9079 windows-aarch64
|
||||
runtime/cds/DeterministicDump.java JBR-9077,JBR-9421 windows-aarch64,macosx-26.0
|
||||
runtime/cds/DeterministicDump.java JBR-9077 windows-aarch64
|
||||
runtime/cds/appcds/LotsOfSyntheticClasses.java JBR-8823 windows-all
|
||||
runtime/cds/appcds/methodHandles/MethodHandlesInvokersTest.java initial_run generic-all
|
||||
runtime/cds/appcds/methodHandles/MethodHandlesCastFailureTest.java initial_run generic-all
|
||||
@@ -346,10 +345,11 @@ vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java#id1 8324756 generic
|
||||
|
||||
vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all
|
||||
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi001/Multi001.java JBR-8545 windows-aarch64
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi002/TestDescription.java JBR-8927,JBR-8545 windows-all
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi003/TestDescription.java JBR-8927,JBR-8545 windows-all
|
||||
mTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java JBR-8927,JBR-8545 windows-all
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi001/Multi001.java JBR-8545, windows-all
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi002/TestDescription.java JBR-8743 windows-all
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi003/TestDescription.java JBR-8743 windows-all
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi004/TestDescription.java JBR-8743 windows-all
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java 8076494,JBR-8927 windows-x64,windows-aarch64
|
||||
|
||||
vmTestbase/nsk/monitoring/ThreadMXBean/findMonitorDeadlockedThreads/find006/TestDescription.java 8310144 macosx-aarch64
|
||||
|
||||
|
||||
@@ -1034,8 +1034,6 @@ jdk_awt_wayland = \
|
||||
-java/awt/MultipleGradientPaint \
|
||||
-java/awt/Multiscreen/MouseEventTest/MouseEventTest.java \
|
||||
-java/awt/Multiscreen/MultiScreenLocationTest/MultiScreenLocationTest.java \
|
||||
-java/awt/Multiscreen/MultiScreenCheckScreenIDTest.java \
|
||||
-java/awt/Multiscreen/UpdateGCTest/UpdateGCTest.java \
|
||||
-java/awt/Paint/bug8024864.java \
|
||||
-java/awt/Paint/ButtonRepaint.java \
|
||||
-java/awt/Paint/CheckboxRepaint.java \
|
||||
@@ -1089,7 +1087,6 @@ jdk_swing_wayland= \
|
||||
-javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java \
|
||||
-javax/swing/dnd/7171812/bug7171812.java \
|
||||
-javax/swing/event/FocusEventCauseTest.java \
|
||||
-javax/swing/GraphicsConfigNotifier/TestMultiScreenGConfigNotify.java \
|
||||
-javax/swing/JButton/4368790/bug4368790.java \
|
||||
-javax/swing/JButton/8151303/PressedIconTest.java \
|
||||
-javax/swing/JButton/bug4234034.java \
|
||||
|
||||
@@ -35,7 +35,6 @@ public class DetectingOSThemeTest {
|
||||
private static final String LIGHT_THEME_NAME = "Light";
|
||||
private static final String DARK_THEME_NAME = "Dark";
|
||||
private static final String UNDEFINED_THEME_NAME = "Undefined";
|
||||
private static boolean isKDE = false;
|
||||
|
||||
private static String currentTheme() {
|
||||
Boolean val = (Boolean) Toolkit.getDefaultToolkit().getDesktopProperty("awt.os.theme.isDark");
|
||||
@@ -45,14 +44,8 @@ public class DetectingOSThemeTest {
|
||||
return (val) ? DARK_THEME_NAME : LIGHT_THEME_NAME;
|
||||
}
|
||||
|
||||
private static void setOsDarkTheme(String val) throws Exception {
|
||||
if (isKDE) {
|
||||
if (val.equals(DARK_THEME_NAME)) {
|
||||
Runtime.getRuntime().exec("plasma-apply-colorscheme BreezeDark");
|
||||
} else {
|
||||
Runtime.getRuntime().exec("plasma-apply-colorscheme BreezeLight");
|
||||
}
|
||||
} else {
|
||||
private static void setOsDarkTheme(String val) {
|
||||
try {
|
||||
if (val.equals(DARK_THEME_NAME)) {
|
||||
Runtime.getRuntime().exec("gsettings set org.gnome.desktop.interface gtk-theme 'Adwaita-dark'");
|
||||
Runtime.getRuntime().exec("gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark'");
|
||||
@@ -60,13 +53,14 @@ public class DetectingOSThemeTest {
|
||||
Runtime.getRuntime().exec("gsettings set org.gnome.desktop.interface gtk-theme 'Adwaita'");
|
||||
Runtime.getRuntime().exec("gsettings set org.gnome.desktop.interface color-scheme 'default'");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String currentTheme = null;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
isKDE = "KDE".equals(System.getenv("XDG_CURRENT_DESKTOP"));
|
||||
currentTheme = currentTheme();
|
||||
if (currentTheme.equals(UNDEFINED_THEME_NAME)) {
|
||||
throw new RuntimeException("Test Failed! Cannot detect current OS theme");
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024-2025 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import jtreg.SkippedException;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.vulkan.VKEnv;
|
||||
import sun.java2d.vulkan.VKGraphicsConfig;
|
||||
import sun.java2d.vulkan.VKRenderQueue;
|
||||
import sun.java2d.vulkan.VKSurfaceData;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @requires os.family == "linux"
|
||||
* @library /test/lib
|
||||
* @summary Verifies that disposal of blit destination image doesn't crash the process.
|
||||
* @modules java.desktop/sun.java2d.vulkan:+open java.desktop/sun.java2d:+open java.desktop/sun.awt.image:+open
|
||||
* @run main/othervm -Djava.awt.headless=true -Dsun.java2d.vulkan=True -Dsun.java2d.vulkan.accelsd=true -Dsun.java2d.vulkan.leOptimizations=true VulkanDisposeBlitDstTest
|
||||
*/
|
||||
|
||||
|
||||
public class VulkanDisposeBlitDstTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (!VKEnv.isVulkanEnabled()) {
|
||||
throw new Error("Vulkan not enabled");
|
||||
}
|
||||
if (!VKEnv.isSurfaceDataAccelerated()) {
|
||||
throw new Error("Accelerated surface data not enabled");
|
||||
}
|
||||
|
||||
VKGraphicsConfig gc = VKEnv.getDevices().findFirst().get().getOffscreenGraphicsConfigs().findFirst().get();
|
||||
VolatileImage a = gc.createCompatibleVolatileImage(100, 100, VolatileImage.TRANSLUCENT, VKSurfaceData.RT_TEXTURE);
|
||||
VolatileImage b = gc.createCompatibleVolatileImage(100, 100, VolatileImage.TRANSLUCENT, VKSurfaceData.RT_TEXTURE);
|
||||
|
||||
// Blit a onto b
|
||||
Graphics2D g = (Graphics2D) b.getGraphics();
|
||||
g.drawImage(a, 0, 0, null);
|
||||
g.dispose();
|
||||
|
||||
// Dispose b
|
||||
WeakReference<SurfaceData> ref = new WeakReference<>(SurfaceManager.getManager(b).getPrimarySurfaceData());
|
||||
MemorySegment vksd = MemorySegment.ofAddress(ref.get().getNativeOps()).reinterpret(160); // sizeof(VKSDOps)
|
||||
b = null;
|
||||
final int MAX_ITERATIONS = 1000;
|
||||
for (int i = 0; i < MAX_ITERATIONS && ref.get() != null; i++) System.gc();
|
||||
if (ref.get() != null) throw new SkippedException("SurfaceData was not collected after " + MAX_ITERATIONS + " iterations");
|
||||
// Mess b's native data
|
||||
Thread.sleep(100);
|
||||
vksd.fill((byte) 0xec);
|
||||
|
||||
// Mutate a
|
||||
g = (Graphics2D) a.getGraphics();
|
||||
g.fillRect(10, 10, 10, 10);
|
||||
g.dispose();
|
||||
VKRenderQueue.getInstance().flushNow();
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024-2025 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import jtreg.SkippedException;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.vulkan.VKEnv;
|
||||
import sun.java2d.vulkan.VKGraphicsConfig;
|
||||
import sun.java2d.vulkan.VKRenderQueue;
|
||||
import sun.java2d.vulkan.VKSurfaceData;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @requires os.family == "linux"
|
||||
* @library /test/lib
|
||||
* @summary Verifies that disposal of blit source image doesn't crash the process.
|
||||
* @modules java.desktop/sun.java2d.vulkan:+open java.desktop/sun.java2d:+open java.desktop/sun.awt.image:+open
|
||||
* @run main/othervm -Djava.awt.headless=true -Dsun.java2d.vulkan=True -Dsun.java2d.vulkan.accelsd=true -Dsun.java2d.vulkan.leOptimizations=true VulkanDisposeBlitSrcTest
|
||||
*/
|
||||
|
||||
|
||||
public class VulkanDisposeBlitSrcTest {
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (!VKEnv.isVulkanEnabled()) {
|
||||
throw new Error("Vulkan not enabled");
|
||||
}
|
||||
if (!VKEnv.isSurfaceDataAccelerated()) {
|
||||
throw new Error("Accelerated surface data not enabled");
|
||||
}
|
||||
|
||||
VKGraphicsConfig gc = VKEnv.getDevices().findFirst().get().getOffscreenGraphicsConfigs().findFirst().get();
|
||||
VolatileImage a = gc.createCompatibleVolatileImage(100, 100, VolatileImage.TRANSLUCENT, VKSurfaceData.RT_TEXTURE);
|
||||
VolatileImage b = gc.createCompatibleVolatileImage(100, 100, VolatileImage.TRANSLUCENT, VKSurfaceData.RT_TEXTURE);
|
||||
|
||||
// Blit a onto b
|
||||
Graphics2D g = (Graphics2D) b.getGraphics();
|
||||
g.drawImage(a, 0, 0, null);
|
||||
g.dispose();
|
||||
|
||||
// Dispose a
|
||||
WeakReference<SurfaceData> ref = new WeakReference<>(SurfaceManager.getManager(a).getPrimarySurfaceData());
|
||||
MemorySegment vksd = MemorySegment.ofAddress(ref.get().getNativeOps()).reinterpret(160); // sizeof(VKSDOps)
|
||||
a = null;
|
||||
final int MAX_ITERATIONS = 1000;
|
||||
for (int i = 0; i < MAX_ITERATIONS && ref.get() != null; i++) System.gc();
|
||||
if (ref.get() != null) throw new SkippedException("SurfaceData was not collected after " + MAX_ITERATIONS + " iterations");
|
||||
// Mess a's native data
|
||||
Thread.sleep(100);
|
||||
vksd.fill((byte) 0xec);
|
||||
|
||||
// Flush b
|
||||
b.getSnapshot();
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @requires os.family == "linux"
|
||||
* @summary Verifies that robot correctly pick color
|
||||
* @run main/othervm -Dawt.toolkit.name=WLToolkit -Dsun.java2d.vulkan=True -Dsun.java2d.vulkan.accelsd=true ClipRenderTest
|
||||
* @run main/othervm -Dawt.toolkit.name=WLToolkit -Dsun.java2d.vulkan=True -Dsun.java2d.vulkan.accelsd=false ClipRenderTest
|
||||
* @run main/othervm -Dawt.toolkit.name=WLToolkit -Dsun.java2d.vulkan=False ClipRenderTest
|
||||
*/
|
||||
|
||||
|
||||
public class ClipRenderTest {
|
||||
final static int W = 600;
|
||||
final static int H = 600;
|
||||
|
||||
final static CountDownLatch latchShownFrame = new CountDownLatch(1);
|
||||
static volatile boolean failed = false;
|
||||
|
||||
static boolean compareColors(Color c1, Color c2, double tolerance) {
|
||||
return Math.abs(c1.getRed() - c2.getRed()) < tolerance &&
|
||||
Math.abs(c1.getGreen() - c2.getGreen()) < tolerance &&
|
||||
Math.abs(c1.getBlue() - c2.getBlue()) < tolerance;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException, AWTException {
|
||||
if (GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance()) {
|
||||
System.out.println("No WLToolkit, skipping test");
|
||||
return;
|
||||
}
|
||||
|
||||
final Robot robot = new Robot();
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JFrame frame = new JFrame("Robot Test");
|
||||
frame.setSize(W, H);
|
||||
frame.add(new JPanel(){
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setClip(0, 0, W, H);
|
||||
g2d.setColor(Color.BLUE);
|
||||
g2d.setClip(new Ellipse2D.Double(W/3, H/3, W/3, H/3));
|
||||
g2d.fillRect(W/3, H/3, W/3, H/3);
|
||||
g2d.setClip(0, 0, W/3, H/3);
|
||||
g2d.setColor(Color.RED);
|
||||
g2d.fillRect(0, 0, W/3, H/3);
|
||||
}
|
||||
});
|
||||
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowActivated(WindowEvent e) {
|
||||
var loc = frame.getLocationOnScreen();
|
||||
int x = loc.x + frame.getInsets().bottom + W/6;
|
||||
int y = loc.y + frame.getInsets().left + H/6;
|
||||
Color c = robot.getPixelColor(x, y);
|
||||
if (!compareColors(c, Color.RED, 10)) {
|
||||
System.out.println("Unexpected color: " + c + " at (" + x + ", " + y + ")");
|
||||
failed = true;
|
||||
}
|
||||
|
||||
x += W / 3;
|
||||
y += H / 3;
|
||||
|
||||
c = robot.getPixelColor(x, y);
|
||||
if (!compareColors(c, Color.BLUE, 10)) {
|
||||
System.out.println("Unexpected color: " + c + " at (" + x + ", " + y + ")");
|
||||
failed = true;
|
||||
}
|
||||
|
||||
latchShownFrame.countDown();
|
||||
}
|
||||
});
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setVisible(true);
|
||||
});
|
||||
|
||||
latchShownFrame.await();
|
||||
if (failed) throw new RuntimeException("Test failed");
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreeCellRenderer;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary regression test for JBR-9365 Unnecessary operations on tree node update
|
||||
*/
|
||||
|
||||
public class NodeUpdatePerformance {
|
||||
private static int countBefore;
|
||||
private static int countAfter;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
DefaultMutableTreeNode child = new DefaultMutableTreeNode();
|
||||
root.add(child);
|
||||
DefaultTreeModel model = new DefaultTreeModel(root);
|
||||
JTree tree = new JTree(model);
|
||||
tree.setRowHeight(10);
|
||||
tree.setLargeModel(true);
|
||||
OurRenderer renderer = new OurRenderer();
|
||||
tree.setCellRenderer(renderer);
|
||||
|
||||
countBefore = renderer.invocationCount;
|
||||
model.valueForPathChanged(new TreePath(child.getPath()), "newValue");
|
||||
countAfter = renderer.invocationCount;
|
||||
});
|
||||
if (countBefore != countAfter) {
|
||||
throw new RuntimeException("Unexpected renderer access: countBefore=" + countBefore + ", countAfter=" + countAfter);
|
||||
}
|
||||
}
|
||||
|
||||
private static class OurRenderer extends JLabel implements TreeCellRenderer {
|
||||
private int invocationCount;
|
||||
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
invocationCount++;
|
||||
setText(Objects.toString(value));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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
|
||||
* @summary
|
||||
* @requires os.family == "linux"
|
||||
* @key headful
|
||||
* @library /test/lib
|
||||
* @run main/othervm -Dsun.awt.wl.WindowDecorationStyle=builtin CloseOnlyDialogShownTest
|
||||
*/
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Robot;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class CloseOnlyDialogShownTest {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
AtomicReference<Throwable> edtFailure = new AtomicReference<>();
|
||||
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
edtFailure.compareAndSet(null, e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
AtomicReference<JDialog> holder = new AtomicReference<>();
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
JDialog dialog = new JDialog((java.awt.Frame) null, "Close-only window", false);
|
||||
holder.set(dialog);
|
||||
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
dialog.add(new JLabel("This dialog should show with only a close button."));
|
||||
dialog.setMinimumSize(new Dimension(200, 120));
|
||||
dialog.setVisible(true);
|
||||
});
|
||||
|
||||
Robot robot = new Robot();
|
||||
robot.waitForIdle();
|
||||
robot.delay(500);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
JDialog dialog = holder.get();
|
||||
if (dialog != null) {
|
||||
dialog.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
if (edtFailure.get() != null) {
|
||||
throw edtFailure.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Verifies that a small window does not generate GTK warnings in Wayland
|
||||
* @requires os.family == "linux"
|
||||
* @key headful
|
||||
* @library /test/lib
|
||||
* @run main WLFrameMinSize
|
||||
*/
|
||||
public class WLFrameMinSize {
|
||||
private static JFrame frame;
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length > 0 && args[0].equals("--test")) {
|
||||
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
frame = new JFrame("WLFrameMinSize");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.getContentPane().add(new JLabel("a"));
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
});
|
||||
Thread.sleep(2000);
|
||||
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
frame.dispose();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(
|
||||
WLFrameMinSize.class.getName(),
|
||||
"--test");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldNotContain("Gtk-WARNING");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Verifies popups and tooltips are disposed of when switching to a different window
|
||||
* @requires os.family == "linux"
|
||||
* @key headful
|
||||
* @run main/manual WLUngrab
|
||||
*/
|
||||
public class WLUngrab {
|
||||
static final CompletableFuture<RuntimeException> swingError = new CompletableFuture<>();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SwingUtilities.invokeAndWait(WLUngrab::showUI);
|
||||
swingError.get();
|
||||
}
|
||||
|
||||
private static void showUI() {
|
||||
JFrame frame = new JFrame("Ungrab test");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
JMenuBar menuBar = new JMenuBar();
|
||||
JMenu menu1 = new JMenu("Test menu");
|
||||
menu1.add(new JMenuItem("item 1"));
|
||||
menu1.add(new JMenuItem("item 2"));
|
||||
menu1.addSeparator();
|
||||
JMenu submenu = new JMenu("submenu...");
|
||||
submenu.add(new JMenuItem("subitem1"));
|
||||
submenu.add(new JMenuItem("subitem2"));
|
||||
submenu.add(new JMenuItem("subitem3"));
|
||||
menu1.add(submenu);
|
||||
menuBar.add(menu1);
|
||||
|
||||
JMenu menu2 = new JMenu("Another");
|
||||
menu2.add(new JMenuItem("test"));
|
||||
menuBar.add(menu2);
|
||||
|
||||
frame.setJMenuBar(menuBar);
|
||||
|
||||
JLabel label = new JLabel("Right-click here for a popup-menu.");
|
||||
|
||||
final JPopupMenu popup = new JPopupMenu();
|
||||
popup.add(new JMenuItem("popup menu item"));
|
||||
popup.add(new JMenuItem("popup menu item 2"));
|
||||
popup.add(new JMenuItem("popup menu item 3"));
|
||||
label.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (e.isPopupTrigger()) {
|
||||
popup.show(e.getComponent(),
|
||||
e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
});
|
||||
JPanel content = new JPanel();
|
||||
var layout = new GridLayout(3, 2, 10, 10);
|
||||
content.setLayout(layout);
|
||||
content.add(label);
|
||||
JButton button = new JButton("Hover here for a tooltip");
|
||||
button.setToolTipText("<html><h1>TOOLTIP</h2><p>tooltip text</p></html>");
|
||||
content.add(button);
|
||||
JButton passButton = new JButton("Pass");
|
||||
passButton.addActionListener(e -> {swingError.complete(null);});
|
||||
JButton failButton = new JButton("Fail");
|
||||
failButton.addActionListener(e -> {swingError.completeExceptionally(new RuntimeException("The tester has pressed FAILED"));});
|
||||
content.add(failButton);
|
||||
content.add(passButton);
|
||||
content.add(new JLabel("<html><h1>INSTRUCTIONS</h1>" +
|
||||
"<p>Make a tooltip, popup, or pulldown menu appear.</p>" +
|
||||
"<p>Switch to a different application window.</p>" +
|
||||
"<p>Switch back to this window.</p>" +
|
||||
"<p>Press Pass iff the tooltip/popup/menu was closed upon switching back.</p>" +
|
||||
"<p>Otherwise press Fail.</p></html>"));
|
||||
frame.setContentPane(content);
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
71
test/jdk/jb/tools/jstack/JStackHangTest.java
Normal file
71
test/jdk/jb/tools/jstack/JStackHangTest.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8354460
|
||||
* @summary <code>JStackHangTest</code> verifies the streaming output of the attach API. It launches
|
||||
* <code>JStackLauncher</code> in a child VM and ensures <code>jstack</code> does not hang.
|
||||
* @library /test/lib
|
||||
* @compile JStackLauncher.java
|
||||
* @run main/othervm JStackHangTest
|
||||
*/
|
||||
|
||||
public class JStackHangTest {
|
||||
|
||||
static final int JSTACK_WAIT_TIME = JStackLauncher.JSTACK_WAIT_TIME * 2;
|
||||
|
||||
public static final int CODE_NOT_RETURNED = 100;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(JStackLauncher.class.getName());
|
||||
|
||||
Process process = ProcessTools.startProcess("Child", pb);
|
||||
OutputAnalyzer outputAnalyzer = new OutputAnalyzer(process);
|
||||
|
||||
int returnCode;
|
||||
|
||||
if (!process.waitFor(JSTACK_WAIT_TIME, TimeUnit.MILLISECONDS)) {
|
||||
System.out.println("jstack did not complete in " + JSTACK_WAIT_TIME + " ms.");
|
||||
|
||||
System.out.println("killing all the jstack processes");
|
||||
ProcessTools.executeCommand("killall", "-9", "jstack");
|
||||
returnCode = CODE_NOT_RETURNED;
|
||||
|
||||
} else {
|
||||
returnCode = outputAnalyzer.getExitValue();
|
||||
System.out.println("returnCode = " + returnCode);
|
||||
}
|
||||
|
||||
if (returnCode == CODE_NOT_RETURNED)
|
||||
throw new RuntimeException("jstack: failed to start or hanged");
|
||||
else
|
||||
System.out.println("jstack: completed successfully");
|
||||
}
|
||||
}
|
||||
118
test/jdk/jb/tools/jstack/JStackLauncher.java
Normal file
118
test/jdk/jb/tools/jstack/JStackLauncher.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2025 JetBrains s.r.o.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* <code>JStackLauncher</code> is used to launch <code>jstack</code> in the test of streaming output for the attach API
|
||||
*
|
||||
*/
|
||||
|
||||
public class JStackLauncher {
|
||||
|
||||
public static final String JAVA_HOME = System.getProperty("java.home");
|
||||
public static final String JAVA_BIN = JAVA_HOME + File.separator + "bin";
|
||||
public static final String JSTACK_PATH = JAVA_BIN + File.separator + "jstack";
|
||||
|
||||
static final int JSTACK_WAIT_TIME = 5000;
|
||||
|
||||
static final int THREAD_COUNT = 10;
|
||||
static final int STACK_DEPTH = 100;
|
||||
|
||||
static Process process;
|
||||
static CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
// Create threads with deep stacks
|
||||
List<Thread> threads = createManyThreadsWithDeepStacks();
|
||||
|
||||
// Run jstack against current process
|
||||
System.out.println("Starting jstack...");
|
||||
try {
|
||||
process = new ProcessBuilder(JSTACK_PATH, String.valueOf(ProcessHandle.current().pid())).start();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
System.out.println("Reading jstack output...");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
Stream<String> output = reader.lines();
|
||||
output.forEach(System.out::println);
|
||||
|
||||
if (!process.waitFor(JSTACK_WAIT_TIME, TimeUnit.MILLISECONDS)) {
|
||||
process.destroyForcibly();
|
||||
throw new RuntimeException("jstack failed to complete in " + JSTACK_WAIT_TIME + " ms.");
|
||||
}
|
||||
|
||||
threads.forEach(Thread::interrupt);
|
||||
}
|
||||
|
||||
public static List<Thread> createManyThreadsWithDeepStacks() throws InterruptedException {
|
||||
List<Thread> threads = new ArrayList<>();
|
||||
|
||||
for (int threadIndex = 0; threadIndex < THREAD_COUNT; threadIndex++) {
|
||||
System.out.println("Creating thread " + threadIndex);
|
||||
|
||||
Thread t = new DeepStackThread(threadIndex);
|
||||
|
||||
t.start();
|
||||
threads.add(t);
|
||||
}
|
||||
latch.await();
|
||||
|
||||
return threads;
|
||||
}
|
||||
|
||||
static class DeepStackThread extends Thread {
|
||||
DeepStackThread(int index) {
|
||||
super.setName("DeepStackThread-" + index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void run() {
|
||||
try {
|
||||
createDeepStack(STACK_DEPTH);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
System.out.println("Thread " + getName() + " exiting");
|
||||
}
|
||||
|
||||
void createDeepStack(int depth) throws InterruptedException {
|
||||
if (depth > 0) {
|
||||
createDeepStack(depth - 1);
|
||||
} else {
|
||||
latch.countDown();
|
||||
Thread.sleep(Long.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ java/awt/Choice/ChoiceHandleMouseEvent_2.java JBR-7174 windows-all
|
||||
java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java JBR-64 windows-all
|
||||
java/awt/Choice/SelectItem/SelectCurrentItemTest.java JBR-8333 windows-all
|
||||
java/awt/Choice/SelectItem/SelectNewItemTest.java JBR-8387 windows-x64
|
||||
java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.java JBR-9427 windows-x64
|
||||
java/awt/Graphics/XORPaint.java#id0 JBR-7499 windows-x64
|
||||
java/awt/Graphics2D/TextPerf.java JBR-8541 windows-x64
|
||||
java/awt/grab/SystemMenuTest.java JBR-8944 windows-x64
|
||||
@@ -37,14 +36,12 @@ java/awt/Window/GrabSequence/GrabSequence.java 6848409,JBR-8584 macosx-all,linux
|
||||
javax/accessibility/JFileChooserAccessibleDescriptionTest.java JBR-5397,JBR-7379 macosx-all,windows-x64
|
||||
javax/accessibility/SlowPanelIteration/SlowPanelIteration.java JBR-870,JBR-5397 windows-x64,linux-x64,macosx-all
|
||||
javax/swing/event/FocusEventCauseTest.java JBR-7381 windows-x64
|
||||
javax/swing/JButton/4796987/bug4796987.java JBR-9345 windows-x64
|
||||
javax/swing/JButton/8151303/PressedIconTest.java JBR-5210,JBR-5510,JBR-5397 windows-all,linux-all,macosx-all
|
||||
javax/swing/JComboBox/4743225/bug4743225.java JBR-5210,JBR-5397 windows-all,macosx-all
|
||||
javax/swing/JComboBox/6559152/bug6559152.java JBR-5397,JBR-7382 macosx-all,windows-x64
|
||||
javax/swing/JComboBox/8041909/ActionListenerExceptionTest.java JBR-5210 windows-all
|
||||
javax/swing/JComboBox/bug4996503.java JBR-7412 windows-x64
|
||||
javax/swing/JComboBox/EditableComboBoxPopupPos.java JBR-7383 windows-x64
|
||||
javax/swing/JFileChooser/4150029/bug4150029.java JBR-9419 windows-x64
|
||||
javax/swing/JFileChooser/4847375/bug4847375.java JBR-8855 windows-x64
|
||||
javax/swing/JFileChooser/4966171/bug4966171.java JBR-8855 windows-x64
|
||||
javax/swing/JFileChooser/FileChooserListenerLeak.java JBR-8855 windows-x64
|
||||
@@ -60,11 +57,9 @@ javax/swing/text/StyledEditorKit/4506788/bug4506788.java JBR-7386 windows-x64
|
||||
|
||||
jb/java/awt/CustomTitleBar/DialogNativeControlsTest.java JBR-9083 windows-x64
|
||||
jb/java/awt/Desktop/AboutHandlerTest.java nobug macosx-all,linux-all,windows-all
|
||||
jb/java/awt/Focus/ChainOfPopupsFocusTest.java JBR-8407 windows-x64
|
||||
jb/java/awt/Focus/FrameAfterPopup.java JBR-9161 windows-x64
|
||||
jb/java/awt/Focus/MaximizedCustomDecorationsTest.java JBR-9346 windows-x64
|
||||
jb/java/awt/Focus/ModalDialogFromMenuTest.java JBR-9426 windows-x64
|
||||
jb/java/awt/Focus/NewFrameAfterDialogTest.java JBR-7387 windows-x64
|
||||
jb/java/awt/Focus/ChainOfPopupsFocusTest.java JBR-8407 windows-x64
|
||||
|
||||
# VoiceOver on MacOS
|
||||
java/awt/event/KeyEvent/ExtendedModifiersTest/ExtendedModifiersTest.java JBR-5397 macosx-all
|
||||
|
||||
@@ -13,6 +13,7 @@ javax/swing/JComponent/7154030/bug7154030.java JBR-7713 macosx-aarch64
|
||||
javax/swing/JDialog/Transparency/TransparencyTest.java JBR-7554 macosx-aarch64
|
||||
javax/swing/JSplitPane/4820080/JSplitPaneDragColorTest.java JBR-7247 macosx-all
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java JBR-7404 macosx-all
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java JBR-8327 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6
|
||||
javax/swing/plaf/aqua/CustomComboBoxFocusTest.java JBR-5190 macosx-all
|
||||
javax/swing/SwingGraphics/TranslateTest.java JBR-7510 macosx-aarch64
|
||||
|
||||
|
||||
@@ -112,21 +112,15 @@
|
||||
############################################################################
|
||||
|
||||
java/awt/dnd/RemoveDropTargetCrashTest/RemoveDropTargetCrashTest.java JBR-8960 windows-x64
|
||||
java/awt/Focus/ModalDialogInFocusEventTest.java JBR-7818 linux-6.14.0-1010-aws,linux-6.14.0-1012-aws,linux-6.14.0-1014-aws
|
||||
java/awt/Focus/ModalDialogInFocusEventTest.java JBR-7818 linux-6.14.0-1010-aws
|
||||
java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java JBR-8542 windows-all timeout
|
||||
java/awt/Graphics2D/TextPerf.java JBR-8541 linux-all,windows-all
|
||||
java/awt/GridBagLayout/ComponentShortage.java 8355280,JBR-9347 windows-all,linux-all,macosx-x64
|
||||
java/awt/KeyboardFocusmanager/TypeAhead/EnqueueWithDialogTest/EnqueueWithDialogTest.java JBR-7077 linux-all,windows-all
|
||||
java/awt/MenuItem/EnableTest.java JBR-8543 windows-all timeout
|
||||
java/awt/Modal/MultipleDialogs/MixOfModalAndNonModalDialogs.java JBR-9317 linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Robot/NonEmptyErrorStream.java 8340330,JBR-5510,JBR-6275,JBR-8299,JBR-9259 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1,macosx-all,linux-5.18.2-arch1-1,linux-aarch64,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64
|
||||
java/awt/Robot/NonEmptyErrorStream.java JBR-6275 macosx-all
|
||||
|
||||
javax/swing/border/TestTitledBorderLeak.java JBR-9272 macosx-14.8
|
||||
javax/swing/JButton/TestMnemonicAction.java JBR-6508 windows-all,linux-all,macosx-all
|
||||
javax/swing/JComboBox/8072767/bug8072767.java JBR-5540 windows-all,macosx-all
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java JBR-7404 macosx-all
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentGradient.java JBR-9446 macosx-all
|
||||
javax/swing/plaf/synth/7158712/bug7158712.java 8322653,JBR-9061 macosx-all,linux-6.8.0-1033-aws,linux-6.8.0-1036-aws,linux-6.8.0-1039-aws
|
||||
javax/swing/plaf/synth/7158712/bug7158712.java 8322653,JBR-9061 macosx-all,linux-6.8.0-1033-aws
|
||||
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952,8340330,JBR-6274 windows-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-all
|
||||
|
||||
jb/build/ResolveSymbolsTest/ResolveSymbolsRealEnv.java JBR-8544 linux-all
|
||||
|
||||
@@ -27,7 +27,7 @@ java/awt/Robot/CheckCommonColors/CheckCommonColors.java 8253184,JBR-5510,JBR-544
|
||||
java/awt/Robot/HiDPIScreenCapture/ScreenCaptureTest.java 8253184,JBR-5442 windows-all,linux-all
|
||||
java/awt/Robot/InfiniteLoopException.java 8342638,JBR-8830 windows-x64,windows-all,linux-all
|
||||
java/awt/Robot/MouseLocationOnScreen/MouseLocationOnScreen.java JBR-5390 macosx-all,linux-all
|
||||
java/awt/Robot/NonEmptyErrorStream.java JBR-5442,8340330,JBR-5510,JBR-8299 linux-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1,linux-5.18.2-arch1-1,linux-aarch64
|
||||
java/awt/Robot/NonEmptyErrorStream.java JBR-5442,8340330,JBR-5510,JBR-8299 linux-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,linux-5.18.2-arch1-1,linux-aarch64
|
||||
java/awt/Robot/RobotMoveMultiscreen.java JBR-5442 linux-all
|
||||
java/awt/Toolkit/AWTEventListenerProxyTest/AWTEventListenerProxyTest.java JBR-6065 windows-all
|
||||
java/awt/Window/SlowMotion/SlowMotion.java JBR-5442 linux-all
|
||||
@@ -108,6 +108,7 @@ java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java 8198665,8253184,JBR-551
|
||||
java/awt/Paint/PaintNativeOnUpdate.java 8253184,JBR-5510 windows-all,linux-all
|
||||
java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java 8253184,NOBUG windows-all,linux-all
|
||||
java/awt/Robot/HiDPIScreenCapture/ScreenCaptureGtkTest.java NOBUG linux-all
|
||||
java/awt/Window/8159168/SetShapeTest.java 8253184,JBR-5510 windows-all,linux-all
|
||||
java/awt/Window/BackgroundIsNotUpdated/BackgroundIsNotUpdated.java JBR-5510 linux-all
|
||||
java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java JBR-5510 linux-all
|
||||
java/awt/Window/MultiWindowApp/MultiWindowAppTest.java 8253184,JBR-5510 windows-all,linux-all
|
||||
|
||||
@@ -24,7 +24,6 @@ java/awt/font/TextLayout/VisibleAdvance.java JBR-8766 linux-all
|
||||
java/awt/FontMetrics/ExtremeFontSizeTest.java JBR-7823 linux-all
|
||||
java/awt/Graphics2D/DrawString/IgnoredWhitespaceTest.java JBR-9086 linux-all
|
||||
java/awt/Graphics2D/DrawString/RotTransText.java JBR-8767 linux-all
|
||||
java/awt/Graphics/NativeWin32Clear.java JBR-8689 linux-x64
|
||||
java/awt/Graphics/XORPaint.java#id2 JBR-7373 linux-x64
|
||||
java/awt/image/DrawImage/SimpleManagedImage.java JBR-8769 linux-all
|
||||
java/awt/image/DrawImage/SimpleUnmanagedImage.java JBR-8769 linux-all
|
||||
|
||||
@@ -123,12 +123,10 @@ java/awt/event/MouseEvent/MouseClickTest/MouseClickTest.java 8168389 windows-all
|
||||
java/awt/event/KeyEvent/CorrectTime/CorrectTime.java JBR-6665 linux-5.15.0-1083-aws,linux-5.15.0-1084-aws,windows-all
|
||||
java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java 8224055,JBR-5906 macosx-all,linux-all
|
||||
java/awt/event/MouseEvent/MouseButtonsAndKeyMasksTest/MouseButtonsAndKeyMasksTest.java JBR-6578 windows-all,linux-all
|
||||
java/awt/event/SequencedEvent/MultipleContextsFunctionalTest.java 8305061 macosx-x64
|
||||
java/awt/event/StressTest/MouseAndKeyEventStressTest.java JBR-6479 generic-all
|
||||
java/awt/FileDialog/8003399/bug8003399.java JBR-6930 windows-all
|
||||
java/awt/FlowLayout/PreferredLayoutSize.java JBR-6349 linux-all
|
||||
java/awt/Focus/EmptyWindowKeyTest.java JBR-7913 windows-all
|
||||
java/awt/Focus/FocusKeepTest.java JBR-9487 linux-6.8.0-1040-aws
|
||||
java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java 8081489 generic-all
|
||||
java/awt/Focus/FocusSubRequestTest/FocusSubRequestTest.java JBR-5178 windows-all
|
||||
java/awt/Focus/FocusTransitionTest/FocusTransitionTest.java JBR-5809 linux-all
|
||||
@@ -136,7 +134,6 @@ java/awt/Focus/FocusTraversalPolicy/ButtonGroupLayoutTraversal/ButtonGroupLayout
|
||||
java/awt/Focus/FrameMinimizeTest/FrameMinimizeTest.java 8016266 linux-all
|
||||
java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java 6849364 generic-all
|
||||
java/awt/Focus/InactiveFocusRace.java 8023263,JBR-8586 linux-all,windows-x64
|
||||
java/awt/Focus/InputVerifierTest3/InputVerifierTest3.java JBR-7311 linux-6.8.0-1036-aws,linux-6.8.0-1039-aws
|
||||
java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java 6848406 generic-all
|
||||
java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java 6848407 generic-all
|
||||
java/awt/Focus/LabelScrollBarFocus.java JBR-8027 linux-all
|
||||
@@ -150,7 +147,7 @@ java/awt/Frame/DisposeTest.java JBR-7937,JBR-7938,JBR-8718 macosx-aarch64,window
|
||||
java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all
|
||||
java/awt/Frame/MaximizeUndecoratedTest.java JBR-8064 linux-all
|
||||
java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java JBR-7509 macosx-all
|
||||
java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java 8340374,JBR-7947 macosx-all
|
||||
java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java JBR-7947 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6
|
||||
java/awt/Frame/MaximizedToOppositeScreen/MaximizedToOppositeScreenBig.java JBR-5303 windows-all
|
||||
java/awt/Frame/RestoreToOppositeScreen/RestoreToOppositeScreen.java 8286840 linux-all
|
||||
java/awt/Frame/InitialIconifiedTest.java 7144049,8203920 macosx-all,linux-all
|
||||
@@ -207,7 +204,7 @@ java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java JBR-5210,JBR-6126
|
||||
java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150,JBR-4880,8253184,JBR-5510 macosx-all,windows-all,linux-5.18.2-arch1-1
|
||||
java/awt/grab/GrabOnUnfocusableToplevel/GrabOnUnfocusableToplevel.java 8169109,JBR-4880 linux-all,windows-all
|
||||
java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java 8168646 generic-all
|
||||
java/awt/MenuShortcut/FunctionKeyShortcut.java JBR-9207 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/MenuShortcut/FunctionKeyShortcut.java JBR-9207 linux-6.15.8-100.fc41.x86_64
|
||||
java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java 8049405,8253184 generic-all
|
||||
java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java 8049405,8253184 generic-all
|
||||
java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java 8294264 windows-x64
|
||||
@@ -331,7 +328,7 @@ java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java 8150540,JBR-3107 wind
|
||||
java/awt/TrayIcon/TrayIconPopup/TrayIconPopupClickTest.java 8150540,JBR-3107 windows-all,macosx-all,linux-all
|
||||
java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java 8150540,JBR-3107 windows-all,linux-all
|
||||
java/awt/Window/8027025/Test8027025.java 8253184 windows-all
|
||||
java/awt/Window/8159168/SetShapeTest.java 8253184 windows-all
|
||||
java/awt/Window/8159168/SetShapeTest.java 8253184,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
java/awt/Window/HandleWindowDestroyTest/HandleWindowDestroyTest.java JBR-6540 macosx-x64
|
||||
java/awt/Window/SetWindowLocationByPlatformTest/SetWindowLocationByPlatformTest.java 8253184,JBR-5728 windows-all,linux-all
|
||||
java/awt/Window/ShapedAndTranslucentWindows/SetShape.java 8253184,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
@@ -341,7 +338,7 @@ java/awt/Window/ShapedAndTranslucentWindows/ShapedTranslucentWindowClick.java 80
|
||||
java/awt/Window/ShapedAndTranslucentWindows/TranslucentChoice.java 8253184 windows-all
|
||||
java/awt/Window/ShapedAndTranslucentWindows/TranslucentWindowClick.java 8253184 windows-all
|
||||
java/awt/Window/setLocRelativeTo/SetLocationRelativeToTest.java 8253184 windows-all
|
||||
java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java JBR-9192 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Window/MultiWindowApp/ChildAlwaysOnTopTest.java JBR-5510,JBR-9192 linux-5.18.2-arch1-1,linux-6.15.8-100.fc41.x86_64
|
||||
java/awt/Window/MultiWindowApp/MultiWindowAppTest.java 8253184,JBR-5510,JBR-6463 windows-all,linux-all
|
||||
java/awt/Window/ShapedAndTranslucentWindows/FocusAWTTest.java 8222328 windows-all,linux-all,macosx-all
|
||||
java/awt/Window/ShapedAndTranslucentWindows/Shaped.java 8222328 windows-all,linux-all,macosx-all
|
||||
@@ -356,9 +353,14 @@ java/awt/Window/Grab/GrabTest.java 8253184 windows-all
|
||||
java/awt/Window/GrabSequence/GrabSequence.java 6848409 macosx-all,linux-all
|
||||
java/awt/Window/LocationAtScreenCorner/LocationAtScreenCorner.java 8203371 linux-all
|
||||
java/awt/FontClass/FontAccess.java JBR-5225 windows-all
|
||||
java/awt/font/ComplexEmoji.java JBR-5009 linux-aarch64
|
||||
java/awt/font/Emoji/ComplexEmoji.java JBR-8282 generic-all
|
||||
java/awt/font/Emoji/EmojiVariation.java JBR-8716 linux-5.18.2-arch1-1
|
||||
java/awt/font/EmojiVariation.java JBR-5009,JBR-5510 linux-aarch64,linux-5.18.2-arch1-1
|
||||
java/awt/font/FontScaling/StretchedFontTest.java JBR-6225 macosx-all
|
||||
java/awt/font/GlyphVector/LayoutCompatTest.java JBR-8437 linux-aarch64
|
||||
java/awt/font/JNICheck/JNICheck.sh JBR-5011 linux-all
|
||||
java/awt/font/OutlineTextRendererEmoji.java JBR-5009 linux-aarch64
|
||||
java/awt/font/TextLayout/ArabicDiacriticTest.java JBR-6760 linux-i386
|
||||
java/awt/font/TextLayout/DecorationBoundsTest.java JBR-6760 linux-i386
|
||||
java/awt/font/TextLayout/FormatCharAdvanceTest.java JBR-8289 macosx-all
|
||||
@@ -381,7 +383,7 @@ java/awt/image/multiresolution/MultiresolutionIconTest.java 8252812 windows-all,
|
||||
java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8253184,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
java/awt/print/Headless/HeadlessPrinterJob.java 8196088 windows-all
|
||||
sun/awt/datatransfer/SuplementaryCharactersTransferTest.java 8011371 generic-all
|
||||
sun/awt/font/TestArabicHebrew.java JBR-8826,JBR-9210 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
sun/awt/font/TestArabicHebrew.java JBR-8826,JBR-9210 linux-5.18.2-arch1-1,linux-6.15.8-100.fc41.x86_64
|
||||
sun/awt/font/TestDevTransform.java JBR-7882 linux-all,windows-all
|
||||
sun/awt/shell/ShellFolderMemoryLeak.java 8197794 windows-all
|
||||
sun/awt/windows/TestPen.java JBR-8718 linux-5.18.2-arch1-1
|
||||
@@ -395,8 +397,8 @@ sun/java2d/loops/XORClearRect.java JBR-8718 linux-5.18.2-arch1-1
|
||||
java/awt/Graphics/GDIResourceExhaustionTest.java JBR-8719 linux-5.18.2-arch1-1
|
||||
java/awt/Graphics/NativeWin32Clear.java JBR-8689 linux-aarch64,linux-5.18.2-arch1-1
|
||||
java/awt/Graphics/XORPaint.java#id1 JBR-8642 macosx-aarch64
|
||||
java/awt/Graphics/XORPaint.java#id2 JBR-9348 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Graphics2D/CopyAreaOOB.java JBR-5354,JBR-9206 macosx-all,windows-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Graphics/XORPaint.java#id2 JBR-5510 linux-5.18.2-arch1-1
|
||||
java/awt/Graphics2D/CopyAreaOOB.java JBR-5354,JBR-9206 macosx-all,windows-all,linux-5.18.2-arch1-1,linux-6.15.8-100.fc41.x86_64
|
||||
java/awt/Graphics2D/DrawString/DisposerTest.java JBR-5010,JBR-5510 linux-aarch64,linux-5.18.2-arch1-1
|
||||
java/awt/Graphics2D/DrawString/DrawRotatedStringUsingRotatedFont.java 8266283 generic-all
|
||||
sun/java2d/SunGraphics2D/DrawImageBilinear.java 8297175 linux-all
|
||||
@@ -445,7 +447,7 @@ java/awt/Frame/MiscUndecorated/FrameCloseTest.java JBR-5210 windows-all
|
||||
java/awt/Frame/MiscUndecorated/RepaintTest.java 8266244,JBR-5786 macosx-aarch64,generic-all
|
||||
java/awt/Robot/HiDPIMouseClick/HiDPIRobotMouseClick.java 8253184 windows-all
|
||||
java/awt/Robot/InfiniteLoopException.java 8342638 windows-all,linux-all
|
||||
java/awt/Robot/NonEmptyErrorStream.java 8340330,JBR-5510,JBR-8299,JBR-9259 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1,linux-5.18.2-arch1-1,linux-aarch64,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64
|
||||
java/awt/Robot/NonEmptyErrorStream.java 8340330,JBR-5510,JBR-8299,JBR-9259 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,linux-5.18.2-arch1-1,linux-aarch64,linux-6.15.8-100.fc41.x86_64
|
||||
java/awt/Robot/RobotExtraButton/RobotExtraButton.java JBR-6554 linux-all
|
||||
java/awt/Modal/FileDialog/FileDialogAppModal1Test.java 7186009,8253184 macosx-all,windows-all
|
||||
java/awt/Modal/FileDialog/FileDialogAppModal2Test.java 7186009,8253184 macosx-all,windows-all
|
||||
@@ -590,7 +592,6 @@ java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal1Test.java 825318
|
||||
java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal2Test.java 8253184,8196432 windows-all,linux-all
|
||||
java/awt/Modal/ModalFocusTransferTests/FocusTransferWDFNonModal3Test.java 8253184 windows-all
|
||||
java/awt/Modal/ModalInternalFrameTest/ModalInternalFrameTest.java 8253184,JBR-6302 windows-all,linux-all
|
||||
java/awt/Modal/MultipleDialogs/MixOfModalAndNonModalDialogs.java JBR-9317 linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Modal/MultipleDialogs/MultipleDialogs1Test.java 8198665,8253184 macosx-all,windows-all
|
||||
java/awt/Modal/MultipleDialogs/MultipleDialogs2Test.java 8198665,8253184 macosx-all,windows-all
|
||||
java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java 8198665,8253184 macosx-all,windows-all,linux-all
|
||||
@@ -599,7 +600,7 @@ java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java 8198665,8253184 macosx-
|
||||
java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java 8177326,8253184,JBR-6305 macosx-all,windows-all,linux-x64
|
||||
java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8253184 windows-all
|
||||
java/awt/Mouse/EnterExitEvents/ModalDialogEnterExitEventsTest.java 8253184,JBR-5811 windows-all,linux-all
|
||||
java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021,8253184,JBR-9208 macosx-all,windows-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021,8253184,JBR-9208 macosx-all,windows-all,linux-6.15.8-100.fc41.x86_64
|
||||
java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java 8051455 macosx-all
|
||||
java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.java 8253184,JBR-5709 windows-all,linux-all
|
||||
java/awt/Mouse/MouseComboBoxTest/MouseComboBoxTest.java 8253184,JBR-6752 windows-all,linux-all
|
||||
@@ -734,8 +735,8 @@ java/awt/Mouse/MouseWheelAbsXY/MouseWheelAbsXY.java 8253184 windows-all
|
||||
java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java 6847163 linux-all,windows-all
|
||||
java/awt/xembed/server/RunTestXEmbed.java 7034201 linux-all
|
||||
java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsDocModalTest.java 8164473 linux-all
|
||||
java/awt/Frame/DecoratedFrameInsets/DecoratedFrameInsetsTest.java JBR-5205,JBR-9204 linux-5.4.0-1103-aws,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Frame/DynamicLayout/DynamicLayout.java JBR-9205 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Frame/DecoratedFrameInsets/DecoratedFrameInsetsTest.java JBR-5205,JBR-9204 linux-5.4.0-1103-aws,linux-6.15.8-100.fc41.x86_64
|
||||
java/awt/Frame/DynamicLayout/DynamicLayout.java JBR-9205 linux-6.15.8-100.fc41.x86_64
|
||||
|
||||
java/awt/GraphicsDevice/CheckDisplayModes.java JBR-8183 macosx-x64
|
||||
java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java 7099223,8274106 macosx-all,linux-all,windows-all
|
||||
@@ -760,7 +761,7 @@ java/awt/Paint/bug8024864.java JBR-6544 generic-all
|
||||
java/awt/Paint/ComponentIsNotDrawnAfterRemoveAddTest/ComponentIsNotDrawnAfterRemoveAddTest.java 8253184,JBR-6844 windows-all,linux-5.18.2-arch1-1
|
||||
java/awt/Paint/ListRepaint.java JBR-5060 linux-all
|
||||
java/awt/Paint/PaintNativeOnUpdate.java 8253184,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
java/awt/PopupMenu/PopupMenuLocation.java 8238720,JBR-7035,JBR-9251 windows-all,macosx-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/PopupMenu/PopupMenuLocation.java 8238720,JBR-7035,JBR-9257 windows-all,macosx-all,linux-6.15.8-100.fc41.x86_64
|
||||
java/awt/GridBagLayout/ComponentShortage.java 8355280 windows-all,linux-all
|
||||
java/awt/GridBagLayout/GridBagLayoutIpadXYTest/GridBagLayoutIpadXYTest.java 8253184 windows-all
|
||||
java/awt/GridLayout/ChangeGridSize/ChangeGridSize.java 8238720,8322653 windows-all,macosx-all
|
||||
@@ -850,9 +851,9 @@ com/sun/management/OperatingSystemMXBean/GetSystemCpuLoad.java 8030957 aix-all
|
||||
|
||||
java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java 8247426 generic-all
|
||||
|
||||
sun/management/jdp/JdpDefaultsTest.java 8241865,JBR-9229 linux-aarch64,macosx-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
sun/management/jdp/JdpJmxRemoteDynamicPortTest.java 8241865,JBR-9229 macosx-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
sun/management/jdp/JdpSpecificAddressTest.java 8241865,JBR-9229 macosx-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
sun/management/jdp/JdpDefaultsTest.java 8241865,JBR-9229 linux-aarch64,macosx-all,linux-6.15.8-100.fc41.x86_64
|
||||
sun/management/jdp/JdpJmxRemoteDynamicPortTest.java 8241865,JBR-9229 macosx-all,linux-6.15.8-100.fc41.x86_64
|
||||
sun/management/jdp/JdpSpecificAddressTest.java 8241865,JBR-9229 macosx-all,linux-6.15.8-100.fc41.x86_64
|
||||
|
||||
sun/management/jmxremote/bootstrap/RmiSslNoKeyStoreTest.java JBR-8707 windows-all
|
||||
sun/management/jmxremote/bootstrap/RmiBootstrapTest.java#id0 JBR-8707 windows-all
|
||||
@@ -894,16 +895,14 @@ java/net/MulticastSocket/Test.java 7145658 macosx-a
|
||||
# jdk_nio
|
||||
|
||||
java/nio/channels/AsynchronousSocketChannel/StressLoopback.java JBR-8817 windows-aarch64
|
||||
java/nio/channels/DatagramChannel/AdaptorMulticasting.java 8144003,JBR-8455,JBR-8456,8308807,JBR-9219 macosx-all,aix-ppc64,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/nio/channels/DatagramChannel/AdaptorMulticasting.java 8144003,JBR-8455,JBR-8456,8308807,JBR-9219 macosx-all,aix-ppc64,linux-6.15.8-100.fc41.x86_64
|
||||
java/nio/channels/DatagramChannel/BasicMulticastTests.java 8144003 macosx-all
|
||||
java/nio/channels/DatagramChannel/Loopback.java JBR-9219 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/nio/channels/DatagramChannel/Loopback.java JBR-9219 linux-6.15.8-100.fc41.x86_64
|
||||
java/nio/channels/DatagramChannel/ManySourcesAndTargets.java 8264385 macosx-aarch64
|
||||
java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java 8144003,JBR-9218 macosx-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/nio/channels/DatagramChannel/Promiscuous.java 8144003,JBR-9218 macosx-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/nio/channels/DatagramChannel/PromiscuousIPv6.java JBR-8828,JBR-9218 macosx-x64,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/nio/channels/DatagramChannel/SendReceiveMaxSize.java JBR-9447 linux-6.14.0-1013-aws,linux-6.14.0-1014-aws
|
||||
java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java 8144003,JBR-9218 macosx-all,linux-6.15.8-100.fc41.x86_64
|
||||
java/nio/channels/DatagramChannel/Promiscuous.java 8144003,JBR-9218 macosx-all,linux-6.15.8-100.fc41.x86_64
|
||||
java/nio/channels/DatagramChannel/PromiscuousIPv6.java JBR-8828,JBR-9218 macosx-x64,linux-6.15.8-100.fc41.x86_64
|
||||
java/nio/channels/DatagramChannel/Unref.java 8233437 generic-all
|
||||
java/nio/channels/FileChannel/LargeGatheringWrite.java JBR-9316 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/nio/channels/Selector/LotsOfInterrupts.java#virtual JBR-8940 windows-aarch64
|
||||
java/nio/channels/Selector/Wakeup.java 6963118 windows-all
|
||||
|
||||
@@ -956,7 +955,7 @@ sun/security/smartcardio/TestExclusive.java 8039280 generic-
|
||||
sun/security/smartcardio/TestMultiplePresent.java 8039280 generic-all
|
||||
sun/security/smartcardio/TestPresent.java 8039280 generic-all
|
||||
sun/security/smartcardio/TestTransmit.java 8039280 generic-all
|
||||
sun/security/ssl/SSLSessionImpl/MultiNSTClient.java JBR-9058 macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1
|
||||
sun/security/ssl/SSLSessionImpl/MultiNSTClient.java JBR-9058 macosx-15.5,macosx-15.6
|
||||
com/sun/crypto/provider/Cipher/DES/PerformanceTest.java 8039280 generic-all
|
||||
com/sun/security/auth/callback/TextCallbackHandler/Default.java 8039280 generic-all
|
||||
com/sun/security/auth/callback/TextCallbackHandler/Password.java 8039280 generic-all
|
||||
@@ -1052,7 +1051,7 @@ javax/swing/DataTransfer/bug4655513.java JBR-8849 windows-aarch64,windows-10.0
|
||||
javax/swing/DefaultButtonModel/DefaultButtonModelCrashTest.java JBR-5210,JBR-5799 windows-all
|
||||
javax/swing/dnd/7171812/bug7171812.java 8253184 windows-all
|
||||
javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765,JBR-5210 macosx-all,linux-all,windows-all
|
||||
javax/swing/GraphicsConfigNotifier/StalePreferredSize.java JBR-5210,JBR-9273 windows-all,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
javax/swing/GraphicsConfigNotifier/StalePreferredSize.java JBR-5210 windows-all
|
||||
javax/swing/JButton/4368790/bug4368790.java JBR-5210 windows-all
|
||||
javax/swing/JButton/4659800/SpaceKeyActivatesButton.java JBR-4949 linux-all,windows-all
|
||||
javax/swing/JButton/8151303/PressedIconTest.java JBR-5210,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
@@ -1065,7 +1064,6 @@ javax/swing/JButton/SwingButtonResizeTestWithOpenGL.java#id1 JBR-7965 windows-al
|
||||
javax/swing/JButton/TestMnemonicAction.java JBR-6508 windows-all,linux-all
|
||||
javax/swing/JColorChooser/Test6524757.java JBR-5210 windows-all
|
||||
javax/swing/JColorChooser/Test6827032.java JBR-5210 windows-all
|
||||
javax/swing/JComboBox/4231298/JComboBoxPrototypeDisplayValueTest.java JBR-6777 linux-all
|
||||
javax/swing/JComboBox/4743225/bug4743225.java JBR-5210 windows-all
|
||||
javax/swing/JComboBox/6236162/bug6236162.java JBR-5210 windows-all
|
||||
javax/swing/JComboBox/6406264/bug6406264.java JBR-5210,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
@@ -1086,7 +1084,7 @@ javax/swing/JDialog/Transparency/TransparencyTest.java 8253184,JBR-5510 windows-
|
||||
javax/swing/JFrame/MaximizeWindowTest.java 8321289,JBR-8292 linux-all
|
||||
javax/swing/JFrame/NSTexturedJFrame/NSTexturedJFrame.java JBR-8837 macosx-all
|
||||
javax/swing/JLabel/4138746/JLabelMnemonicsTest.java JBR-4949 linux-all,windows-all
|
||||
javax/swing/JLabel/6596966/bug6596966.java 8197552,JBR-9195 windows-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
javax/swing/JLabel/6596966/bug6596966.java 8197552,JBR-9195 windows-all,linux-6.15.8-100.fc41.x86_64
|
||||
javax/swing/JLabel/7004134/bug7004134.java JBR-5437 linux-all
|
||||
javax/swing/JLabel/bug4822331.java JBR-7422 windows-all
|
||||
javax/swing/JList/6462008/bug6462008.java JBR-8063 windows-all
|
||||
@@ -1100,7 +1098,7 @@ javax/swing/JMenu/8072900/WrongSelectionOnMouseOver.java JBR-5799,JBR-6306 windo
|
||||
javax/swing/JMenu/bug4140643.java JBR-8489 windows-all
|
||||
javax/swing/JMenu/PopupReferenceMemoryLeak.java JBR-5890,JBR-6056 windows-aarch64,windows-x64
|
||||
javax/swing/JMenuBar/TestMenuMnemonic.java JBR-7301 windows-all
|
||||
javax/swing/JMenuBar/TestMenuMnemonicLinuxAndMac.java JBR-7927,JBR-8718бОИК-9416 linux-5.15.0-1080-aws,linux-5.15.0-1083-aws,linux-5.15.0-1084-aws,linux-5.18.2-arch1-1,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
javax/swing/JMenuBar/TestMenuMnemonicLinuxAndMac.java JBR-7927,JBR-8718 linux-5.15.0-1080-aws,linux-5.15.0-1083-aws,linux-5.15.0-1084-aws,linux-5.18.2-arch1-1
|
||||
javax/swing/JMenuBar/4750590/bug4750590.java 8197552,JBR-6094 windows-all,windows-x64
|
||||
javax/swing/JMenuItem/4171437/bug4171437.java 8197552,JBR-6112 windows-all,windows-x64
|
||||
javax/swing/JMenuItem/4654927/bug4654927.java JBR-164,JBR-4337 windows-all,linux-all
|
||||
@@ -1128,9 +1126,8 @@ javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java 8
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java 8194128,8253184,JBR-5510,JBR-6515 macosx-all,windows-all,linux-5.18.2-arch1-1,linux-all
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/SetShapeAndClickSwing.java 8013450,8253184 macosx-all,windows-all
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentJComboBox.java 8024627,8253184 macosx-all,windows-all
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentPerPixelTranslucentGradient.java JBR-8327 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.5,macosx-15.6,macosx-15.6.1,macosx-15.7,macosx-15.7
|
||||
javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentWindowClickSwing.java 8253184 windows-all
|
||||
javax/swing/LookAndFeel/8145547/DemandGTK3.sh JBR-5510,JBR-9202 linux-5.18.2-arch1-1,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64
|
||||
javax/swing/LookAndFeel/8145547/DemandGTK3.sh JBR-5510,JBR-9202 linux-5.18.2-arch1-1,linux-6.15.8-100.fc41.x86_64
|
||||
# The next test below is an intermittent failure
|
||||
javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java 8159131 linux-all
|
||||
javax/swing/JTree/4330357/bug4330357.java 8253184,JBR-6466 windows-all,linux-all
|
||||
@@ -1160,18 +1157,18 @@ javax/swing/JFormattedTextField/bug4863121.java JBR-7424 windows-all
|
||||
javax/swing/JFrame/8016356/bug8016356.java JBR-108 windows-all
|
||||
javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106,JBR-5510 macosx-aarch64,linux-5.18.2-arch1-1
|
||||
javax/swing/JPopupMenu/6800513/bug6800513.java 7184956,JBR-6533 macosx-all,linux-all,windows-all
|
||||
javax/swing/JSlider/bug4382876.java JBR-8666 linux-6.14.0-1010-aws,linux-6.14.0-1012-aws,linux-6.14.0-1014-aws,linux-6.16.7-100.fc41.x86_64
|
||||
javax/swing/JSlider/bug4382876.java JBR-8666 linux-6.14.0-1010-aws
|
||||
javax/swing/JScrollBar/4708809/bug4708809.java 8169957 windows-x64
|
||||
javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java 8197552 windows-all
|
||||
javax/swing/JSplitPane/4885629/bug4885629.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JTabbedPane/4361477/bug4361477.java JBR-5932 linux-all
|
||||
javax/swing/JTabbedPane/4624207/bug4624207.java 8064922,8197552,JBR-6235 macosx-all,windows-all,linux-all 8064922:macosx-all, 8197552:windows-all
|
||||
javax/swing/JTabbedPane/TestBackgroundScrollPolicy.java 8253184,JBR-8498,JBR-8718 windows-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1,linux-5.18.2-arch1-1
|
||||
javax/swing/JTabbedPane/TestJTabbedPaneBackgroundColor.java JBR-8718,JBR-8493 linux-5.18.2-arch1-1,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1
|
||||
javax/swing/JTabbedPane/TestBackgroundScrollPolicy.java 8253184,JBR-8498,JBR-8718 windows-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,linux-5.18.2-arch1-1
|
||||
javax/swing/JTabbedPane/TestJTabbedPaneBackgroundColor.java JBR-8718,JBR-8493 linux-5.18.2-arch1-1,macosx-15.4.1,macosx-15.5,macosx-15.6
|
||||
javax/swing/JToggleButton/TestSelectedKey.java JBR-5846 windows-all
|
||||
javax/swing/JToolBar/4529206/bug4529206.java JBR-5387 linux-all
|
||||
javax/swing/JToolTip/6219960/bug6219960.java 8253184 windows-all
|
||||
javax/swing/JToolTip/TestTooltipBackgroundColor.java JBR-5510,JBR-9201 linux-5.18.2-arch1-1,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
javax/swing/JToolTip/TestTooltipBackgroundColor.java JBR-5510,JBR-9201 linux-5.18.2-arch1-1,linux-6.15.8-100.fc41.x86_64
|
||||
javax/swing/SwingGraphics/TranslateTest.java JBR-8718 linux-5.18.2-arch1-1
|
||||
javax/swing/SwingUtilities/TestBadBreak/TestBadBreak.java 8160720 generic-all
|
||||
javax/swing/text/AbstractDocument/8190763/TestCCEOnEditEvent.java JBR-5799,JBR-8290 windows-all,linux-all
|
||||
@@ -1189,8 +1186,8 @@ javax/swing/JInternalFrame/6288609/TestJInternalFrameDispose.java JBR-788 window
|
||||
javax/swing/JInternalFrame/6647340/bug6647340.java 8253184 windows-all
|
||||
javax/swing/JInternalFrame/8145060/TestJInternalFrameMinimize.java JBR-788 windows-all,linux-all
|
||||
javax/swing/JInternalFrame/8145896/TestJInternalFrameMaximize.java JBR-5539 windows-all
|
||||
javax/swing/JInternalFrame/JInternalFrameTest.java JBR-9193 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
javax/swing/JInternalFrame/Test6325652.java JBR-6111,JBR-9194 windows-all,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
javax/swing/JInternalFrame/JInternalFrameTest.java JBR-9193 linux-6.15.8-100.fc41.x86_64
|
||||
javax/swing/JInternalFrame/Test6325652.java JBR-6111,JBR-9194 windows-all,linux-6.15.8-100.fc41.x86_64
|
||||
javax/swing/JInternalFrame/Test6505027.java JBR-5954 linux-all,macosx-all
|
||||
javax/swing/JInternalFrame/Test6802868.java 8253184 windows-all
|
||||
javax/swing/JPopupMenu/4634626/bug4634626.java 8253184 windows-all
|
||||
@@ -1220,14 +1217,13 @@ javax/swing/text/GlyphPainter2/6427244/bug6427244.java JBR-896,JBR-6760 windows-
|
||||
javax/swing/text/JTextComponent/5074573/bug5074573.java CODETOOLS-7901623,JBR-5386 windows-all,linux-all
|
||||
javax/swing/text/JTextComponent/6361367/bug6361367.java JBR-521,JBR-6687 windows-all,linux-5.18.2-arch1-1
|
||||
javax/swing/text/View/8014863/bug8014863.java JBR-5541 windows-all,linux-all
|
||||
javax/swing/text/View/8048110/bug8048110.java JBR-9256,JBR-9207 windows-all,linux-6.16.7-100.fc41.x86_64
|
||||
javax/swing/text/View/8156217/FPMethodCalledTest.java JBR-5542 linux-all
|
||||
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952,8340330 windows-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1
|
||||
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952,8340330 windows-all,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6
|
||||
java/awt/Robot/CheckCommonColors/CheckCommonColors.java 8253184,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java 8253184,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
java/awt/Robot/HiDPIScreenCapture/ScreenCaptureTest.java 8253184,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
java/awt/Robot/ModifierRobotKey/ModifierRobotKeyTest.java JBR-5802 windows-all
|
||||
java/awt/Robot/MouseLocationOnScreen/MouseLocationOnScreen.java JBR-9209 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Robot/MouseLocationOnScreen/MouseLocationOnScreen.java JBR-9209 linux-6.15.8-100.fc41.x86_64
|
||||
java/awt/ColorClass/AlphaColorTest.java JBR-5510 linux-5.18.2-arch1-1
|
||||
|
||||
sanity/client/SwingSet/src/ToolTipDemoTest.java 8293001 linux-all
|
||||
@@ -1330,9 +1326,9 @@ jdk/jfr/event/runtime/TestShutdownEvent.java JBR-8781 windows-aarch64
|
||||
jdk/jfr/jvm/TestDumpOnCrash.java JBR-8780 windows-aarch64
|
||||
jdk/jfr/jvm/TestWaste.java 8282427 generic-all
|
||||
jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64
|
||||
jdk/jfr/api/consumer/streaming/TestOutOfProcessMigration.java JBR-8460 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1
|
||||
jdk/jfr/api/consumer/streaming/TestJVMCrash.java JBR-8459 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1
|
||||
jdk/jfr/api/consumer/streaming/TestJVMExit.java JBR-8460 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1
|
||||
jdk/jfr/api/consumer/streaming/TestOutOfProcessMigration.java JBR-8460 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6
|
||||
jdk/jfr/api/consumer/streaming/TestJVMCrash.java JBR-8459 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6
|
||||
jdk/jfr/api/consumer/streaming/TestJVMExit.java JBR-8460 macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6
|
||||
|
||||
jdk/jfr/tool/TestPrint.java JBR-8704 macosx-all
|
||||
############################################################################
|
||||
@@ -1370,7 +1366,7 @@ javax/swing/JFileChooser/6698013/bug6698013.java 8024419 macosx-all
|
||||
javax/swing/JColorChooser/8065098/bug8065098.java 8065647 macosx-all
|
||||
java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java 8068378 generic-all
|
||||
javax/swing/JTabbedPane/4666224/bug4666224.html 8144124 macosx-all
|
||||
javax/swing/JTextArea/4697612/bug4697612.java JBR-9200 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
javax/swing/JTextArea/4697612/bug4697612.java JBR-9200 linux-6.15.8-100.fc41.x86_64
|
||||
javax/swing/JTextArea/7049024/bug7049024.java JBR-5836 linux-all
|
||||
javax/swing/JTextArea/8149849/DNDTextToScaledArea.java 8253184 windows-all
|
||||
java/awt/event/MouseEvent/AltGraphModifierTest/AltGraphModifierTest.java 8162380,JBR-4207 generic-all,windows-all
|
||||
@@ -1449,13 +1445,13 @@ com/sun/java/swing/plaf/windows/AltFocusIssueTest.java
|
||||
jb/hotspot/AsyncProfilerRunnerTest.java JBR-7175 macosx-all
|
||||
|
||||
jb/java/awt/CustomTitleBar/DialogNativeControlsTest.java JBR-8794 windows-aarch64
|
||||
jb/java/awt/Graphics2D/TextRender/OGLMetalTextRender.java JBR-4091,JBR-5392 windows-aarch64,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6,macosx-15.7,macosx-15.7.1
|
||||
jb/java/awt/Graphics2D/TextRender/OGLMetalTextRender.java JBR-4091,JBR-5392 windows-aarch64,macosx-15.3,macosx-15.3.1,macosx-15.3.2,macosx-15.4,macosx-15.4.1,macosx-15.5,macosx-15.6
|
||||
jb/java/awt/event/TouchScreenEvent/TouchScreenEventsTestLinux.sh JBR-4078 linux-all
|
||||
jb/java/awt/Font/Font467.java JBR-3960 generic-all
|
||||
jb/java/awt/image/BufferedFontRenderingTest.java JBR-6493 generic-all
|
||||
jb/java/awt/keyboard/AltGrMustGenerateAltGrModifierTest4207.java JBR-4207 windows-all
|
||||
jb/java/awt/Toolkit/AWTThreadingTest.java JBR-4350 macosx-all
|
||||
jb/java/awt/Toolkit/DetectingOSThemeTest.java JBR-9228 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64
|
||||
jb/java/awt/Toolkit/DetectingOSThemeTest.java JBR-9228 linux-6.15.8-100.fc41.x86_64
|
||||
jb/java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java JBR-4896,JBR-5163 macosx-all,
|
||||
|
||||
java/awt/Dialog/NonResizableDialogSysMenuResize/NonResizableDialogSysMenuResize.java JBR-4250 windows-all
|
||||
@@ -1502,7 +1498,7 @@ jb/java/awt/wayland/VulkanBlitTest.java JBR-8394 linux-5.18.2-arch1-1,linux-5.15
|
||||
jb/java/awt/wayland/VulkanCompositeTest.java JBR-8394 linux-5.18.2-arch1-1,linux-5.15.0-1081-aws,linux-5.15.0-1083-aws,linux-5.15.0-1084-aws
|
||||
jb/java/awt/wayland/VulkanGCCompatibilityTest.java JBR-8394 linux-5.18.2-arch1-1
|
||||
jb/java/awt/wayland/VulkanMaskFillTest.java JBR-8394 linux-5.18.2-arch1-1
|
||||
jb/java/io/IoOverNio/FileTest.java JBR-8723 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
jb/java/io/IoOverNio/FileTest.java JBR-8723 linux-6.15.8-100.fc41.x86_64
|
||||
javax/swing/text/StyledEditorKit/bug4329418.java
|
||||
jb/java/jcef/HandleJSQueryTest3314.sh JBR-4866 linux-all
|
||||
jb/java/jcef/HwFacadeWindowNoFrontTest.java JBR-6556 windows-all
|
||||
@@ -1523,7 +1519,6 @@ jb/javax/swing/JComboBox/ComboBoxTransparentTittleBarTest.java JBR-5432,JBR-4875
|
||||
jb/javax/swing/JDialog/JDialog186.java JBR-5210 windows-all
|
||||
jb/javax/swing/JDialog/JDialog392.java JBR-4941 macosx-all,linux-all
|
||||
jb/javax/swing/JDialog/JDialog705.java JBR-4934 generic-all
|
||||
jb/javax/swing/JDialog/JDialog1054.java JBR-5004 macosx-all
|
||||
jb/javax/swing/JEditorPane/ZeroMargin.java JBR-2256 generic-all
|
||||
jb/javax/swing/JPopupMenu/JPopupMenuOutOfWindowTest.java JBR-6682 windows-all,linux-all
|
||||
|
||||
@@ -1543,7 +1538,7 @@ java/awt/Frame/InvisibleOwner/InvisibleOwner.java JBR-5510 linux-5.18.2-arch1-1
|
||||
java/awt/Mixing/AWT_Mixing/JGlassPaneInternalFrameOverlapping.java JBR-5510 linux-5.18.2-arch1-1
|
||||
java/awt/Mixing/AWT_Mixing/JGlassPaneMoveOverlapping.java JBR-5510 linux-5.18.2-arch1-1
|
||||
java/awt/Mixing/AWT_Mixing/JInternalFrameOverlapping.java JBR-5510 linux-5.18.2-arch1-1
|
||||
java/awt/Mixing/LWComboBox.java JBR-7595 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64
|
||||
java/awt/Mixing/LWComboBox.java JBR-7595 linux-6.15.8-100.fc41.x86_64
|
||||
java/awt/Mixing/LWPopupMenu.java JBR-824 generic-all
|
||||
java/awt/Mixing/OpaqueTest.java JBR-5707 linux-all
|
||||
java/awt/Mixing/OverlappingButtons.java JBR-5707 linux-all
|
||||
@@ -1600,7 +1595,7 @@ java/awt/Toolkit/DesktopProperties/rfe4758438.java JBR-5510 linux-5.18.2-arch1-1
|
||||
java/awt/Toolkit/LockingKeyStateTest/LockingKeyStateTest.java JBR-5765 macosx-all
|
||||
javax/swing/JMenu/TestDisabledMenuForegroundColor.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JProgressBar/TestJProgressBarHighlightColor.java JBR-5510,JBR-9199 linux-5.18.2-arch1-1,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
javax/swing/JProgressBar/TestJProgressBarHighlightColor.java JBR-5510,JBR-9199 linux-5.18.2-arch1-1,linux-6.15.8-100.fc41.x86_64
|
||||
javax/swing/JSlider/TestJSliderRendering.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JSpinner/TestSelectedTextBackgroundColor.java JBR-5510 linux-5.18.2-arch1-1
|
||||
javax/swing/JTextPane/TestJTextPaneBackgroundColor.java JBR-5510 linux-5.18.2-arch1-1
|
||||
|
||||
@@ -8,7 +8,6 @@ java/awt/dnd/DnDAWTLockTest.java JBR-8745 linux-all
|
||||
java/awt/dnd/DragOverDropTargetPerformanceTest.java JBR-5799 windows-all
|
||||
java/awt/dnd/DragSourceGCrashTest.java JBR-8745 linux-all
|
||||
java/awt/dnd/InterJVMGetDropSuccessTest/InterJVMGetDropSuccessTest.java JBR-8745 linux-all
|
||||
java/awt/dnd/InterJVMLinkTest.java JBR-9255 linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Dialog/ChoiceModalDialogTest.java JBR-8724 windows-all
|
||||
java/awt/dnd/MozillaDnDTest.java JBR-6442 linux-all
|
||||
java/awt/event/ComponentEvent/TextComponentTextEventTest.java JBR-6287 windows-all
|
||||
@@ -33,7 +32,7 @@ java/awt/Frame/WindowDragTest/WindowDragTest.java JBR-6090 windows-all
|
||||
java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java 7124275,JBR-5799 macosx-all,windows-all
|
||||
java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java JBR-7299,JBR-8728 linux-all,windows-all
|
||||
java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150,JBR-4880,8253184,JBR-5510,JBR-8725 macosx-all,windows-all,linux-5.18.2-arch1-1,linux-6.8.0-all
|
||||
java/awt/Graphics/LineClipTest.java JBR-9386 linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Graphics/LineClipTest.java JBR-5071 linux-aarch64
|
||||
java/awt/Graphics/NativeWin32Clear.java JBR-8730 windows-all
|
||||
java/awt/GridLayout/ChangeGridSize/ChangeGridSize.java 8238720,8322653,JBR-5071 windows-all,macosx-all,linux-all
|
||||
java/awt/GridLayout/ComponentPreferredSize/ComponentPreferredSize.java 8238720,8322653,JBR-5071 windows-all,macosx-all,linux-all
|
||||
@@ -44,19 +43,17 @@ java/awt/List/ItemEventTest/ItemEventTest.java JBR-5711,JBR-6234 linux-all,windo
|
||||
java/awt/List/TriggerActionEventTest.java JBR-6234 windows-all
|
||||
java/awt/MenuItem/SetLabelTest.java JBR-8731 windows-all
|
||||
java/awt/MenuShortcut/ActionCommandTest.java JBR-8822 windows-10.0
|
||||
java/awt/MenuShortcut/FunctionKeyShortcut.java JBR-8732,JBR-9207 windows-all,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/MenuShortcut/FunctionKeyShortcut.java JBR-8732 windows-all
|
||||
java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java 8049405,JBR-5510,JBR-6134 macosx-all,linux-5.18.2-arch1-1,windows-all
|
||||
java/awt/Mixing/AWT_Mixing/JGlassPaneInternalFrameOverlapping.java JBR-5510,JBR-6234 linux-5.18.2-arch1-1,windows-all
|
||||
java/awt/Mixing/AWT_Mixing/JGlassPaneMoveOverlapping.java JBR-5510,JBR-6134 linux-5.18.2-arch1-1,windows-all
|
||||
java/awt/Mixing/MixingOnDialog.java JBR-6134 windows-all
|
||||
java/awt/Modal/BlockedMouseInputTest2.java JBR-6090 windows-all
|
||||
java/awt/Mouse/MouseEnterExitTest.java JBR-8096 linux-all,windows-all
|
||||
java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java JBR-7309 linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/MouseInfo/ContainerResizeMousePositionTest.java JBR-7881,JBR-7915,JBR-8746 macosx-all,linux-all
|
||||
java/awt/PopupMenu/PopupMenuLocation.java 8238720,JBR-7035,JBR-8726 windows-all,macosx-all,linux-all
|
||||
java/awt/Robot/ScreenCaptureRobotTest.java#id0 JBR-8784 macosx-all
|
||||
java/awt/Scrollbar/UnitIncrementTest.java JBR-8733 windows-all
|
||||
java/awt/TextArea/ScrollbarIntersectionTest/ScrollbarIntersectionTest.java 8253184,JBR-9387 windows-all,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/TextField/GetTextTest/GetTextTest.java JBR-8734 windows-all
|
||||
java/awt/Window/AlwaysOnTop/SyncAlwaysOnTopFieldTest.java JBR-6845 linux-all
|
||||
java/awt/Window/TopLevelLocation/TopLevelLocation.java JBR-5799 windows-all
|
||||
@@ -70,7 +67,7 @@ javax/swing/JButton/bug4490179.java JBR-8925 windows-all
|
||||
javax/swing/JFileChooser/JFileChooserSetLocationTest.java JBR-8098 linux-all,windows-all
|
||||
javax/swing/JInternalFrame/4202966/IntFrameCoord.java JBR-9006 window-all
|
||||
javax/swing/JMenu/bug4342646.java JBR-8727 linux-all,windows-all
|
||||
javax/swing/JPopupMenu/6580930/bug6580930.java JBR-5071 linux-6.8.0-1033-aws,linux-6.8.0-1036-aws,linux-6.8.0-1039-aws,linux-6.15.8-100.fc41.x86_64,linux-6.16.7-100.fc41.x86_64
|
||||
javax/swing/JPopupMenu/6580930/bug6580930.java JBR-5071 linux-6.8.0-1033-aws
|
||||
javax/swing/JTable/JTableRightOrientationTest.java JBR-8102 linux-all,windows-all
|
||||
javax/swing/text/ParagraphView/6364882/bug6364882.java JBR-8747 linux-all
|
||||
javax/swing/plaf/basic/BasicGraphicsUtils/8132119/bug8132119.java JBR-8357 linux-all
|
||||
@@ -88,8 +85,7 @@ jb/java/awt/Window/UndecoratedDialogInTransientsChain.java
|
||||
jdk/editpad/EditPadTest.java JBR-5712 windows-all
|
||||
|
||||
sanity/client/SwingSet/src/ColorChooserDemoTest.java JBR-8354,JBR-8933 linux-all,windows-aarch64,windows-10.0
|
||||
sanity/client/SwingSet/src/EditorPaneDemoTest.java JBR-6285 generic-all
|
||||
sanity/client/SwingSet/src/GridBagLayoutDemoTest.java JBR-6285 generic-all
|
||||
sanity/client/SwingSet/src/EditorPaneDemoTest.java JBR-5510,JBR-6285 linux-5.18.2-arch1-1,linux-all
|
||||
sanity/client/SwingSet/src/InternalFrameDemoTest.java JBR-6685 linux-all
|
||||
sanity/client/SwingSet/src/ToolTipDemoTest.java 8293001,JBR-6293 linux-all,windows-all
|
||||
sun/java2d/GdiRendering/ClipShapeRendering.java JBR-5204 linux-all,macosx-all,windows-all
|
||||
@@ -114,7 +110,7 @@ java/awt/Frame/ShapeNotSetSometimes/ShapeNotSetSometimes.java nobug generic-all
|
||||
java/awt/Graphics/CopyScaledArea/CopyScaledAreaTest.java nobug generic-all
|
||||
java/awt/Graphics/DrawOvalTest.java nobug generic-all
|
||||
java/awt/Graphics/XORPaint.java#id1 JBR-8642,nobug macosx-aarch64,windows-all
|
||||
java/awt/Graphics/XORPaint.java#id2 nobug generic-all
|
||||
java/awt/Graphics/XORPaint.java#id2 JBR-5510,nobug linux-5.18.2-arch1-1,windows-all
|
||||
java/awt/Graphics/XORPaint.java#id3 nobug windows-all
|
||||
java/awt/Graphics/XORPaint.java#id4 nobug windows-all
|
||||
java/awt/Graphics/XORPaint.java#id5 nobug windows-all
|
||||
@@ -138,7 +134,6 @@ java/awt/Robot/HiDPIScreenCapture/ScreenCaptureResolutionTest.java nobug generic
|
||||
java/awt/Robot/HiDPIScreenCapture/ScreenCaptureTest.java nobug generic-all
|
||||
java/awt/Robot/ScreenCaptureRobotTest.java#id1 nobug generic-all
|
||||
java/awt/Toolkit/ScreenInsetsDPIVariation/ScreenInsetsDPIVariation.java nobug generic-all
|
||||
java/awt/TrayIcon/RightClickWhenBalloonDisplayed/RightClickWhenBalloonDisplayed.java 8238720,JBR-6931 windows-all,linux-aarch64,linux-6.16.7-100.fc41.x86_64,linux-6.16.7-200.fc42.x86_64
|
||||
java/awt/Window/8159168/SetShapeTest.java nobug generic-all
|
||||
java/awt/Window/BackgroundIsNotUpdated/BackgroundIsNotUpdated.java nobug generic-all
|
||||
java/awt/Window/GetScreenLocation/GetScreenLocationTest.java nobug generic-all
|
||||
@@ -182,7 +177,6 @@ javax/swing/JButton/SwingButtonResizeTestWithOpenGL.java#id0 JBR-7965,JBR-8345 w
|
||||
javax/swing/JButton/SwingButtonResizeTestWithOpenGL.java#id2 JBR-8345 linux-all
|
||||
javax/swing/JButton/TestGlyphBreak.java nobug generic-all
|
||||
javax/swing/JComboBox/6559152/bug6559152.java JBR-8964 windows-all
|
||||
javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java JBR-9342 windows-x64
|
||||
javax/swing/JComboBox/DisabledComboBoxFontTestAuto.java nobug generic-all
|
||||
javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java nobug generic-all
|
||||
javax/swing/JInternalFrame/8069348/bug8069348.java nobug generic-all
|
||||
|
||||
@@ -22,14 +22,9 @@ java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Disable.java JBR-9100 l
|
||||
javax/swing/AbstractButton/bug4147740.java JBR-9100 linux-all
|
||||
javax/swing/AbstractButton/bug4246045.java JBR-9100 linux-all
|
||||
javax/swing/border/Test6981576.java JBR-9100 linux-all
|
||||
java/awt/image/DrawImage/BlitRotateClippedArea.java JBR-9026 linux-all
|
||||
java/awt/image/DrawImage/EABlitTest.java JBR-9027 linux-all
|
||||
javax/swing/GraphicsConfigNotifier/StalePreferredSize.java JBR-9031 linux-all
|
||||
javax/swing/GraphicsConfigNotifier/TestMultiScreenGConfigNotify.java JBR-8266 linux-x64
|
||||
javax/swing/GroupLayout/8079640/bug8079640.java JBR-9100 linux-all
|
||||
javax/swing/JButton/JButtonPaintNPE/JButtonPaintNPE.java JBR-9100 linux-all
|
||||
javax/swing/JButton/SwingButtonResizeTestWithOpenGL.java#id0 JBR-7928,JBR-9341 linux-6.8.0-1036-aws,linux-6.8.0-1039-aws,linux-6.14.9-arch1-1
|
||||
javax/swing/JButton/SwingButtonResizeTestWithOpenGL.java#id2 JBR-7928 linux-6.8.0-1036-aws,linux-6.8.0-1039-aws
|
||||
javax/swing/JColorChooser/Test4177735.java JBR-9100 linux-all
|
||||
javax/swing/JComboBox/8019180/Test8019180.java JBR-9100 linux-all
|
||||
javax/swing/JComboBox/bug4276920.java JBR-9100 linux-all
|
||||
@@ -44,7 +39,6 @@ javax/swing/JFileChooser/6489130/bug6489130.java JBR-9100 linux-all
|
||||
javax/swing/JFileChooser/DeserializedJFileChooser/DeserializedJFileChooserTest.java JBR-9100 linux-all
|
||||
javax/swing/JFileChooser/FileSizeCheck.java JBR-9100 linux-all
|
||||
javax/swing/JFileChooser/FileViewNPETest.java JBR-9100 linux-all
|
||||
javax/swing/JFormattedTextField/bug4741926.java JBR-9321 linux-6.14.9-arch1-1
|
||||
javax/swing/JFormattedTextField/TestSelectedTextBackgroundColor.java JBR-9100 linux-all
|
||||
javax/swing/JFrame/AlwaysOnTop/AlwaysOnTopImeTest.java JBR-9100 linux-all
|
||||
javax/swing/JFrame/HangNonVolatileBuffer/HangNonVolatileBuffer.java JBR-9100 linux-all
|
||||
@@ -54,7 +48,7 @@ javax/swing/JLayer/6824395/bug6824395.java JBR-9100 linux-all
|
||||
javax/swing/JLayer/8041982/bug8041982.java JBR-9100 linux-all
|
||||
javax/swing/JMenu/8178430/LabelDotTest.java JBR-9100 linux-all
|
||||
javax/swing/JPanel/bug4907772.java JBR-9100 linux-all
|
||||
javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java JBR-9277 linux-6.14.9-arch1-1
|
||||
javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java JBR-9100 linux-all
|
||||
javax/swing/JProgressBar/8161664/ProgressBarMemoryLeakTest.java JBR-9100 linux-all
|
||||
javax/swing/JProgressBar/TestJProgressBarHighlightColor.java JBR-9100 linux-all
|
||||
javax/swing/JScrollPane/bug8044371.java JBR-9100 linux-all
|
||||
@@ -63,7 +57,7 @@ javax/swing/JSlider/TestJSliderRendering.java JBR-9100 linux-all
|
||||
javax/swing/JSpinner/8008657/bug8008657.java JBR-9100 linux-all
|
||||
javax/swing/JSpinner/bug4656590.java JBR-9100 linux-all
|
||||
javax/swing/JSpinner/bug4680204.java JBR-9100 linux-all
|
||||
javax/swing/JSpinner/TestSelectedTextBackgroundColor.java JBR-9277 linux-6.14.9-arch1-1
|
||||
javax/swing/JSpinner/TestSelectedTextBackgroundColor.java JBR-9100 linux-all
|
||||
javax/swing/JSplitPane/4816114/bug4816114.java JBR-9100 linux-all
|
||||
javax/swing/JSplitPane/JSplitPaneTestNegDivSize.java JBR-9100 linux-all
|
||||
javax/swing/JTabbedPane/7170310/bug7170310.java JBR-9100 linux-all
|
||||
@@ -84,7 +78,6 @@ javax/swing/JTextPane/JTextPaneDocumentWrapping.java JBR-9100 linux-all
|
||||
javax/swing/JTextPane/TestJTextPaneBackgroundColor.java JBR-9100 linux-all
|
||||
javax/swing/JTree/8041705/DefaultTreeCellRendererBorderTest.java JBR-9100 linux-all
|
||||
javax/swing/JViewport/7107099/bug7107099.java JBR-9100 linux-all
|
||||
javax/swing/InputVerifier/VerifyTarget/VerifyTargetTest.java JBR-9320 linux-6.14.9-arch1-1
|
||||
javax/swing/LookAndFeel/8145547/DemandGTK.java JBR-9100 linux-all
|
||||
javax/swing/LookAndFeel/8145547/DemandGTK3.sh JBR-9100 linux-all
|
||||
javax/swing/plaf/basic/6866751/bug6866751.java JBR-9100 linux-all
|
||||
|
||||
@@ -1,10 +1,2 @@
|
||||
javax/swing/JFileChooser/6520101/bug6520101.java JBR-8434 linux-all
|
||||
javax/swing/JMenu/bug4342646.java JBR-8727 linux-all
|
||||
javax/swing/JTable/JTableRightOrientationTest.java JBR-8102 linux-all
|
||||
javax/swing/plaf/basic/BasicGraphicsUtils/8132119/bug8132119.java JBR-8357 linux-all
|
||||
javax/swing/text/ParagraphView/6364882/bug6364882.java JBR-8324 linux-all
|
||||
|
||||
jb/java/awt/wayland/vulkan/ImageTransformTest.java JBR-8434 linux-all
|
||||
jb/java/awt/wayland/vulkan/RobotGetPixelsTest.java JBR-8434 linux-all
|
||||
jb/java/awt/wayland/vulkan/RobotGetPixelTest.java JBR-8434 linux-all
|
||||
jb/java/awt/wayland/vulkan/VulkanMaskFillTest.java JBR-8434 linux-all
|
||||
javax/swing/plaf/basic/BasicGraphicsUtils/8132119/bug8132119.java JBR-8357 linux-all
|
||||
@@ -3,25 +3,28 @@ java/awt/MenuShortcut/FunctionKeyShortcut.java JBR-7932 linux-all
|
||||
java/awt/Multiscreen/MultiScreenCheckScreenIDTest.java JBR-8263 linux-x64
|
||||
java/awt/Multiscreen/UpdateGCTest/UpdateGCTest.java JBR-8264 linux-x64
|
||||
|
||||
javax/swing/JComponent/6989617/bug6989617.java JBR-8796 linux-6.14.0-1010-aws,linux-6.14.0-1012-aws,linux-6.14.0-1014-aws
|
||||
javax/swing/AbstractDocument/bug4549069.java JBR-8267 linux-6.14.0-1010-aws
|
||||
javax/swing/JComponent/6989617/bug6989617.java JBR-8796 linux-6.14.0-1010-aws
|
||||
javax/swing/JDesktopPane/TestDesktopManagerNPE.java JBR-8449 linux-x64
|
||||
javax/swing/GraphicsConfigNotifier/TestMultiScreenGConfigNotify.java JBR-8266 linux-x64
|
||||
javax/swing/InputVerifier/VerifyTarget/VerifyTargetTest.java JBR-7520,JBR-9320 linux-6.8.0-1036-aws,linux-6.8.0-1039-aws,linux-6.14.9-arch1-1
|
||||
javax/swing/JButton/SwingButtonResizeTestWithOpenGL.java#id0 JBR-7928,JBR-9341 linux-6.8.0-1036-aws,linux-6.8.0-1039-aws,linux-6.14.9-arch1-1
|
||||
javax/swing/JButton/SwingButtonResizeTestWithOpenGL.java#id2 JBR-7928,JBR-9341 linux-6.8.0-1036-aws,linux-6.8.0-1039-aws,linux-6.14.9-arch1-1
|
||||
javax/swing/InputVerifier/VerifyTarget/VerifyTargetTest.java JBR-7520 linux-all
|
||||
javax/swing/JButton/SwingButtonResizeTestWithOpenGL.java#id0 JBR-7928,JBR-8265 linux-all
|
||||
javax/swing/JButton/SwingButtonResizeTestWithOpenGL.java#id2 JBR-8265 linux-all
|
||||
javax/swing/JEditorPane/bug4325606.java JBR-8267 linux-aarch64
|
||||
javax/swing/JEditorPane/JEditorPaneFontFallback.java JBR-8305 linux-all
|
||||
javax/swing/JFormattedTextField/bug4741926.java JBR-7530,JBR-9321 linux-all,linux-6.14.9-arch1-1
|
||||
javax/swing/JFormattedTextField/bug4741926.java JBR-7530 linux-all
|
||||
javax/swing/JFormattedTextField/TestSelectedTextBackgroundColor.java JBR-8790 linux-all
|
||||
javax/swing/JInternalFrame/bug5009724.java JBR-7087 linux-all
|
||||
javax/swing/JMenu/JMenuSelectedColorTest.java JBR-8551 linux-all
|
||||
javax/swing/JPasswordField/TestSelectedTextBackgroundColor.java JBR-9277 linux-6.14.9-arch1-1
|
||||
javax/swing/JPopupMenu/7156657/bug7156657.java JBR-8210 linux-all
|
||||
javax/swing/JRadioButton/bug4823809.java JBR-7774 linux-all
|
||||
javax/swing/JSlider/TestJSliderRendering.java JBR-8551 linux-all
|
||||
javax/swing/JSpinner/TestSelectedTextBackgroundColor.java JBR-9277 linux-6.14.9-arch1-1
|
||||
javax/swing/JTabbedPane/6495408/bug6495408.java JBR-8267 linux-aarch64
|
||||
javax/swing/JToolTip/TestTooltipBackgroundColor.java JBR-8551 linux-all
|
||||
javax/swing/LookAndFeel/8145547/DemandGTK3.sh JBR-8274 linux-all
|
||||
javax/swing/text/html/CSS/bug8234913.java JBR-8306 linux-all
|
||||
javax/swing/text/ParagraphView/6364882/bug6364882.java JBR-8324 linux-all
|
||||
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-8304 linux-all
|
||||
|
||||
jb/java/awt/wayland/VulkanMaskFillTest.java JBR-8446 linux-6.8.0-1017-raspi
|
||||
jb/javax/swing/wayland/WLPopupMoves.java JBR-8296 linux-all
|
||||
jb/javax/swing/Popup/WLPopupMoves.java JBR-8296 linux-all
|
||||
@@ -1,5 +1,2 @@
|
||||
javax/swing/JFileChooser/6520101/bug6520101.java JBR-7140 linux-all
|
||||
javax/swing/JMenu/bug4342646.java JBR-8727 linux-all
|
||||
javax/swing/JTable/JTableRightOrientationTest.java JBR-8102 linux-all
|
||||
javax/swing/plaf/basic/BasicGraphicsUtils/8132119/bug8132119.java JBR-8357 linux-all
|
||||
javax/swing/text/ParagraphView/6364882/bug6364882.java JBR-8324 linux-all
|
||||
javax/swing/plaf/basic/BasicGraphicsUtils/8132119/bug8132119.java JBR-8357 linux-all
|
||||
@@ -1,601 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*/
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.CubicCurve2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.Timer;
|
||||
|
||||
import static java.lang.System.out;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8341381
|
||||
* @summary fix cubic offsetting issue (numerical accuracy)
|
||||
* @run main/othervm/timeout=20 Bug8341381
|
||||
* @modules java.desktop/sun.java2d.marlin
|
||||
*/
|
||||
public final class Bug8341381 {
|
||||
|
||||
static final boolean SHOW_GUI = false;
|
||||
|
||||
static final boolean CHECK_PIXELS = true;
|
||||
static final boolean TRACE_ALL = false;
|
||||
static final boolean TRACE_CHECK_PIXELS = false;
|
||||
|
||||
static final boolean SAVE_IMAGE = false;
|
||||
|
||||
static final boolean INTENSIVE = false;
|
||||
|
||||
static final double DPI = 96;
|
||||
static final float STROKE_WIDTH = 15f;
|
||||
|
||||
// delay is 1 frame at 60hz
|
||||
static final int DELAY = 16;
|
||||
// off-screen test step (1.0 by default)
|
||||
static final double STEP = (INTENSIVE) ? 1.0 / 117 : 1.0;
|
||||
|
||||
// stats:
|
||||
static int N_TEST = 0;
|
||||
static int N_FAIL = 0;
|
||||
|
||||
static final AtomicBoolean isMarlin = new AtomicBoolean();
|
||||
static final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
public static void main(final String[] args) {
|
||||
Locale.setDefault(Locale.US);
|
||||
|
||||
// FIRST: Get Marlin runtime state from its log:
|
||||
|
||||
// initialize j.u.l Logger:
|
||||
final Logger log = Logger.getLogger("sun.java2d.marlin");
|
||||
log.addHandler(new Handler() {
|
||||
@Override
|
||||
public void publish(LogRecord record) {
|
||||
final String msg = record.getMessage();
|
||||
if (msg != null) {
|
||||
// last space to avoid matching other settings:
|
||||
if (msg.startsWith("sun.java2d.renderer ")) {
|
||||
isMarlin.set(msg.contains("DMarlinRenderingEngine"));
|
||||
}
|
||||
}
|
||||
|
||||
final Throwable th = record.getThrown();
|
||||
// detect any Throwable:
|
||||
if (th != null) {
|
||||
out.println("Test failed:\n" + record.getMessage());
|
||||
th.printStackTrace(out);
|
||||
throw new RuntimeException("Test failed: ", th);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
}
|
||||
});
|
||||
|
||||
out.println("Bug8341381: start");
|
||||
final long startTime = System.currentTimeMillis();
|
||||
|
||||
// enable Marlin logging & internal checks:
|
||||
System.setProperty("sun.java2d.renderer.log", "true");
|
||||
System.setProperty("sun.java2d.renderer.useLogger", "true");
|
||||
|
||||
try {
|
||||
startTest();
|
||||
|
||||
out.println("WAITING ...");
|
||||
latch.await(15, TimeUnit.SECONDS); // 2s typically
|
||||
|
||||
if (isMarlin.get()) {
|
||||
out.println("Marlin renderer used at runtime.");
|
||||
} else {
|
||||
throw new RuntimeException("Marlin renderer NOT used at runtime !");
|
||||
}
|
||||
|
||||
// show test report:
|
||||
out.println("TESTS: " + N_TEST + " FAILS: " + N_FAIL);
|
||||
|
||||
if (N_FAIL > 0) {
|
||||
throw new RuntimeException("Bug8341381: " + N_FAIL + " / " + N_TEST + " test(s) failed !");
|
||||
}
|
||||
|
||||
} catch (InterruptedException ie) {
|
||||
throw new RuntimeException(ie);
|
||||
} catch (InvocationTargetException ite) {
|
||||
throw new RuntimeException(ite);
|
||||
} finally {
|
||||
final double elapsed = (System.currentTimeMillis() - startTime) / 1000.0;
|
||||
out.println("Bug8341381: end (" + elapsed + " s)");
|
||||
}
|
||||
}
|
||||
|
||||
private static void startTest() throws InterruptedException, InvocationTargetException {
|
||||
if (SHOW_GUI) {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final JFrame viewer = new JFrame();
|
||||
viewer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
viewer.setContentPane(new CanvasPanel(viewer));
|
||||
viewer.pack();
|
||||
viewer.setVisible(true);
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
out.println("STEP: " + STEP);
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Context ctx = new Context();
|
||||
final Dimension initialDim = ctx.bugDisplay.getSize(DPI);
|
||||
|
||||
double w = initialDim.width;
|
||||
double h = initialDim.height;
|
||||
do {
|
||||
ctx.shouldScale(w, h);
|
||||
ctx.paintImage();
|
||||
|
||||
// resize component:
|
||||
w -= STEP;
|
||||
h -= STEP;
|
||||
|
||||
} while (ctx.iterate());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
static final class Context {
|
||||
|
||||
final BugDisplay bugDisplay = new BugDisplay();
|
||||
double width = 0.0, height = 0.0;
|
||||
|
||||
BufferedImage bimg = null;
|
||||
|
||||
boolean shouldScale(final double w, final double h) {
|
||||
if ((w != width) || (h != height) || !bugDisplay.isScaled) {
|
||||
width = w;
|
||||
height = h;
|
||||
bugDisplay.scale(width, height);
|
||||
N_TEST++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void paintImage() {
|
||||
final int w = bugDisplay.canvasWidth;
|
||||
final int h = bugDisplay.canvasHeight;
|
||||
|
||||
if ((bimg == null) || (w > bimg.getWidth()) || (h > bimg.getHeight())) {
|
||||
bimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
}
|
||||
final Graphics gi = bimg.getGraphics();
|
||||
try {
|
||||
bugDisplay.paint(gi);
|
||||
} finally {
|
||||
gi.dispose();
|
||||
}
|
||||
if (!bugDisplay.checkImage(bimg)) {
|
||||
N_FAIL++;
|
||||
}
|
||||
}
|
||||
|
||||
boolean iterate() {
|
||||
if ((bugDisplay.canvasWidth > 10) || (bugDisplay.canvasHeight > 10)) {
|
||||
// continue:
|
||||
return true;
|
||||
}
|
||||
out.println("Stop");
|
||||
latch.countDown();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static final class CanvasPanel extends JPanel {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Context ctx = new Context();
|
||||
private boolean resized = false;
|
||||
private Timer timer = null;
|
||||
|
||||
public CanvasPanel(final JFrame frame) {
|
||||
timer = new Timer(DELAY, e -> {
|
||||
if (resized) {
|
||||
resized = false;
|
||||
|
||||
if (ctx.iterate()) {
|
||||
// resize component:
|
||||
setSize((int) Math.round(ctx.width - 1), (int) Math.round(ctx.height - 1));
|
||||
} else {
|
||||
timer.stop();
|
||||
if (frame != null) {
|
||||
frame.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
timer.setCoalesce(true);
|
||||
timer.setRepeats(true);
|
||||
timer.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(final Graphics g) {
|
||||
final Dimension dim = getSize();
|
||||
if (ctx.shouldScale(dim.width, dim.height)) {
|
||||
this.resized = true;
|
||||
}
|
||||
super.paint(g);
|
||||
|
||||
// paint on buffered image:
|
||||
if (CHECK_PIXELS) {
|
||||
final int w = ctx.bugDisplay.canvasWidth;
|
||||
final int h = ctx.bugDisplay.canvasHeight;
|
||||
if (this.resized) {
|
||||
ctx.paintImage();
|
||||
}
|
||||
g.drawImage(ctx.bimg.getSubimage(0, 0, w, h), 0, 0, null);
|
||||
} else {
|
||||
ctx.bugDisplay.paint(g);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return ctx.bugDisplay.getSize(DPI);
|
||||
}
|
||||
}
|
||||
|
||||
static final class BugDisplay {
|
||||
|
||||
boolean isScaled = false;
|
||||
int canvasWidth;
|
||||
int canvasHeight;
|
||||
|
||||
private final static java.util.List<CubicCurve2D> curves1 = Arrays.asList(
|
||||
new CubicCurve2D.Double(2191.0, 7621.0, 2191.0, 7619.0, 2191.0, 7618.0, 2191.0, 7617.0),
|
||||
new CubicCurve2D.Double(2191.0, 7617.0, 2191.0, 7617.0, 2191.0, 7616.0, 2191.0, 7615.0),
|
||||
new CubicCurve2D.Double(2198.0, 7602.0, 2200.0, 7599.0, 2203.0, 7595.0, 2205.0, 7590.0),
|
||||
new CubicCurve2D.Double(2205.0, 7590.0, 2212.0, 7580.0, 2220.0, 7571.0, 2228.0, 7563.0),
|
||||
new CubicCurve2D.Double(2228.0, 7563.0, 2233.0, 7557.0, 2239.0, 7551.0, 2245.0, 7546.0),
|
||||
new CubicCurve2D.Double(2245.0, 7546.0, 2252.0, 7540.0, 2260.0, 7534.0, 2267.0, 7528.0),
|
||||
new CubicCurve2D.Double(2267.0, 7528.0, 2271.0, 7526.0, 2275.0, 7524.0, 2279.0, 7521.0),
|
||||
new CubicCurve2D.Double(2279.0, 7521.0, 2279.0, 7520.0, 2280.0, 7520.0, 2281.0, 7519.0)
|
||||
);
|
||||
private final static java.util.List<CubicCurve2D> curves2 = Arrays.asList(
|
||||
new CubicCurve2D.Double(2281.0, 7519.0, 2282.0, 7518.0, 2282.0, 7517.0, 2283.0, 7516.0),
|
||||
new CubicCurve2D.Double(2283.0, 7516.0, 2284.0, 7515.0, 2284.0, 7515.0, 2285.0, 7514.0),
|
||||
new CubicCurve2D.Double(2291.0, 7496.0, 2292.0, 7495.0, 2292.0, 7494.0, 2291.0, 7493.0),
|
||||
new CubicCurve2D.Double(2291.0, 7493.0, 2290.0, 7492.0, 2290.0, 7492.0, 2289.0, 7492.0),
|
||||
new CubicCurve2D.Double(2289.0, 7492.0, 2288.0, 7491.0, 2286.0, 7492.0, 2285.0, 7492.0),
|
||||
new CubicCurve2D.Double(2262.0, 7496.0, 2260.0, 7497.0, 2259.0, 7497.0, 2257.0, 7498.0),
|
||||
new CubicCurve2D.Double(2257.0, 7498.0, 2254.0, 7498.0, 2251.0, 7499.0, 2248.0, 7501.0),
|
||||
new CubicCurve2D.Double(2248.0, 7501.0, 2247.0, 7501.0, 2245.0, 7502.0, 2244.0, 7503.0),
|
||||
new CubicCurve2D.Double(2207.0, 7523.0, 2203.0, 7525.0, 2199.0, 7528.0, 2195.0, 7530.0),
|
||||
new CubicCurve2D.Double(2195.0, 7530.0, 2191.0, 7534.0, 2186.0, 7538.0, 2182.0, 7541.0)
|
||||
);
|
||||
private final static java.util.List<CubicCurve2D> curves3 = Arrays.asList(
|
||||
new CubicCurve2D.Double(2182.0, 7541.0, 2178.0, 7544.0, 2174.0, 7547.0, 2170.0, 7551.0),
|
||||
new CubicCurve2D.Double(2170.0, 7551.0, 2164.0, 7556.0, 2158.0, 7563.0, 2152.0, 7569.0),
|
||||
new CubicCurve2D.Double(2152.0, 7569.0, 2148.0, 7573.0, 2145.0, 7577.0, 2141.0, 7582.0),
|
||||
new CubicCurve2D.Double(2141.0, 7582.0, 2138.0, 7588.0, 2134.0, 7595.0, 2132.0, 7602.0),
|
||||
new CubicCurve2D.Double(2132.0, 7602.0, 2132.0, 7605.0, 2131.0, 7608.0, 2131.0, 7617.0),
|
||||
new CubicCurve2D.Double(2131.0, 7617.0, 2131.0, 7620.0, 2131.0, 7622.0, 2131.0, 7624.0),
|
||||
new CubicCurve2D.Double(2131.0, 7624.0, 2131.0, 7630.0, 2132.0, 7636.0, 2135.0, 7641.0),
|
||||
new CubicCurve2D.Double(2135.0, 7641.0, 2136.0, 7644.0, 2137.0, 7647.0, 2139.0, 7650.0),
|
||||
new CubicCurve2D.Double(2139.0, 7650.0, 2143.0, 7658.0, 2149.0, 7664.0, 2155.0, 7670.0),
|
||||
new CubicCurve2D.Double(2155.0, 7670.0, 2160.0, 7676.0, 2165.0, 7681.0, 2171.0, 7686.0)
|
||||
);
|
||||
private final static java.util.List<CubicCurve2D> curves4 = Arrays.asList(
|
||||
new CubicCurve2D.Double(2171.0, 7686.0, 2174.0, 7689.0, 2177.0, 7692.0, 2180.0, 7694.0),
|
||||
new CubicCurve2D.Double(2180.0, 7694.0, 2185.0, 7698.0, 2191.0, 7702.0, 2196.0, 7706.0),
|
||||
new CubicCurve2D.Double(2196.0, 7706.0, 2199.0, 7708.0, 2203.0, 7711.0, 2207.0, 7713.0),
|
||||
new CubicCurve2D.Double(2244.0, 7734.0, 2245.0, 7734.0, 2247.0, 7735.0, 2248.0, 7736.0),
|
||||
new CubicCurve2D.Double(2248.0, 7736.0, 2251.0, 7738.0, 2254.0, 7739.0, 2257.0, 7739.0),
|
||||
new CubicCurve2D.Double(2257.0, 7739.0, 2259.0, 7739.0, 2260.0, 7739.0, 2262.0, 7740.0),
|
||||
new CubicCurve2D.Double(2285.0, 7745.0, 2286.0, 7745.0, 2288.0, 7745.0, 2289.0, 7745.0),
|
||||
new CubicCurve2D.Double(2289.0, 7745.0, 2290.0, 7745.0, 2290.0, 7744.0, 2291.0, 7743.0),
|
||||
new CubicCurve2D.Double(2291.0, 7743.0, 2292.0, 7742.0, 2292.0, 7741.0, 2291.0, 7740.0),
|
||||
new CubicCurve2D.Double(2285.0, 7722.0, 2284.0, 7721.0, 2284.0, 7721.0, 2283.0, 7720.0),
|
||||
new CubicCurve2D.Double(2283.0, 7720.0, 2282.0, 7719.0, 2282.0, 7719.0, 2281.0, 7718.0),
|
||||
new CubicCurve2D.Double(2281.0, 7718.0, 2280.0, 7717.0, 2279.0, 7716.0, 2279.0, 7716.0),
|
||||
new CubicCurve2D.Double(2279.0, 7716.0, 2275.0, 7712.0, 2271.0, 7710.0, 2267.0, 7708.0),
|
||||
new CubicCurve2D.Double(2267.0, 7708.0, 2260.0, 7702.0, 2252.0, 7697.0, 2245.0, 7691.0),
|
||||
new CubicCurve2D.Double(2245.0, 7691.0, 2239.0, 7685.0, 2233.0, 7679.0, 2228.0, 7673.0),
|
||||
new CubicCurve2D.Double(2228.0, 7673.0, 2220.0, 7665.0, 2212.0, 7656.0, 2205.0, 7646.0),
|
||||
new CubicCurve2D.Double(2205.0, 7646.0, 2203.0, 7641.0, 2200.0, 7637.0, 2198.0, 7634.0)
|
||||
);
|
||||
|
||||
private final static Point2D.Double[] extent = {new Point2D.Double(0.0, 0.0), new Point2D.Double(7777.0, 10005.0)};
|
||||
|
||||
private final static Stroke STROKE = new BasicStroke(STROKE_WIDTH);
|
||||
private final static Stroke STROKE_DASHED = new BasicStroke(STROKE_WIDTH, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL,
|
||||
10.0f, new float[] {100f, 0f}, 0.0f);
|
||||
|
||||
// members:
|
||||
private final java.util.List<CubicCurve2D> allCurves = new ArrayList<>();
|
||||
private final Rectangle2D bboxAllCurves = new Rectangle2D.Double();
|
||||
|
||||
BugDisplay() {
|
||||
allCurves.addAll(curves1);
|
||||
allCurves.addAll(curves2);
|
||||
allCurves.addAll(curves3);
|
||||
allCurves.addAll(curves4);
|
||||
|
||||
// initialize bounding box:
|
||||
double x1 = Double.POSITIVE_INFINITY;
|
||||
double y1 = Double.POSITIVE_INFINITY;
|
||||
double x2 = Double.NEGATIVE_INFINITY;
|
||||
double y2 = Double.NEGATIVE_INFINITY;
|
||||
|
||||
for (final CubicCurve2D c : allCurves) {
|
||||
final Rectangle2D r = c.getBounds2D();
|
||||
if (r.getMinX() < x1) {
|
||||
x1 = r.getMinX();
|
||||
}
|
||||
if (r.getMinY() < y1) {
|
||||
y1 = r.getMinY();
|
||||
}
|
||||
if (r.getMaxX() > x2) {
|
||||
x2 = r.getMaxX();
|
||||
}
|
||||
if (r.getMaxY() > y2) {
|
||||
y2 = r.getMaxY();
|
||||
}
|
||||
}
|
||||
// add margin of 10%:
|
||||
final double m = 1.1 * STROKE_WIDTH;
|
||||
bboxAllCurves.setFrameFromDiagonal(x1 - m, y1 - m, x2 + m, y2 + m);
|
||||
}
|
||||
|
||||
public void paint(final Graphics g) {
|
||||
final Graphics2D g2d = (Graphics2D) g;
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
|
||||
|
||||
// ------ scale
|
||||
final AffineTransform tx_orig = g2d.getTransform();
|
||||
final AffineTransform tx = getDrawTransform();
|
||||
g2d.transform(tx);
|
||||
|
||||
// draw bbox:
|
||||
if (!CHECK_PIXELS) {
|
||||
g2d.setColor(Color.RED);
|
||||
g2d.setStroke(STROKE);
|
||||
g2d.draw(bboxAllCurves);
|
||||
}
|
||||
// draw curves:
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
|
||||
g2d.setColor(Color.BLACK);
|
||||
|
||||
// dasher + stroker:
|
||||
g2d.setStroke(STROKE_DASHED);
|
||||
this.allCurves.forEach(g2d::draw);
|
||||
|
||||
// reset
|
||||
g2d.setTransform(tx_orig);
|
||||
}
|
||||
|
||||
private AffineTransform getDrawTransform() {
|
||||
// ------ scale
|
||||
double minX = extent[0].x, maxX = extent[1].x;
|
||||
double minY = extent[0].y, maxY = extent[1].y;
|
||||
|
||||
// we're scaling and respecting the proportions, check which scale to use
|
||||
double sx = this.canvasWidth / Math.abs(maxX - minX);
|
||||
double sy = this.canvasHeight / Math.abs(maxY - minY);
|
||||
double s = Math.min(sx, sy);
|
||||
|
||||
double m00, m11, m02, m12;
|
||||
if (minX < maxX) {
|
||||
m00 = s;
|
||||
m02 = -s * minX;
|
||||
} else {
|
||||
// inverted X axis
|
||||
m00 = -s;
|
||||
m02 = this.canvasWidth + s * maxX;
|
||||
}
|
||||
if (minY < maxY) {
|
||||
m11 = s;
|
||||
m12 = -s * minY;
|
||||
} else {
|
||||
// inverted Y axis
|
||||
m11 = -s;
|
||||
m12 = this.canvasHeight + s * maxY;
|
||||
}
|
||||
|
||||
// scale to the available view port
|
||||
AffineTransform scaleTransform = new AffineTransform(m00, 0, 0, m11, m02, m12);
|
||||
|
||||
// invert the Y axis since (0, 0) is at top left for AWT
|
||||
AffineTransform invertY = new AffineTransform(1, 0, 0, -1, 0, this.canvasHeight);
|
||||
invertY.concatenate(scaleTransform);
|
||||
|
||||
return invertY;
|
||||
}
|
||||
|
||||
public Dimension getSize(double dpi) {
|
||||
double metricScalingFactor = 0.02539999969303608;
|
||||
// 1 inch = 25,4 millimeter
|
||||
final double factor = dpi * metricScalingFactor / 25.4;
|
||||
|
||||
int width = (int) Math.ceil(Math.abs(extent[1].x - extent[0].x) * factor);
|
||||
int height = (int) Math.ceil(Math.abs(extent[1].y - extent[0].y) * factor);
|
||||
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
|
||||
public void scale(double w, double h) {
|
||||
double extentWidth = Math.abs(extent[1].x - extent[0].x);
|
||||
double extentHeight = Math.abs(extent[1].y - extent[0].y);
|
||||
|
||||
double fx = w / extentWidth;
|
||||
if (fx * extentHeight > h) {
|
||||
fx = h / extentHeight;
|
||||
}
|
||||
this.canvasWidth = (int) Math.round(fx * extentWidth);
|
||||
this.canvasHeight = (int) Math.round(fx * extentHeight);
|
||||
|
||||
// out.println("canvas scaled (" + canvasWidth + " x " + canvasHeight + ")");
|
||||
|
||||
this.isScaled = true;
|
||||
}
|
||||
|
||||
protected boolean checkImage(BufferedImage image) {
|
||||
final AffineTransform tx = getDrawTransform();
|
||||
|
||||
final Point2D pMin = new Point2D.Double(bboxAllCurves.getMinX(), bboxAllCurves.getMinY());
|
||||
final Point2D pMax = new Point2D.Double(bboxAllCurves.getMaxX(), bboxAllCurves.getMaxY());
|
||||
|
||||
final Point2D tMin = tx.transform(pMin, null);
|
||||
final Point2D tMax = tx.transform(pMax, null);
|
||||
|
||||
int xMin = (int) tMin.getX();
|
||||
int xMax = (int) tMax.getX();
|
||||
if (xMin > xMax) {
|
||||
int t = xMin;
|
||||
xMin = xMax;
|
||||
xMax = t;
|
||||
}
|
||||
|
||||
int yMin = (int) tMin.getY();
|
||||
int yMax = (int) tMax.getY();
|
||||
if (yMin > yMax) {
|
||||
int t = yMin;
|
||||
yMin = yMax;
|
||||
yMax = t;
|
||||
}
|
||||
// add pixel margin (AA):
|
||||
xMin -= 3;
|
||||
xMax += 4;
|
||||
yMin -= 3;
|
||||
yMax += 4;
|
||||
|
||||
if (xMin < 0 || xMax > image.getWidth()
|
||||
|| yMin < 0 || yMax > image.getHeight()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// out.println("Checking rectangle: " + tMin + " to " + tMax);
|
||||
// out.println("X min: " + xMin + " - max: " + xMax);
|
||||
// out.println("Y min: " + yMin + " - max: " + yMax);
|
||||
|
||||
final Raster raster = image.getData();
|
||||
final int expected = Color.WHITE.getRGB();
|
||||
int nBadPixels = 0;
|
||||
|
||||
// horizontal lines:
|
||||
for (int x = xMin; x <= xMax; x++) {
|
||||
if (!checkPixel(raster, x, yMin, expected)) {
|
||||
nBadPixels++;
|
||||
}
|
||||
if (!checkPixel(raster, x, yMax, expected)) {
|
||||
nBadPixels++;
|
||||
}
|
||||
}
|
||||
|
||||
// vertical lines:
|
||||
for (int y = yMin; y <= yMax; y++) {
|
||||
if (!checkPixel(raster, xMin, y, expected)) {
|
||||
nBadPixels++;
|
||||
}
|
||||
if (!checkPixel(raster, xMax, y, expected)) {
|
||||
nBadPixels++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nBadPixels != 0) {
|
||||
out.println("(" + canvasWidth + " x " + canvasHeight + ") BAD pixels = " + nBadPixels);
|
||||
|
||||
if (SAVE_IMAGE) {
|
||||
try {
|
||||
final File file = new File("Bug8341381-" + canvasWidth + "-" + canvasHeight + ".png");
|
||||
|
||||
out.println("Writing file: " + file.getAbsolutePath());
|
||||
ImageIO.write(image.getSubimage(0, 0, canvasWidth, canvasHeight), "PNG", file);
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (TRACE_ALL) {
|
||||
out.println("(" + canvasWidth + " x " + canvasHeight + ") OK");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private final static int[] TMP_RGB = new int[1];
|
||||
|
||||
private static boolean checkPixel(final Raster raster,
|
||||
final int x, final int y,
|
||||
final int expected) {
|
||||
|
||||
final int[] rgb = (int[]) raster.getDataElements(x, y, TMP_RGB);
|
||||
|
||||
if (rgb[0] != expected) {
|
||||
if (TRACE_CHECK_PIXELS) {
|
||||
out.println("bad pixel at (" + x + ", " + y + ") = " + rgb[0]
|
||||
+ " expected = " + expected);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user