This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[gui][PATCH] Implement java.awt.Robot
- From: Thomas Fitzsimmons <fitzsim at redhat dot com>
- To: java-patches at gcc dot gnu dot org
- Date: Fri, 31 Dec 2004 13:12:22 -0500
- Subject: [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"