This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gui][PATCH] Implement java.awt.Robot


Hi,

I committed this patch to java-gui-branch.  It implements java.awt.Robot
and fixes some problems with the Mauve dejagnu harness.

Tom

2004-12-31  Thomas Fitzsimmons  <fitzsim@redhat.com>

	* Makefile.am (gtk_c_source_files): Add GdkRobotPeer.c.
	(gtk_awt_peer_sources): Add GdkScreenGraphicsDevice.java and
	GdkRobotPeer.java.
	(lib_gnu_java_awt_peer_gtk_la_CFLAGS): Add X flags.
	(lib_gnu_java_awt_peer_gtk_la_LDFLAGS): Add XTest flags.
	* gnu/awt/xlib/XToolkit.java (createRobot): New method.
	* gnu/java/awt/ClasspathToolkit.java (createRobot): New method.
	* gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
	(getDefaultScreenDevice): Implement.
	* gnu/java/awt/peer/gtk/GdkRobotPeer.java: New file.
	* gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java: Likewise.
	* gnu/java/awt/peer/gtk/GtkToolkit.java (createRobot): New method.
	* java/awt/Robot.java: Implement.
	* java/awt/peer/RobotPeer.java: Rename parameters.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c: New file.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
	(awt_keycode_to_keysym): Make non-static.
	* jni/gtk-peer/gtkpeer.h (AWT_BUTTON1_MASK, AWT_BUTTON2_MASK,
	AWT_BUTTON3_MASK): Declare constants.
	(awt_keycode_to_keysym): Declare.

	* Makefile.am (AM_MAKEFLAGS): Set KEYS variable.
	* testsuite/libjava.mauve/mauve.exp (test_mauve): If KEYS exists
	and is non-empty pass its value to "make check".
	(test_mauve_sim): Likewise.

Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.361.2.67
diff -u -r1.361.2.67 Makefile.am
--- Makefile.am	29 Dec 2004 15:46:32 -0000	1.361.2.67
+++ Makefile.am	31 Dec 2004 17:20:52 -0000
@@ -194,6 +194,7 @@
 jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c \
 jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.c \
 jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c \
+jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c \
 jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c \
 jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCanvasPeer.c \
 jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.c \
@@ -239,8 +240,10 @@
 gnu/java/awt/peer/gtk/GdkGlyphVector.java \
 gnu/java/awt/peer/gtk/GdkGraphics.java \
 gnu/java/awt/peer/gtk/GdkGraphics2D.java \
+gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java \
 gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java \
 gnu/java/awt/peer/gtk/GdkPixbufDecoder.java \
+gnu/java/awt/peer/gtk/GdkRobotPeer.java \
 gnu/java/awt/peer/gtk/GtkButtonPeer.java \
 gnu/java/awt/peer/gtk/GtkCanvasPeer.java \
 gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java	\
@@ -285,6 +288,7 @@
 jniinclude/gnu_java_awt_peer_gtk_GdkGraphics2D.h: gnu/java/awt/peer/gtk/GdkGraphics2D.java
 jniinclude/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h: gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
 jniinclude/gnu_java_awt_peer_gtk_GdkPixbufDecoder.h: gnu/java/awt/peer/gtk/GdkPixbufDecoder.java
+jniinclude/gnu_java_awt_peer_gtk_GdkRobotPeer.h: gnu/java/awt/peer/gtk/GdkRobotPeer.java
 jniinclude/gnu_java_awt_peer_gtk_GtkButtonPeer.h: gnu/java/awt/peer/gtk/GtkButtonPeer.java
 jniinclude/gnu_java_awt_peer_gtk_GtkCanvasPeer.h: gnu/java/awt/peer/gtk/GtkCanvasPeer.java
 jniinclude/gnu_java_awt_peer_gtk_GtkCheckboxGroupPeer.h: gnu/java/awt/peer/gtk/GtkCheckboxGroupPeer.java
@@ -342,7 +346,7 @@
 lib_gnu_java_awt_peer_gtk_la_LIBADD = $(GTK_LIBS) $(GLIB_LIBS) $(LIBART_LIBS) $(CAIRO_LIBS) $(PANGOFT2_LIBS)
 lib_gnu_java_awt_peer_gtk_la_LDFLAGS = \
 ## The mysterious backslash is consumed by make.
-        -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+        -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(X_LIBS) -lXtst
 
 lib_org_w3c_dom_la_SOURCES = org/w3c/dom/Attr.java \
 org/w3c/dom/CDATASection.java \
@@ -548,7 +552,7 @@
 $(gtk_c_files): %.lo: %.c
 	$(LTCOMPILE) -c -Ijniinclude -I$(srcdir)/jni/classpath -I$(srcdir)/jni/gtk-peer \
 	$(PEDANTIC_CFLAGS) $(GTK_CFLAGS) $(LIBART_CFLAGS) \
-	$(CAIRO_CFLAGS) $(PANGOFT2_CFLAGS) -o $@ $<
+	$(X_CFLAGS) $(CAIRO_CFLAGS) $(PANGOFT2_CFLAGS) -o $@ $<
 
 
 jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontMetrics.lo: $(top_builddir)/jniinclude/gnu_java_awt_peer_gtk_GdkFontMetrics.h
@@ -558,6 +562,7 @@
 jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.lo: $(top_builddir)/jniinclude/gnu_java_awt_peer_gtk_GdkGraphicsEnvironment.h
 jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.lo: $(top_builddir)/jniinclude/gnu_java_awt_peer_gtk_GdkGraphics.h
 jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.lo: $(top_builddir)/jniinclude/gnu_java_awt_peer_gtk_GdkPixbufDecoder.h
+jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.lo: $(top_builddir)/jniinclude/gnu_java_awt_peer_gtk_GdkRobotPeer.h
 jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.lo: $(top_builddir)/jniinclude/gnu_java_awt_peer_gtk_GdkTextLayout.h
 jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.lo: $(top_builddir)/jniinclude/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h
 jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.lo: $(top_builddir)/jniinclude/gnu_java_awt_peer_gtk_GtkButtonPeer.h
@@ -3386,6 +3391,7 @@
 	"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
 	"SHELL=$(SHELL)" \
 	"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+	"KEYS=$(KEYS)" \
 	"exec_prefix=$(exec_prefix)" \
 	"infodir=$(infodir)" \
 	"libdir=$(libdir)" \
Index: gnu/awt/xlib/XToolkit.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/awt/xlib/XToolkit.java,v
retrieving revision 1.7.2.1
diff -u -r1.7.2.1 XToolkit.java
--- gnu/awt/xlib/XToolkit.java	4 Oct 2004 16:45:45 -0000	1.7.2.1
+++ gnu/awt/xlib/XToolkit.java	31 Dec 2004 17:21:18 -0000
@@ -438,5 +438,9 @@
   {
     throw new java.lang.UnsupportedOperationException ();
   }
-  
+
+  public RobotPeer createRobot (GraphicsDevice screen) throws AWTException
+  {
+    throw new java.lang.UnsupportedOperationException ();
+  }
 }
Index: gnu/java/awt/ClasspathToolkit.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/ClasspathToolkit.java,v
retrieving revision 1.1.18.3
diff -u -r1.1.18.3 ClasspathToolkit.java
--- gnu/java/awt/ClasspathToolkit.java	16 Oct 2004 15:55:16 -0000	1.1.18.3
+++ gnu/java/awt/ClasspathToolkit.java	31 Dec 2004 17:21:20 -0000
@@ -47,6 +47,7 @@
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.GraphicsEnvironment;
+import java.awt.GraphicsDevice;
 import java.awt.Toolkit;
 import java.awt.font.FontRenderContext;
 import java.awt.image.ColorModel;
@@ -58,6 +59,7 @@
 import java.text.AttributedString;
 import java.util.HashMap;
 import java.util.Map;
+import java.awt.peer.RobotPeer;
 
 
 /**
@@ -348,4 +350,6 @@
   {
     return null;
   }
+
+  public abstract RobotPeer createRobot (GraphicsDevice screen);
 }
Index: gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 GdkGraphicsEnvironment.java
--- gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java	21 Oct 2004 11:24:53 -0000	1.1.2.4
+++ gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java	31 Dec 2004 17:21:20 -0000
@@ -42,6 +42,7 @@
 import java.awt.Graphics2D;
 import java.awt.GraphicsDevice;
 import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
 import java.awt.Rectangle;
 import java.awt.Shape;
 import java.awt.image.BufferedImage;
@@ -61,7 +62,10 @@
 
   public GraphicsDevice getDefaultScreenDevice ()
   {
-    throw new java.lang.UnsupportedOperationException ();
+    if (GraphicsEnvironment.isHeadless ())
+      throw new HeadlessException ();
+
+    return new GdkScreenGraphicsDevice ();
   }
 
   public Graphics2D createGraphics (BufferedImage image)
Index: gnu/java/awt/peer/gtk/GdkRobotPeer.java
===================================================================
RCS file: gnu/java/awt/peer/gtk/GdkRobotPeer.java
diff -N gnu/java/awt/peer/gtk/GdkRobotPeer.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/peer/gtk/GdkRobotPeer.java	31 Dec 2004 17:21:21 -0000
@@ -0,0 +1,95 @@
+/* GdkRobot.java -- an XTest implementation of RobotPeer
+   Copyright (C) 2004  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 gnu.java.awt.peer.gtk;
+
+import java.awt.AWTException;
+import java.awt.Color;
+import java.awt.GraphicsDevice;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.Rectangle;
+import java.awt.peer.RobotPeer;
+
+/**
+ * Implements the RobotPeer interface using the XTest extension.
+ *
+ * @author Thomas Fitzsimmons
+ */
+public class GdkRobotPeer implements RobotPeer
+{
+  // gdk-pixbuf provides data in RGBA format
+  static final ColorModel cm = new DirectColorModel (32, 0xff000000,
+						     0x00ff0000,
+						     0x0000ff00,
+						     0x000000ff);
+
+  public GdkRobotPeer (GraphicsDevice screen) throws AWTException
+  {
+    // FIXME: make use of screen parameter when GraphicsDevice is
+    // implemented.
+    if (!initXTest ())
+      throw new AWTException ("XTest extension not supported");
+  }
+
+  native boolean initXTest ();
+
+  // RobotPeer methods
+  public native void mouseMove (int x, int y);
+  public native void mousePress (int buttons);
+  public native void mouseRelease (int buttons);
+  public native void mouseWheel (int wheelAmt);
+  public native void keyPress (int keycode);
+  public native void keyRelease (int keycode);
+  native int[] nativeGetRGBPixels (int x, int y, int width, int height);
+
+  public int getRGBPixel (int x, int y)
+  {
+    return cm.getRGB (nativeGetRGBPixels (x, y, 1, 1)[0]);
+  }
+
+  public int[] getRGBPixels (Rectangle r)
+  {
+    int[] gdk_pixels = nativeGetRGBPixels (r.x, r.y, r.width, r.height);
+    int[] pixels = new int[r.width * r.height];
+
+    for (int i = 0; i < r.width * r.height; i++)
+      pixels[i] = cm.getRGB (gdk_pixels[i]);
+
+    return pixels;
+  }
+}
Index: gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
===================================================================
RCS file: gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
diff -N gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java	31 Dec 2004 17:21:21 -0000
@@ -0,0 +1,73 @@
+/* GdkScreenGraphicsDevice.java -- information about a screen device
+   Copyright (C) 2004 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 gnu.java.awt.peer.gtk;
+
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsConfiguration;
+
+public class GdkScreenGraphicsDevice extends GraphicsDevice
+{
+  public GdkScreenGraphicsDevice ()
+  {
+    super ();
+  }
+
+  public int getType ()
+  {
+    return GraphicsDevice.TYPE_RASTER_SCREEN;
+  }
+
+  public String getIDstring ()
+  {
+    // FIXME: query X for this string
+    return "default GDK device ID string";
+  }
+
+  public GraphicsConfiguration[] getConfigurations ()
+  {
+    // FIXME: query X for the list of possible configurations
+    return null;
+  }
+
+  public GraphicsConfiguration getDefaultConfiguration ()
+  {
+    // FIXME: query X for default configuration
+    return null;
+  }
+}
Index: gnu/java/awt/peer/gtk/GtkToolkit.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/awt/peer/gtk/GtkToolkit.java,v
retrieving revision 1.8.2.14
diff -u -r1.8.2.14 GtkToolkit.java
--- gnu/java/awt/peer/gtk/GtkToolkit.java	30 Dec 2004 16:51:16 -0000	1.8.2.14
+++ gnu/java/awt/peer/gtk/GtkToolkit.java	31 Dec 2004 17:21:22 -0000
@@ -622,4 +622,9 @@
   {
     throw new UnsupportedOperationException();
   }
+
+  public RobotPeer createRobot (GraphicsDevice screen) throws AWTException
+  {
+    return new GdkRobotPeer (screen);
+  }
 }
Index: java/awt/Robot.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/Robot.java,v
retrieving revision 1.3
diff -u -r1.3 Robot.java
--- java/awt/Robot.java	11 Jun 2003 10:37:47 -0000	1.3
+++ java/awt/Robot.java	31 Dec 2004 17:21:34 -0000
@@ -1,5 +1,5 @@
-/* Robot.java -- 
-   Copyright (C) 2002 Free Software Foundation, Inc.
+/* Robot.java -- a native input event generator
+   Copyright (C) 2004 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -38,112 +38,383 @@
 
 package java.awt;
 
+import java.awt.event.InputEvent;
 import java.awt.image.BufferedImage;
+import java.awt.peer.RobotPeer;
+import gnu.java.awt.ClasspathToolkit;
 
 /**
+ * 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 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
  */
-/** STUB CLASS ONLY */
 public class Robot
 {
-  private GraphicsDevice screen;
   private boolean waitForIdle;
   private int autoDelay;
-  
+  private RobotPeer peer;
+
   /**
-   * Creates a <code>Robot</code> object.
-   * 
-   * @exception AWTException If GraphicsEnvironment.isHeadless() returns true.
-   * @exception SecurityException If createRobot permission is not granted.
+   * 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
+  public Robot () throws AWTException
   {
-    throw new Error("not implemented");
+    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 ());
   }
 
   /**
-   * Creates a <code>Robot</code> object.
-   * 
-   * @exception AWTException If GraphicsEnvironment.isHeadless() returns true.
-   * @exception IllegalArgumentException If <code>screen</code> is not a screen
-   * GraphicsDevice.
-   * @exception SecurityException If createRobot permission is not granted.
+   * 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
+  public Robot (GraphicsDevice screen) throws AWTException
   {
-    this();
-    this.screen = screen;
+    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);
   }
 
-  public void mousePress(int buttons)
+  /**
+   * 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);
   }
 
-  public void mouseWheel(int wheelAmt)
+  /**
+   * 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);
   }
 
-  public void keyPress(int keycode)
+  /**
+   * 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);
   }
 
-  public void keyRelease(int keycode)
+  /**
+   * 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);
   }
-  
-  public Color getPixelColor(int x, int y)
+
+  /**
+   * 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 null;
+    return new Color (peer.getRGBPixel (x, y));
   }
 
-  public BufferedImage createScreenCapture(Rectangle screen)
+  /**
+   * 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)
   {
-    return null;
+    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;
   }
-  
-  public boolean isAutoWaitForIdle()
+
+  /**
+   * Check if this Robot automatically calls {@link waitForIdle} after
+   * generating an event.
+   *
+   * @return true if waitForIdle is automatically called
+   */
+  public boolean isAutoWaitForIdle ()
   {
     return waitForIdle;
   }
-  
-  public void setAutoWaitForIdle(boolean value)
+
+  /**
+   * 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 = value;
+    waitForIdle = isOn;
   }
-  
-  public int getAutoDelay()
+
+  /**
+   * Retrieve the length of time this Robot sleeps after generating an
+   * event.
+   *
+   * @return the length of time in milliseconds
+   */
+  public int getAutoDelay ()
   {
     return autoDelay;
   }
-  
-  public void setAutoDelay(int ms)
+
+  /**
+   * 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();
-    
+    if (ms <= 0 || ms >= 60000)
+      throw new IllegalArgumentException ("Robot: delay length out-of-bounds");
+
     autoDelay = ms;
   }
 
-  public void delay(int 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();
+      throw new IllegalArgumentException ("Robot: delay length out-of-bounds");
+
+    try
+      {
+	Thread.sleep (ms);
+      }
+    catch (InterruptedException e)
+      {
+	System.err.println ("Robot: delay interrupted");
+      }
   }
 
-  public void waitForIdle()
+  /**
+   * Wait until the event dispatch thread is idle.
+   */
+  public void waitForIdle ()
   {
+    if (EventQueue.isDispatchThread ())
+      throw new IllegalThreadStateException ("Robot: waitForIdle called from "
+					     + "the event dispatch thread");
+
+    EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
+
+    while (q.peekEvent () != null)
+      {
+	try
+	  {
+	    wait ();
+	  }
+	catch (InterruptedException e)
+	  {
+	    System.err.println ("Robot: waitForIdle interrupted");
+	  }
+      }
   }
 
-  public String toString()
+  /**
+   * Return a string representation of this Robot.
+   *
+   * @return a string representation
+   */
+  public String toString ()
   {
-    return "unimplemented";
+    return getClass ().getName ()
+	+ "[ autoDelay = " + autoDelay + ", autoWaitForIdle = "
+	+ waitForIdle + " ]";
   }
-} // class Robot
+}
Index: java/awt/peer/RobotPeer.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/awt/peer/RobotPeer.java,v
retrieving revision 1.2
diff -u -r1.2 RobotPeer.java
--- java/awt/peer/RobotPeer.java	11 Oct 2003 18:11:03 -0000	1.2
+++ java/awt/peer/RobotPeer.java	31 Dec 2004 17:21:59 -0000
@@ -43,12 +43,12 @@
 public interface RobotPeer
 {
   void mouseMove (int x, int y);
-  void mousePress (int x);
-  void mouseRelease (int x);
-  void mouseWheel (int x);
-  void keyPress (int x);
-  void keyRelease (int x);
+  void mousePress (int buttons);
+  void mouseRelease (int buttons);
+  void mouseWheel (int wheelAmt);
+  void keyPress (int keycode);
+  void keyRelease (int keycode);
   int getRGBPixel (int x, int y);
-  int[] getRGBPixels (Rectangle r);
+  int[] getRGBPixels (Rectangle screen);
 } // interface RobotPeer
 
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c
===================================================================
RCS file: jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c
diff -N jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GdkRobotPeer.c	31 Dec 2004 17:22:17 -0000
@@ -0,0 +1,325 @@
+/* gdkrobotpeer.c
+   Copyright (C) 2004 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. */
+
+#include "gtkpeer.h"
+#include "gnu_java_awt_peer_gtk_GdkRobotPeer.h"
+#include <gdk/gdkx.h>
+#include <X11/extensions/XTest.h>
+
+static int
+awt_button_mask_to_num (int buttons)
+{
+  switch (buttons)
+    {
+    case AWT_BUTTON1_MASK:
+      return 1;
+    case AWT_BUTTON2_MASK:
+      return 2;
+    case AWT_BUTTON3_MASK:
+      return 3;
+    }
+
+  return 0;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_awt_peer_gtk_GdkRobotPeer_initXTest
+  (JNIEnv *env, jobject obj)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  int event_basep;
+  int error_basep;
+  int majorp;
+  int minorp;
+  jboolean result;
+
+  gdk_threads_enter ();
+
+  display = gdk_display_get_default ();
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  result = XTestQueryExtension (xdisplay,
+				&event_basep,
+				&error_basep,
+				&majorp,
+				&minorp);
+
+  gdk_threads_leave ();
+
+  return result;
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mouseMove
+  (JNIEnv *env, jobject obj, jint x, jint y)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  int result;
+
+  gdk_threads_enter ();
+
+  display = gdk_display_get_default ();
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  result = XTestFakeMotionEvent (xdisplay,
+				 -1,
+				 x, y, CurrentTime);
+
+  XFlush (xdisplay);
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mousePress
+  (JNIEnv *env, jobject obj, jint buttons)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  int result;
+
+  gdk_threads_enter ();
+
+  display = gdk_display_get_default ();
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  result = XTestFakeButtonEvent (xdisplay,
+				 awt_button_mask_to_num (buttons),
+				 True, CurrentTime);
+
+  XFlush (xdisplay);
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mouseRelease
+  (JNIEnv *env, jobject obj, jint buttons)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  int result;
+
+  gdk_threads_enter ();
+
+  display = gdk_display_get_default ();
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  result = XTestFakeButtonEvent (xdisplay,
+				 awt_button_mask_to_num (buttons),
+				 False, CurrentTime);
+
+  XFlush (xdisplay);
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GdkRobotPeer_mouseWheel
+  (JNIEnv *env, jobject obj, jint wheelAmt)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  int i = 0;
+
+  gdk_threads_enter ();
+
+  display = gdk_display_get_default ();
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  if (wheelAmt < 0)
+    for (i = 0; i < -wheelAmt; i++)
+      {
+	XTestFakeButtonEvent (xdisplay,
+			      4,
+			      True, CurrentTime);
+	XTestFakeButtonEvent (xdisplay,
+			      4,
+			      False, CurrentTime);
+      }
+  else
+    for (i = 0; i < wheelAmt; i++)
+      {
+	XTestFakeButtonEvent (xdisplay,
+			      5,
+			      True, CurrentTime);
+	XTestFakeButtonEvent (xdisplay,
+			      5,
+			      False, CurrentTime);
+      }
+
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GdkRobotPeer_keyPress
+  (JNIEnv *env, jobject obj, jint keycode)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  GdkKeymapKey *keymap_keys = NULL;
+  gint n_keys = 0;
+  guint lookup_keyval = 0;
+  int result;
+
+  gdk_threads_enter ();
+
+  display = gdk_display_get_default ();
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  lookup_keyval = awt_keycode_to_keysym (keycode, AWT_KEY_LOCATION_LEFT);
+
+  if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
+                                          lookup_keyval,
+                                          &keymap_keys,
+                                          &n_keys))
+    {
+      /* No matching keymap entry was found. */
+      g_printerr ("No matching keymap entries were found\n");
+      gdk_threads_leave ();
+      return;
+    }
+
+  /* If n_keys > 1 then there are multiple hardware keycodes that
+     translate to lookup_keyval.  We arbitrarily choose the first
+     hardware keycode from the list returned by
+     gdk_keymap_get_entries_for_keyval. */
+  result = XTestFakeKeyEvent (xdisplay,
+			      keymap_keys[0].keycode,
+			      True, CurrentTime);
+
+  g_free (keymap_keys);
+
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GdkRobotPeer_keyRelease
+  (JNIEnv *env, jobject obj, jint keycode)
+{
+  GdkDisplay *display;
+  Display *xdisplay;
+  GdkKeymapKey *keymap_keys = NULL;
+  gint n_keys = 0;
+  guint lookup_keyval = 0;
+  int result;
+
+  gdk_threads_enter ();
+
+  display = gdk_display_get_default ();
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  lookup_keyval = awt_keycode_to_keysym (keycode, AWT_KEY_LOCATION_LEFT);
+
+  if (!gdk_keymap_get_entries_for_keyval (gdk_keymap_get_default (),
+                                          lookup_keyval,
+                                          &keymap_keys,
+                                          &n_keys))
+    {
+      /* No matching keymap entry was found. */
+      g_printerr ("No matching keymap entries were found\n");
+      gdk_threads_leave ();
+      return;
+    }
+
+  /* If n_keys > 1 then there are multiple hardware keycodes that
+     translate to lookup_keyval.  We arbitrarily choose the first
+     hardware keycode from the list returned by
+     gdk_keymap_get_entries_for_keyval. */
+  result = XTestFakeKeyEvent (xdisplay,
+			      keymap_keys[0].keycode,
+			      False, CurrentTime);
+
+  g_free (keymap_keys);
+
+  gdk_threads_leave ();
+}
+
+JNIEXPORT jintArray JNICALL
+Java_gnu_java_awt_peer_gtk_GdkRobotPeer_nativeGetRGBPixels
+  (JNIEnv *env, jobject obj, jint x, jint y,
+   jint width, jint height)
+{
+  jint stride_bytes, stride_pixels, n_channels, n_pixels;
+  jintArray jpixels;  
+  jint *java_pixels;
+  guchar *gdk_pixels;
+  GdkPixbuf *pixbuf_no_alpha = NULL;
+  GdkPixbuf *pixbuf = NULL;
+
+#ifndef WORDS_BIGENDIAN
+  int i;
+#endif
+
+  gdk_threads_enter ();
+
+  pixbuf_no_alpha = gdk_pixbuf_get_from_drawable (NULL,
+						  gdk_get_default_root_window (),
+						  NULL, x, y, 0, 0,
+						  width, height);
+
+  pixbuf = gdk_pixbuf_add_alpha(pixbuf_no_alpha, FALSE, 0, 0, 0);
+  g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
+  
+  stride_bytes = gdk_pixbuf_get_rowstride (pixbuf);
+  n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+  stride_pixels =  stride_bytes / n_channels;
+  n_pixels = height * stride_pixels;
+  gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+  jpixels = (*env)->NewIntArray (env, n_pixels);
+  java_pixels = (*env)->GetIntArrayElements (env, jpixels, NULL);
+
+  memcpy (java_pixels,
+	  gdk_pixels,
+	  (height * stride_bytes));
+
+#ifndef WORDS_BIGENDIAN
+  /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */
+  for (i = 0; i < n_pixels; ++i)
+    {
+      java_pixels[i] = SWAPU32 ((unsigned)java_pixels[i]);
+    }
+#endif
+
+  g_object_unref (pixbuf);
+
+  (*env)->ReleaseIntArrayElements (env, jpixels, java_pixels, 0);
+
+  gdk_threads_leave ();
+
+  return jpixels;
+}
Index: jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c,v
retrieving revision 1.15.2.26
diff -u -r1.15.2.26 gnu_java_awt_peer_gtk_GtkComponentPeer.c
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	7 Nov 2004 00:04:27 -0000	1.15.2.26
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c	31 Dec 2004 17:22:19 -0000
@@ -60,7 +60,7 @@
 #ifdef __GNUC__
 __inline
 #endif
-static guint
+guint
 awt_keycode_to_keysym (jint keyCode, jint keyLocation)
 {
   /* GDK_A through GDK_Z */
Index: jni/gtk-peer/gtkpeer.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni/gtk-peer/gtkpeer.h,v
retrieving revision 1.12.8.13
diff -u -r1.12.8.13 gtkpeer.h
--- jni/gtk-peer/gtkpeer.h	25 Oct 2004 21:14:24 -0000	1.12.8.13
+++ jni/gtk-peer/gtkpeer.h	31 Dec 2004 17:22:21 -0000
@@ -147,6 +147,10 @@
 #define AWT_BUTTON2_DOWN_MASK (1 << 11)
 #define AWT_BUTTON3_DOWN_MASK (1 << 12)
 
+#define AWT_BUTTON1_MASK (1 << 4)
+#define AWT_BUTTON2_MASK (1 << 3)
+#define AWT_BUTTON3_MASK (1 << 2)
+
 #define MULTI_CLICK_TIME   250
 /* as opposed to a MULTI_PASS_TIME :) */
 
@@ -480,6 +484,8 @@
 
 jint keyevent_state_to_awt_mods (GdkEvent *event);
 
+guint awt_keycode_to_keysym (jint keyCode, jint keyLocation);
+
 struct item_event_hook_info
 {
   jobject peer_obj;
Index: testsuite/libjava.mauve/mauve.exp
===================================================================
RCS file: /cvs/gcc/gcc/libjava/testsuite/libjava.mauve/mauve.exp,v
retrieving revision 1.23
diff -u -r1.23 mauve.exp
--- testsuite/libjava.mauve/mauve.exp	12 Aug 2003 17:59:17 -0000	1.23
+++ testsuite/libjava.mauve/mauve.exp	31 Dec 2004 17:22:26 -0000
@@ -144,7 +144,13 @@
   catch {system "ln -s $full_srcdir/libjava.mauve/xfails xfails"}
 
   if {[catch {
-    system "make KEYS=libgcj classes.stamp 2>&1"
+      if { [info exists env(KEYS)] && [string length $env(KEYS)] > 0 } {
+	verbose "running make check with overridden keys: $env(KEYS)"
+	system "make KEYS=\"$env(KEYS)\" classes.stamp 2>&1"
+      } else {
+	verbose "running make check with default keys"
+	system "make KEYS=libgcj classes.stamp 2>&1"
+      }        
   } msg]} then {
     fail "Mauve build"
     verbose "build failed with $msg"
@@ -299,7 +305,13 @@
   catch {system "ln -s $full_srcdir/libjava.mauve/xfails xfails"}
 
   if {[catch {
-    system "make KEYS=libgcj classes.stamp 2>&1"
+      if { [info exists env(KEYS)] && [string length $env(KEYS)] > 0 } {
+	verbose "running make check with overridden keys: $env(KEYS)"
+	system "make KEYS=\"$env(KEYS)\" classes.stamp 2>&1"
+      } else {
+	verbose "running make check with default keys"
+	system "make KEYS=libgcj classes.stamp 2>&1"
+      }
   } msg]} then {
     fail "Mauve build"
     verbose "build failed with $msg"

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]