/*
 * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.swing;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.beans.PropertyVetoException;

import sun.awt.AWTAccessor;
import sun.awt.SunToolkit;

/** This is an implementation of the <code>DesktopManager</code>.
  * It currently implements the basic behaviors for managing
  * <code>JInternalFrame</code>s in an arbitrary parent.
  * <code>JInternalFrame</code>s that are not children of a
  * <code>JDesktop</code> will use this component
  * to handle their desktop-like actions.
  * <p>This class provides a policy for the various JInternalFrame methods,
  * it is not meant to be called directly rather the various JInternalFrame
  * methods will call into the DesktopManager.</p>
  * @see JDesktopPane
  * @see JInternalFrame
  * @author David Kloba
  * @author Steve Wilson
  * @since 1.2
  */
@SuppressWarnings("serial") // No Interesting Non-Transient State
public class DefaultDesktopManager implements DesktopManager, java.io.Serializable {
    static final String HAS_BEEN_ICONIFIED_PROPERTY = "wasIconOnce";

    static final int DEFAULT_DRAG_MODE = 0;
    static final int OUTLINE_DRAG_MODE = 1;
    static final int FASTER_DRAG_MODE = 2;

    int dragMode = DEFAULT_DRAG_MODE;

    private transient Rectangle currentBounds = null;
    private transient Graphics desktopGraphics = null;
    private transient Rectangle desktopBounds = null;
    private transient Rectangle[] floatingItems = {};

    /**
     * Set to true when the user actually drags a frame vs clicks on it
     * to start the drag operation.  This is only used when dragging with
     * FASTER_DRAG_MODE.
     */
    private transient boolean didDrag;

    /**
     * Constructs a {@code DefaultDesktopManager}.
     */
    public DefaultDesktopManager() {}

    /** Normally this method will not be called. If it is, it
      * tries to determine the appropriate parent from the desktopIcon of the frame.
      * Will remove the desktopIcon from its parent if it successfully adds the frame.
      */
    public void openFrame(JInternalFrame f) {
        if(f.getDesktopIcon().getParent() != null) {
            f.getDesktopIcon().getParent().add(f);
            removeIconFor(f);
        }
    }

    /**
     * Removes the frame, and, if necessary, the
     * <code>desktopIcon</code>, from its parent.
     * @param f the <code>JInternalFrame</code> to be removed
     */
    public void closeFrame(JInternalFrame f) {
        JDesktopPane d = f.getDesktopPane();
        if (d == null) {
            return;
        }
        boolean findNext = f.isSelected();
        Container c = f.getParent();
        JInternalFrame nextFrame = null;
        if (findNext) {
            nextFrame = d.getNextFrame(f);
            try { f.setSelected(false); } catch (PropertyVetoException e2) { }
        }
        if(c != null) {
            c.remove(f); // Removes the focus.
            c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight());
        }
        removeIconFor(f);
        if(f.getNormalBounds() != null)
            f.setNormalBounds(null);
        if(wasIcon(f))
            setWasIcon(f, null);
        if (nextFrame != null) {
            try { nextFrame.setSelected(true); }
            catch (PropertyVetoException e2) { }
        } else if (findNext && d.getComponentCount() == 0) {
            // It was selected and was the last component on the desktop.
            d.requestFocus();
        }
    }

    /**
     * Resizes the frame to fill its parents bounds.
     * @param f the frame to be resized
     */
    public void maximizeFrame(JInternalFrame f) {
        if (f.isIcon()) {
            try {
                // In turn calls deiconifyFrame in the desktop manager.
                // That method will handle the maximization of the frame.
                f.setIcon(false);
            } catch (PropertyVetoException e2) {
            }
        } else {
            Container c = f.getParent();
            if (c == null) {
                return;
            }
            f.setNormalBounds(f.getBounds());
            Rectangle desktopBounds = c.getBounds();
            setBoundsForFrame(f, 0, 0,
                desktopBounds.width, desktopBounds.height);
        }

        // Set the maximized frame as selected.
        try {
            f.setSelected(true);
        } catch (PropertyVetoException e2) {
        }
    }

    /**
     * Restores the frame back to its size and position prior
     * to a <code>maximizeFrame</code> call.
     * @param f the <code>JInternalFrame</code> to be restored
     */
    public void minimizeFrame(JInternalFrame f) {
        // If the frame was an icon restore it back to an icon.
        if (f.isIcon()) {
            iconifyFrame(f);
            return;
        }

        if ((f.getNormalBounds()) != null) {
            Rectangle r = f.getNormalBounds();
            f.setNormalBounds(null);
            try { f.setSelected(true); } catch (PropertyVetoException e2) { }
            setBoundsForFrame(f, r.x, r.y, r.width, r.height);
        }
    }

    /**
     * Removes the frame from its parent and adds its
     * <code>desktopIcon</code> to the parent.
     * @param f the <code>JInternalFrame</code> to be iconified
     */
    public void iconifyFrame(JInternalFrame f) {
        JInternalFrame.JDesktopIcon desktopIcon;
        Container c = f.getParent();
        JDesktopPane d = f.getDesktopPane();
        boolean findNext = f.isSelected();
        desktopIcon = f.getDesktopIcon();
        if(!wasIcon(f)) {
            Rectangle r = getBoundsForIconOf(f);
            desktopIcon.setBounds(r.x, r.y, r.width, r.height);
            // we must validate the hierarchy to not break the hw/lw mixing
            desktopIcon.revalidate();
            setWasIcon(f, Boolean.TRUE);
        }

        if (c == null || d == null) {
            return;
        }

        if (c instanceof JLayeredPane) {
            JLayeredPane lp = (JLayeredPane)c;
            int layer = JLayeredPane.getLayer(f);
            JLayeredPane.putLayer(desktopIcon, layer);
        }
        d.setComponentOrderCheckingEnabled(true);
        c.remove(f);
        c.add(desktopIcon);
        if (findNext) {
            if (d.selectFrame(true) == null) {
                // The icon is the last frame.
                f.restoreSubcomponentFocus();
            }
        }
        c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight());
    }

    /**
     * Removes the desktopIcon from its parent and adds its frame
     * to the parent.
     * @param f the <code>JInternalFrame</code> to be de-iconified
     */
    public void deiconifyFrame(JInternalFrame f) {
        JInternalFrame.JDesktopIcon desktopIcon = f.getDesktopIcon();
        Container c = desktopIcon.getParent();
        JDesktopPane d = f.getDesktopPane();
        if (c != null && d != null) {
            c.add(f);
            // If the frame is to be restored to a maximized state make
            // sure it still fills the whole desktop.
            if (f.isMaximum()) {
                Rectangle desktopBounds = c.getBounds();
                if (f.getWidth() != desktopBounds.width ||
                        f.getHeight() != desktopBounds.height) {
                    setBoundsForFrame(f, 0, 0,
                        desktopBounds.width, desktopBounds.height);
                }
            }
            removeIconFor(f);
            if (f.isSelected()) {
                f.moveToFront();
                f.restoreSubcomponentFocus();
            }
            else {
                try {
                    f.setSelected(true);
                } catch (PropertyVetoException e2) {}

            }
        }
    }

    /** This will activate <b>f</b> moving it to the front. It will
      * set the current active frame's (if any)
      * <code>IS_SELECTED_PROPERTY</code> to <code>false</code>.
      * There can be only one active frame across all Layers.
      * @param f the <code>JInternalFrame</code> to be activated
      */
    public void activateFrame(JInternalFrame f) {
        Container p = f.getParent();
        Component[] c;
        JDesktopPane d = f.getDesktopPane();
        JInternalFrame currentlyActiveFrame =
          (d == null) ? null : d.getSelectedFrame();
        // fix for bug: 4162443
        if(p == null) {
            // If the frame is not in parent, its icon maybe, check it
            p = f.getDesktopIcon().getParent();
            if(p == null)
                return;
        }
        // we only need to keep track of the currentActive InternalFrame, if any
        if (currentlyActiveFrame == null){
          if (d != null) { d.setSelectedFrame(f);}
        } else if (currentlyActiveFrame != f) {
          // if not the same frame as the current active
          // we deactivate the current
          if (currentlyActiveFrame.isSelected()) {
            try {
              currentlyActiveFrame.setSelected(false);
            }
            catch(PropertyVetoException e2) {}
          }
          if (d != null) { d.setSelectedFrame(f);}
        }
        f.moveToFront();
    }

    // implements javax.swing.DesktopManager
    public void deactivateFrame(JInternalFrame f) {
      JDesktopPane d = f.getDesktopPane();
      JInternalFrame currentlyActiveFrame =
          (d == null) ? null : d.getSelectedFrame();
      if (currentlyActiveFrame == f)
        d.setSelectedFrame(null);
    }

    // implements javax.swing.DesktopManager
    public void beginDraggingFrame(JComponent f) {
        setupDragMode(f);

        if (dragMode == FASTER_DRAG_MODE) {
          Component desktop = f.getParent();
          floatingItems = findFloatingItems(f);
          currentBounds = f.getBounds();
          if (desktop instanceof JComponent) {
              desktopBounds = ((JComponent)desktop).getVisibleRect();
          }
          else {
              desktopBounds = desktop.getBounds();
              desktopBounds.x = desktopBounds.y = 0;
          }
          desktopGraphics = JComponent.safelyGetGraphics(desktop);
          ((JInternalFrame)f).isDragging = true;
          didDrag = false;
        }

    }

    private void setupDragMode(JComponent f) {
        JDesktopPane p = getDesktopPane(f);
        Container parent = f.getParent();
        dragMode = DEFAULT_DRAG_MODE;
        if (p != null) {
            String mode = (String)p.getClientProperty("JDesktopPane.dragMode");
            Window window = SwingUtilities.getWindowAncestor(f);
            if (window != null && !window.isOpaque()) {
                dragMode = DEFAULT_DRAG_MODE;
            } else if ("outline".equals(mode)) {
                dragMode = OUTLINE_DRAG_MODE;
            } else if ("faster".equals(mode)
                    && f instanceof JInternalFrame
                    && ((JInternalFrame)f).isOpaque() &&
                       (parent == null || parent.isOpaque())) {
                dragMode = FASTER_DRAG_MODE;
            } else {
                if (p.getDragMode() == JDesktopPane.OUTLINE_DRAG_MODE ) {
                    dragMode = OUTLINE_DRAG_MODE;
                } else if ( p.getDragMode() == JDesktopPane.LIVE_DRAG_MODE
                        && f instanceof JInternalFrame
                        && ((JInternalFrame)f).isOpaque()) {
                    dragMode = FASTER_DRAG_MODE;
                } else {
                    dragMode = DEFAULT_DRAG_MODE;
                }
            }
        }
    }

    private transient Point currentLoc = null;

    /**
      * Moves the visible location of the frame being dragged
      * to the location specified.  The means by which this occurs can vary depending
      * on the dragging algorithm being used.  The actual logical location of the frame
      * might not change until <code>endDraggingFrame</code> is called.
      */
    public void dragFrame(JComponent f, int newX, int newY) {

        if (dragMode == OUTLINE_DRAG_MODE) {
            JDesktopPane desktopPane = getDesktopPane(f);
            if (desktopPane != null){
              Graphics g = JComponent.safelyGetGraphics(desktopPane);

              g.setXORMode(Color.white);
              if (currentLoc != null) {
                g.drawRect(currentLoc.x, currentLoc.y,
                        f.getWidth()-1, f.getHeight()-1);
              }
              g.drawRect( newX, newY, f.getWidth()-1, f.getHeight()-1);
              /* Work around for 6635462: XOR mode may cause a SurfaceLost on first use.
              * Swing doesn't expect that its XOR drawRect did
              * not complete, so believes that on re-entering at
              * the next update location, that there is an XOR rect
              * to draw out at "currentLoc". But in fact
              * its now got a new clean surface without that rect,
              * so drawing it "out" in fact draws it on, leaving garbage.
              * So only update/set currentLoc if the draw completed.
              */
              sun.java2d.SurfaceData sData =
                  ((sun.java2d.SunGraphics2D)g).getSurfaceData();

              if (!sData.isSurfaceLost()) {
                  currentLoc = new Point (newX, newY);
              }
              g.dispose();
            }
        } else if (dragMode == FASTER_DRAG_MODE) {
            dragFrameFaster(f, newX, newY);
        } else {
            setBoundsForFrame(f, newX, newY, f.getWidth(), f.getHeight());
        }
    }

    // implements javax.swing.DesktopManager
    public void endDraggingFrame(JComponent f) {
        if ( dragMode == OUTLINE_DRAG_MODE && currentLoc != null) {
            setBoundsForFrame(f, currentLoc.x, currentLoc.y, f.getWidth(), f.getHeight() );
            currentLoc = null;
        } else if (dragMode == FASTER_DRAG_MODE) {
            currentBounds = null;
            if (desktopGraphics != null) {
                desktopGraphics.dispose();
                desktopGraphics = null;
            }
            desktopBounds = null;
            ((JInternalFrame)f).isDragging = false;
        }
    }

    // implements javax.swing.DesktopManager
    public void beginResizingFrame(JComponent f, int direction) {
        setupDragMode(f);
    }

    /**
     * Calls <code>setBoundsForFrame</code> with the new values.
     * @param f the component to be resized
     * @param newX the new x-coordinate
     * @param newY the new y-coordinate
     * @param newWidth the new width
     * @param newHeight the new height
     */
    public void resizeFrame(JComponent f, int newX, int newY, int newWidth, int newHeight) {

        if ( dragMode == DEFAULT_DRAG_MODE || dragMode == FASTER_DRAG_MODE ) {
            setBoundsForFrame(f, newX, newY, newWidth, newHeight);
        } else {
            JDesktopPane desktopPane = getDesktopPane(f);
            if (desktopPane != null){
              Graphics g = JComponent.safelyGetGraphics(desktopPane);

              g.setXORMode(Color.white);
              if (currentBounds != null) {
                g.drawRect( currentBounds.x, currentBounds.y, currentBounds.width-1, currentBounds.height-1);
              }
              g.drawRect( newX, newY, newWidth-1, newHeight-1);

              // Work around for 6635462, see comment in dragFrame()
              sun.java2d.SurfaceData sData =
                  ((sun.java2d.SunGraphics2D)g).getSurfaceData();
              if (!sData.isSurfaceLost()) {
                  currentBounds = new Rectangle (newX, newY, newWidth, newHeight);
              }

              g.setPaintMode();
              g.dispose();
            }
        }

    }

    // implements javax.swing.DesktopManager
    public void endResizingFrame(JComponent f) {
        if ( dragMode == OUTLINE_DRAG_MODE && currentBounds != null) {
            setBoundsForFrame(f, currentBounds.x, currentBounds.y, currentBounds.width, currentBounds.height );
            currentBounds = null;
        }
    }


    /** This moves the <code>JComponent</code> and repaints the damaged areas. */
    public void setBoundsForFrame(JComponent f, int newX, int newY, int newWidth, int newHeight) {
        f.setBounds(newX, newY, newWidth, newHeight);
        // we must validate the hierarchy to not break the hw/lw mixing
        f.revalidate();
    }

    /**
     * Convenience method to remove the desktopIcon of <b>f</b> is necessary.
     *
     * @param f the {@code JInternalFrame} for which to remove the
     *          {@code desktopIcon}
     */
    protected void removeIconFor(JInternalFrame f) {
        JInternalFrame.JDesktopIcon di = f.getDesktopIcon();
        Container c = di.getParent();
        if(c != null) {
            c.remove(di);
            c.repaint(di.getX(), di.getY(), di.getWidth(), di.getHeight());
        }
    }

    /**
     * The {@code iconifyFrame()} code calls this to determine the proper bounds
     * for the desktopIcon.
     *
     * @param f the {@code JInternalFrame} of interest
     * @return a {@code Rectangle} containing bounds for the {@code desktopIcon}
     */
    protected Rectangle getBoundsForIconOf(JInternalFrame f) {
      //
      // Get the icon for this internal frame and its preferred size
      //

      JInternalFrame.JDesktopIcon icon = f.getDesktopIcon();
      Dimension prefSize = icon.getPreferredSize();
      //
      // Get the parent bounds and child components.
      //

      Container c = f.getParent();
      if (c == null) {
          c = f.getDesktopIcon().getParent();
      }

      if (c == null) {
        /* the frame has not yet been added to the parent; how about (0,0) ?*/
        return new Rectangle(0, 0, prefSize.width, prefSize.height);
      }

      Rectangle parentBounds = c.getBounds();
      Component [] components = c.getComponents();


      //
      // Iterate through valid default icon locations and return the
      // first one that does not intersect any other icons.
      //

      Rectangle availableRectangle = null;
      JInternalFrame.JDesktopIcon currentIcon = null;

      int x = 0;
      int y = parentBounds.height - prefSize.height;
      int w = prefSize.width;
      int h = prefSize.height;

      boolean found = false;

      while (!found) {

        availableRectangle = new Rectangle(x,y,w,h);

        found = true;

        for ( int i=0; i<components.length; i++ ) {

          //
          // Get the icon for this component
          //

          if ( components[i] instanceof JInternalFrame ) {
            currentIcon = ((JInternalFrame)components[i]).getDesktopIcon();
          }
          else if ( components[i] instanceof JInternalFrame.JDesktopIcon ){
            currentIcon = (JInternalFrame.JDesktopIcon)components[i];
          } else
            /* found a child that's neither an internal frame nor
               an icon. I don't believe this should happen, but at
               present it does and causes a null pointer exception.
               Even when that gets fixed, this code protects against
               the npe. hania */
            continue;

          //
          // If this icon intersects the current location, get next location.
          //

          if ( !currentIcon.equals(icon) ) {
            if ( availableRectangle.intersects(currentIcon.getBounds()) ) {
              found = false;
              break;
            }
          }
        }

        if (currentIcon == null)
          /* didn't find any useful children above. This probably shouldn't
           happen, but this check protects against an npe if it ever does
           (and it's happening now) */
          return availableRectangle;

        x += currentIcon.getBounds().width;

        if ( x + w > parentBounds.width ) {
          x = 0;
          y -= h;
        }
      }

      return(availableRectangle);
    }

    /**
     * Stores the bounds of the component just before a maximize call.
     * @param f the component about to be resized
     * @param r the normal bounds to be saved away
     */
    protected void setPreviousBounds(JInternalFrame f, Rectangle r)     {
        f.setNormalBounds(r);
    }

    /**
     * Gets the normal bounds of the component prior to the component
     * being maximized.
     * @param f the <code>JInternalFrame</code> of interest
     * @return the normal bounds of the component
     */
    protected Rectangle getPreviousBounds(JInternalFrame f)     {
        return f.getNormalBounds();
    }

    /**
     * Sets that the component has been iconized and the bounds of the
     * <code>desktopIcon</code> are valid.
     *
     * @param f     the {@code JInternalFrame} of interest
     * @param value a {@code Boolean} signifying if component has been iconized
     */
    protected void setWasIcon(JInternalFrame f, Boolean value)  {
        if (value != null) {
            f.putClientProperty(HAS_BEEN_ICONIFIED_PROPERTY, value);
        }
    }

    /**
     * Returns <code>true</code> if the component has been iconized
     * and the bounds of the <code>desktopIcon</code> are valid,
     * otherwise returns <code>false</code>.
     *
     * @param f the <code>JInternalFrame</code> of interest
     * @return <code>true</code> if the component has been iconized;
     *    otherwise returns <code>false</code>
     */
    protected boolean wasIcon(JInternalFrame f) {
        return (f.getClientProperty(HAS_BEEN_ICONIFIED_PROPERTY) == Boolean.TRUE);
    }


    JDesktopPane getDesktopPane( JComponent frame ) {
        JDesktopPane pane = null;
        Component c = frame.getParent();

        // Find the JDesktopPane
        while ( pane == null ) {
            if ( c instanceof JDesktopPane ) {
                pane = (JDesktopPane)c;
            }
            else if ( c == null ) {
                break;
            }
            else {
                c = c.getParent();
            }
        }

        return pane;
    }


  // =========== stuff for faster frame dragging ===================

   private void dragFrameFaster(JComponent f, int newX, int newY) {

      Rectangle previousBounds = new Rectangle(currentBounds.x,
                                               currentBounds.y,
                                               currentBounds.width,
                                               currentBounds.height);

   // move the frame
      currentBounds.x = newX;
      currentBounds.y = newY;

      if (didDrag) {
          // Only initiate cleanup if we have actually done a drag.
          emergencyCleanup(f);
      }
      else {
          didDrag = true;
          // We reset the danger field as until now we haven't actually
          // moved the internal frame so we don't need to initiate repaint.
          ((JInternalFrame)f).danger = false;
      }

      boolean floaterCollision = isFloaterCollision(previousBounds, currentBounds);

      JComponent parent = (JComponent)f.getParent();
      Rectangle visBounds = previousBounds.intersection(desktopBounds);

      RepaintManager currentManager = RepaintManager.currentManager(f);

      currentManager.beginPaint();
      try {
          if(!floaterCollision) {
              currentManager.copyArea(parent, desktopGraphics, visBounds.x,
                                      visBounds.y,
                                      visBounds.width,
                                      visBounds.height,
                                      newX - previousBounds.x,
                                      newY - previousBounds.y,
                                      true);
          }

          f.setBounds(currentBounds);

          if (!floaterCollision) {
              Rectangle r = currentBounds;
              currentManager.notifyRepaintPerformed(parent, r.x, r.y, r.width, r.height);
          }

          if(floaterCollision) {
              // since we couldn't blit we just redraw as fast as possible
              // the isDragging mucking is to avoid activating emergency
              // cleanup
              ((JInternalFrame)f).isDragging = false;
              parent.paintImmediately(currentBounds);
              ((JInternalFrame)f).isDragging = true;
          }

          // fake out the repaint manager.  We'll take care of everything

          currentManager.markCompletelyClean(parent);
          currentManager.markCompletelyClean(f);

          // compute the minimal newly exposed area
          // if the rects intersect then we use computeDifference.  Otherwise
          // we'll repaint the entire previous bounds
          Rectangle[] dirtyRects = null;
          if ( previousBounds.intersects(currentBounds) ) {
              dirtyRects = SwingUtilities.computeDifference(previousBounds,
                                                            currentBounds);
          } else {
              dirtyRects = new Rectangle[1];
              dirtyRects[0] = previousBounds;
          }

          // Fix the damage
          for (int i = 0; i < dirtyRects.length; i++) {
              parent.paintImmediately(dirtyRects[i]);
              Rectangle r = dirtyRects[i];
              currentManager.notifyRepaintPerformed(parent, r.x, r.y, r.width, r.height);
          }

          // new areas of blit were exposed
          if ( !(visBounds.equals(previousBounds)) ) {
              dirtyRects = SwingUtilities.computeDifference(previousBounds,
                                                            desktopBounds);
              for (int i = 0; i < dirtyRects.length; i++) {
                  dirtyRects[i].x += newX - previousBounds.x;
                  dirtyRects[i].y += newY - previousBounds.y;
                  ((JInternalFrame)f).isDragging = false;
                  parent.paintImmediately(dirtyRects[i]);
                  ((JInternalFrame)f).isDragging = true;
                  Rectangle r = dirtyRects[i];
                  currentManager.notifyRepaintPerformed(parent, r.x, r.y, r.width, r.height);
              }

          }
      } finally {
          currentManager.endPaint();
      }

      // update window if it's non-opaque
      Window topLevel = SwingUtilities.getWindowAncestor(f);
      Toolkit tk = Toolkit.getDefaultToolkit();
      if (!topLevel.isOpaque() &&
          (tk instanceof SunToolkit) &&
          ((SunToolkit)tk).needUpdateWindow())
      {
          AWTAccessor.getWindowAccessor().updateWindow(topLevel);
      }
   }

   private boolean isFloaterCollision(Rectangle moveFrom, Rectangle moveTo) {
      if (floatingItems.length == 0) {
        // System.out.println("no floaters");
         return false;
      }

      for (int i = 0; i < floatingItems.length; i++) {
         boolean intersectsFrom = moveFrom.intersects(floatingItems[i]);
         if (intersectsFrom) {
            return true;
         }
         boolean intersectsTo = moveTo.intersects(floatingItems[i]);
         if (intersectsTo) {
            return true;
         }
      }

      return false;
   }

   private Rectangle[] findFloatingItems(JComponent f) {
      Container desktop = f.getParent();
      Component[] children = desktop.getComponents();
      int i = 0;
      for (i = 0; i < children.length; i++) {
         if (children[i] == f) {
            break;
         }
      }
      // System.out.println(i);
      Rectangle[] floaters = new Rectangle[i];
      for (i = 0; i < floaters.length; i++) {
         floaters[i] = children[i].getBounds();
      }

      return floaters;
   }

   /**
     * This method is here to clean up problems associated
     * with a race condition which can occur when the full contents
     * of a copyArea's source argument is not available onscreen.
     * This uses brute force to clean up in case of possible damage
     */
   private void emergencyCleanup(final JComponent f) {

        if ( ((JInternalFrame)f).danger ) {

           SwingUtilities.invokeLater( new Runnable(){
                                       public void run(){

                                       ((JInternalFrame)f).isDragging = false;
                                       f.paintImmediately(0,0,
                                                          f.getWidth(),
                                                          f.getHeight());

                                        //finalFrame.repaint();
                                        ((JInternalFrame)f).isDragging = true;
                                        // System.out.println("repair complete");
                                       }});

             ((JInternalFrame)f).danger = false;
        }

   }


}
