diff --git a/CHANGELOG.md b/CHANGELOG.md index 56a034e0..f5742448 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ FlatLaf Change Log - Fixed white lines at bottom and right side of window (in dark themes on HiDPI screens with scaling enabled). +- ToolTip: Fixed positioning of huge tooltips. (issue #333) ## 1.2 diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java index a9410c06..061d9e0a 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupFactory.java @@ -20,12 +20,16 @@ import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; import java.awt.Insets; import java.awt.MouseInfo; import java.awt.Panel; import java.awt.Point; import java.awt.PointerInfo; import java.awt.Rectangle; +import java.awt.Toolkit; import java.awt.Window; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; @@ -63,7 +67,7 @@ public class FlatPopupFactory public Popup getPopup( Component owner, Component contents, int x, int y ) throws IllegalArgumentException { - Point pt = fixToolTipLocation( contents, x, y ); + Point pt = fixToolTipLocation( owner, contents, x, y ); if( pt != null ) { x = pt.x; y = pt.y; @@ -207,13 +211,13 @@ public class FlatPopupFactory /** * Usually ToolTipManager places a tooltip at (mouseLocation.x, mouseLocation.y + 20). * In case that the tooltip would be partly outside of the screen, - * ToolTipManagerthe changes the location so that the entire tooltip fits on screen. + * the ToolTipManager changes the location so that the entire tooltip fits on screen. * But this can place the tooltip under the mouse location and hide the owner component. *
* This method checks whether the current mouse location is within tooltip bounds * and corrects the y-location so that the tooltip is placed above the mouse location. */ - private Point fixToolTipLocation( Component contents, int x, int y ) { + private Point fixToolTipLocation( Component owner, Component contents, int x, int y ) { if( !(contents instanceof JToolTip) || !wasInvokedFromToolTipManager() ) return null; @@ -229,8 +233,30 @@ public class FlatPopupFactory if( !tipBounds.contains( mouseLocation ) ) return null; - // place tooltip above mouse location - return new Point( x, mouseLocation.y - tipSize.height - UIScale.scale( 20 ) ); + // find GraphicsConfiguration at mouse location (similar to ToolTipManager.getDrawingGC()) + GraphicsConfiguration gc = null; + for( GraphicsDevice device : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices() ) { + GraphicsConfiguration dgc = device.getDefaultConfiguration(); + if( dgc.getBounds().contains( mouseLocation ) ) { + gc = dgc; + break; + } + } + if( gc == null ) + gc = owner.getGraphicsConfiguration(); + if( gc == null ) + return null; + + Rectangle screenBounds = gc.getBounds(); + Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets( gc ); + int screenTop = screenBounds.y + screenInsets.top; + + // place tooltip above mouse location if there is enough space + int newY = mouseLocation.y - tipSize.height - UIScale.scale( 20 ); + if( newY < screenTop ) + return null; + + return new Point( x, newY ); } private boolean wasInvokedFromToolTipManager() {