mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-13 23:37:13 -06:00
Native window decorations: show window system menu when left-clicking on application icon, close window on left-double-click on app icon
This commit is contained in:
@@ -196,7 +196,9 @@ public class FlatNativeWindowBorder
|
|||||||
nativeProvider.setHasCustomDecoration( window, hasCustomDecoration );
|
nativeProvider.setHasCustomDecoration( window, hasCustomDecoration );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setTitleBarHeightAndHitTestSpots( Window window, int titleBarHeight, List<Rectangle> hitTestSpots ) {
|
static void setTitleBarHeightAndHitTestSpots( Window window, int titleBarHeight,
|
||||||
|
List<Rectangle> hitTestSpots, Rectangle appIconBounds )
|
||||||
|
{
|
||||||
if( canUseJBRCustomDecorations ) {
|
if( canUseJBRCustomDecorations ) {
|
||||||
JBRCustomDecorations.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots );
|
JBRCustomDecorations.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots );
|
||||||
return;
|
return;
|
||||||
@@ -207,6 +209,7 @@ public class FlatNativeWindowBorder
|
|||||||
|
|
||||||
nativeProvider.setTitleBarHeight( window, titleBarHeight );
|
nativeProvider.setTitleBarHeight( window, titleBarHeight );
|
||||||
nativeProvider.setTitleBarHitTestSpots( window, hitTestSpots );
|
nativeProvider.setTitleBarHitTestSpots( window, hitTestSpots );
|
||||||
|
nativeProvider.setTitleBarAppIconBounds( window, appIconBounds );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initialize() {
|
private static void initialize() {
|
||||||
@@ -240,5 +243,6 @@ public class FlatNativeWindowBorder
|
|||||||
void setHasCustomDecoration( Window window, boolean hasCustomDecoration );
|
void setHasCustomDecoration( Window window, boolean hasCustomDecoration );
|
||||||
void setTitleBarHeight( Window window, int titleBarHeight );
|
void setTitleBarHeight( Window window, int titleBarHeight );
|
||||||
void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots );
|
void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots );
|
||||||
|
void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -453,6 +453,12 @@ public class FlatTitlePane
|
|||||||
for( Rectangle r : debugHitTestSpots )
|
for( Rectangle r : debugHitTestSpots )
|
||||||
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
||||||
}
|
}
|
||||||
|
if( debugAppIconBounds != null ) {
|
||||||
|
g.setColor( Color.red );
|
||||||
|
Point offset = SwingUtilities.convertPoint( this, 0, 0, window );
|
||||||
|
Rectangle r = debugAppIconBounds;
|
||||||
|
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
debug*/
|
debug*/
|
||||||
|
|
||||||
@@ -632,16 +638,31 @@ debug*/
|
|||||||
titleBarHeight--;
|
titleBarHeight--;
|
||||||
|
|
||||||
List<Rectangle> hitTestSpots = new ArrayList<>();
|
List<Rectangle> hitTestSpots = new ArrayList<>();
|
||||||
if( iconLabel.isVisible() )
|
Rectangle appIconBounds = null;
|
||||||
addNativeHitTestSpot( iconLabel, false, hitTestSpots );
|
if( iconLabel.isVisible() ) {
|
||||||
|
// compute real icon size (without insets)
|
||||||
|
Point location = SwingUtilities.convertPoint( iconLabel, 0, 0, window );
|
||||||
|
Insets iconInsets = iconLabel.getInsets();
|
||||||
|
Rectangle iconBounds = new Rectangle(
|
||||||
|
location.x + iconInsets.left,
|
||||||
|
location.y + iconInsets.top,
|
||||||
|
iconLabel.getWidth() - iconInsets.left - iconInsets.right,
|
||||||
|
iconLabel.getHeight() - iconInsets.top - iconInsets.bottom );
|
||||||
|
|
||||||
|
if( hasJBRCustomDecoration() )
|
||||||
|
hitTestSpots.add( iconBounds );
|
||||||
|
else
|
||||||
|
appIconBounds = iconBounds;
|
||||||
|
}
|
||||||
addNativeHitTestSpot( buttonPanel, false, hitTestSpots );
|
addNativeHitTestSpot( buttonPanel, false, hitTestSpots );
|
||||||
addNativeHitTestSpot( menuBarPlaceholder, true, hitTestSpots );
|
addNativeHitTestSpot( menuBarPlaceholder, true, hitTestSpots );
|
||||||
|
|
||||||
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots );
|
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots, appIconBounds );
|
||||||
|
|
||||||
/*debug
|
/*debug
|
||||||
debugTitleBarHeight = titleBarHeight;
|
debugTitleBarHeight = titleBarHeight;
|
||||||
debugHitTestSpots = hitTestSpots;
|
debugHitTestSpots = hitTestSpots;
|
||||||
|
debugAppIconBounds = appIconBounds;
|
||||||
repaint();
|
repaint();
|
||||||
debug*/
|
debug*/
|
||||||
}
|
}
|
||||||
@@ -663,6 +684,7 @@ debug*/
|
|||||||
/*debug
|
/*debug
|
||||||
private int debugTitleBarHeight;
|
private int debugTitleBarHeight;
|
||||||
private List<Rectangle> debugHitTestSpots;
|
private List<Rectangle> debugHitTestSpots;
|
||||||
|
private Rectangle debugAppIconBounds;
|
||||||
debug*/
|
debug*/
|
||||||
|
|
||||||
//---- class TitlePaneBorder ----------------------------------------------
|
//---- class TitlePaneBorder ----------------------------------------------
|
||||||
|
|||||||
@@ -157,6 +157,15 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
wndProc.hitTestSpots = hitTestSpots.toArray( new Rectangle[hitTestSpots.size()] );
|
wndProc.hitTestSpots = hitTestSpots.toArray( new Rectangle[hitTestSpots.size()] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds ) {
|
||||||
|
WndProc wndProc = windowsMap.get( window );
|
||||||
|
if( wndProc == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null;
|
||||||
|
}
|
||||||
|
|
||||||
//---- class WndProc ------------------------------------------------------
|
//---- class WndProc ------------------------------------------------------
|
||||||
|
|
||||||
private class WndProc
|
private class WndProc
|
||||||
@@ -164,14 +173,16 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
{
|
{
|
||||||
private static final int GWLP_WNDPROC = -4;
|
private static final int GWLP_WNDPROC = -4;
|
||||||
|
|
||||||
private static final int WM_NCCALCSIZE = 0x0083;
|
private static final int
|
||||||
private static final int WM_NCHITTEST = 0x0084;
|
WM_NCCALCSIZE = 0x0083,
|
||||||
private static final int WM_NCRBUTTONUP = 0x00A5;
|
WM_NCHITTEST = 0x0084,
|
||||||
|
WM_NCRBUTTONUP = 0x00A5;
|
||||||
|
|
||||||
// WM_NCHITTEST mouse position codes
|
// WM_NCHITTEST mouse position codes
|
||||||
private static final int
|
private static final int
|
||||||
HTCLIENT = 1,
|
HTCLIENT = 1,
|
||||||
HTCAPTION = 2,
|
HTCAPTION = 2,
|
||||||
|
HTSYSMENU = 3,
|
||||||
HTTOP = 12;
|
HTTOP = 12;
|
||||||
|
|
||||||
private static final int ABS_AUTOHIDE = 0x0000001;
|
private static final int ABS_AUTOHIDE = 0x0000001;
|
||||||
@@ -198,6 +209,7 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
|
|
||||||
private int titleBarHeight;
|
private int titleBarHeight;
|
||||||
private Rectangle[] hitTestSpots;
|
private Rectangle[] hitTestSpots;
|
||||||
|
private Rectangle appIconBounds;
|
||||||
|
|
||||||
WndProc( Window window ) {
|
WndProc( Window window ) {
|
||||||
this.window = window;
|
this.window = window;
|
||||||
@@ -242,7 +254,7 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
return WmNcHitTest( hwnd, uMsg, wParam, lParam );
|
return WmNcHitTest( hwnd, uMsg, wParam, lParam );
|
||||||
|
|
||||||
case WM_NCRBUTTONUP:
|
case WM_NCRBUTTONUP:
|
||||||
if( wParam.longValue() == HTCAPTION )
|
if( wParam.longValue() == HTCAPTION || wParam.longValue() == HTSYSMENU )
|
||||||
openSystemMenu( hwnd, GET_X_LPARAM( lParam ), GET_Y_LPARAM( lParam ) );
|
openSystemMenu( hwnd, GET_X_LPARAM( lParam ), GET_Y_LPARAM( lParam ) );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -367,6 +379,12 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
int sx = pt.x;
|
int sx = pt.x;
|
||||||
int sy = pt.y;
|
int sy = pt.y;
|
||||||
|
|
||||||
|
// return HTSYSMENU if mouse is over application icon
|
||||||
|
// - left-click on HTSYSMENU area shows system menu
|
||||||
|
// - double-left-click sends WM_CLOSE
|
||||||
|
if( appIconBounds != null && appIconBounds.contains( sx, sy ) )
|
||||||
|
return new LRESULT( HTSYSMENU );
|
||||||
|
|
||||||
int resizeBorderHeight = getResizeHandleHeight();
|
int resizeBorderHeight = getResizeHandleHeight();
|
||||||
boolean isOnResizeBorder = (y < resizeBorderHeight) &&
|
boolean isOnResizeBorder = (y < resizeBorderHeight) &&
|
||||||
(User32.INSTANCE.GetWindowLong( hwnd, GWL_STYLE ) & WS_THICKFRAME) != 0;
|
(User32.INSTANCE.GetWindowLong( hwnd, GWL_STYLE ) & WS_THICKFRAME) != 0;
|
||||||
@@ -415,7 +433,7 @@ public class FlatWindowsNativeWindowBorder
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Scales down in the same way as AWT.
|
* Scales down in the same way as AWT.
|
||||||
* See AwtWin32GraphicsDevice::ScaleDownX()
|
* See AwtWin32GraphicsDevice::ScaleDownX() and ::ScaleDownY()
|
||||||
*/
|
*/
|
||||||
private Point scaleDown( int x, int y ) {
|
private Point scaleDown( int x, int y ) {
|
||||||
GraphicsConfiguration gc = window.getGraphicsConfiguration();
|
GraphicsConfiguration gc = window.getGraphicsConfiguration();
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ import java.util.WeakHashMap;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import com.formdev.flatlaf.FlatLightLaf;
|
import com.formdev.flatlaf.FlatLightLaf;
|
||||||
import com.formdev.flatlaf.extras.FlatInspector;
|
import com.formdev.flatlaf.extras.FlatInspector;
|
||||||
import com.formdev.flatlaf.nativejna.windows.FlatWindowsNativeWindowBorder;
|
|
||||||
import com.formdev.flatlaf.ui.FlatLineBorder;
|
import com.formdev.flatlaf.ui.FlatLineBorder;
|
||||||
|
import com.formdev.flatlaf.ui.FlatNativeWindowBorder;
|
||||||
import net.miginfocom.swing.*;
|
import net.miginfocom.swing.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -258,7 +258,7 @@ public class FlatNativeWindowBorderTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void nativeChanged() {
|
private void nativeChanged() {
|
||||||
FlatWindowsNativeWindowBorder.getInstance().setHasCustomDecoration( window, nativeCheckBox.isSelected() );
|
FlatNativeWindowBorder.setHasCustomDecoration( window, nativeCheckBox.isSelected() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void revalidateLayout() {
|
private void revalidateLayout() {
|
||||||
|
|||||||
Reference in New Issue
Block a user