From 12d0eb12771326009ca62fdece2c5c30bec59b12 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 26 Jan 2024 20:24:57 -0500 Subject: [PATCH] ui: readd window opacity setting The undecorated frame requirement appears to not be real, at least on Windows. AWT applies translucency via setting WS_EX_LAYERED to make the window layered and then changes the opacity of the layered window with SetLayeredWindowAttributes. This appears to work regardless of the frame state, even with custom chrome off. --- .../client/config/RuneLiteConfig.java | 16 +++++++++++ .../java/net/runelite/client/ui/ClientUI.java | 6 ++++ .../runelite/client/ui/ContainableFrame.java | 28 +++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java index 98b65669eda..faa52b83130 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/config/RuneLiteConfig.java @@ -133,6 +133,22 @@ default boolean enableCustomChrome() return OSType.getOSType() == OSType.Windows; } + @Range( + min = 10, + max = 100 + ) + @ConfigItem( + keyName = "uiWindowOpacity", + name = "Window opacity", + description = "Set the windows opacity.", + position = 16, + section = windowSettings + ) + default int windowOpacity() + { + return 100; + } + @ConfigItem( keyName = "gameAlwaysOnTop", name = "Always on top", diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java index f28a29fec9c..8eff248e553 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -1114,6 +1114,12 @@ private void updateFrameConfig(boolean updateResizable) return; } + if (frame.getGraphicsConfiguration().isTranslucencyCapable() && + frame.getGraphicsConfiguration().getDevice().getFullScreenWindow() == null) + { + frame.setOpacity(((float) config.windowOpacity()) / 100.0f); + } + if (config.usernameInTitle() && (client instanceof Client)) { final Player player = ((Client) client).getLocalPlayer(); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java b/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java index 42a0f3a158b..c95b9648de8 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java @@ -27,6 +27,7 @@ import com.formdev.flatlaf.ui.FlatNativeWindowsLibrary; import java.awt.Dimension; import java.awt.Frame; +import java.awt.IllegalComponentStateException; import java.awt.Insets; import java.awt.Rectangle; import java.awt.geom.AffineTransform; @@ -52,6 +53,7 @@ public enum Mode private boolean rightSideSuction; private boolean boundsOpSet; private boolean scaleMinSize = false; + private boolean overrideUndecorated; @Override @SuppressWarnings("deprecation") @@ -259,4 +261,30 @@ void updateContainsInScreen() FlatNativeWindowsLibrary.setContainInScreen(this, containedInScreen == Mode.ALWAYS); } } + + @Override + public void setOpacity(float opacity) + { + // JDK-6993784 requires the frame to be undecorated to apply opacity, but in practice it works on Windows regardless. + // Temporarily pretend to be an undecorated frame to satisfy Frame.setOpacity(). + overrideUndecorated = true; + try + { + super.setOpacity(opacity); + } + catch (IllegalComponentStateException | UnsupportedOperationException | IllegalArgumentException ex) + { + log.warn("unable to set opacity {}", opacity, ex); + } + finally + { + overrideUndecorated = false; + } + } + + @Override + public boolean isUndecorated() + { + return overrideUndecorated || super.isUndecorated(); + } }