diff --git a/core/src/main/java/com/github/weisj/darklaf/ui/DarkPopupFactory.java b/core/src/main/java/com/github/weisj/darklaf/ui/DarkPopupFactory.java index aec53200..8a0a40e0 100644 --- a/core/src/main/java/com/github/weisj/darklaf/ui/DarkPopupFactory.java +++ b/core/src/main/java/com/github/weisj/darklaf/ui/DarkPopupFactory.java @@ -52,7 +52,7 @@ public class DarkPopupFactory extends PopupFactory { Pair result = getEffectivePopup(owner, contents, x, y); Popup popup = result.getFirst(); PopupType type = result.getSecond(); - setupPopup(popup, type, contents); + setupPopup(type, contents, x, y); return popup; } @@ -77,7 +77,7 @@ public class DarkPopupFactory extends PopupFactory { return PopupType.HEAVY_WEIGHT; } - protected void setupPopup(final Popup popup, final PopupType type, final Component contents) { + protected void setupPopup(final PopupType type, final Component contents, final int x, final int y) { if (type == PopupType.MEDIUM_WEIGHT) { JRootPane rootPane = SwingUtilities.getRootPane(contents); // Prevents decorations from being reinstalled. @@ -103,10 +103,12 @@ public class DarkPopupFactory extends PopupFactory { } protected void setupWindowBackground(final Window window, final boolean opaque, final boolean decorations) { - // Sometimes the background is java.awt.SystemColor[i=7] - // It results in a flash of white background, that is repainted with - // the proper popup background later. - // That is why we set window background explicitly. + /* + * Sometimes the background is java.awt.SystemColor[i=7] + * It results in a flash of white background, that is repainted with + * the proper popup background later. + * That is why we set window background explicitly. + */ if (window instanceof RootPaneContainer) { JRootPane rootPane = ((RootPaneContainer) window).getRootPane(); rootPane.setOpaque(opaque); diff --git a/core/src/main/java/com/github/weisj/darklaf/ui/combobox/DarkComboPopup.java b/core/src/main/java/com/github/weisj/darklaf/ui/combobox/DarkComboPopup.java index e169cf27..49f324c0 100644 --- a/core/src/main/java/com/github/weisj/darklaf/ui/combobox/DarkComboPopup.java +++ b/core/src/main/java/com/github/weisj/darklaf/ui/combobox/DarkComboPopup.java @@ -30,11 +30,11 @@ import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import javax.swing.*; -import javax.swing.border.Border; import javax.swing.plaf.basic.BasicComboPopup; import com.github.weisj.darklaf.components.OverlayScrollPane; import com.github.weisj.darklaf.ui.scrollpane.DarkScrollBarUI; +import com.github.weisj.darklaf.util.DarkUIUtil; /** * @author Jannis Weis @@ -144,8 +144,8 @@ public class DarkComboPopup extends BasicComboPopup { // is the same width as the combo box. popupSize.setSize(popupSize.width - (insets.right + insets.left), getPopupHeightForRowCount(comboBox.getMaximumRowCount())); - Rectangle popupBounds = computePopupBounds(0, comboBox.getBounds().height - borderSize, - popupSize.width, popupSize.height); + Rectangle popupBounds = computePopupBounds(borderSize, comboBox.getBounds().height - borderSize, + popupSize.width - 2 * borderSize, popupSize.height); Dimension scrollSize = popupBounds.getSize(); Point popupLocation = popupBounds.getLocation(); @@ -159,36 +159,17 @@ public class DarkComboPopup extends BasicComboPopup { } protected Rectangle computePopupBounds(final int px, final int py, final int pw, final int ph) { - Toolkit toolkit = Toolkit.getDefaultToolkit(); - Rectangle screenBounds; - - // Calculate the desktop dimensions relative to the combo box. - GraphicsConfiguration gc = comboBox.getGraphicsConfiguration(); - Point p = new Point(); - SwingUtilities.convertPointFromScreen(p, comboBox); - if (gc != null) { - Insets screenInsets = toolkit.getScreenInsets(gc); - screenBounds = gc.getBounds(); - screenBounds.width -= (screenInsets.left + screenInsets.right); - screenBounds.height -= (screenInsets.top + screenInsets.bottom); - screenBounds.x += (p.x + screenInsets.left); - screenBounds.y += (p.y + screenInsets.top); - } else { - screenBounds = new Rectangle(p, toolkit.getScreenSize()); - } - int borderHeight = 0; - Border popupBorder = getBorder(); - if (popupBorder != null) { - Insets borderInsets = popupBorder.getBorderInsets(this); - borderHeight = borderInsets.top + borderInsets.bottom; - screenBounds.width -= (borderInsets.left + borderInsets.right); - screenBounds.height -= borderHeight; - } + Rectangle screenBounds = DarkUIUtil.getScreenBounds(comboBox, null); + + Point relativeOrigin = new Point(); + SwingUtilities.convertPointFromScreen(relativeOrigin, comboBox); + screenBounds.setLocation(relativeOrigin); + Rectangle rect = new Rectangle(px, py, pw, ph); if (py + ph > screenBounds.y + screenBounds.height) { - if (ph <= -screenBounds.y - borderHeight) { + if (ph <= -screenBounds.y) { // popup goes above - rect.y = -ph - borderHeight + borderSize; + rect.y = -ph + borderSize; } else { // a full screen height popup rect.y = screenBounds.y + Math.max(0, (screenBounds.height - ph) / 2); diff --git a/core/src/main/java/com/github/weisj/darklaf/ui/popupmenu/PopupMenuContainer.java b/core/src/main/java/com/github/weisj/darklaf/ui/popupmenu/PopupMenuContainer.java index 5441ed11..a0d360ff 100644 --- a/core/src/main/java/com/github/weisj/darklaf/ui/popupmenu/PopupMenuContainer.java +++ b/core/src/main/java/com/github/weisj/darklaf/ui/popupmenu/PopupMenuContainer.java @@ -92,11 +92,17 @@ public class PopupMenuContainer extends JPanel { } public void setPopupMenu(final JPopupMenu popupMenu) { + if (this.popupMenu != null) { + this.popupMenu.removeMenuKeyListener(menuKeyListener); + this.popupMenu.removePopupMenuListener(menuListener); + } this.popupMenu = popupMenu; - popupMenu.removeMenuKeyListener(menuKeyListener); - popupMenu.removePopupMenuListener(menuListener); - popupMenu.addMenuKeyListener(menuKeyListener); - popupMenu.addPopupMenuListener(menuListener); + if (popupMenu != null) { + popupMenu.removeMenuKeyListener(menuKeyListener); + popupMenu.removePopupMenuListener(menuListener); + popupMenu.addMenuKeyListener(menuKeyListener); + popupMenu.addPopupMenuListener(menuListener); + } } public Popup createPopup(final JPopupMenu popupMenu, final int posX, final int posY, final int maxHeight) { diff --git a/core/src/main/java/com/github/weisj/darklaf/util/DarkUIUtil.java b/core/src/main/java/com/github/weisj/darklaf/util/DarkUIUtil.java index fbca8e79..efeca352 100644 --- a/core/src/main/java/com/github/weisj/darklaf/util/DarkUIUtil.java +++ b/core/src/main/java/com/github/weisj/darklaf/util/DarkUIUtil.java @@ -404,6 +404,7 @@ public final class DarkUIUtil { } public static Rectangle getScreenBounds(final JComponent target, final Point p) { + if (p == null) return getScreenBounds(target, target.getLocationOnScreen()); return getScreenBounds(target, p.x, p.y); } @@ -415,7 +416,7 @@ public final class DarkUIUtil { final boolean subtractInsets) { GraphicsConfiguration gc = target != null ? target.getGraphicsConfiguration() : null; if (gc == null) { - gc = getDrawingGC(x, y); + gc = getGraphicsConfigurationForLocation(x, y); } if (gc == null) { // Should never happen. @@ -435,7 +436,7 @@ public final class DarkUIUtil { return sBounds; } - private static GraphicsConfiguration getDrawingGC(final int x, final int y) { + public static GraphicsConfiguration getGraphicsConfigurationForLocation(final int x, final int y) { if (GraphicsEnvironment.isHeadless()) return null; GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice[] devices = env.getScreenDevices(); diff --git a/utils/src/main/java/com/github/weisj/darklaf/util/Scale.java b/utils/src/main/java/com/github/weisj/darklaf/util/Scale.java index 06931a4f..1549a4b5 100644 --- a/utils/src/main/java/com/github/weisj/darklaf/util/Scale.java +++ b/utils/src/main/java/com/github/weisj/darklaf/util/Scale.java @@ -60,6 +60,18 @@ public class Scale { return transform.getScaleY() * value; } + public static double inverseScaleWidth(final double value, final GraphicsConfiguration gc) { + if (gc == null) return inverseScaleWidth(value); + AffineTransform transform = gc.getDefaultTransform(); + return (1 / transform.getScaleX()) * value; + } + + public static double inverseScaleHeight(final double value, final GraphicsConfiguration gc) { + if (gc == null) return inverseScaleHeight(value); + AffineTransform transform = gc.getDefaultTransform(); + return (1 / transform.getScaleY()) * value; + } + public static int scaleWidth(final int i) { return (int) (SCALE_X * i); } @@ -72,6 +84,18 @@ public class Scale { return SCALE_X * d; } + public static int inverseScaleWidth(final int i) { + return (int) ((1 / SCALE_X) * i); + } + + public static float inverseScaleWidth(final float f) { + return (float) ((1 / SCALE_X) * f); + } + + public static double inverseScaleWidth(final double d) { + return (1 / SCALE_X) * d; + } + public static int scaleHeight(final int i) { return (int) (SCALE_Y * i); } @@ -84,6 +108,18 @@ public class Scale { return SCALE_Y * d; } + public static int inverseScaleHeight(final int i) { + return (int) ((1 / SCALE_Y) * i); + } + + public static float inverseScaleHeight(final float f) { + return (float) ((1 / SCALE_Y) * f); + } + + public static double inverseScaleHeight(final double d) { + return (1 / SCALE_Y) * d; + } + public static double getScaleX(final Graphics2D g) { return g.getTransform().getScaleX(); } @@ -106,6 +142,18 @@ public class Scale { return new Dimension((int) scaleWidth(size.width, gc), (int) scaleHeight(size.height, gc)); } + public static Point scale(final GraphicsConfiguration gc, final Point p) { + return new Point((int) scaleWidth(p.x, gc), (int) scaleHeight(p.y, gc)); + } + + public static Dimension inverseScale(final GraphicsConfiguration gc, final Dimension size) { + return new Dimension((int) inverseScaleWidth(size.width, gc), (int) inverseScaleHeight(size.height, gc)); + } + + public static Point inverseScale(final GraphicsConfiguration gc, final Point p) { + return new Point((int) inverseScaleWidth(p.x, gc), (int) inverseScaleHeight(p.y, gc)); + } + public static double scale(final double scale, final double value) { return scale * value; } 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 7f6083c9..7c3dc7fa 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 @@ -121,6 +121,8 @@ public class WindowsTitlePane extends CustomTitlePane { private int right; private int height; + private GraphicsConfiguration gc; + public WindowsTitlePane(final JRootPane root, final int decorationStyle, final Window window) { this.rootPane = root; this.window = window; @@ -213,7 +215,7 @@ public class WindowsTitlePane extends CustomTitlePane { determineColors(); setActive(window.isActive()); installListeners(); - updateSystemIcon(); + updateSystemIcon(getGraphicsConfiguration()); } } @@ -465,6 +467,13 @@ public class WindowsTitlePane extends CustomTitlePane { g.setColor(border); g.fillRect(0, height - 1, width, 1); } + + GraphicsConfiguration currentGC = getGraphicsConfiguration(); + if (currentGC != null && currentGC != gc) { + gc = currentGC; + updateDragArea(gc); + updateSystemIcon(gc); + } } public JRootPane getRootPane() { @@ -566,7 +575,7 @@ public class WindowsTitlePane extends CustomTitlePane { : window.getComponentOrientation().isLeftToRight(); } - private void updateSystemIcon() { + private void updateSystemIcon(final GraphicsConfiguration gc) { boolean frame = getDecorationStyle() == JRootPane.FRAME; Window window = getWindow(); if (window == null) { @@ -575,7 +584,6 @@ public class WindowsTitlePane extends CustomTitlePane { } List icons = window.getIconImages(); - GraphicsConfiguration gc = getGraphicsConfiguration(); Icon systemIcon = null; if (icons == null || icons.size() == 0) { if (frame) { @@ -665,6 +673,13 @@ public class WindowsTitlePane extends CustomTitlePane { return Math.max(BAR_HEIGHT, height); } + protected void updateDragArea(final GraphicsConfiguration gc) { + JNIDecorationsWindows.updateValues(windowHandle, + (int) Scale.scaleWidth(left, gc), + (int) Scale.scaleWidth(right, gc), + (int) Scale.scaleHeight(height, gc)); + } + private class TitlePaneLayout implements LayoutManager { public void addLayoutComponent(final String name, final Component c) {} @@ -749,12 +764,7 @@ public class WindowsTitlePane extends CustomTitlePane { } right++; // Make sure mouse exit event is produced for left most button. - GraphicsConfiguration gc = getGraphicsConfiguration(); - JNIDecorationsWindows.updateValues(windowHandle, - (int) Scale.scaleWidth(left, gc), - (int) Scale.scaleWidth(right, gc), - (int) Scale.scaleHeight(height, gc)); - + updateDragArea(getGraphicsConfiguration()); } private void mirror(final JComponent component, final int w) { @@ -775,6 +785,8 @@ public class WindowsTitlePane extends CustomTitlePane { } protected class PropertyChangeHandler implements PropertyChangeListener { + + @Override public void propertyChange(final PropertyChangeEvent pce) { String name = pce.getPropertyName(); if (KEY_RESIZABLE.equals(name) || KEY_STATE.equals(name)) { @@ -794,20 +806,13 @@ public class WindowsTitlePane extends CustomTitlePane { revalidate(); repaint(); } else if (KEY_ICON_IMAGE.equals(name)) { - updateSystemIcon(); + updateSystemIcon(getGraphicsConfiguration()); revalidate(); repaint(); } else if (PropertyKey.BACKGROUND.equals(name) && pce.getNewValue() instanceof Color) { Color color = (Color) pce.getNewValue(); if (color == null) return; JNIDecorationsWindows.setBackground(windowHandle, color.getRed(), color.getGreen(), color.getBlue()); - } else if (PropertyKey.GRAPHICS_CONFIGURATION.equals(name)) { - GraphicsConfiguration gc = getGraphicsConfiguration(); - JNIDecorationsWindows.updateValues(windowHandle, - (int) Scale.scaleWidth(left, gc), - (int) Scale.scaleWidth(right, gc), - (int) Scale.scaleHeight(height, gc)); - updateSystemIcon(); } } }