From 8e363503c445308dd8114096e4c8f23eaf366bd2 Mon Sep 17 00:00:00 2001 From: weisj Date: Tue, 30 Jun 2020 16:57:27 +0200 Subject: [PATCH] Properly handle toggling decorations on Windows. --- .../darklaf/ui/rootpane/DarkRootPaneUI.java | 6 +++-- core/src/test/java/ui/ComponentDemo.java | 6 +++++ windows/src/main/cpp/Decorations.cpp | 26 +++++++++++++++++-- .../windows/JNIDecorationsWindows.java | 2 +- .../windows/WindowsDecorationsProvider.java | 2 +- .../platform/windows/ui/WindowsTitlePane.java | 16 ++++++++++-- 6 files changed, 50 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/github/weisj/darklaf/ui/rootpane/DarkRootPaneUI.java b/core/src/main/java/com/github/weisj/darklaf/ui/rootpane/DarkRootPaneUI.java index df95cada..5cd1d29d 100644 --- a/core/src/main/java/com/github/weisj/darklaf/ui/rootpane/DarkRootPaneUI.java +++ b/core/src/main/java/com/github/weisj/darklaf/ui/rootpane/DarkRootPaneUI.java @@ -103,14 +103,15 @@ public class DarkRootPaneUI extends BasicRootPaneUI implements HierarchyListener public void propertyChange(final PropertyChangeEvent e) { super.propertyChange(e); String propertyName = e.getPropertyName(); - if (PropertyKey.ANCESTOR.equals(propertyName)) { + if (PropertyKey.ANCESTOR.equals(propertyName) || KEY_NO_DECORATIONS.equals(propertyName)) { updateWindow(rootPane.getParent()); } } protected int decorationsStyleFromWindow(final Window window, final int windowDecorationsStyle) { + if (DarkUIUtil.isUndecorated(window) + || PropertyUtil.getBooleanProperty(rootPane, KEY_NO_DECORATIONS)) return JRootPane.NONE; if (windowDecorationsStyle != JRootPane.NONE) return windowDecorationsStyle; - if (DarkUIUtil.isUndecorated(window)) return JRootPane.NONE; if (window instanceof JFrame) return JRootPane.FRAME; if (window instanceof JDialog) return JRootPane.PLAIN_DIALOG; return windowDecorationsStyle; @@ -183,6 +184,7 @@ public class DarkRootPaneUI extends BasicRootPaneUI implements HierarchyListener private void updateWindow(final Component parent) { window = DarkUIUtil.getWindow(parent); windowDecorationsStyle = decorationsStyleFromWindow(window, windowDecorationsStyle); + if (titlePane != null) titlePane.setDecorationsStyle(windowDecorationsStyle); installBorder(rootPane); } diff --git a/core/src/test/java/ui/ComponentDemo.java b/core/src/test/java/ui/ComponentDemo.java index 1575b5cc..5c753866 100644 --- a/core/src/test/java/ui/ComponentDemo.java +++ b/core/src/test/java/ui/ComponentDemo.java @@ -206,6 +206,12 @@ public interface ComponentDemo { dev.add(logging); dev.add(aaPainting); dev.add(experimentalAA); + dev.add(new JCheckBoxMenuItem("Custom Decorations") { + { + setSelected(LafManager.isDecorationsEnabled()); + addActionListener(e -> LafManager.setDecorationsEnabled(isSelected())); + } + }); return dev; } diff --git a/windows/src/main/cpp/Decorations.cpp b/windows/src/main/cpp/Decorations.cpp index 1da1b2bb..79defaa0 100644 --- a/windows/src/main/cpp/Decorations.cpp +++ b/windows/src/main/cpp/Decorations.cpp @@ -303,6 +303,28 @@ bool InstallDecorations(HWND handle, bool is_popup) { return true; } +void UninstallDecorations(WindowWrapper *wrapper, bool decorated) { + HWND handle = wrapper->window; + + // Restore old window procedure. + SetWindowLongPtr(handle, GWLP_WNDPROC, reinterpret_cast(wrapper->prev_proc)); + + // Restore old client area. + MARGINS margins = { 0, 0, 0, 0 }; + DwmExtendFrameIntoClientArea(handle, &margins); + + auto style = GetWindowLongPtr(handle, GWL_STYLE); + if (!decorated) { + style &= ~WS_THICKFRAME; + } else { + style |= WS_THICKFRAME; + } + SetWindowLongPtr(handle, GWL_STYLE, style); + + UINT flags = SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED; + SetWindowPos(handle, NULL, 0, 0, 0, 0, flags); +} + // @formatter:off LRESULT CALLBACK WindowWrapper::WindowProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam) { HWND handle = reinterpret_cast(hwnd); @@ -402,11 +424,11 @@ Java_com_github_weisj_darklaf_platform_windows_JNIDecorationsWindows_installDeco } JNIEXPORT void JNICALL -Java_com_github_weisj_darklaf_platform_windows_JNIDecorationsWindows_uninstallDecorations(JNIEnv *env, jclass obj, jlong hwnd) { +Java_com_github_weisj_darklaf_platform_windows_JNIDecorationsWindows_uninstallDecorations(JNIEnv *env, jclass obj, jlong hwnd, jboolean decorated) { HWND handle = reinterpret_cast(hwnd); auto wrap = wrapper_map[handle]; if (wrap) { - SetWindowLongPtr(handle, GWLP_WNDPROC, reinterpret_cast(wrap->prev_proc)); + UninstallDecorations(wrap, decorated); wrapper_map.erase(handle); delete (wrap); } diff --git a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/JNIDecorationsWindows.java b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/JNIDecorationsWindows.java index 47ceb31d..9388f91f 100644 --- a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/JNIDecorationsWindows.java +++ b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/JNIDecorationsWindows.java @@ -43,7 +43,7 @@ public class JNIDecorationsWindows { public static native boolean installDecorations(final long hwnd); - public static native void uninstallDecorations(final long hwnd); + public static native void uninstallDecorations(final long hwnd, final boolean decorated); public static native boolean installPopupMenuDecorations(final long hwnd); } diff --git a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/WindowsDecorationsProvider.java b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/WindowsDecorationsProvider.java index bab33eb1..4c1e8daf 100644 --- a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/WindowsDecorationsProvider.java +++ b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/WindowsDecorationsProvider.java @@ -76,7 +76,7 @@ public class WindowsDecorationsProvider implements DecorationsProvider { if (window.isDisplayable()) { long hwnd = PointerUtil.getHWND(window); if (hwnd != 0) { - JNIDecorationsWindows.uninstallDecorations(hwnd); + JNIDecorationsWindows.uninstallDecorations(hwnd, false); } window.dispose(); } diff --git a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/ui/WindowsTitlePane.java b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/ui/WindowsTitlePane.java index b0baa11e..2037e34e 100644 --- a/windows/src/main/java/com/github/weisj/darklaf/platform/windows/ui/WindowsTitlePane.java +++ b/windows/src/main/java/com/github/weisj/darklaf/platform/windows/ui/WindowsTitlePane.java @@ -130,7 +130,7 @@ public class WindowsTitlePane extends CustomTitlePane { this.rootPane = root; this.window = window; bundle = ResourceBundle.getBundle("com.github.weisj.darklaf.bundles.actions", getLocale()); - setDecorationsStyle(decorationStyle); + this.decorationStyle = decorationStyle; rootPane.addContainerListener(rootPaneContainerListener); rootPane.getLayeredPane().addContainerListener(layeredPaneContainerListener); state = -1; @@ -194,7 +194,7 @@ public class WindowsTitlePane extends CustomTitlePane { protected void uninstallDecorations() { if (windowHandle != 0) { - JNIDecorationsWindows.uninstallDecorations(windowHandle); + JNIDecorationsWindows.uninstallDecorations(windowHandle, decorationStyle != JRootPane.NONE); windowHandle = 0; } rootPane.removeContainerListener(rootPaneContainerListener); @@ -224,7 +224,19 @@ public class WindowsTitlePane extends CustomTitlePane { } } + @Override + public void setDecorationsStyle(final int style) { + super.setDecorationsStyle(style); + if (style == JRootPane.NONE && windowHandle != 0) { + uninstall(); + } else if (windowHandle == 0) { + install(); + } + } + private boolean installDecorations() { + if (getDecorationStyle() == JRootPane.NONE) return false; + if (!window.isDisplayable()) return false; if (window instanceof Dialog || window instanceof Frame) { windowHandle = PointerUtil.getHWND(window); if (windowHandle != 0) {