diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java index 7f10ca61684..c1a97a3f989 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -116,6 +116,7 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; @@ -358,6 +359,11 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } finally { awtLock(); } + } else { + final XAtom XA_NET_WORKAREA = XAtom.get("_NET_WORKAREA"); + final boolean rootWindowWorkareaResized = (ev.get_type() == XConstants.PropertyNotify + && ev.get_xproperty().get_atom() == XA_NET_WORKAREA.getAtom()); + if (rootWindowWorkareaResized) resetScreenInsetsCache(); } } }); @@ -843,8 +849,7 @@ public final class XToolkit extends UNIXToolkit implements Runnable { * When two screens overlap and the first contains a dock(*****), then * _NET_WORKAREA may start at point x1,y1 and end at point x2,y2. */ - @Override - public Insets getScreenInsets(final GraphicsConfiguration gc) { + private Insets getScreenInsetsImpl(final GraphicsConfiguration gc) { GraphicsDevice gd = gc.getDevice(); XNETProtocol np = XWM.getWM().getNETProtocol(); if (np == null || !(gd instanceof X11GraphicsDevice) || !np.active()) { @@ -872,6 +877,30 @@ public final class XToolkit extends UNIXToolkit implements Runnable { } } + private void resetScreenInsetsCache() { + final GraphicsDevice[] devices = ((X11GraphicsEnvironment)GraphicsEnvironment. + getLocalGraphicsEnvironment()).getScreenDevices(); + for (var gd : devices) { + ((X11GraphicsDevice)gd).resetInsets(); + } + } + + @Override + public Insets getScreenInsets(final GraphicsConfiguration gc) { + final X11GraphicsDevice device = (X11GraphicsDevice) gc.getDevice(); + Insets insets = device.getInsets(); + if (insets == null) { + synchronized (device) { + insets = device.getInsets(); + if (insets == null) { + insets = getScreenInsetsImpl(gc); + device.setInsets(insets); + } + } + } + return (Insets) insets.clone(); + } + /* * The current implementation of disabling background erasing for * canvases is that we don't set any native background color diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java index 847386c9b0d..4b05b387a89 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -30,6 +30,7 @@ import java.awt.DisplayMode; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; +import java.awt.Insets; import java.awt.Rectangle; import java.awt.Window; import java.security.AccessController; @@ -37,6 +38,7 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.Objects; import sun.awt.util.ThreadGroupUtils; import sun.java2d.SunGraphicsEnvironment; @@ -66,12 +68,15 @@ public final class X11GraphicsDevice extends GraphicsDevice private static Boolean xrandrExtSupported; private SunDisplayChanger topLevels = new SunDisplayChanger(); private DisplayMode origDisplayMode; + private volatile Rectangle bounds; + private volatile Insets insets; private boolean shutdownHookRegistered; private int scale; public X11GraphicsDevice(int screennum) { this.screen = screennum; this.scale = initScaleFactor(); + this.bounds = getBoundsImpl(); } /** @@ -118,7 +123,7 @@ public final class X11GraphicsDevice extends GraphicsDevice return Region.clipRound(x / (double)getScaleFactor()); } - public Rectangle getBounds() { + private Rectangle getBoundsImpl() { Rectangle rect = pGetBounds(getScreen()); if (getScaleFactor() != 1) { rect.x = scaleDown(rect.x); @@ -129,6 +134,23 @@ public final class X11GraphicsDevice extends GraphicsDevice return rect; } + public Rectangle getBounds() { + return bounds.getBounds(); + } + + public Insets getInsets() { + return insets; + } + + public void setInsets(Insets newInsets) { + Objects.requireNonNull(newInsets); + insets = newInsets; + } + + public void resetInsets() { + insets = null; + } + /** * Returns the identification string associated with this graphics * device. @@ -516,6 +538,8 @@ public final class X11GraphicsDevice extends GraphicsDevice @Override public synchronized void displayChanged() { scale = initScaleFactor(); + bounds = getBoundsImpl(); + insets = null; // On X11 the visuals do not change, and therefore we don't need // to reset the defaultConfig, config, doubleBufferVisuals, // neither do we need to reset the native data.