diff --git a/CHANGELOG.md b/CHANGELOG.md index 782b3e8f..6d0fe407 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ FlatLaf Change Log ## 3.6.1-SNAPSHOT - Extras: Support JSVG 2.0.0. Minimum JSVG version is now 1.6.0. (issue #997) +- FlatLaf window decorations (Windows 10/11 only): Improved diagonal window + resizing on top-left and top-right window corners. Top window resize area now + also covers iconify/maximize/close buttons. (issue #1015) - ToggleButton: Styling `selectedForeground` did not work if `foreground` is also styled. (issue #1017) - JideSplitButton: Fixed updating popup when switching theme. (issue #1000) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatWindowsNativeWindowBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatWindowsNativeWindowBorder.java index a4014001..b61b94a1 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatWindowsNativeWindowBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatWindowsNativeWindowBorder.java @@ -21,6 +21,7 @@ import java.awt.Dialog; import java.awt.EventQueue; import java.awt.Frame; import java.awt.GraphicsConfiguration; +import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.Window; @@ -39,6 +40,7 @@ import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.SystemInfo; +import com.formdev.flatlaf.util.UIScale; // // Interesting resources: @@ -282,6 +284,8 @@ class FlatWindowsNativeWindowBorder HTMINBUTTON = 8, HTMAXBUTTON = 9, HTTOP = 12, + HTTOPLEFT = 13, + HTTOPRIGHT = 14, HTCLOSE = 20; private Window window; @@ -341,6 +345,31 @@ class FlatWindowsNativeWindowBorder // scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen Point pt = scaleDown( x, y ); + // limit top resize border to 4px, which seems to be standard for modern WinUI apps + if( isOnResizeBorder && pt.y > UIScale.scale( 4 ) ) + isOnResizeBorder = false; + + if( isOnResizeBorder ) { + Insets insets = window.getInsets(); + + // return HTTOPLEFT if mouse is over top resize border on left side + // - hovering mouse shows top-left resize cursor + // - left-click-and-drag resizes window + if( pt.x <= insets.left + UIScale.scale( 12 ) ) + return HTTOPLEFT; + + // return HTTOPRIGHT if mouse is over top resize border on right side + // - hovering mouse shows top-right resize cursor + // - left-click-and-drag resizes window + if( pt.x >= window.getWidth() - insets.right - UIScale.scale( 12 ) ) + return HTTOPRIGHT; + + // return HTTOP if mouse is over top resize border + // - hovering mouse shows vertical resize cursor + // - left-click-and-drag vertically resizes window + return HTTOP; + } + // return HTSYSMENU if mouse is over application icon // - left-click on HTSYSMENU area shows system menu // - double-left-click sends WM_CLOSE @@ -364,12 +393,6 @@ class FlatWindowsNativeWindowBorder if( contains( closeButtonBounds, pt ) ) return HTCLOSE; - // return HTTOP if mouse is over top resize border - // - hovering mouse shows vertical resize cursor - // - left-click and drag vertically resizes window - if( isOnResizeBorder ) - return HTTOP; - boolean isOnTitleBar = (pt.y < titleBarHeight); if( isOnTitleBar ) { // return HTCLIENT if mouse is over any Swing component in title bar diff --git a/flatlaf-natives/flatlaf-natives-jna/src/main/java/com/formdev/flatlaf/natives/jna/windows/FlatWindowsNativeWindowBorder.java b/flatlaf-natives/flatlaf-natives-jna/src/main/java/com/formdev/flatlaf/natives/jna/windows/FlatWindowsNativeWindowBorder.java index 19c20796..95d4cc82 100644 --- a/flatlaf-natives/flatlaf-natives-jna/src/main/java/com/formdev/flatlaf/natives/jna/windows/FlatWindowsNativeWindowBorder.java +++ b/flatlaf-natives/flatlaf-natives-jna/src/main/java/com/formdev/flatlaf/natives/jna/windows/FlatWindowsNativeWindowBorder.java @@ -24,6 +24,7 @@ import java.awt.Dialog; import java.awt.EventQueue; import java.awt.Frame; import java.awt.GraphicsConfiguration; +import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.Window; @@ -42,6 +43,7 @@ import javax.swing.event.ChangeListener; import javax.swing.event.EventListenerList; import com.formdev.flatlaf.ui.FlatNativeWindowBorder; import com.formdev.flatlaf.util.SystemInfo; +import com.formdev.flatlaf.util.UIScale; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.Structure; @@ -326,6 +328,8 @@ public class FlatWindowsNativeWindowBorder HTMINBUTTON = 8, HTMAXBUTTON = 9, HTTOP = 12, + HTTOPLEFT = 13, + HTTOPRIGHT = 14, HTCLOSE = 20; private static final int ABS_AUTOHIDE = 0x0000001; @@ -674,6 +678,35 @@ public class FlatWindowsNativeWindowBorder // scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen Point pt = scaleDown( x, y ); + int resizeBorderHeight = getResizeHandleHeight(); + boolean isOnResizeBorder = (y < resizeBorderHeight) && + (User32.INSTANCE.GetWindowLong( hwnd, GWL_STYLE ) & WS_THICKFRAME) != 0; + + // limit top resize border to 4px, which seems to be standard for modern WinUI apps + if( isOnResizeBorder && pt.y > UIScale.scale( 4 ) ) + isOnResizeBorder = false; + + if( isOnResizeBorder ) { + Insets insets = window.getInsets(); + + // return HTTOPLEFT if mouse is over top resize border on left side + // - hovering mouse shows top-left resize cursor + // - left-click-and-drag resizes window + if( pt.x <= insets.left + UIScale.scale( 12 ) ) + return new LRESULT( HTTOPLEFT ); + + // return HTTOPRIGHT if mouse is over top resize border on right side + // - hovering mouse shows top-right resize cursor + // - left-click-and-drag resizes window + if( pt.x >= window.getWidth() - insets.right - UIScale.scale( 12 ) ) + return new LRESULT( HTTOPRIGHT ); + + // return HTTOP if mouse is over top resize border + // - hovering mouse shows vertical resize cursor + // - left-click-and-drag vertically resizes window + return new LRESULT( HTTOP ); + } + // return HTSYSMENU if mouse is over application icon // - left-click on HTSYSMENU area shows system menu // - double-left-click sends WM_CLOSE @@ -697,16 +730,6 @@ public class FlatWindowsNativeWindowBorder if( contains( closeButtonBounds, pt ) ) return new LRESULT( HTCLOSE ); - int resizeBorderHeight = getResizeHandleHeight(); - boolean isOnResizeBorder = (y < resizeBorderHeight) && - (User32.INSTANCE.GetWindowLong( hwnd, GWL_STYLE ) & WS_THICKFRAME) != 0; - - // return HTTOP if mouse is over top resize border - // - hovering mouse shows vertical resize cursor - // - left-click and drag vertically resizes window - if( isOnResizeBorder ) - return new LRESULT( HTTOP ); - boolean isOnTitleBar = (pt.y < titleBarHeight); if( isOnTitleBar ) { // return HTCLIENT if mouse is over any Swing component in title bar