jdk/src/java.desktop/share/classes/sun/swing/JLightweightFrame.java
changeset 42199 8c0e8e13d4d8
parent 30469 bac0a7ff7e1e
child 42216 621af0ebf6c4
equal deleted inserted replaced
42198:6ff366cc096b 42199:8c0e8e13d4d8
     1 /*
     1 /*
     2  * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package sun.swing;
    26 package sun.swing;
    27 
    27 
    28 import java.awt.BorderLayout;
    28 import java.awt.*;
    29 import java.awt.Color;
       
    30 import java.awt.Component;
       
    31 import java.awt.Container;
       
    32 import java.awt.Dimension;
       
    33 import java.awt.EventQueue;
       
    34 import java.awt.Graphics;
       
    35 import java.awt.Graphics2D;
       
    36 import java.awt.MouseInfo;
       
    37 import java.awt.Point;
       
    38 import java.awt.Rectangle;
       
    39 import java.awt.Window;
       
    40 import java.awt.dnd.DragGestureEvent;
    29 import java.awt.dnd.DragGestureEvent;
    41 import java.awt.dnd.DragGestureListener;
    30 import java.awt.dnd.DragGestureListener;
    42 import java.awt.dnd.DragGestureRecognizer;
    31 import java.awt.dnd.DragGestureRecognizer;
    43 import java.awt.dnd.DragSource;
    32 import java.awt.dnd.DragSource;
    44 import java.awt.dnd.DropTarget;
    33 import java.awt.dnd.DropTarget;
    45 import java.awt.dnd.InvalidDnDOperationException;
    34 import java.awt.dnd.InvalidDnDOperationException;
    46 import java.awt.dnd.peer.DragSourceContextPeer;
    35 import java.awt.dnd.peer.DragSourceContextPeer;
    47 import java.awt.event.ContainerEvent;
    36 import java.awt.event.ContainerEvent;
    48 import java.awt.event.ContainerListener;
    37 import java.awt.event.ContainerListener;
       
    38 import java.awt.geom.AffineTransform;
    49 import java.awt.image.BufferedImage;
    39 import java.awt.image.BufferedImage;
    50 import java.awt.image.DataBufferInt;
    40 import java.awt.image.DataBufferInt;
    51 import java.beans.PropertyChangeEvent;
    41 import java.beans.PropertyChangeEvent;
    52 import java.beans.PropertyChangeListener;
    42 import java.beans.PropertyChangeListener;
    53 import java.security.AccessController;
    43 import java.security.AccessController;
    87     private Component component;
    77     private Component component;
    88     private JPanel contentPane;
    78     private JPanel contentPane;
    89 
    79 
    90     private BufferedImage bbImage;
    80     private BufferedImage bbImage;
    91 
    81 
    92     private volatile int scaleFactor = 1;
    82     private volatile double scaleFactorX;
       
    83     private volatile double scaleFactorY;
    93 
    84 
    94     /**
    85     /**
    95      * {@code copyBufferEnabled}, true by default, defines the following strategy.
    86      * {@code copyBufferEnabled}, true by default, defines the following strategy.
    96      * A duplicating (copy) buffer is created for the original pixel buffer.
    87      * A duplicating (copy) buffer is created for the original pixel buffer.
    97      * The copy buffer is synchronized with the original buffer every time the
    88      * The copy buffer is synchronized with the original buffer every time the
   122      * Constructs a new, initially invisible {@code JLightweightFrame}
   113      * Constructs a new, initially invisible {@code JLightweightFrame}
   123      * instance.
   114      * instance.
   124      */
   115      */
   125     public JLightweightFrame() {
   116     public JLightweightFrame() {
   126         super();
   117         super();
       
   118         AffineTransform defaultTransform =
       
   119                            getGraphicsConfiguration().getDefaultTransform();
       
   120         scaleFactorX = defaultTransform.getScaleX();
       
   121         scaleFactorY = defaultTransform.getScaleY();
   127         copyBufferEnabled = "true".equals(AccessController.
   122         copyBufferEnabled = "true".equals(AccessController.
   128             doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true")));
   123             doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true")));
   129 
   124 
   130         add(rootPane, BorderLayout.CENTER);
   125         add(rootPane, BorderLayout.CENTER);
   131         setFocusTraversalPolicy(new LayoutFocusTraversalPolicy());
   126         setFocusTraversalPolicy(new LayoutFocusTraversalPolicy());
   155             if (jlf != JLightweightFrame.this) {
   150             if (jlf != JLightweightFrame.this) {
   156                 return;
   151                 return;
   157             }
   152             }
   158             Point p = SwingUtilities.convertPoint(c, x, y, jlf);
   153             Point p = SwingUtilities.convertPoint(c, x, y, jlf);
   159             Rectangle r = new Rectangle(p.x, p.y, w, h).intersection(
   154             Rectangle r = new Rectangle(p.x, p.y, w, h).intersection(
   160                     new Rectangle(0, 0, bbImage.getWidth() / scaleFactor,
   155                     new Rectangle(0, 0,
   161                                   bbImage.getHeight() / scaleFactor));
   156                           (int)Math.round(bbImage.getWidth() / scaleFactorX),
       
   157                           (int)Math.round(bbImage.getHeight() / scaleFactorY)));
   162 
   158 
   163             if (!r.isEmpty()) {
   159             if (!r.isEmpty()) {
   164                 notifyImageUpdated(r.x, r.y, r.width, r.height);
   160                 notifyImageUpdated(r.x, r.y, r.width, r.height);
   165             }
   161             }
   166         };
   162         };
   210 
   206 
   211         Graphics2D g = bbImage.createGraphics();
   207         Graphics2D g = bbImage.createGraphics();
   212         g.setBackground(getBackground());
   208         g.setBackground(getBackground());
   213         g.setColor(getForeground());
   209         g.setColor(getForeground());
   214         g.setFont(getFont());
   210         g.setFont(getFont());
   215         g.scale(scaleFactor, scaleFactor);
   211         g.scale(scaleFactorX, scaleFactorY);
   216         return g;
   212         return g;
   217     }
   213     }
   218 
   214 
   219     /**
   215     /**
   220      * {@inheritDoc}
   216      * {@inheritDoc}
   235     public void ungrabFocus() {
   231     public void ungrabFocus() {
   236         if (content != null) content.focusUngrabbed();
   232         if (content != null) content.focusUngrabbed();
   237     }
   233     }
   238 
   234 
   239     @Override
   235     @Override
       
   236     @SuppressWarnings("deprecation")
   240     public int getScaleFactor() {
   237     public int getScaleFactor() {
   241         return scaleFactor;
   238         return (int)scaleFactorX;
       
   239     }
       
   240 
       
   241     @Override
       
   242     public double getScaleFactorX() {
       
   243         return scaleFactorX;
       
   244     }
       
   245 
       
   246     @Override
       
   247     public double getScaleFactorY() {
       
   248         return scaleFactorY;
   242     }
   249     }
   243 
   250 
   244     @Override
   251     @Override
   245     public void notifyDisplayChanged(final int scaleFactor) {
   252     public void notifyDisplayChanged(final int scaleFactor) {
   246         if (scaleFactor != this.scaleFactor) {
   253         notifyDisplayChanged(scaleFactor, scaleFactor);
       
   254     }
       
   255 
       
   256     @Override
       
   257     public void notifyDisplayChanged(final double scaleFactorX,
       
   258                                                     final double scaleFactorY) {
       
   259         if (Double.compare(scaleFactorX, this.scaleFactorX) != 0 ||
       
   260                          Double.compare(scaleFactorY, this.scaleFactorY) != 0) {
   247             if (!copyBufferEnabled) content.paintLock();
   261             if (!copyBufferEnabled) content.paintLock();
   248             try {
   262             try {
   249                 if (bbImage != null) {
   263                 if (bbImage != null) {
   250                     resizeBuffer(getWidth(), getHeight(), scaleFactor);
   264                     resizeBuffer(getWidth(), getHeight(), scaleFactorX,
       
   265                                                                   scaleFactorY);
   251                 }
   266                 }
   252             } finally {
   267             } finally {
   253                 if (!copyBufferEnabled) content.paintUnlock();
   268                 if (!copyBufferEnabled) content.paintUnlock();
   254             }
   269             }
   255             this.scaleFactor = scaleFactor;
   270             this.scaleFactorX = scaleFactorX;
   256         }
   271             this.scaleFactorY = scaleFactorY;
   257         final Object peer = AWTAccessor.getComponentAccessor().getPeer(this);
   272 
   258         if (peer instanceof DisplayChangedListener) {
   273             if(isVisible()) {
   259             ((DisplayChangedListener) peer).displayChanged();
   274                 final Object peer =
   260         }
   275                         AWTAccessor.getComponentAccessor().getPeer(this);
   261         repaint();
   276                 if (peer instanceof DisplayChangedListener) {
       
   277                     ((DisplayChangedListener) peer).displayChanged();
       
   278                 }
       
   279                 repaint();
       
   280             }
       
   281         }
   262     }
   282     }
   263 
   283 
   264     @Override
   284     @Override
   265     public void addNotify() {
   285     public void addNotify() {
   266         super.addNotify();
   286         super.addNotify();
   268         if (peer instanceof DisplayChangedListener) {
   288         if (peer instanceof DisplayChangedListener) {
   269             ((DisplayChangedListener) peer).displayChanged();
   289             ((DisplayChangedListener) peer).displayChanged();
   270         }
   290         }
   271     }
   291     }
   272 
   292 
   273     private void syncCopyBuffer(boolean reset, int x, int y, int w, int h, int scale) {
   293     private void syncCopyBuffer(boolean reset, int x, int y, int w, int h,
       
   294                                                  double scaleX, double scaleY) {
   274         content.paintLock();
   295         content.paintLock();
   275         try {
   296         try {
   276             int[] srcBuffer = ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData();
   297             int[] srcBuffer = ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData();
   277             if (reset) {
   298             if (reset) {
   278                 copyBuffer = new int[srcBuffer.length];
   299                 copyBuffer = new int[srcBuffer.length];
   279             }
   300             }
   280             int linestride = bbImage.getWidth();
   301             int linestride = bbImage.getWidth();
   281 
   302 
   282             x *= scale;
   303             int startX = (int)Math.floor(x * scaleX);
   283             y *= scale;
   304             int startY = (int)Math.floor(y * scaleY);
   284             w *= scale;
   305             int width  = (int)Math.ceil((x + w) * scaleX) - startX;
   285             h *= scale;
   306             int height = (int)Math.ceil((y + h) * scaleY) - startY;
   286 
   307 
   287             for (int i=0; i<h; i++) {
   308             for (int i = 0; i < height; i++) {
   288                 int from = (y + i) * linestride + x;
   309                 int from = (startY + i) * linestride + startX;
   289                 System.arraycopy(srcBuffer, from, copyBuffer, from, w);
   310                 System.arraycopy(srcBuffer, from, copyBuffer, from, width);
   290             }
   311             }
   291         } finally {
   312         } finally {
   292             content.paintUnlock();
   313             content.paintUnlock();
   293         }
   314         }
   294     }
   315     }
   295 
   316 
   296     private void notifyImageUpdated(int x, int y, int width, int height) {
   317     private void notifyImageUpdated(int x, int y, int width, int height) {
   297         if (copyBufferEnabled) {
   318         if (copyBufferEnabled) {
   298             syncCopyBuffer(false, x, y, width, height, scaleFactor);
   319             syncCopyBuffer(false, x, y, width, height, scaleFactorX,
       
   320                                                                   scaleFactorY);
   299         }
   321         }
   300         content.imageUpdated(x, y, width, height);
   322         content.imageUpdated(x, y, width, height);
   301     }
   323     }
   302 
   324 
   303     @SuppressWarnings("serial") // anonymous class inside
   325     @SuppressWarnings("serial") // anonymous class inside
   380         try {
   402         try {
   381             boolean createBB = (bbImage == null);
   403             boolean createBB = (bbImage == null);
   382             int newW = width;
   404             int newW = width;
   383             int newH = height;
   405             int newH = height;
   384             if (bbImage != null) {
   406             if (bbImage != null) {
   385                 int imgWidth = bbImage.getWidth() / scaleFactor;
   407                 int imgWidth = (int)Math.round(bbImage.getWidth() /
   386                 int imgHeight = bbImage.getHeight() / scaleFactor;
   408                                                                   scaleFactorX);
       
   409                 int imgHeight = (int)Math.round(bbImage.getHeight() /
       
   410                                                                   scaleFactorY);
   387                 if (width != imgWidth || height != imgHeight) {
   411                 if (width != imgWidth || height != imgHeight) {
   388                     createBB = true;
   412                     createBB = true;
   389                     if (bbImage != null) {
   413                     if (bbImage != null) {
   390                         int oldW = imgWidth;
   414                         int oldW = imgWidth;
   391                         int oldH = imgHeight;
   415                         int oldH = imgHeight;
   405                         }
   429                         }
   406                     }
   430                     }
   407                 }
   431                 }
   408             }
   432             }
   409             if (createBB) {
   433             if (createBB) {
   410                 resizeBuffer(newW, newH, scaleFactor);
   434                 resizeBuffer(newW, newH, scaleFactorX, scaleFactorY);
   411                 return;
   435                 return;
   412             }
   436             }
   413             content.imageReshaped(0, 0, width, height);
   437             content.imageReshaped(0, 0, width, height);
   414 
   438 
   415         } finally {
   439         } finally {
   417                 content.paintUnlock();
   441                 content.paintUnlock();
   418             }
   442             }
   419         }
   443         }
   420     }
   444     }
   421 
   445 
   422     private void resizeBuffer(int width, int height, int newScaleFactor) {
   446     private void resizeBuffer(int width, int height, double newScaleFactorX,
   423             bbImage = new BufferedImage(width*newScaleFactor,height*newScaleFactor,
   447                                                      double newScaleFactorY) {
       
   448         bbImage = new BufferedImage((int)Math.round(width * newScaleFactorX),
       
   449                                     (int)Math.round(height * newScaleFactorY),
   424                                         BufferedImage.TYPE_INT_ARGB_PRE);
   450                                         BufferedImage.TYPE_INT_ARGB_PRE);
   425         int[] pixels= ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData();
   451         int[] pixels= ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData();
   426         if (copyBufferEnabled) {
   452         if (copyBufferEnabled) {
   427             syncCopyBuffer(true, 0, 0, width, height, newScaleFactor);
   453             syncCopyBuffer(true, 0, 0, width, height, newScaleFactorX,
       
   454                                                                newScaleFactorY);
   428             pixels = copyBuffer;
   455             pixels = copyBuffer;
   429         }
   456         }
   430         content.imageBufferReset(pixels, 0, 0, width, height,
   457         content.imageBufferReset(pixels, 0, 0, width, height,
   431                                  width * newScaleFactor, newScaleFactor);
   458                           bbImage.getWidth(), newScaleFactorX, newScaleFactorY);
   432     }
   459     }
   433 
   460 
   434     @Override
   461     @Override
   435     public JRootPane getRootPane() {
   462     public JRootPane getRootPane() {
   436         return rootPane;
   463         return rootPane;