Compare commits

..

2 Commits

Author SHA1 Message Date
Vitaly Provodin
31cf28628c update exclude list on results of 25.0.1_272.54 test runs 2026-01-20 13:09:38 +04:00
Vitaly Provodin
f60cc8b407 JBR-9855 provide JBR25 with AL2 (glibc 2.26) support 2026-01-17 04:55:31 +04:00
12 changed files with 45 additions and 259 deletions

View File

@@ -245,10 +245,7 @@ public abstract class FullFrameDecorationHelper extends FrameDecoration {
}
if (e.getID() == MouseEvent.MOUSE_PRESSED) {
pressedLocation = point;
} else if (e.getID() == MouseEvent.MOUSE_DRAGGED
&& pressedLocation != null
&& pressedInDragStartArea(pressedLocation)
&& isSignificantDrag(point)) {
} else if (e.getID() == MouseEvent.MOUSE_DRAGGED && pressedInDragStartArea(point) && isSignificantDrag(point)) {
startDrag();
} else if (e.getID() == MouseEvent.MOUSE_CLICKED && e.getClickCount() == 2 && pressedInDragStartArea(point)
&& peer.isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {

View File

@@ -34,7 +34,6 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
public final class WLClipboard extends SunClipboard {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLClipboard");
@@ -62,10 +61,6 @@ public final class WLClipboard extends SunClipboard {
// Guarded by dataLock.
private WLDataSource ourDataSource;
// Set when announcing a clipboard data source to a random value
// Guarded by dataLock.
private String ourDataSourceCookie = null;
static {
flavorTable = DataTransferer.adaptFlavorMap(getDefaultFlavorTable());
}
@@ -82,10 +77,6 @@ public final class WLClipboard extends SunClipboard {
}
}
private static String generateRandomMimeTypeCookie() {
return "JAVA_DATATRANSFER_COOKIE_" + UUID.randomUUID();
}
private int getProtocol() {
if (isPrimary) {
return WLDataDevice.DATA_TRANSFER_PROTOCOL_PRIMARY_SELECTION;
@@ -155,26 +146,14 @@ public final class WLClipboard extends SunClipboard {
log.fine("Clipboard: Offering new contents (" + contents + ")");
}
WLDataSource newOffer = new WLDataSource(dataDevice, getProtocol(), contents) {
@Override
protected void handleCancelled() {
synchronized (dataLock) {
if (ourDataSource == this) {
ourDataSource = null;
ourDataSourceCookie = null;
}
destroy();
}
}
};
WLDataSource newOffer = null;
newOffer = new WLDataSource(dataDevice, getProtocol(), contents);
synchronized (dataLock) {
if (ourDataSource != null) {
ourDataSource.destroy();
}
ourDataSource = newOffer;
ourDataSourceCookie = generateRandomMimeTypeCookie();
ourDataSource.offerExtraMime(ourDataSourceCookie);
dataDevice.setSelection(getProtocol(), newOffer, eventSerial);
}
}
@@ -261,11 +240,9 @@ public final class WLClipboard extends SunClipboard {
}
void handleClipboardOffer(WLDataOffer offer /* nullable */) {
synchronized (dataLock) {
if (offer == null || ourDataSourceCookie == null || !offer.getMimes().contains(ourDataSourceCookie)) {
lostOwnershipNow(null);
}
lostOwnershipNow(null);
synchronized (dataLock) {
if (clipboardDataOfferedToUs != null) {
clipboardDataOfferedToUs.destroy();
}

View File

@@ -1143,14 +1143,6 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
}
}
final void reactivate(long serial, long surface) {
performLocked(() -> {
if (serial != 0 &&wlSurface != null && surface != 0) {
wlSurface.activateByAnotherSurface(serial, surface);
}
});
}
private static long getSerialForActivation() {
long serial;
if (WLToolkit.isKDE()) {
@@ -1240,14 +1232,14 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
* the freshly updated WLInputState, and the previous WLInputState.
*/
void dispatchPointerEventInContext(WLPointerEvent e, WLInputState oldInputState, WLInputState newInputState) {
final long timestamp = System.currentTimeMillis();
final int x = newInputState.getPointerX();
final int y = newInputState.getPointerY();
final Point abs = relativePointToAbsolute(new Point(x, y));
int xAbsolute = abs.x;
int yAbsolute = abs.y;
final long timestamp = newInputState.getTimestamp();
if (e.hasEnterEvent()) {
updateCursorImmediately();
final MouseEvent mouseEvent = new MouseEvent(getTarget(), MouseEvent.MOUSE_ENTERED,
@@ -1283,7 +1275,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
postMouseEvent(mouseEvent);
final boolean isButtonReleased = !e.getIsButtonPressed();
final boolean wasSameButtonPressed = oldInputState.hasThisPointerButtonPressedAt(e.getButtonCode(), x, y);
final boolean wasSameButtonPressed = oldInputState.hasThisPointerButtonPressed(e.getButtonCode());
final boolean isButtonClicked = isButtonReleased && wasSameButtonPressed;
if (isButtonClicked) {
final MouseEvent mouseClickEvent = new MouseEvent(getTarget(),

View File

@@ -121,13 +121,6 @@ public class WLDataSource {
setDnDIconImpl(nativePtr, scale, width, height, offsetX, offsetY, pixels);
}
public void offerExtraMime(String mime) {
if (nativePtr == 0) {
throw new IllegalStateException("Native pointer is null");
}
offerMimeImpl(nativePtr, mime);
}
public synchronized void destroy() {
if (nativePtr != 0) {
destroyImpl(nativePtr);

View File

@@ -24,13 +24,8 @@
*/
package sun.awt.wl;
import sun.awt.AWTAccessor;
import java.awt.Dialog;
import java.awt.Frame;
import java.awt.Window;
import java.awt.*;
import java.awt.peer.DialogPeer;
import java.awt.peer.WindowPeer;
import java.util.List;
public class WLDialogPeer extends WLDecoratedPeer implements DialogPeer {
@@ -46,12 +41,7 @@ public class WLDialogPeer extends WLDecoratedPeer implements DialogPeer {
@Override
public void blockWindows(List<Window> windows) {
for (Window w : windows) {
WindowPeer wp = AWTAccessor.getComponentAccessor().getPeer(w);
if (wp != null) {
wp.setModalBlocked((Dialog)getTarget(), true);
}
}
}
@Override

View File

@@ -35,10 +35,7 @@ import java.awt.GraphicsDevice;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Window;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
@@ -122,7 +119,7 @@ public class WLGraphicsDevice extends GraphicsDevice {
* Top-level window peers that consider this device as their primary one
* and get their graphics configuration from it
*/
private final Set<WeakReference<WLComponentPeer>> toplevels = new HashSet<>(); // guarded by 'this'
private final Set<WLComponentPeer> toplevels = new HashSet<>(); // guarded by 'this'
private WLGraphicsDevice(int id,
String name,
@@ -208,14 +205,9 @@ public class WLGraphicsDevice extends GraphicsDevice {
}
private void notifyToplevels() {
List<WLComponentPeer> toplevelsCopy = new ArrayList<>(toplevels.size());
Set<WLComponentPeer> toplevelsCopy = new HashSet<>(toplevels.size());
synchronized (this) {
for (var toplevel: toplevels) {
WLComponentPeer peer = toplevel.get();
if (peer != null) {
toplevelsCopy.add(peer);
}
}
toplevelsCopy.addAll(toplevels);
}
toplevelsCopy.forEach(WLComponentPeer::checkIfOnNewScreen);
}
@@ -377,16 +369,13 @@ public class WLGraphicsDevice extends GraphicsDevice {
public void addWindow(WLComponentPeer peer) {
synchronized (this) {
toplevels.add(new WeakReference<>(peer));
toplevels.add(peer);
}
}
public void removeWindow(WLComponentPeer peer) {
synchronized (this) {
toplevels.removeIf(ref -> {
WLComponentPeer p = ref.get();
return p == null || p == peer;
});
toplevels.remove(peer);
}
}

View File

@@ -295,9 +295,8 @@ record WLInputState(WLPointerEvent eventWithSurface,
return newModifiers;
}
public boolean hasThisPointerButtonPressedAt(int linuxCode, long x, long y) {
return pointerButtonPressedEvent != null && pointerButtonPressedEvent.linuxCode == linuxCode
&& pointerButtonPressedEvent.surfaceX == x && pointerButtonPressedEvent.surfaceY == y;
public boolean hasThisPointerButtonPressed(int linuxCode) {
return pointerButtonPressedEvent != null && pointerButtonPressedEvent.linuxCode == linuxCode;
}
public boolean hasPointerButtonPressed() {
@@ -354,12 +353,6 @@ record WLInputState(WLPointerEvent eventWithSurface,
return true;
}
/**
* @return the timestamp of the most recent known {@code wl_pointer::*} event or 0 if no such event is known.
*
* @apiNote don't use these timestamps for constructing any new {@link java.awt.event.InputEvent}s
* because they are not guaranteed to be based on the midnight of Jan 1, 1970 UTC.
*/
public long getTimestamp() {
return eventWithTimestamp != null ? eventWithTimestamp.getTimestamp() : 0;
}

View File

@@ -6,12 +6,11 @@ import sun.util.logging.PlatformLogger;
import java.awt.Component;
import java.awt.Window;
import java.lang.ref.WeakReference;
public class WLKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.wl.focus.WLKeyboardFocusManagerPeer");
private WeakReference<Window> currentFocusedWindow = new WeakReference<>(null);
private Window currentFocusedWindow;
private static final WLKeyboardFocusManagerPeer instance = new WLKeyboardFocusManagerPeer();
public static WLKeyboardFocusManagerPeer getInstance() {
@@ -24,14 +23,14 @@ public class WLKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
focusLog.finer("Current focused window -> " + win);
}
currentFocusedWindow = new WeakReference<>(win);
currentFocusedWindow = win;
}
}
@Override
public Window getCurrentFocusedWindow() {
synchronized (this) {
return currentFocusedWindow.get();
return currentFocusedWindow;
}
}
@@ -62,7 +61,7 @@ public class WLKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
@Override
public Component getCurrentFocusOwner() {
synchronized (this) {
return currentFocusedWindow.get();
return currentFocusedWindow;
}
}
}

View File

@@ -353,6 +353,7 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
}
private static void dispatchKeyboardKeyEvent(long serial,
long timestamp,
int id,
int keyCode,
int keyLocation,
@@ -363,10 +364,14 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
// Invoked from the native code
assert EventQueue.isDispatchThread() : "Method must only be invoked on EDT";
final long timestamp = System.currentTimeMillis();
inputState = inputState.updatedFromKeyEvent(serial);
if (timestamp == 0) {
// Happens when a surface was focused with keys already pressed.
// Fake the timestamp by peeking at the last known event.
timestamp = inputState.getTimestamp();
}
final long surfacePtr = inputState.surfaceForKeyboardInput();
final WLComponentPeer peer = peerFromSurface(surfacePtr);
if (peer != null) {
@@ -434,32 +439,22 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
+ Long.toHexString(surfacePtr));
}
final WLWindowPeer peer = peerFromSurface(surfacePtr);
final WLInputState newInputState = inputState.updatedFromKeyboardEnterEvent(serial, surfacePtr);
final WLWindowPeer peer = peerFromSurface(surfacePtr);
if (peer != null) {
Dialog blocker = peer.getBlocker();
if (blocker != null) { // Modality support
long activationSerial = serial;
if (WLToolkit.isKDE()) {
activationSerial = inputState.latestInputSerial();
}
WLWindowPeer blockerPeer = AWTAccessor.getComponentAccessor().getPeer(blocker);
blockerPeer.reactivate(activationSerial, surfacePtr);
} else {
Window window = (Window) peer.getTarget();
Window winToFocus = window;
Window window = (Window) peer.getTarget();
Window winToFocus = window;
Component s = peer.getSyntheticFocusOwner();
if (s instanceof Window synthWindow) {
if (synthWindow.isVisible() && synthWindow.isFocusableWindow()) {
winToFocus = synthWindow;
}
Component s = peer.getSyntheticFocusOwner();
if (s instanceof Window synthWindow) {
if (synthWindow.isVisible() && synthWindow.isFocusableWindow()) {
winToFocus = synthWindow;
}
WLKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(window);
WindowEvent windowEnterEvent = new WindowEvent(winToFocus, WindowEvent.WINDOW_GAINED_FOCUS);
postPriorityEvent(windowEnterEvent);
}
WLKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(window);
WindowEvent windowEnterEvent = new WindowEvent(winToFocus, WindowEvent.WINDOW_GAINED_FOCUS);
postPriorityEvent(windowEnterEvent);
}
inputState = newInputState;
}
@@ -475,13 +470,12 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
keyboard.onLostFocus();
WLKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null);
WLKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
final WLInputState newInputState = inputState.updatedFromKeyboardLeaveEvent(serial, surfacePtr);
final WLWindowPeer peer = peerFromSurface(surfacePtr);
if (peer != null && peer.getTarget() instanceof Window window) {
final WindowEvent winLostFocusEvent = new WindowEvent(window, WindowEvent.WINDOW_LOST_FOCUS);
WLKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null);
WLKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
postPriorityEvent(winLostFocusEvent);
}
inputState = newInputState;
@@ -1121,17 +1115,6 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
protected static void targetDisposedPeer(Object target, Object peer) {
SunToolkit.targetDisposedPeer(target, peer);
if (target instanceof Window window) {
// TODO: focusedWindow and activeWindow of class java.awt.KeyboardFocusManager
// may still retain references to 'window' because disposed peer may not
// get the keyboard_leave event and therefore will not send the WINDOW_LOST_FOCUS
// event that would've cleared those references.
var gc = window.getGraphicsConfiguration();
if (gc != null && peer instanceof WLWindowPeer windowPeer) {
WLGraphicsDevice gd = (WLGraphicsDevice) gc.getDevice();
gd.removeWindow(windowPeer);
}
}
}
static void postEvent(AWTEvent event) {

View File

@@ -58,7 +58,7 @@ import java.util.List;
public class WLWindowPeer extends WLComponentPeer implements WindowPeer, SurfacePixelGrabber {
private static Font defaultFont;
private Dialog blocker; // guarded by getStateLock()
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
@@ -180,15 +180,7 @@ public class WLWindowPeer extends WLComponentPeer implements WindowPeer, Surface
@Override
public void setModalBlocked(Dialog blocker, boolean blocked) {
synchronized (getStateLock()) {
this.blocker = blocked ? blocker : null;
}
}
public Dialog getBlocker() {
synchronized (getStateLock()) {
return blocker;
}
this.blocker = blocked ? blocker : null;
}
@Override

View File

@@ -454,6 +454,7 @@ wlPostKeyEvent(const struct WLKeyEvent* event)
tkClass,
dispatchKeyboardKeyEventMID,
event->serial,
event->timestamp,
event->id,
event->keyCode,
event->keyLocation,
@@ -806,7 +807,7 @@ initJavaRefs(JNIEnv *env, jclass clazz)
JNI_FALSE);
CHECK_NULL_RETURN(dispatchKeyboardKeyEventMID = (*env)->GetStaticMethodID(env, tkClass,
"dispatchKeyboardKeyEvent",
"(JIIIIICI)V"),
"(JJIIIIICI)V"),
JNI_FALSE);
CHECK_NULL_RETURN(dispatchKeyboardModifiersEventMID = (*env)->GetStaticMethodID(env, tkClass,
"dispatchKeyboardModifiersEvent",

View File

@@ -1,120 +0,0 @@
/*
* Copyright 2026 JetBrains s.r.o.
* Copyright (c) 2026, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @key headful
* @summary Tests that nothing prevents windows from being removed from the global list
* after they have been disposed
* @library /javax/swing/regtesthelpers
* @modules java.desktop/sun.awt
* java.desktop/sun.java2d
* @build Util
* @run main/othervm -Xms32M -Xmx32M WLWindowsLeak
*/
import java.awt.Color;
import java.awt.Frame;
import java.awt.Robot;
import java.awt.Window;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import com.sun.management.HotSpotDiagnosticMXBean;
import sun.awt.AppContext;
import sun.java2d.Disposer;
public class WLWindowsLeak {
public static final int WINDOWS_COUNT = 42;
private static volatile boolean disposerPhantomComplete;
public static void main(String[] args) throws Exception {
spawnWindows();
Disposer.addRecord(new Object(), () -> disposerPhantomComplete = true);
while (!disposerPhantomComplete) {
Util.generateOOME();
}
Vector<WeakReference<Window>> windowList =
(Vector<WeakReference<Window>>) AppContext.getAppContext().get(Window.class);
// Note: focusedWindow and activeWindow of class java.awt.KeyboardFocusManager
// may still retain references to the last window shown. This makes the test flaky and
// therefore less useful. Until this is fixed, the test allows for 1 retained window.
if (windowList != null && !windowList.isEmpty() && windowList.size() > 1) {
dumpHeap("heap_dump_live_windows.hprof");
System.out.println("Live window list:");
windowList.forEach(ref -> System.out.println(ref.get()));
throw new RuntimeException("Test FAILED: Window list is not empty: " + windowList.size());
}
System.out.println("Test PASSED");
}
private static void dumpHeap(String filePath) {
try {
HotSpotDiagnosticMXBean mxBean = ManagementFactory
.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
mxBean.dumpHeap(filePath, true); // true = live objects only
System.out.println("Heap dump created at: " + filePath);
} catch (IOException e) {
System.err.println("Failed to dump heap: " + e.getMessage());
}
}
private static void spawnWindows() throws Exception {
List<WeakReference<Frame>> frameList = new ArrayList<>();
Robot r = new Robot();
for (int i = 0; i < WINDOWS_COUNT; i++) {
Frame f = new Frame(String.format("Frame %d", i));
f.setBackground(Color.WHITE);
f.setSize(100, 100);
f.setVisible(true);
frameList.add(new WeakReference<>(f));
Thread.sleep(42);
}
r.waitForIdle();
frameList.forEach(ref -> {
ref.get().setVisible(false);
});
r.waitForIdle();
frameList.forEach(ref -> {
var f = ref.get();
if (f != null) f.dispose();
});
frameList.clear();
r.waitForIdle(); // to make sure no events hold a reference to frames
System.gc();
}
}