mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-10 10:31:39 +01:00
JBR-5274 recreate CGraphicsDevice if it was changed.
- AWT code heavily relies on reference comparison when updating graphics devices & configurations, so we need to actually re-create CGraphicsDevice if it was changed. - Also do not rely on graphicsConfig.getDefaultTransform() when firing `graphicsContextScaleTransform` property change, as graphics devices are mutable and returned default transform may change over time, e.g. when device is invalidated.
This commit is contained in:
@@ -92,12 +92,14 @@ public final class CGraphicsDevice extends GraphicsDevice
|
||||
}
|
||||
}
|
||||
|
||||
// initializes default device state, might be redundant step since we
|
||||
// call "displayChanged()" later anyway, but we do not want to leave the
|
||||
// device in an inconsistent state after construction
|
||||
// [JBR] we don't call displayChanged after creating a device, so call it here.
|
||||
displayChanged();
|
||||
}
|
||||
|
||||
int getDisplayID() {
|
||||
return displayID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of all configurations.
|
||||
*/
|
||||
@@ -175,6 +177,17 @@ public final class CGraphicsDevice extends GraphicsDevice
|
||||
//TODO configs?
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false if display parameters were changed, so we need to recreate the device.
|
||||
*/
|
||||
boolean updateDevice() {
|
||||
int s = scale;
|
||||
double xr = xResolution, yr = yResolution;
|
||||
var b = bounds;
|
||||
displayChanged();
|
||||
return s == scale && xr == xResolution && yr == yResolution && b.equals(bounds);
|
||||
}
|
||||
|
||||
public void displayParametersChanged() {
|
||||
Insets newScreenInsets = nativeGetScreenInsets(displayID);
|
||||
if (!newScreenInsets.equals(screenInsets)) {
|
||||
|
||||
@@ -175,7 +175,8 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
*/
|
||||
private void rebuildDevices() {
|
||||
initDevices();
|
||||
displayChanged();
|
||||
// Do not notify devices, this was already done in initDevices.
|
||||
displayChanger.notifyListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,8 +233,17 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
displayIDs = new int[]{mainDisplayID};
|
||||
}
|
||||
for (int id : displayIDs) {
|
||||
devices.put(id, old.containsKey(id) ? old.remove(id)
|
||||
: new CGraphicsDevice(id));
|
||||
old.compute(id, (i, d) -> {
|
||||
if (d != null && d.updateDevice()) {
|
||||
// Device didn't change -> reuse
|
||||
devices.put(i, d);
|
||||
return null;
|
||||
} else {
|
||||
// Device changed -> create new
|
||||
devices.put(i, new CGraphicsDevice(i));
|
||||
return d;
|
||||
}
|
||||
});
|
||||
}
|
||||
// fetch the main display again, the old value might be outdated
|
||||
mainDisplayID = getMainDisplayID();
|
||||
@@ -269,9 +279,12 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
}
|
||||
|
||||
private CGraphicsDevice getSimilarDevice(CGraphicsDevice old) {
|
||||
CGraphicsDevice sameId = devices.get(old.getDisplayID());
|
||||
if (sameId != null) {
|
||||
return sameId;
|
||||
}
|
||||
for (CGraphicsDevice device : devices.values()) {
|
||||
if (device.getBounds().equals(old.getBounds())) {
|
||||
// for now we will use the bounds only
|
||||
return device;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,6 +351,13 @@ public abstract class Component implements ImageObserver, MenuContainer,
|
||||
*/
|
||||
private transient volatile GraphicsConfiguration graphicsConfig;
|
||||
|
||||
/**
|
||||
* Last observed value of {@code graphicsConfig.getDefaultTransform()}.
|
||||
* Used for firing 'graphicsContextScaleTransform' property change,
|
||||
* as values returned by {@link #graphicsConfig} may change over time.
|
||||
*/
|
||||
private transient volatile AffineTransform lastGraphicsConfigTransform;
|
||||
|
||||
/**
|
||||
* A reference to a {@code BufferStrategy} object
|
||||
* used to manipulate the buffers on this component.
|
||||
@@ -1207,13 +1214,17 @@ public abstract class Component implements ImageObserver, MenuContainer,
|
||||
return false;
|
||||
}
|
||||
|
||||
AffineTransform tx = graphicsConfig != null ? graphicsConfig.getDefaultTransform() : new AffineTransform();
|
||||
AffineTransform tx = lastGraphicsConfigTransform;
|
||||
AffineTransform newTx = gc != null ? gc.getDefaultTransform() : new AffineTransform();
|
||||
graphicsConfig = gc;
|
||||
if (tx.getScaleX() != newTx.getScaleX() ||
|
||||
tx.getScaleY() != newTx.getScaleY())
|
||||
// We cannot rely on graphicsConfig.getDefaultTransform(),
|
||||
// because its device might have been invalidated and now
|
||||
// reports different scale than it did before.
|
||||
if (!newTx.equals(lastGraphicsConfigTransform))
|
||||
{
|
||||
firePropertyChange("graphicsContextScaleTransform", tx, newTx);
|
||||
lastGraphicsConfigTransform = newTx;
|
||||
firePropertyChange("graphicsContextScaleTransform",
|
||||
tx != null ? tx : new AffineTransform(), newTx);
|
||||
}
|
||||
|
||||
ComponentPeer peer = this.peer;
|
||||
|
||||
Reference in New Issue
Block a user