/* Robot.java -- a native input event generator
   Copyright (C) 2004, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.awt;

import gnu.java.awt.ClasspathToolkit;

import java.lang.reflect.InvocationTargetException;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.awt.peer.RobotPeer;

/**
 * The Robot class is used to simulate user interaction with graphical
 * programs.  It can generate native windowing system input events and
 * retrieve image data from the current screen.  Robot is used to test
 * the AWT and Swing library implementations; it can also be used to
 * create self-running demo programs.
 *
 * Since Robot generates native windowing system events, rather than
 * simply inserting {@link AWTEvents} on the AWT event queue, its use
 * is not restricted to Java programs.  It can be used to
 * programatically drive any graphical application.
 *
 * This implementation requires an X server that supports the XTest
 * extension.
 *
 * @author Thomas Fitzsimmons (fitzsim@redhat.com)
 *
 * @since 1.3
 */
public class Robot
{
  private boolean waitForIdle;
  private int autoDelay;
  private RobotPeer peer;

  /**
   * Construct a Robot object that operates on the default screen.
   *
   * @exception AWTException if GraphicsEnvironment.isHeadless()
   * returns true or if the X server does not support the XTest
   * extension
   * @exception SecurityException if createRobot permission is not
   * granted
   */
  public Robot () throws AWTException
  {
    if (GraphicsEnvironment.isHeadless ())
      throw new AWTException ("Robot: headless graphics environment");

    SecurityManager sm = System.getSecurityManager ();
    if (sm != null)
      sm.checkPermission (new AWTPermission ("createRobot"));

    ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit ();

    // createRobot will throw AWTException if XTest is not supported.
    peer = tk.createRobot (GraphicsEnvironment.getLocalGraphicsEnvironment ()
			   .getDefaultScreenDevice ());
  }

  /**
   * Construct a Robot object that operates on the specified screen.
   *
   * @exception AWTException if GraphicsEnvironment.isHeadless()
   * returns true or if the X server does not support the XTest
   * extension
   * @exception IllegalArgumentException if screen is not a screen
   * GraphicsDevice
   * @exception SecurityException if createRobot permission is not
   * granted
   */
  public Robot (GraphicsDevice screen) throws AWTException
  {
    if (GraphicsEnvironment.isHeadless ())
      throw new AWTException ("Robot: headless graphics environment");

    if (screen.getType () != GraphicsDevice.TYPE_RASTER_SCREEN)
      throw new IllegalArgumentException ("Robot: graphics"
					  + " device is not a screen");

    SecurityManager sm = System.getSecurityManager ();
    if (sm != null)
      sm.checkPermission (new AWTPermission ("createRobot"));

    ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit ();

    // createRobot will throw AWTException if XTest is not supported.
    peer = tk.createRobot (screen);
  }

  /**
   * Move the mouse pointer to absolute coordinates (x, y).
   *
   * @param x the destination x coordinate
   * @param y the destination y coordinate
   */
  public void mouseMove(int x, int y)
  {
    peer.mouseMove (x, y);

    if (waitForIdle)
      waitForIdle ();

    if (autoDelay > 0)
      delay (autoDelay);
  }

  /**
   * Press one or more mouse buttons.
   *
   * @param buttons the buttons to press; a bitmask of one or more of
   * these {@link InputEvent} fields:
   *
   * <ul>
   *   <li>BUTTON1_MASK</li>
   *   <li>BUTTON2_MASK</li>
   *   <li>BUTTON3_MASK</li>
   * </ul>
   *
   * @exception IllegalArgumentException if the button mask is invalid
   */
  public void mousePress (int buttons)
  {
    if ((buttons & InputEvent.BUTTON1_MASK) == 0
	&& (buttons & InputEvent.BUTTON2_MASK) == 0
	&& (buttons & InputEvent.BUTTON3_MASK) == 0)
      throw new IllegalArgumentException ("Robot: mousePress:"
					  + " invalid button mask");

    peer.mousePress (buttons);

    if (waitForIdle)
      waitForIdle ();

    if (autoDelay > 0)
      delay (autoDelay);
  }

  /**
   * Release one or more mouse buttons.
   *
   * @param buttons the buttons to release; a bitmask of one or more
   * of these {@link InputEvent} fields:
   *
   * <ul>
   *   <li>BUTTON1_MASK</li>
   *   <li>BUTTON2_MASK</li>
   *   <li>BUTTON3_MASK</li>
   * </ul>
   *
   * @exception IllegalArgumentException if the button mask is invalid
   */
  public void mouseRelease(int buttons)
  {
    if ((buttons & InputEvent.BUTTON1_MASK) == 0
	&& (buttons & InputEvent.BUTTON2_MASK) == 0
	&& (buttons & InputEvent.BUTTON3_MASK) == 0)
      throw new IllegalArgumentException ("Robot: mouseRelease:"
					  + " invalid button mask");

    peer.mouseRelease (buttons);

    if (waitForIdle)
      waitForIdle ();

    if (autoDelay > 0)
      delay (autoDelay);
  }

  /**
   * Rotate the mouse scroll wheel.
   *
   * @param wheelAmt number of steps to rotate mouse wheel.  negative
   * to rotate wheel up (away from the user), positive to rotate wheel
   * down (toward the user).
   *
   * @since 1.4
   */
  public void mouseWheel (int wheelAmt)
  {
    peer.mouseWheel (wheelAmt);

    if (waitForIdle)
      waitForIdle ();

    if (autoDelay > 0)
      delay (autoDelay);
  }

  /**
   * Press a key.
   *
   * @param keycode key to press, a {@link KeyEvent} VK_ constant
   *
   * @exception IllegalArgumentException if keycode is not a valid key
   */
  public void keyPress (int keycode)
  {
    peer.keyPress (keycode);

    if (waitForIdle)
      waitForIdle ();

    if (autoDelay > 0)
      delay (autoDelay);
  }

  /**
   * Release a key.
   *
   * @param keycode key to release, a {@link KeyEvent} VK_ constant
   *
   * @exception IllegalArgumentException if keycode is not a valid key
   */
  public void keyRelease (int keycode)
  {
    peer.keyRelease (keycode);

    if (waitForIdle)
      waitForIdle ();

    if (autoDelay > 0)
      delay (autoDelay);
  }

  /**
   * Return the color of the pixel at the given screen coordinates.
   *
   * @param x the x coordinate of the pixel
   * @param y the y coordinate of the pixel
   *
   * @return the Color of the pixel at screen coodinates <code>(x, y)</code>
   */
  public Color getPixelColor (int x, int y)
  {
    return new Color (peer.getRGBPixel (x, y));
  }

  /**
   * Create an image containing pixels read from the screen.  The
   * image does not include the mouse pointer.
   *
   * @param screenRect the rectangle of pixels to capture, in screen
   * coordinates
   *
   * @return a BufferedImage containing the requested pixels
   *
   * @exception IllegalArgumentException if requested width and height
   * are not both greater than zero
   * @exception SecurityException if readDisplayPixels permission is
   * not granted
   */
  public BufferedImage createScreenCapture (Rectangle screenRect)
  {
    if (screenRect.width <= 0)
      throw new IllegalArgumentException ("Robot: capture width is <= 0");

    if (screenRect.height <= 0)
      throw new IllegalArgumentException ("Robot: capture height is <= 0");

    SecurityManager sm = System.getSecurityManager ();
    if (sm != null)
      sm.checkPermission (new AWTPermission ("readDisplayPixels"));

    int[] pixels = peer.getRGBPixels (screenRect);

    BufferedImage bufferedImage =
      new BufferedImage (screenRect.width, screenRect.height,
			 BufferedImage.TYPE_INT_ARGB);

    bufferedImage.setRGB (0, 0, screenRect.width, screenRect.height,
			  pixels, 0, screenRect.width);

    return bufferedImage;
  }

  /**
   * Check if this Robot automatically calls {@link waitForIdle} after
   * generating an event.
   *
   * @return true if waitForIdle is automatically called
   */
  public boolean isAutoWaitForIdle ()
  {
    return waitForIdle;
  }

  /**
   * Set whether or not this Robot automatically calls {@link
   * waitForIdle} after generating an event.
   *
   * @param isOn true if waitForIdle should be called automatically
   */
  public void setAutoWaitForIdle (boolean isOn)
  {
    waitForIdle = isOn;
  }

  /**
   * Retrieve the length of time this Robot sleeps after generating an
   * event.
   *
   * @return the length of time in milliseconds
   */
  public int getAutoDelay ()
  {
    return autoDelay;
  }

  /**
   * Set the length of time this Robot sleeps after generating an
   * event.
   *
   * @param ms the length of time in milliseconds
   *
   * @exception IllegalArgumentException if ms is not between 0 and
   * 60,000 milliseconds inclusive
   */
  public void setAutoDelay (int ms)
  {
    if (ms <= 0 || ms >= 60000)
      throw new IllegalArgumentException ("Robot: delay length out-of-bounds");

    autoDelay = ms;
  }

  /**
   * Sleep for a specified length of time.
   *
   * @param ms the length of time in milliseconds
   *
   * @exception IllegalArgumentException if ms is not between 0 and
   * 60,000 milliseconds inclusive
   */
  public void delay (int ms)
  {
    if (ms < 0 || ms > 60000)
      throw new IllegalArgumentException ("Robot: delay length out-of-bounds");

    try
      {
	Thread.sleep (ms);
      }
    catch (InterruptedException e)
      {
	System.err.println ("Robot: delay interrupted");
      }
  }

  /**
   * Wait until all events currently on the event queue have been
   * dispatched.
   */
  public void waitForIdle ()
  {
    if (EventQueue.isDispatchThread ())
      throw new IllegalThreadStateException ("Robot: waitForIdle called from "
					     + "the event dispatch thread");

    EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
    try
      {
	q.invokeAndWait (new Runnable () { public void run () { } });
      }
    catch (InterruptedException e)
      {
	System.err.println ("Robot: waitForIdle interrupted");
      }
    catch (InvocationTargetException e)
      {
	System.err.println ("Robot: waitForIdle cannot invoke target");
      }
  }

  /**
   * Return a string representation of this Robot.
   *
   * @return a string representation
   */
  public String toString ()
  {
    return getClass ().getName ()
	+ "[ autoDelay = " + autoDelay + ", autoWaitForIdle = "
	+ waitForIdle + " ]";
  }
}
