This is an automated email from the ASF dual-hosted git repository.

ebakke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git

commit 44ff1b91e10dd9641876c2fb9340560fecfe8d0c
Author: Eirik Bakke <[email protected]>
AuthorDate: Tue Mar 11 00:07:04 2025 -0400

    When dragging window system tabs, show the dragged tab image at full HiDPI 
resolution.
    
    Tested on MacOS with a Retina screen (2x scaling) and Windows 11 with 150% 
HiDPI scaling.
---
 .../netbeans/core/windows/view/dnd/DragWindow.java | 42 +++++++++++++++++-----
 1 file changed, 33 insertions(+), 9 deletions(-)

diff --git 
a/platform/core.windows/src/org/netbeans/core/windows/view/dnd/DragWindow.java 
b/platform/core.windows/src/org/netbeans/core/windows/view/dnd/DragWindow.java
index 4bd52662f9e..2994733311f 100644
--- 
a/platform/core.windows/src/org/netbeans/core/windows/view/dnd/DragWindow.java
+++ 
b/platform/core.windows/src/org/netbeans/core/windows/view/dnd/DragWindow.java
@@ -27,7 +27,9 @@ import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.GraphicsConfiguration;
 import java.awt.GraphicsEnvironment;
+import java.awt.Image;
 import java.awt.Rectangle;
+import java.awt.RenderingHints;
 import java.awt.Window;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -44,6 +46,9 @@ import org.netbeans.swing.tabcontrol.customtabs.Tabbed;
  * @author sa
  */
 class DragWindow extends JWindow {
+    /* Store buffers at 2x the logical resolution. Then scale them down by 50% 
when painting to the
+    JWindow. This ensures full-resolution painting on HiDPI and Retina 
screens. */
+    private static final int DPI_SCALE = 2;
 
     private boolean useFadeEffects = !Boolean.getBoolean( 
"winsys.dnd.nofadeeffects" );
 
@@ -83,8 +88,10 @@ class DragWindow extends JWindow {
         //button icons will be messed up
         Window parentWindow = 
SwingUtilities.getWindowAncestor(container.getComponent());
         Rectangle rect = 
SwingUtilities.convertRectangle(container.getComponent(), tabRectangle, 
parentWindow);
-        BufferedImage res = config.createCompatibleImage(tabRectangle.width, 
tabRectangle.height);
+        BufferedImage res = config.createCompatibleImage(
+                tabRectangle.width * DPI_SCALE, tabRectangle.height * 
DPI_SCALE);
         Graphics2D g = res.createGraphics();
+        g.scale(DPI_SCALE, DPI_SCALE);
         g.translate(-rect.x, -rect.y);
         g.setClip(rect);
         parentWindow.paint(g);
@@ -95,15 +102,17 @@ class DragWindow extends JWindow {
         GraphicsConfiguration config = 
GraphicsEnvironment.getLocalGraphicsEnvironment()
                     .getDefaultScreenDevice().getDefaultConfiguration();
 
-        BufferedImage res = config.createCompatibleImage(contentSize.width, 
contentSize.height);
+        BufferedImage res = config.createCompatibleImage(
+                contentSize.width * DPI_SCALE, contentSize.height * DPI_SCALE);
         Graphics2D g = res.createGraphics();
+        g.scale(DPI_SCALE, DPI_SCALE);
         //some components may be non-opaque so just black rectangle would be 
painted then
         g.setColor( Color.white );
         g.fillRect(0, 0, contentSize.width, contentSize.height);
         if( WinSysPrefs.HANDLER.getBoolean(WinSysPrefs.DND_SMALLWINDOWS, true) 
&& c.getWidth() > 0 && c.getHeight() > 0 ) {
             double xScale = contentSize.getWidth() / c.getWidth();
             double yScale = contentSize.getHeight() / c.getHeight();
-            g.setTransform(AffineTransform.getScaleInstance(xScale, yScale) );
+            g.scale(xScale, yScale);
         }
         c.paint(g);
         return res;
@@ -121,25 +130,40 @@ class DragWindow extends JWindow {
         return res;
     }
 
+    private static void drawImageScaled(Graphics2D g2d, Image image, int x, 
int y) {
+        AffineTransform oldTransform = g2d.getTransform();
+        g2d.translate(x, y);
+        g2d.scale(1.0 / DPI_SCALE, 1.0 / DPI_SCALE);
+        g2d.drawImage(image, 0, 0, null);
+        g2d.setTransform(oldTransform);
+    }
+
     @Override
     public void paint(Graphics g) {
         Graphics2D g2d = (Graphics2D) g.create();
+        /* Set scaling hints in case we are drawing on a surface with a 
different HiDPI scaling than
+        exactly DPI_SCALE. */
+        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, 
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
+        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, 
RenderingHints.VALUE_RENDER_QUALITY);
+
         g2d.setColor(Color.white);
         g2d.fillRect(0,0,getWidth(),tabRectangle.height);
         g2d.setColor(Color.gray);
         g2d.drawRect(0, tabRectangle.height, getWidth()-1, 
getHeight()-tabRectangle.height-1);
         
-        if( WinSysPrefs.HANDLER.getBoolean(WinSysPrefs.DND_SMALLWINDOWS, true) 
)
-            g2d.drawImage(tabImage, 0, 0, null);
-        else
-            g2d.drawImage(tabImage, tabRectangle.x, tabRectangle.y, null);
+        if( WinSysPrefs.HANDLER.getBoolean(WinSysPrefs.DND_SMALLWINDOWS, true) 
) {
+            drawImageScaled(g2d, tabImage, 0, 0);
+        } else {
+            drawImageScaled(g2d, tabImage, tabRectangle.x, tabRectangle.y);
+        }
         if( !useFadeEffects || null == imageBuffer ) {
             g2d.setColor( Color.black );
             g2d.fillRect(1, tabRectangle.height+1, getWidth()-2, 
getHeight()-tabRectangle.height-2);
             g2d.setComposite( 
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, contentAlpha ));
-            g2d.drawImage( contentImage, 1, tabRectangle.height+1, null );
+            drawImageScaled(g2d, contentImage, 1, tabRectangle.height+1);
         } else if( null != imageBuffer ) {
-            g2d.drawImage( imageBuffer, 1, tabRectangle.height+1, null );
+            drawImageScaled(g2d, imageBuffer, 1, tabRectangle.height+1);
         }
         g2d.dispose();
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to