From fe45d922cf8efc7b24496427d619030eb9061fa8 Mon Sep 17 00:00:00 2001 From: weisj Date: Tue, 24 Sep 2019 22:23:09 +0200 Subject: [PATCH] Preliminary support for custom decorations. --- .../darklaf/ui/rootpane/DarkTitlePane.java | 28 ++++--- .../weis/darklaf/util/WindowsFrameUtil.java | 79 +++++++++++++++++++ 2 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/weis/darklaf/util/WindowsFrameUtil.java diff --git a/src/main/java/com/weis/darklaf/ui/rootpane/DarkTitlePane.java b/src/main/java/com/weis/darklaf/ui/rootpane/DarkTitlePane.java index 7e4f5955..43bcc41e 100644 --- a/src/main/java/com/weis/darklaf/ui/rootpane/DarkTitlePane.java +++ b/src/main/java/com/weis/darklaf/ui/rootpane/DarkTitlePane.java @@ -217,8 +217,8 @@ public class DarkTitlePane extends JComponent { titleLabel = new JLabel(); add(titleLabel); if (decorationStyle == JRootPane.FRAME) { - createActions(); createIcons(); + createActions(); createButtons(); windowIconButton = createWindowIcon(); @@ -294,13 +294,21 @@ public class DarkTitlePane extends JComponent { } private void addMenuItems(@NotNull final JPopupMenu menu) { - menu.add(restoreAction); - menu.add(minimizeAction); + menu.add(new JMenuItem(restoreAction) {{ + setDisabledIcon(restoreIcon); + }}); + menu.add(new JMenuItem(minimizeAction) {{ + setDisabledIcon(minimizeIcon); + }}); if (Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { - menu.add(maximizeAction); + menu.add(new JMenuItem(maximizeAction) {{ + setDisabledIcon(maximizeIcon); + }}); } menu.add(new JSeparator()); - menu.add(closeAction); + menu.add(new JMenuItem(closeAction) {{ + setDisabledIcon(closeIcon); + }}); } private void close() { @@ -362,8 +370,6 @@ public class DarkTitlePane extends JComponent { private void createButtons() { closeButton = createButton("Close", closeIcon, closeAction); closeButton.setRolloverIcon(UIManager.getIcon("TitlePane.closeHover.icon")); - closeButton.putClientProperty("rolloverColor", Color.RED); - closeButton.putClientProperty("rolloverArmedColor", Color.RED); closeButton.setUI(new CloseButtonUI()); if (getWindowDecorationStyle() == JRootPane.FRAME) { @@ -524,7 +530,7 @@ public class DarkTitlePane extends JComponent { private class CloseAction extends AbstractAction { public CloseAction() { - super("Close"); + super("Close", closeIcon); } public void actionPerformed(final ActionEvent e) { @@ -536,7 +542,7 @@ public class DarkTitlePane extends JComponent { private class MinimizeAction extends AbstractAction { public MinimizeAction() { //UIManager.getString("Minimize", getLocale()) - super("Minimize"); + super("Minimize", minimizeIcon); } public void actionPerformed(final ActionEvent e) { @@ -546,7 +552,7 @@ public class DarkTitlePane extends JComponent { private class MaximizeAction extends AbstractAction { public MaximizeAction() { - super("Maximize"); + super("Maximize", maximizeIcon); } public void actionPerformed(final ActionEvent e) { @@ -556,7 +562,7 @@ public class DarkTitlePane extends JComponent { private class RestoreAction extends AbstractAction { public RestoreAction() { - super("Restore"); + super("Restore", restoreIcon); } public void actionPerformed(final ActionEvent e) { diff --git a/src/main/java/com/weis/darklaf/util/WindowsFrameUtil.java b/src/main/java/com/weis/darklaf/util/WindowsFrameUtil.java new file mode 100644 index 00000000..63d8b74e --- /dev/null +++ b/src/main/java/com/weis/darklaf/util/WindowsFrameUtil.java @@ -0,0 +1,79 @@ +package com.weis.darklaf.util; + +import com.sun.jna.LastErrorException; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.User32; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.platform.win32.WinDef.HWND; +import com.sun.jna.win32.StdCallLibrary; +import com.sun.jna.win32.W32APIOptions; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; + +public final class WindowsFrameUtil { + + public static final WinDef.LRESULT PASS_TO_SUPER = new WinDef.LRESULT(-1); + public static final WinDef.LRESULT PASS_TO_DEFAULT = new WinDef.LRESULT(-2); + private static int prevWndProc; + + public static void enableTitleBar(final Window window, final boolean enabled) { + if (window == null) return; + + final HWND hwnd = getHWND(window); + int style = User32.INSTANCE.GetWindowLong(hwnd, User32dll.GWL_STYLE); + if (enabled) { + style |= 0xc00000; + } else { + style = 0x00040000; + } + //ResizeMode="CanResizeWithGrip" AllowsTransparency="True" + User32.INSTANCE.SetWindowLong(hwnd, User32dll.GWL_STYLE, style); + User32.INSTANCE.SetWindowPos(hwnd, new HWND(new Pointer(0L)), + 0, 0, 0, 0, 0x27); + } + + public static void setWindowCallback(final Window window, final WindowProc callback) { + if (window == null) return; + + final HWND hwnd = getHWND(window); + callback.parent = User32dll.INSTANCE.GetWindowLongPtr(hwnd, (long) User32dll.GWL_WNDPROC); + User32dll.INSTANCE.SetWindowLongPtr(hwnd, User32dll.GWL_WNDPROC, callback); + } + + @NotNull + @Contract("_ -> new") + public static HWND getHWND(final Component component) { + var hwnd = new HWND(); + hwnd.setPointer(Native.getComponentPointer(component)); + return hwnd; + } + + public interface User32dll extends User32 { + + User32dll INSTANCE = Native.loadLibrary("user32", User32dll.class, + W32APIOptions.UNICODE_OPTIONS); + + WNDPROC GetWindowLongPtr(HWND hWnd, long nIndex) throws LastErrorException; + + LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, WNDPROC wndProc) throws LastErrorException; + + void DisableProcessWindowsGhosting() throws LastErrorException; + + INT_PTR GetWindowDC(HWND hwnd); + + int ReleaseDC(HWND hwnd, INT_PTR hdc); + } + + public interface WNDPROC extends StdCallLibrary.StdCallCallback { + WinDef.LRESULT callback(HWND hWnd, int uMsg, WinDef.WPARAM uParam, WinDef.LPARAM lParam) throws LastErrorException; + } + + public abstract static class WindowProc implements WNDPROC { + + protected WNDPROC parent; + + } +}