gt:             int y1 = Math.min(y + height, compY1);
context: /**
   * Open Wonderland
   *
   * Copyright (c) 2010-12, Open Wonderland Foundation, All Rights Reserved
   *
   * Redistributions in source code form must reproduce the above
   * copyright and this condition.
   *
   * The contents of this file are subject to the GNU General Public
   * License, Version 2 (the "License"); you may not use this file
   * except in compliance with the License. A copy of the License is
   * available at http://www.opensource.org/licenses/gpl-license.php.
   *
   * The Open Wonderland Foundation designates this particular file as
   * subject to the "Classpath" exception as provided by the Open Wonderland
   * Foundation in the License file that accompanied this code.
   */
  
  /**
   * Project Wonderland
   *
   * Copyright (c) 2004-2009, Sun Microsystems, Inc., All Rights Reserved
   *
   * Redistributions in source code form must reproduce the above
   * copyright and this condition.
   *
   * The contents of this file are subject to the GNU General Public
   * License, Version 2 (the "License"); you may not use this file
   * except in compliance with the License. A copy of the License is
   * available at http://www.opensource.org/licenses/gpl-license.php.
   *
   * Sun designates this particular file as subject to the "Classpath" 
   * exception as provided by Sun in the License file that accompanied 
   * this code.
   */
  package org.jdesktop.wonderland.modules.appbase.client.swing;
  
  import com.jme.math.Vector3f;
  import java.awt.Component;
  import java.awt.event.MouseEvent;
  import java.awt.geom.Point2D;
  import javax.swing.JComponent;
  import javax.swing.Popup;
  import com.sun.embeddedswing.EmbeddedToolkit;
  import com.sun.embeddedswing.EmbeddedPeer;
  import java.awt.Canvas;
  import org.jdesktop.wonderland.modules.appbase.client.DrawingSurface;
  import java.awt.Dimension;
  import java.awt.EventQueue;
  import java.awt.Point;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  import javax.swing.JFrame;
  import javax.swing.SwingUtilities;
  import org.jdesktop.mtgame.EntityComponent;
  import org.jdesktop.wonderland.client.input.InputManager;
  import org.jdesktop.wonderland.client.jme.JmeClientMain;
  import org.jdesktop.wonderland.modules.appbase.client.DrawingSurfaceBufferedImage;
  import org.jdesktop.wonderland.modules.appbase.client.Window2D;
  import org.jdesktop.wonderland.modules.appbase.client.view.View2D;
  import org.jdesktop.wonderland.modules.appbase.client.App2D;
  
  /**
   * The main interface to Embedded Swing. This singleton provides access to the three basic capabilities
   * of Embedded Swing.
   * <br><br>
   * 1. Component embedding for the purpose of drawing.
   * <br><br>
   * 2. Mouse event handling.
   * <br><br>
   * 3. Popup window creation.
   */
  class WindowSwingEmbeddedToolkit
          extends EmbeddedToolkit<WindowSwingEmbeddedToolkit.WindowSwingEmbeddedPeer> {
  
      private static final Logger logger = Logger.getLogger(WindowSwingEmbeddedToolkit.class.getName());
      private static final WindowSwingEmbeddedToolkit embeddedToolkit = new WindowSwingEmbeddedToolkit();
      private Point lastPressPointScreen;
      private WindowSwing.EventHook lastPressEventHook;
      private WindowSwing lastWindow;
  
      public static WindowSwingEmbeddedToolkit getWindowSwingEmbeddedToolkit() {
          return embeddedToolkit;
      }
  
      @Override
      protected WindowSwingEmbeddedPeer createEmbeddedPeer(JComponent parent, Component embedded, Object... args) {
          return new WindowSwingEmbeddedPeer(parent, embedded, this);
      }
  
      @Override
      protected CoordinateHandler createCoordinateHandler(JComponent parent, Point2D point, MouseEvent e) {
          logger.fine("Enter WSET.createCoordinateHandler, frame coords: mouseEvent = " + e);
  
          // Temporarily convert event from frame coords into canvas coords
          Canvas canvas = JmeClientMain.getFrame().getCanvas();
          JFrame frame = (JFrame) e.getSource();
          Point framePoint = e.getPoint();
          Point canvasPoint = SwingUtilities.convertPoint(frame, framePoint, canvas);
          e.translatePoint(canvasPoint.x - framePoint.x, canvasPoint.y - framePoint.y);
  
          logger.fine("Canvas coords, mouseEvent = " + e);
  
          InputManager.PickEventReturn ret = InputManager.inputManager().pickMouseEventSwing(e);
          if (ret == null || ret.entity == null || ret.destPickDetails == null) {
              logger.fine("WindowSwing miss");
              e.translatePoint(-(canvasPoint.x - framePoint.x), -(canvasPoint.y - framePoint.y));
  
              // OWL issue #71: if the previous event was on a swing window and
              // this one is not, generate a fake mouse event outside of the
              // last swing window to ensure that a MouseExit event is generated.
              if (lastWindow != null) {
                  logger.fine("Exit swing");
  
                  // request focus in main window
                  InputManager.ensureKeyFocusInMainWindow();
  
                  // send a fake mouse event to generate an exit
                  final EmbeddedPeer targetEmbeddedPeer = lastWindow.getEmbeddedPeer();
                  lastWindow = null;
                  return new CoordinateHandler() {
                      public EmbeddedPeer getEmbeddedPeer() {
                          return targetEmbeddedPeer;
                      }
  
                      public Point2D transform(Point2D src, Point2D dst, 
                                               MouseEvent event) 
                      {
                          if (dst == null) {
                              dst = new Point2D.Float();
                          }
                          
                          dst.setLocation(-1, -1);
                          return dst;
                      }
                  };
              } else {
                  return null;
              }
          }
          logger.fine("WindowSwing hit");
          logger.fine("Pick hit entity = " + ret.entity);
  
          EntityComponent comp = ret.entity.getComponent(WindowSwing.WindowSwingViewReference.class);
          assert comp != null;
          final View2D view = ((WindowSwing.WindowSwingViewReference) comp).getView();
          WindowSwing windowSwing = (WindowSwing) view.getWindow();
  
          // Keep track of the last window we hit
          if (lastWindow == null) {
              logger.fine("Enter swing");
          }
          lastWindow = windowSwing;
  
          // TODO: someday: I don't think we need to set this anymore for drag events. But it doesn't hurt.
          final Vector3f intersectionPointWorld = ret.destPickDetails.getPosition();
          logger.fine("intersectionPointWorld = " + intersectionPointWorld);
  
          if (e.getID() == MouseEvent.MOUSE_PRESSED) {
              lastPressPointScreen = new Point(e.getX(), e.getY());
  
              lastPressEventHook = windowSwing.getEventHook();
              if (lastPressEventHook != null) {
                  WindowSwing.EventHookInfo hookInfo = new WindowSwing.EventHookInfo(intersectionPointWorld, 
                                                                                     e.getX(), e.getY());
                  lastPressEventHook.specifyHookInfoForEvent(e, hookInfo);
              }
          }
  
          final EmbeddedPeer targetEmbeddedPeer = windowSwing.getEmbeddedPeer();
          CoordinateHandler coordinateHandler = new CoordinateHandler() {
  
              public EmbeddedPeer getEmbeddedPeer() {
                  return targetEmbeddedPeer;
              }
  
              // Note: event is in frame coordinates
              public Point2D transform(Point2D src, Point2D dst, MouseEvent event) {
  
                  logger.fine("event = " + event);
                  logger.fine("src = " + src);
  
                  Point pt;
                  if (event.getID() == MouseEvent.MOUSE_DRAGGED) {
  
                      // We will need the event in canvas coordinates
                      Canvas canvas = JmeClientMain.getFrame().getCanvas();
                      JFrame frame = (JFrame) event.getSource();
                      Point framePoint = event.getPoint();
                      Point canvasPoint = SwingUtilities.convertPoint(frame, framePoint, canvas);
                      int canvasX = event.getX() + canvasPoint.x - framePoint.x;
                      int canvasY = event.getY() + canvasPoint.y - framePoint.y;
                      pt = view.calcIntersectionPixelOfEyeRay(canvasX, canvasY);
  
                      if (lastPressEventHook != null) {
                          WindowSwing.EventHookInfo hookInfo = 
                              new WindowSwing.EventHookInfo(intersectionPointWorld, canvasX, canvasY);
                          lastPressEventHook.specifyHookInfoForEvent(event, hookInfo);
                      }
  
                  } else {
                      pt = view.calcPositionInPixelCoordinates(intersectionPointWorld, true);
                  }
                  
                  // TODO: temp
                  if (pt == null) {
                      logger.severe("pt is null");
                      return src;
                  }
  
                  if (dst == null) {
                      dst = new Point2D.Double();
                  }
  
                  // TODO: for now
                  dst.setLocation(new Point2D.Double((double) pt.x, (double) pt.y));
                  logger.fine("dst = " + dst);
  
                  return dst;
              }
          };
  
          // Restore the event to frame coordinates
          e.translatePoint(-(canvasPoint.x - framePoint.x), -(canvasPoint.y - framePoint.y));
  
          return coordinateHandler;
      }
  
      @Override
      // Note: peer should be the owning WindowSwing.embeddedPeer	
      public Popup getPopup(EmbeddedPeer peer, Component contents, int x, int y) {
  
          int width = (int) contents.getPreferredSize().getWidth();
          int height = (int) contents.getPreferredSize().getHeight();
  
          if (!(peer instanceof WindowSwingEmbeddedPeer)) {
              throw new RuntimeException("Invalid embedded peer type");
          }
          WindowSwing winOwner = ((WindowSwingEmbeddedPeer) peer).getWindowSwing();
          if (winOwner instanceof PopupProvider) {
              return ((PopupProvider) winOwner).getPopup(contents, x, y);
          }
  
          WindowSwing winPopup = null;
          winPopup = new WindowSwing(winOwner.getApp(), Window2D.Type.POPUP, winOwner, width, height,
                                     false, winOwner.getPixelScale(), "Popup for " + winOwner.getName());
          winPopup.setComponent(contents);
  
          final WindowSwing popup = winPopup;
  
          winPopup.setPixelOffset(x, y);
  
          return new Popup() {
  
              @Override
              public void show() {
                  App2D.invokeLater(new Runnable() {
                      public void run () {
                          popup.setVisibleApp(true);
                      }
                  });
              }
  
              @Override
              public void hide() {
                  App2D.invokeLater(new Runnable() {
                      public void run () {
                          popup.setVisibleApp(false);
                      }
                  });
              }
          };
      }
  
      static class WindowSwingEmbeddedPeer extends EmbeddedPeer {
  
          WindowSwingEmbeddedToolkit toolkit;
          private WindowSwing windowSwing = null;
  
          protected WindowSwingEmbeddedPeer(JComponent parent, Component embedded, WindowSwingEmbeddedToolkit toolkit) {
              super(parent, embedded);
              this.toolkit = toolkit;
          }
  
          void repaint() {
              Component embedded = getEmbeddedComponent();
              repaint(embedded.getX(), embedded.getY(), embedded.getWidth(), embedded.getHeight());
          }
  
          @Override
          public void repaint(int x, int y, int width, int height) {
              if (windowSwing == null) {
                  return;
              }
  
              //System.err.println("repaint xywh = " + x + ", " + y + ", " + width + ", " + height);
  
              // Clip the dirty region to the component
              Component embedded = getEmbeddedComponent();
              int compX0 = embedded.getX();
              int compY0 = embedded.getY();
              int compX1 = compX0 + embedded.getWidth();
              int compY1 = compY0 + embedded.getHeight();
              int x0 = Math.max(x, compX0);
              int y0 = Math.max(y, compY0);
              int x1 = Math.min(x + width, compX1);
  