mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
JBR-6783 MouseEvent/MenuDragMouseEventAbsoluteCoordsTest/MenuDragMouseEventAbsoluteCoordsTest.java: Found one Java-level deadlock
This commit is contained in:
committed by
Maxim Kartashёv
parent
01d4fd6334
commit
3058c046ad
@@ -85,18 +85,18 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
private static final int MINIMUM_WIDTH = 1;
|
||||
private static final int MINIMUM_HEIGHT = 1;
|
||||
|
||||
private long nativePtr;
|
||||
private long nativePtr; // accessed under AWT lock
|
||||
private volatile boolean surfaceAssigned = false;
|
||||
protected final Component target;
|
||||
|
||||
// Graphics devices this top-level component is visible on
|
||||
protected final java.util.List<WLGraphicsDevice> devices = new ArrayList<>();
|
||||
|
||||
protected Color background;
|
||||
SurfaceData surfaceData;
|
||||
WLRepaintArea paintArea;
|
||||
boolean paintPending = false;
|
||||
boolean isLayouting = false;
|
||||
protected Color background; // protected by dataLock
|
||||
SurfaceData surfaceData; // accessed under AWT lock
|
||||
final WLRepaintArea paintArea;
|
||||
boolean paintPending = false; // protected by dataLock
|
||||
boolean isLayouting = false; // protected by dataLock
|
||||
boolean visible = false;
|
||||
|
||||
private final Object dataLock = new Object();
|
||||
@@ -143,7 +143,9 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
|
||||
public Color getBackground() {
|
||||
return background;
|
||||
synchronized (dataLock) {
|
||||
return background;
|
||||
}
|
||||
}
|
||||
|
||||
public void postPaintEvent(int x, int y, int w, int h) {
|
||||
@@ -158,9 +160,7 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
|
||||
void postPaintEvent() {
|
||||
if (isVisible()) {
|
||||
synchronized (dataLock) {
|
||||
postPaintEvent(0, 0, width, height);
|
||||
}
|
||||
postPaintEvent(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,12 +179,13 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
|
||||
@Override
|
||||
public boolean isReparentSupported() {
|
||||
throw new UnsupportedOperationException();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObscured() {
|
||||
throw new UnsupportedOperationException();
|
||||
// In general, it is impossible to know this in Wayland
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -322,13 +323,11 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
|
||||
void configureWLSurface() {
|
||||
synchronized (dataLock) {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine(String.format("%s is configured to %dx%d with %dx scale", this, getBufferWidth(), getBufferHeight(), getBufferScale()));
|
||||
}
|
||||
SurfaceData.convertTo(WLSurfaceDataExt.class, surfaceData).revalidate(
|
||||
getBufferWidth(), getBufferHeight(), getBufferScale());
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine(String.format("%s is configured to %dx%d with %dx scale", this, getBufferWidth(), getBufferHeight(), getBufferScale()));
|
||||
}
|
||||
SurfaceData.convertTo(WLSurfaceDataExt.class, surfaceData).revalidate(
|
||||
getBufferWidth(), getBufferHeight(), getBufferScale());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -407,10 +406,8 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
|
||||
private void setLocationTo(int newX, int newY) {
|
||||
synchronized (dataLock) {
|
||||
var acc = AWTAccessor.getComponentAccessor();
|
||||
acc.setLocation(target, newX, newY);
|
||||
}
|
||||
var acc = AWTAccessor.getComponentAccessor();
|
||||
acc.setLocation(target, newX, newY);
|
||||
}
|
||||
|
||||
public void setBounds(int newX, int newY, int newWidth, int newHeight, int op) {
|
||||
@@ -451,8 +448,8 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
|
||||
private void setSizeTo(int newWidth, int newHeight) {
|
||||
Dimension newSize = constrainSize(newWidth, newHeight);
|
||||
synchronized (dataLock) {
|
||||
Dimension newSize = constrainSize(newWidth, newHeight);
|
||||
this.width = newSize.width;
|
||||
this.height = newSize.height;
|
||||
}
|
||||
@@ -663,21 +660,29 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
|
||||
public void beginLayout() {
|
||||
// Skip all painting till endLayout
|
||||
isLayouting = true;
|
||||
synchronized (dataLock) {
|
||||
isLayouting = true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean needPaintEvent() {
|
||||
synchronized (dataLock) {
|
||||
// If not waiting for native painting, repaint the damaged area
|
||||
return !paintPending && !paintArea.isEmpty()
|
||||
&& !AWTAccessor.getComponentAccessor().getIgnoreRepaint(target);
|
||||
}
|
||||
}
|
||||
|
||||
public void endLayout() {
|
||||
if (log.isLoggable(Level.FINE)) {
|
||||
log.fine("WLComponentPeer.endLayout(): paintArea.isEmpty() " + paintArea.isEmpty());
|
||||
}
|
||||
if (!paintPending && !paintArea.isEmpty()
|
||||
&& !AWTAccessor.getComponentAccessor().getIgnoreRepaint(target)) {
|
||||
// if not waiting for native painting repaint damaged area
|
||||
WLToolkit.postEvent(new PaintEvent(target, PaintEvent.PAINT,
|
||||
new Rectangle()));
|
||||
if (needPaintEvent()) {
|
||||
WLToolkit.postEvent(new PaintEvent(target, PaintEvent.PAINT, new Rectangle()));
|
||||
}
|
||||
synchronized (dataLock) {
|
||||
isLayouting = false;
|
||||
}
|
||||
isLayouting = false;
|
||||
}
|
||||
|
||||
public Dimension getMinimumSize() {
|
||||
@@ -717,11 +722,13 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
|
||||
@Override
|
||||
public void setBackground(Color c) {
|
||||
if (Objects.equals(background, c)) {
|
||||
return;
|
||||
synchronized (dataLock) {
|
||||
if (Objects.equals(background, c)) {
|
||||
return;
|
||||
}
|
||||
background = c;
|
||||
// TODO: propagate this change to WLSurfaceData
|
||||
}
|
||||
background = c;
|
||||
// TODO: propagate this change to WLSurfaceData
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1015,7 +1022,7 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
final long timestamp = newInputState.getTimestamp();
|
||||
|
||||
if (e.hasEnterEvent()) {
|
||||
updateCursorImmediately(newInputState);
|
||||
performUnlocked(() -> updateCursorImmediately(newInputState));
|
||||
final MouseEvent mouseEvent = new MouseEvent(getTarget(), MouseEvent.MOUSE_ENTERED,
|
||||
timestamp,
|
||||
newInputState.getModifiers(),
|
||||
@@ -1119,9 +1126,10 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
|
||||
void notifyConfigured(int newX, int newY, int newWidth, int newHeight, boolean active, boolean maximized) {
|
||||
final long wlSurfacePtr = getWLSurface(nativePtr);
|
||||
// TODO: this needs to be done only once after wlSetVisible(true)
|
||||
SurfaceData.convertTo(WLSurfaceDataExt.class, surfaceData).assignSurface(wlSurfacePtr);
|
||||
surfaceAssigned = true;
|
||||
if (!surfaceAssigned) {
|
||||
SurfaceData.convertTo(WLSurfaceDataExt.class, surfaceData).assignSurface(wlSurfacePtr);
|
||||
surfaceAssigned = true;
|
||||
}
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine(String.format("%s configured to %dx%d", this, newWidth, newHeight));
|
||||
}
|
||||
@@ -1213,8 +1221,10 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
if (log.isLoggable(Level.FINE)) {
|
||||
log.fine(this + " is on (possibly) new device " + newDevice);
|
||||
}
|
||||
var acc = AWTAccessor.getComponentAccessor();
|
||||
acc.setGraphicsConfiguration(target, gc);
|
||||
performUnlocked(() -> {
|
||||
var acc = AWTAccessor.getComponentAccessor();
|
||||
acc.setGraphicsConfiguration(target, gc);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1294,6 +1304,15 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
}
|
||||
|
||||
static <T> T performUnlocked(Supplier<T> task) {
|
||||
WLToolkit.awtUnlock();
|
||||
try {
|
||||
return task.get();
|
||||
} finally {
|
||||
WLToolkit.awtLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void startMovingWindowTogetherWithMouse(Window window, int mouseButton)
|
||||
{
|
||||
if (isWlPopup(window)) return; // xdg_popup's do not support the necessary interface
|
||||
|
||||
Reference in New Issue
Block a user