diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2005-09-23 21:31:04 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-09-23 21:31:04 +0000 |
commit | 1ea63ef8be1cc54dd0de9d82c684713a1dcf1e06 (patch) | |
tree | 3ca4b2e68dc14c3128b9c781d23f1d0b1f2bee49 /libjava/classpath/gnu/java | |
parent | 9b044d19517541c95681d35a92dbc81e6e21d94f (diff) | |
download | gcc-1ea63ef8be1cc54dd0de9d82c684713a1dcf1e06.zip gcc-1ea63ef8be1cc54dd0de9d82c684713a1dcf1e06.tar.gz gcc-1ea63ef8be1cc54dd0de9d82c684713a1dcf1e06.tar.bz2 |
Imported Classpath 0.18.
* sources.am, Makefile.in: Updated.
* Makefile.am (nat_source_files): Removed natProxy.cc.
* java/lang/reflect/natProxy.cc: Removed.
* gnu/classpath/jdwp/VMFrame.java,
gnu/classpath/jdwp/VMIdManager.java,
gnu/classpath/jdwp/VMVirtualMachine.java,
java/lang/reflect/VMProxy.java: New files.
2005-09-23 Thomas Fitzsimmons <fitzsim@redhat.com>
* scripts/makemake.tcl (verbose): Add gnu/java/awt/peer/qt to BC
list.
2005-09-23 Thomas Fitzsimmons <fitzsim@redhat.com>
* gnu/java/net/DefaultContentHandlerFactory.java (getContent):
Remove ClasspathToolkit references.
2005-09-23 Thomas Fitzsimmons <fitzsim@redhat.com>
* gnu/awt/xlib/XCanvasPeer.java: Add new peer methods.
* gnu/awt/xlib/XFramePeer.java: Likewise.
* gnu/awt/xlib/XGraphicsConfiguration.java: Likewise.
2005-09-23 Thomas Fitzsimmons <fitzsim@redhat.com>
* Makefile.am (libgcjawt_la_SOURCES): Remove jawt.c. Add
classpath/native/jawt/jawt.c.
* Makefile.in: Regenerate.
* jawt.c: Remove file.
* include/Makefile.am (tool_include__HEADERS): Remove jawt.h and
jawt_md.h. Add ../classpath/include/jawt.h and
../classpath/include/jawt_md.h.
* include/Makefile.in: Regenerate.
* include/jawt.h: Regenerate.
* include/jawt_md.h: Regenerate.
From-SVN: r104586
Diffstat (limited to 'libjava/classpath/gnu/java')
37 files changed, 1649 insertions, 588 deletions
diff --git a/libjava/classpath/gnu/java/awt/AWTUtilities.java b/libjava/classpath/gnu/java/awt/AWTUtilities.java index a02d1c4..af1fc13 100644 --- a/libjava/classpath/gnu/java/awt/AWTUtilities.java +++ b/libjava/classpath/gnu/java/awt/AWTUtilities.java @@ -37,17 +37,28 @@ exception statement from your version. */ package gnu.java.awt; +import java.applet.Applet; import java.awt.Component; import java.awt.Container; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.MouseEvent; import java.util.AbstractSequentialList; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.WeakHashMap; +import java.lang.reflect.InvocationTargetException; /** - * This class provides utility methods that are commonly used in AWT - * (and Swing). + * This class mirrors the javax.swing.SwingUtilities class. It + * provides commonly needed functionalities for AWT classes without + * the need to reference classes in the javax.swing package. */ public class AWTUtilities { @@ -318,4 +329,366 @@ public class AWTUtilities return visibleChildren; } + + /** + * Calculates the portion of the base rectangle which is inside the + * insets. + * + * @param base The rectangle to apply the insets to + * @param insets The insets to apply to the base rectangle + * @param ret A rectangle to use for storing the return value, or + * <code>null</code> + * + * @return The calculated area inside the base rectangle and its insets, + * either stored in ret or a new Rectangle if ret is <code>null</code> + * + * @see #calculateInnerArea + */ + public static Rectangle calculateInsetArea(Rectangle base, Insets insets, + Rectangle ret) + { + if (ret == null) + ret = new Rectangle(); + ret.setBounds(base.x + insets.left, base.y + insets.top, + base.width - (insets.left + insets.right), + base.height - (insets.top + insets.bottom)); + return ret; + } + + /** + * Calculates the bounds of a component in the component's own coordinate + * space. The result has the same height and width as the component's + * bounds, but its location is set to (0,0). + * + * @param aComponent The component to measure + * + * @return The component's bounds in its local coordinate space + */ + public static Rectangle getLocalBounds(Component aComponent) + { + Rectangle bounds = aComponent.getBounds(); + return new Rectangle(0, 0, bounds.width, bounds.height); + } + + /** + * Returns the font metrics object for a given font. The metrics can be + * used to calculate crude bounding boxes and positioning information, + * for laying out components with textual elements. + * + * @param font The font to get metrics for + * + * @return The font's metrics + * + * @see java.awt.font.GlyphMetrics + */ + public static FontMetrics getFontMetrics(Font font) + { + return Toolkit.getDefaultToolkit().getFontMetrics(font); + } + + /** + * Returns the least ancestor of <code>comp</code> which has the + * specified name. + * + * @param name The name to search for + * @param comp The component to search the ancestors of + * + * @return The nearest ancestor of <code>comp</code> with the given + * name, or <code>null</code> if no such ancestor exists + * + * @see java.awt.Component#getName + * @see #getAncestorOfClass + */ + public static Container getAncestorNamed(String name, Component comp) + { + while (comp != null && (comp.getName() != name)) + comp = comp.getParent(); + return (Container) comp; + } + + /** + * Returns the least ancestor of <code>comp</code> which is an instance + * of the specified class. + * + * @param c The class to search for + * @param comp The component to search the ancestors of + * + * @return The nearest ancestor of <code>comp</code> which is an instance + * of the given class, or <code>null</code> if no such ancestor exists + * + * @see #getAncestorOfClass + * @see #windowForComponent + * @see + * + */ + public static Container getAncestorOfClass(Class c, Component comp) + { + while (comp != null && (! c.isInstance(comp))) + comp = comp.getParent(); + return (Container) comp; + } + + /** + * Equivalent to calling <code>getAncestorOfClass(Window, comp)</code>. + * + * @param comp The component to search for an ancestor window + * + * @return An ancestral window, or <code>null</code> if none exists + */ + public static Window windowForComponent(Component comp) + { + return (Window) getAncestorOfClass(Window.class, comp); + } + + /** + * Returns the "root" of the component tree containint <code>comp</code> + * The root is defined as either the <em>least</em> ancestor of + * <code>comp</code> which is a {@link Window}, or the <em>greatest</em> + * ancestor of <code>comp</code> which is a {@link Applet} if no {@link + * Window} ancestors are found. + * + * @param comp The component to search for a root + * + * @return The root of the component's tree, or <code>null</code> + */ + public static Component getRoot(Component comp) + { + Applet app = null; + Window win = null; + + while (comp != null) + { + if (win == null && comp instanceof Window) + win = (Window) comp; + else if (comp instanceof Applet) + app = (Applet) comp; + comp = comp.getParent(); + } + + if (win != null) + return win; + else + return app; + } + + /** + * Return true if a descends from b, in other words if b is an + * ancestor of a. + * + * @param a The child to search the ancestry of + * @param b The potential ancestor to search for + * + * @return true if a is a descendent of b, false otherwise + */ + public static boolean isDescendingFrom(Component a, Component b) + { + while (true) + { + if (a == null || b == null) + return false; + if (a == b) + return true; + a = a.getParent(); + } + } + + /** + * Returns the deepest descendent of parent which is both visible and + * contains the point <code>(x,y)</code>. Returns parent when either + * parent is not a container, or has no children which contain + * <code>(x,y)</code>. Returns <code>null</code> when either + * <code>(x,y)</code> is outside the bounds of parent, or parent is + * <code>null</code>. + * + * @param parent The component to search the descendents of + * @param x Horizontal coordinate to search for + * @param y Vertical coordinate to search for + * + * @return A component containing <code>(x,y)</code>, or + * <code>null</code> + * + * @see java.awt.Container#findComponentAt + */ + public static Component getDeepestComponentAt(Component parent, int x, int y) + { + if (parent == null || (! parent.contains(x, y))) + return null; + + if (! (parent instanceof Container)) + return parent; + + Container c = (Container) parent; + return c.findComponentAt(x, y); + } + + /** + * Converts a point from a component's local coordinate space to "screen" + * coordinates (such as the coordinate space mouse events are delivered + * in). This operation is equivalent to translating the point by the + * location of the component (which is the origin of its coordinate + * space). + * + * @param p The point to convert + * @param c The component which the point is expressed in terms of + * + * @see convertPointFromScreen + */ + public static void convertPointToScreen(Point p, Component c) + { + Point c0 = c.getLocationOnScreen(); + p.translate(c0.x, c0.y); + } + + /** + * Converts a point from "screen" coordinates (such as the coordinate + * space mouse events are delivered in) to a component's local coordinate + * space. This operation is equivalent to translating the point by the + * negation of the component's location (which is the origin of its + * coordinate space). + * + * @param p The point to convert + * @param c The component which the point should be expressed in terms of + */ + public static void convertPointFromScreen(Point p, Component c) + { + Point c0 = c.getLocationOnScreen(); + p.translate(-c0.x, -c0.y); + } + + /** + * Converts a point <code>(x,y)</code> from the coordinate space of one + * component to another. This is equivalent to converting the point from + * <code>source</code> space to screen space, then back from screen space + * to <code>destination</code> space. If exactly one of the two + * Components is <code>null</code>, it is taken to refer to the root + * ancestor of the other component. If both are <code>null</code>, no + * transformation is done. + * + * @param source The component which the point is expressed in terms of + * @param x Horizontal coordinate of point to transform + * @param y Vertical coordinate of point to transform + * @param destination The component which the return value will be + * expressed in terms of + * + * @return The point <code>(x,y)</code> converted from the coordinate + * space of the + * source component to the coordinate space of the destination component + * + * @see #convertPointToScreen + * @see #convertPointFromScreen + * @see #convertRectangle + * @see #getRoot + */ + public static Point convertPoint(Component source, int x, int y, + Component destination) + { + Point pt = new Point(x, y); + + if (source == null && destination == null) + return pt; + + if (source == null) + source = getRoot(destination); + + if (destination == null) + destination = getRoot(source); + + convertPointToScreen(pt, source); + convertPointFromScreen(pt, destination); + + return pt; + } + + + /** + * Converts a rectangle from the coordinate space of one component to + * another. This is equivalent to converting the rectangle from + * <code>source</code> space to screen space, then back from screen space + * to <code>destination</code> space. If exactly one of the two + * Components is <code>null</code>, it is taken to refer to the root + * ancestor of the other component. If both are <code>null</code>, no + * transformation is done. + * + * @param source The component which the rectangle is expressed in terms of + * @param rect The rectangle to convert + * @param destination The component which the return value will be + * expressed in terms of + * + * @return A new rectangle, equal in size to the input rectangle, but + * with its position converted from the coordinate space of the source + * component to the coordinate space of the destination component + * + * @see #convertPointToScreen + * @see #convertPointFromScreen + * @see #convertPoint + * @see #getRoot + */ + public static Rectangle convertRectangle(Component source, Rectangle rect, + Component destination) + { + Point pt = convertPoint(source, rect.x, rect.y, destination); + return new Rectangle(pt.x, pt.y, rect.width, rect.height); + } + + /** + * Convert a mouse event which refrers to one component to another. This + * includes changing the mouse event's coordinate space, as well as the + * source property of the event. If <code>source</code> is + * <code>null</code>, it is taken to refer to <code>destination</code>'s + * root component. If <code>destination</code> is <code>null</code>, the + * new event will remain expressed in <code>source</code>'s coordinate + * system. + * + * @param source The component the mouse event currently refers to + * @param sourceEvent The mouse event to convert + * @param destination The component the new mouse event should refer to + * + * @return A new mouse event expressed in terms of the destination + * component's coordinate space, and with the destination component as + * its source + * + * @see #convertPoint + */ + public static MouseEvent convertMouseEvent(Component source, + MouseEvent sourceEvent, + Component destination) + { + Point newpt = convertPoint(source, sourceEvent.getX(), sourceEvent.getY(), + destination); + + return new MouseEvent(destination, sourceEvent.getID(), + sourceEvent.getWhen(), sourceEvent.getModifiers(), + newpt.x, newpt.y, sourceEvent.getClickCount(), + sourceEvent.isPopupTrigger(), + sourceEvent.getButton()); + } + + + /** + * Calls {@link java.awt.EventQueue.invokeLater} with the + * specified {@link Runnable}. + */ + public static void invokeLater(Runnable doRun) + { + java.awt.EventQueue.invokeLater(doRun); + } + + /** + * Calls {@link java.awt.EventQueue.invokeAndWait} with the + * specified {@link Runnable}. + */ + public static void invokeAndWait(Runnable doRun) + throws InterruptedException, + InvocationTargetException + { + java.awt.EventQueue.invokeAndWait(doRun); + } + + /** + * Calls {@link java.awt.EventQueue.isEventDispatchThread}. + */ + public static boolean isEventDispatchThread() + { + return java.awt.EventQueue.isDispatchThread(); + } } diff --git a/libjava/classpath/gnu/java/awt/ClasspathToolkit.java b/libjava/classpath/gnu/java/awt/ClasspathToolkit.java index 5fb444f..1ec5664 100644 --- a/libjava/classpath/gnu/java/awt/ClasspathToolkit.java +++ b/libjava/classpath/gnu/java/awt/ClasspathToolkit.java @@ -1,5 +1,5 @@ /* ClasspathToolkit.java -- Abstract superclass for Classpath toolkits. - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -42,11 +42,12 @@ import gnu.java.awt.EmbeddedWindow; import gnu.java.awt.peer.ClasspathFontPeer; import gnu.java.awt.peer.EmbeddedWindowPeer; import gnu.java.awt.peer.ClasspathTextLayoutPeer; +import gnu.java.security.action.SetAccessibleAction; import java.awt.AWTException; +import java.awt.Component; import java.awt.Dimension; import java.awt.DisplayMode; -import java.awt.EventQueue; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GraphicsDevice; @@ -59,11 +60,14 @@ import java.awt.image.ImageProducer; import java.awt.peer.RobotPeer; import java.io.File; import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.text.AttributedString; import java.util.HashMap; import java.util.Map; +import java.security.AccessController; import javax.imageio.spi.IIORegistry; @@ -92,14 +96,6 @@ public abstract class ClasspathToolkit extends Toolkit { /** - * A map from URLs to previously loaded images, used by {@link - * #getImage(java.net.URL)}. For images that were loaded via a path - * to an image file, the map contains a key with a file URL. - */ - private HashMap imageCache; - - - /** * Returns a shared instance of the local, platform-specific * graphics environment. * @@ -109,59 +105,6 @@ public abstract class ClasspathToolkit */ public abstract GraphicsEnvironment getLocalGraphicsEnvironment(); - - /** - * Determines the current size of the default, primary screen. - * - * @throws HeadlessException if the local graphics environment is - * headless, which means that no screen is attached and no user - * interaction is allowed. - */ - public Dimension getScreenSize() - { - DisplayMode mode; - - // getDefaultScreenDevice throws HeadlessException if the - // local graphics environment is headless. - mode = GraphicsEnvironment.getLocalGraphicsEnvironment() - .getDefaultScreenDevice().getDisplayMode(); - - return new Dimension(mode.getWidth(), mode.getHeight()); - } - - - /** - * Determines the current color model of the default, primary - * screen. - * - * @see GraphicsEnvironment#getDefaultScreenDevice() - * @see java.awt.GraphicsDevice#getDefaultConfiguration() - * @see java.awt.GraphicsConfiguration#getColorModel() - * - * @throws HeadlessException if the local graphics environment is - * headless, which means that no screen is attached and no user - * interaction is allowed. - */ - public ColorModel getColorModel() - { - // getDefaultScreenDevice throws HeadlessException if the - // local graphics environment is headless. - return GraphicsEnvironment.getLocalGraphicsEnvironment() - .getDefaultScreenDevice().getDefaultConfiguration() - .getColorModel(); - } - - /** - * Retrieves the metrics for rendering a font on the screen. - * - * @param font the font whose metrics are requested. - */ - public FontMetrics getFontMetrics(Font font) - { - return ((ClasspathFontPeer) font.getPeer ()).getFontMetrics (font); - } - - /** * Acquires an appropriate {@link ClasspathFontPeer}, for use in * classpath's implementation of {@link java.awt.Font}. @@ -185,15 +128,42 @@ public abstract class ClasspathToolkit * Creates a {@link Font}, in a platform-specific manner. * * The default implementation simply constructs a {@link Font}, but some - * toolkits may wish to override this, to return {@link Font} subclasses which - * implement {@link java.awt.font.OpenType} or + * toolkits may wish to override this, to return {@link Font} subclasses + * which implement {@link java.awt.font.OpenType} or * {@link java.awt.font.MultipleMaster}. */ public Font getFont (String name, Map attrs) { - return new Font (name, attrs); - } + Font f = null; + // Circumvent the package-privateness of the + // java.awt.Font.Font(String,Map) constructor. + try + { + Constructor fontConstructor = Font.class.getDeclaredConstructor + (new Class[] { String.class, Map.class }); + AccessController.doPrivileged + (new SetAccessibleAction(fontConstructor)); + f = (Font) fontConstructor.newInstance(new Object[] { name, attrs }); + } + catch (IllegalAccessException e) + { + throw new AssertionError(e); + } + catch (NoSuchMethodException e) + { + throw new AssertionError(e); + } + catch (InstantiationException e) + { + throw new AssertionError(e); + } + catch (InvocationTargetException e) + { + throw new AssertionError(e); + } + return f; + } /** * Creates a font, reading the glyph definitions from a stream. @@ -223,137 +193,6 @@ public abstract class ClasspathToolkit */ public abstract Font createFont(int format, InputStream stream); - - /** - * Returns an image from the specified file, which must be in a - * recognized format. The set of recognized image formats may vary - * from toolkit to toolkit. - * - * <p>This method maintains a cache for images. If an image has been - * loaded from the same path before, the cached copy will be - * returned. The implementation may hold cached copies for an - * indefinite time, which can consume substantial resources with - * large images. Users are therefore advised to use {@link - * #createImage(java.lang.String)} instead. - * - * <p>The default implementation creates a file URL for the - * specified path and invokes {@link #getImage(URL)}. - * - * @param path A path to the image file. - * - * @return IllegalArgumentException if <code>path</code> does not - * designate a valid path. - */ - public Image getImage(String path) - { - try - { - return getImage(new File(path).toURL()); - } - catch (MalformedURLException muex) - { - throw (IllegalArgumentException) new IllegalArgumentException(path) - .initCause(muex); - } - } - - - /** - * Loads an image from the specified URL. The image data must be in - * a recognized format. The set of recognized image formats may vary - * from toolkit to toolkit. - * - * <p>This method maintains a cache for images. If an image has been - * loaded from the same URL before, the cached copy will be - * returned. The implementation may hold cached copies for an - * indefinite time, which can consume substantial resources with - * large images. Users are therefore advised to use {@link - * #createImage(java.net.URL)} instead. - * - * @param url the URL from where the image is read. - */ - public Image getImage(URL url) - { - Image result; - - synchronized (this) - { - // Many applications never call getImage. Therefore, we lazily - // create the image cache when it is actually needed. - if (imageCache == null) - imageCache = new HashMap(); - else - { - result = (Image) imageCache.get(url); - if (result != null) - return result; - } - - // The createImage(URL) method, which is specified by - // java.awt.Toolkit, is not implemented by this abstract class - // because it is platform-dependent. Once Classpath has support - // for the javax.imageio package, it might be worth considering - // that toolkits provide native stream readers. Then, the class - // ClasspathToolkit could provide a general implementation that - // delegates the image format parsing to javax.imageio. - result = createImage(url); - - // It is not clear whether it would be a good idea to use weak - // references here. The advantage would be reduced memory - // consumption, since loaded images would not be kept - // forever. But on VMs that frequently perform garbage - // collection (which includes VMs with a parallel or incremental - // collector), the image might frequently need to be re-loaded, - // possibly over a slow network connection. - imageCache.put(url, result); - - return result; - } - } - - - /** - * Returns an image from the specified file, which must be in a - * recognized format. The set of recognized image formats may vary - * from toolkit to toolkit. - * - * <p>A new image is created every time this method gets called, - * even if the same path has been passed before. - * - * <p>The default implementation creates a file URL for the - * specified path and invokes {@link #createImage(URL)}. - * - * @param path A path to the file to be read in. - */ - public Image createImage(String path) - { - try - { - // The abstract method createImage(URL) is defined by - // java.awt.Toolkit, but intentionally not implemented by - // ClasspathToolkit because it is platform specific. - return createImage(new File(path).toURL()); - } - catch (MalformedURLException muex) - { - throw (IllegalArgumentException) new IllegalArgumentException(path) - .initCause(muex); - } - } - - /** - * Creates an ImageProducer from the specified URL. The image is assumed - * to be in a recognised format. If the toolkit does not implement the - * image format or the image format is not recognised, null is returned. - * This default implementation is overriden by the Toolkit implementations. - * - * @param url URL to read image data from. - */ - public ImageProducer createImageProducer(URL url) - { - return null; - } - public abstract RobotPeer createRobot (GraphicsDevice screen) throws AWTException; @@ -365,15 +204,10 @@ public abstract class ClasspathToolkit */ public abstract EmbeddedWindowPeer createEmbeddedWindow (EmbeddedWindow w); - /** + /** * Used to register ImageIO SPIs provided by the toolkit. */ - - public void registerImageIOSpis(IIORegistry reg) - { - } - - public abstract boolean nativeQueueEmpty(); - public abstract void wakeNativeQueue(); - public abstract void iterateNativeQueue(EventQueue locked, boolean block); + public void registerImageIOSpis(IIORegistry reg) + { + } } diff --git a/libjava/classpath/gnu/java/awt/EmbeddedWindow.java b/libjava/classpath/gnu/java/awt/EmbeddedWindow.java index a85ce74..08b2140 100644 --- a/libjava/classpath/gnu/java/awt/EmbeddedWindow.java +++ b/libjava/classpath/gnu/java/awt/EmbeddedWindow.java @@ -98,11 +98,13 @@ public class EmbeddedWindow extends Frame } catch (IllegalAccessException e) { - // This should never happen. + throw new RuntimeException + ("couldn't set java.awt.Component.peer field"); } catch (NoSuchFieldException e) { - // This should never happen. + throw new RuntimeException + ("couldn't set java.awt.Component.peer field"); } super.addNotify(); diff --git a/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java index 3bcaebc..5252e80 100644 --- a/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/GLightweightPeer.java @@ -52,6 +52,7 @@ import java.awt.GraphicsConfiguration; import java.awt.Image; import java.awt.Insets; import java.awt.Point; +import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.PaintEvent; import java.awt.image.ColorModel; @@ -295,4 +296,44 @@ public class GLightweightPeer public void flip(BufferCapabilities.FlipContents contents) { } public void destroyBuffers() { } + + public boolean isRestackSupported() + { + return false; + } + + public void cancelPendingPaint(int x, int y, int width, int height) + { + + } + + public void restack() + { + + } + + public Rectangle getBounds() + { + return null; + } + + public void reparent(ContainerPeer parent) + { + + } + + public void setBounds(int x, int y, int z, int width, int height) + { + + } + + public boolean isReparentSupported() + { + return false; + } + + public void layout() + { + + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java index a125be7..160602b 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java @@ -38,6 +38,8 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; +import gnu.classpath.Configuration; + import java.awt.Color; import java.awt.Dimension; import java.awt.Font; @@ -52,7 +54,17 @@ import java.text.AttributedCharacterIterator; public class GdkGraphics extends Graphics { - private final int native_state = GtkGenericPeer.getUniqueInteger(); + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("gtkpeer"); + } + initStaticState (); + } + + static native void initStaticState(); + private final int native_state = GtkGenericPeer.getUniqueInteger (); Color color, xorColor; GtkComponentPeer component; @@ -66,6 +78,7 @@ public class GdkGraphics extends Graphics static final int GDK_COPY = 0, GDK_XOR = 2; native void initState (GtkComponentPeer component); + native void initStateUnlocked (GtkComponentPeer component); native void initState (int width, int height); native void initFromImage (GtkImage image); native void copyState (GdkGraphics g); @@ -119,6 +132,15 @@ public class GdkGraphics extends Graphics clip = new Rectangle (0, 0, d.width, d.height); } + // called back by native side: realize_cb + void initComponentGraphicsUnlocked () + { + initStateUnlocked (component); + color = component.awtComponent.getForeground (); + Dimension d = component.awtComponent.getSize (); + clip = new Rectangle (0, 0, d.width, d.height); + } + native void connectSignals (GtkComponentPeer component); public native void clearRect(int x, int y, int width, int height); @@ -327,7 +349,13 @@ public class GdkGraphics extends Graphics public void setClip (Shape clip) { - if (clip != null) + if (clip == null) + { + // Reset clipping. + Dimension d = component.awtComponent.getSize(); + setClip(new Rectangle (0, 0, d.width, d.height)); + } + else setClip(clip.getBounds()); } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java index b820317..6d9aabf 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java @@ -45,6 +45,7 @@ import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Composite; +import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; @@ -106,8 +107,7 @@ public class GdkGraphics2D extends Graphics2D if (Configuration.INIT_LOAD_LIBRARY) System.loadLibrary("gtkpeer"); - if (GtkToolkit.useGraphics2D()) - initStaticState(); + initStaticState(); } static native void initStaticState(); @@ -132,12 +132,14 @@ public class GdkGraphics2D extends Graphics2D Composite comp; private Stack stateStack; + private native void initStateUnlocked(GtkComponentPeer component); private native void initState(GtkComponentPeer component); private native void initState(int width, int height); private native void initState(int[] pixes, int width, int height); private native void copyState(GdkGraphics2D g); public native void dispose(); private native void cairoSurfaceSetFilter(int filter); + private native void cairoSurfaceSetFilterUnlocked(int filter); native void connectSignals(GtkComponentPeer component); public void finalize() @@ -236,6 +238,21 @@ public class GdkGraphics2D extends Graphics2D stateStack = new Stack(); } + void initComponentGraphics2DUnlocked() + { + initStateUnlocked(component); + + setColorUnlocked(component.awtComponent.getForeground()); + setBackgroundUnlocked(component.awtComponent.getBackground()); + setPaintUnlocked(getColorUnlocked()); + setTransformUnlocked(new AffineTransform()); + setStrokeUnlocked(new BasicStroke()); + setRenderingHintsUnlocked(getDefaultHints()); + setFontUnlocked(new Font("SansSerif", Font.PLAIN, 12)); + + stateStack = new Stack(); + } + GdkGraphics2D(BufferedImage bimage) { this.bimage = bimage; @@ -280,25 +297,37 @@ public class GdkGraphics2D extends Graphics2D // drawing utility methods private native void drawPixels(int[] pixels, int w, int h, int stride, double[] i2u); + private native void setTexturePixelsUnlocked(int[] pixels, int w, int h, int stride); private native void setTexturePixels(int[] pixels, int w, int h, int stride); private native void setGradient(double x1, double y1, double x2, double y2, int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2, boolean cyclic); + private native void setGradientUnlocked(double x1, double y1, double x2, double y2, + int r1, int g1, int b1, int a1, int r2, + int g2, int b2, int a2, boolean cyclic); // simple passthroughs to cairo private native void cairoSave(); private native void cairoRestore(); private native void cairoSetMatrix(double[] m); + private native void cairoSetMatrixUnlocked(double[] m); private native void cairoSetOperator(int cairoOperator); private native void cairoSetRGBAColor(double red, double green, double blue, double alpha); + private native void cairoSetRGBAColorUnlocked(double red, double green, + double blue, double alpha); private native void cairoSetFillRule(int cairoFillRule); private native void cairoSetLineWidth(double width); + private native void cairoSetLineWidthUnlocked(double width); private native void cairoSetLineCap(int cairoLineCap); + private native void cairoSetLineCapUnlocked(int cairoLineCap); private native void cairoSetLineJoin(int cairoLineJoin); + private native void cairoSetLineJoinUnlocked(int cairoLineJoin); private native void cairoSetDash(double[] dashes, int ndash, double offset); + private native void cairoSetDashUnlocked(double[] dashes, int ndash, double offset); private native void cairoSetMiterLimit(double limit); + private native void cairoSetMiterLimitUnlocked(double limit); private native void cairoNewPath(); private native void cairoMoveTo(double x, double y); private native void cairoLineTo(double x, double y); @@ -689,6 +718,49 @@ public class GdkGraphics2D extends Graphics2D throw new java.lang.UnsupportedOperationException(); } + public void setPaintUnlocked(Paint p) + { + if (paint == null) + return; + + paint = p; + if (paint instanceof Color) + { + setColorUnlocked((Color) paint); + } + else if (paint instanceof TexturePaint) + { + TexturePaint tp = (TexturePaint) paint; + BufferedImage img = tp.getImage(); + + // map the image to the anchor rectangle + int width = (int) tp.getAnchorRect().getWidth(); + int height = (int) tp.getAnchorRect().getHeight(); + + double scaleX = width / (double) img.getWidth(); + double scaleY = width / (double) img.getHeight(); + + AffineTransform at = new AffineTransform(scaleX, 0, 0, scaleY, 0, 0); + AffineTransformOp op = new AffineTransformOp(at, getRenderingHints()); + BufferedImage texture = op.filter(img, null); + int[] pixels = texture.getRGB(0, 0, width, height, null, 0, width); + setTexturePixelsUnlocked(pixels, width, height, width); + } + else if (paint instanceof GradientPaint) + { + GradientPaint gp = (GradientPaint) paint; + Point2D p1 = gp.getPoint1(); + Point2D p2 = gp.getPoint2(); + Color c1 = gp.getColor1(); + Color c2 = gp.getColor2(); + setGradientUnlocked(p1.getX(), p1.getY(), p2.getX(), p2.getY(), c1.getRed(), + c1.getGreen(), c1.getBlue(), c1.getAlpha(), c2.getRed(), + c2.getGreen(), c2.getBlue(), c2.getAlpha(), gp.isCyclic()); + } + else + throw new java.lang.UnsupportedOperationException(); + } + public void setTransform(AffineTransform tx) { transform = tx; @@ -700,6 +772,17 @@ public class GdkGraphics2D extends Graphics2D } } + public void setTransformUnlocked(AffineTransform tx) + { + transform = tx; + if (transform != null) + { + double[] m = new double[6]; + transform.getMatrix(m); + cairoSetMatrixUnlocked(m); + } + } + public void transform(AffineTransform tx) { if (transform == null) @@ -784,6 +867,32 @@ public class GdkGraphics2D extends Graphics2D cairoSetDash(double_dashes, double_dashes.length, (double) bs.getDashPhase()); } + else + cairoSetDash(new double[0], 0, 0.0); + } + } + + public void setStrokeUnlocked(Stroke st) + { + stroke = st; + if (stroke instanceof BasicStroke) + { + BasicStroke bs = (BasicStroke) stroke; + cairoSetLineCapUnlocked(bs.getEndCap()); + cairoSetLineWidthUnlocked(bs.getLineWidth()); + cairoSetLineJoinUnlocked(bs.getLineJoin()); + cairoSetMiterLimitUnlocked(bs.getMiterLimit()); + float[] dashes = bs.getDashArray(); + if (dashes != null) + { + double[] double_dashes = new double[dashes.length]; + for (int i = 0; i < dashes.length; i++) + double_dashes[i] = dashes[i]; + cairoSetDashUnlocked(double_dashes, double_dashes.length, + (double) bs.getDashPhase()); + } + else + cairoSetDashUnlocked(new double[0], 0, 0.0); } } @@ -812,11 +921,27 @@ public class GdkGraphics2D extends Graphics2D fg.getBlue() / 255.0, fg.getAlpha() / 255.0); } + public void setColorUnlocked(Color c) + { + if (c == null) + c = Color.BLACK; + + fg = c; + paint = c; + cairoSetRGBAColorUnlocked(fg.getRed() / 255.0, fg.getGreen() / 255.0, + fg.getBlue() / 255.0, fg.getAlpha() / 255.0); + } + public Color getColor() { return fg; } + public Color getColorUnlocked() + { + return getColor(); + } + public void clipRect(int x, int y, int width, int height) { clip(new Rectangle(x, y, width, height)); @@ -864,7 +989,13 @@ public class GdkGraphics2D extends Graphics2D public void setClip(Shape s) { clip = s; - if (s != null) + if (clip == null) + { + // Reset clipping. + Dimension d = component.awtComponent.getSize(); + setClip(0, 0, d.width, d.height); + } + else { cairoNewPath(); if (s instanceof Rectangle2D) @@ -929,6 +1060,11 @@ public class GdkGraphics2D extends Graphics2D bg = c; } + public void setBackgroundUnlocked(Color c) + { + setBackground(c); + } + public Color getBackground() { return bg; @@ -1180,6 +1316,36 @@ public class GdkGraphics2D extends Graphics2D || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT); } + public void setRenderingHintsUnlocked(Map hints) + { + this.hints = new RenderingHints(getDefaultHints()); + this.hints.add(new RenderingHints(hints)); + + if (hints.containsKey(RenderingHints.KEY_INTERPOLATION)) + { + if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)) + cairoSurfaceSetFilterUnlocked(0); + + else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) + cairoSurfaceSetFilterUnlocked(1); + } + + if (hints.containsKey(RenderingHints.KEY_ALPHA_INTERPOLATION)) + { + if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED)) + cairoSurfaceSetFilterUnlocked(2); + + else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY)) + cairoSurfaceSetFilterUnlocked(3); + + else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)) + cairoSurfaceSetFilterUnlocked(4); + } + + shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE) + || hints.containsValue(RenderingHints.VALUE_STROKE_DEFAULT); + } + public void addRenderingHints(Map hints) { this.hints.add(new RenderingHints(hints)); @@ -1344,6 +1510,9 @@ public class GdkGraphics2D extends Graphics2D public void drawString(String str, float x, float y) { + if (str == null || str.length() == 0) + return; + drawGlyphVector(getFont().createGlyphVector(null, str), x, y); updateBufferedImage (); } @@ -1443,6 +1612,11 @@ public class GdkGraphics2D extends Graphics2D .getFont(f.getName(), f.getAttributes()); } + public void setFontUnlocked(Font f) + { + setFont (f); + } + public String toString() { return (getClass().getName() diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java index bfad87a..6cf7310 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsConfiguration.java @@ -42,6 +42,7 @@ import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.ImageCapabilities; import java.awt.Rectangle; +import java.awt.Toolkit; import java.awt.geom.AffineTransform; @@ -56,16 +57,11 @@ public class GdkGraphicsConfiguration ColorModel cm; Rectangle bounds; - public GtkToolkit getToolkit() - { - return gdkScreenGraphicsDevice.getToolkit(); - } - public GdkGraphicsConfiguration(GdkScreenGraphicsDevice dev) { this.gdkScreenGraphicsDevice = dev; cm = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).getColorModel(); - bounds = getToolkit().getBounds(); + bounds = ((GtkToolkit) Toolkit.getDefaultToolkit()).getBounds(); } public GraphicsDevice getDevice() @@ -135,4 +131,10 @@ public class GdkGraphicsConfiguration return new ImageCapabilities(false); } + public VolatileImage createCompatibleVolatileImage(int width, int height, int transparency) + { + // FIXME: implement + return null; + } + } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java index 4f9d1c2..4b0b5d3 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java @@ -43,22 +43,14 @@ import java.awt.Graphics2D; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.HeadlessException; +import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.util.Locale; public class GdkGraphicsEnvironment extends GraphicsEnvironment { - GtkToolkit gtkToolkit; - - public GtkToolkit getToolkit() - { - return gtkToolkit; - } - - public GdkGraphicsEnvironment (GtkToolkit tk) + public GdkGraphicsEnvironment () { - super(); - gtkToolkit = tk; } public GraphicsDevice[] getScreenDevices () diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java index 57d5a36..85cb1e4 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java @@ -122,7 +122,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder super (imagedata, imageoffset, imagelength); } - // called back by native side + // called back by native side: area_prepared_cb void areaPrepared (int width, int height) { @@ -138,7 +138,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder } } - // called back by native side + // called back by native side: area_updated_cb void areaUpdated (int x, int y, int width, int height, int pixels[], int scansize) { @@ -306,7 +306,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder static String findFormatName(Object ext, boolean needWritable) { if (ext == null) - throw new IllegalArgumentException("extension is null"); + return null; if (!(ext instanceof String)) throw new IllegalArgumentException("extension is not a string"); diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java index 2bf9d23..b5d1237 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkScreenGraphicsDevice.java @@ -42,16 +42,12 @@ import java.awt.Dimension; import java.awt.DisplayMode; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; +import java.awt.Toolkit; public class GdkScreenGraphicsDevice extends GraphicsDevice { GdkGraphicsEnvironment env; - public GtkToolkit getToolkit() - { - return env.getToolkit(); - } - public GdkScreenGraphicsDevice (GdkGraphicsEnvironment e) { super (); @@ -94,7 +90,7 @@ public class GdkScreenGraphicsDevice extends GraphicsDevice public DisplayMode getDisplayMode() { // determine display mode - Dimension dim = getToolkit().getScreenSize(); + Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); DisplayMode mode = new DisplayMode(dim.width, dim.height, 0, DisplayMode.REFRESH_RATE_UNKNOWN); return mode; diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java index ab5df9f..054ead6 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkButtonPeer.java @@ -42,10 +42,14 @@ import java.awt.AWTEvent; import java.awt.Button; import java.awt.Component; import java.awt.Point; +import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.peer.ButtonPeer; +// A composite widget. GtkButtons have transparent backgrounds. An +// AWT Button is opaque. To compensate, a GtkButtonPeer is a +// GtkButton packed in a GtkEventBox. public class GtkButtonPeer extends GtkComponentPeer implements ButtonPeer { @@ -61,6 +65,11 @@ public class GtkButtonPeer extends GtkComponentPeer native void gtkWidgetRequestFocus (); native void setNativeBounds (int x, int y, int width, int height); + // Because this is a composite widget, we need to retrieve the + // GtkButton's preferred dimensions, not the enclosing + // GtkEventBox's. + native void gtkWidgetGetPreferredDimensions (int[] dim); + public GtkButtonPeer (Button b) { super (b); @@ -76,32 +85,11 @@ public class GtkButtonPeer extends GtkComponentPeer gtkSetLabel(label); } - public void handleEvent (AWTEvent e) + void postActionEvent (int mods) { - if (e.getID () == MouseEvent.MOUSE_RELEASED && isEnabled ()) - { - MouseEvent me = (MouseEvent) e; - Point p = me.getPoint(); - p.translate(((Component) me.getSource()).getX(), - ((Component) me.getSource()).getY()); - if (!me.isConsumed () - && (me.getModifiersEx () & MouseEvent.BUTTON1_DOWN_MASK) != 0 - && awtComponent.getBounds().contains(p)) - postActionEvent (((Button) awtComponent).getActionCommand (), - me.getModifiersEx ()); - } - - if (e.getID () == KeyEvent.KEY_PRESSED) - { - KeyEvent ke = (KeyEvent) e; - if (!ke.isConsumed () && ke.getKeyCode () == KeyEvent.VK_SPACE) - { - postActionEvent (((Button) awtComponent).getActionCommand (), - ke.getModifiersEx ()); - gtkActivate (); - } - } - - super.handleEvent (e); + q().postEvent (new ActionEvent (awtWidget, + ActionEvent.ACTION_PERFORMED, + ((Button) awtComponent).getActionCommand (), + mods)); } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java index 8517572..3e05cf8 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkCheckboxPeer.java @@ -49,6 +49,7 @@ public class GtkCheckboxPeer extends GtkComponentPeer public GtkCheckboxGroupPeer old_group; // The current state of the GTK checkbox. private boolean currentState; + private boolean changing = false; public native void create (GtkCheckboxGroupPeer group); public native void nativeSetCheckboxGroup (GtkCheckboxGroupPeer group); @@ -76,6 +77,15 @@ public class GtkCheckboxPeer extends GtkComponentPeer public void setState (boolean state) { + // prevent item_toggled_cb -> postItemEvent -> + // awtComponent.setState -> this.setState -> + // gtkToggleButtonSetActive self-deadlock on the GDK lock. + if (changing && Thread.currentThread() == GtkToolkit.mainThread) + { + changing = false; + return; + } + if (currentState != state) gtkToggleButtonSetActive (state); } @@ -100,6 +110,7 @@ public class GtkCheckboxPeer extends GtkComponentPeer // Override the superclass postItemEvent so that the peer doesn't // need information that we have. + // called back by native side: item_toggled_cb public void postItemEvent (Object item, int stateChange) { Checkbox currentCheckBox = ((Checkbox)awtComponent); @@ -113,6 +124,7 @@ public class GtkCheckboxPeer extends GtkComponentPeer { super.postItemEvent (awtComponent, stateChange); currentState = !currentCheckBox.getState(); + changing = true; currentCheckBox.setState(currentState); } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java index 5028ea7..c140744 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkChoicePeer.java @@ -74,8 +74,17 @@ public class GtkChoicePeer extends GtkComponentPeer native void connectSignals (); - public native void select (int position); - + native void selectNative (int position); + native void selectNativeUnlocked (int position); + + public void select (int position) + { + if (Thread.currentThread() == GtkToolkit.mainThread) + selectNativeUnlocked (position); + else + selectNative (position); + } + public void add (String item, int index) { int before = nativeGetSelected(); diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java index c719cdd..a502e1f 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkClipboard.java @@ -38,133 +38,357 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.ClipboardOwner; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.StringSelection; -import java.awt.datatransfer.Transferable; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.awt.Image; +import java.awt.datatransfer.*; + +import java.io.*; + +import java.util.List; +import java.util.Iterator; public class GtkClipboard extends Clipboard { - /* the number of milliseconds that we'll wait around for the - owner of the GDK_SELECTION_PRIMARY selection to convert - the requested data */ - static final int SELECTION_RECEIVED_TIMEOUT = 5000; - /* We currently only support transferring of text between applications */ - static String selection; - static Object selectionLock = new Object (); + // Given to the native side so it can signal special targets that + // can be converted to one of the special predefined DataFlavors. + static final String stringMimeType; + static final String imageMimeType; + static final String filesMimeType; + + // Indicates whether the results of the clipboard selection can be + // cached by GtkSelection. True if + // gdk_display_supports_selection_notification. + static final boolean canCache; + + static + { + stringMimeType = DataFlavor.stringFlavor.getMimeType(); + imageMimeType = DataFlavor.imageFlavor.getMimeType(); + filesMimeType = DataFlavor.javaFileListFlavor.getMimeType(); + + canCache = initNativeState(stringMimeType, imageMimeType, filesMimeType); + } - static boolean hasSelection = false; + /** + * The one and only gtk+ clipboard instance. + */ + private static GtkClipboard instance = new GtkClipboard(); - protected GtkClipboard() + /** + * Creates the clipboard and sets the initial contents to the + * current gtk+ selection. + */ + private GtkClipboard() { super("System Clipboard"); - initNativeState(); + setContents(new GtkSelection(), null); + } + + /** + * Returns the one and only GtkClipboard instance. + */ + + static GtkClipboard getInstance() + { + return instance; } - public Transferable getContents(Object requestor) + /** + * Sets the GtkSelection facade as new contents of the clipboard. + * Called from gtk+ when another application grabs the clipboard and + * we loose ownership. + */ + private static void setSystemContents() { - synchronized (this) + GtkClipboardNotifier.announce(); + } + + /** + * Sets the new contents and advertises the available flavors to the + * gtk+ clipboard. + */ + public synchronized void setContents(Transferable contents, + ClipboardOwner owner) + { + super.setContents(contents, owner); + + if (contents == null) { - if (hasSelection) - return contents; + advertiseContent(null, false, false, false); + return; } - /* Java doesn't own the selection, so we need to ask X11 */ - // XXX: Does this hold with Swing too ? - synchronized (selectionLock) + // We don't need to do anything for a GtkSelection facade. + if (contents instanceof GtkSelection) + return; + + boolean text = false; + boolean images = false; + boolean files = false; + + if (contents instanceof StringSelection + || contents.isDataFlavorSupported(DataFlavor.stringFlavor) + || contents.isDataFlavorSupported(DataFlavor.plainTextFlavor) + || contents.isDataFlavorSupported(DataFlavor + .getTextPlainUnicodeFlavor())) + text = true; + + DataFlavor[] flavors = contents.getTransferDataFlavors(); + String[] mimeTargets = new String[flavors.length]; + for (int i = 0; i < flavors.length; i++) { - requestStringConversion(); - - try - { - selectionLock.wait(SELECTION_RECEIVED_TIMEOUT); - } - catch (InterruptedException e) + DataFlavor flavor = flavors[i]; + String mimeType = flavor.getMimeType(); + mimeTargets[i] = mimeType; + + if (! text) + if ("text".equals(flavor.getPrimaryType()) + || flavor.isRepresentationClassReader()) + text = true; + + // XXX - We only support automatic image conversion for + // GtkImages at the moment. So explicitly check that we have + // one. + if (! images && flavors[i].equals(DataFlavor.imageFlavor)) { - return null; + try + { + Object o = contents.getTransferData(DataFlavor.imageFlavor); + if (o instanceof GtkImage) + images = true; + } + catch (UnsupportedFlavorException ufe) + { + } + catch (IOException ioe) + { + } + catch (ClassCastException cce) + { + } } - - return selection == null ? null : new StringSelection(selection); + + if (flavors[i].equals(DataFlavor.javaFileListFlavor)) + files = true; } + + advertiseContent(mimeTargets, text, images, files); } - void stringSelectionReceived(String newSelection) + /** + * Advertises new contents to the gtk+ clipboard given a string + * array of (mime-type) targets. When the boolean flags text, images + * and/or files are set then gtk+ is asked to also advertise the + * availability of any text, image or uri/file content types it + * supports. If targets is null (and all flags false) then the + * selection has explicitly been erased. + */ + private native void advertiseContent(String[] targets, + boolean text, + boolean images, + boolean files); + + /** + * Called by the gtk+ clipboard when an application has requested + * text. Return a string representing the current clipboard + * contents or null when no text can be provided. + */ + private String provideText() { - synchronized (selectionLock) + Transferable contents = this.contents; + if (contents == null || contents instanceof GtkSelection) + return null; + + // Handle StringSelection special since that is just pure text. + if (contents instanceof StringSelection) { - selection = newSelection; - selectionLock.notify(); + try + { + return (String) contents.getTransferData(DataFlavor.stringFlavor); + } + catch (UnsupportedFlavorException ufe) + { + } + catch (IOException ioe) + { + } + catch (ClassCastException cce) + { + } } - } - - /* convert Java clipboard data into a String suitable for sending - to another application */ - synchronized String stringSelectionHandler() throws IOException - { - String selection = null; + // Try to get a plain text reader for the current contents and + // turn the result into a string. try { - if (contents.isDataFlavorSupported(DataFlavor.stringFlavor)) - selection = (String)contents.getTransferData(DataFlavor.stringFlavor); - else if (contents.isDataFlavorSupported(DataFlavor.plainTextFlavor)) + DataFlavor plainText = DataFlavor.getTextPlainUnicodeFlavor(); + Reader r = plainText.getReaderForText(contents); + if (r != null) { - StringBuffer sbuf = new StringBuffer(); - InputStreamReader reader; - char readBuf[] = new char[512]; - int numChars; - - reader = new InputStreamReader - ((InputStream) - contents.getTransferData(DataFlavor.plainTextFlavor), "UNICODE"); - - while (true) + StringBuffer sb = new StringBuffer(); + char[] cs = new char[1024]; + int l = r.read(cs); + while (l != -1) { - numChars = reader.read(readBuf); - if (numChars == -1) - break; - sbuf.append(readBuf, 0, numChars); + sb.append(cs, 0, l); + l = r.read(cs); } - - selection = new String(sbuf); + return sb.toString(); } } - catch (Exception e) + catch (IllegalArgumentException iae) + { + } + catch (UnsupportedEncodingException iee) { } - - return selection; + catch (UnsupportedFlavorException ufe) + { + } + catch (IOException ioe) + { + } + + return null; } - public synchronized void setContents(Transferable contents, - ClipboardOwner owner) + /** + * Called by the gtk+ clipboard when an application has requested an + * image. Returns a GtkImage representing the current clipboard + * contents or null when no image can be provided. + */ + private GtkImage provideImage() + { + Transferable contents = this.contents; + if (contents == null || contents instanceof GtkSelection) + return null; + + try + { + return (GtkImage) contents.getTransferData(DataFlavor.imageFlavor); + } + catch (UnsupportedFlavorException ufe) + { + } + catch (IOException ioe) + { + } + catch (ClassCastException cce) + { + } + + return null; + } + + /** + * Called by the gtk+ clipboard when an application has requested a + * uri-list. Return a string array containing the URIs representing + * the current clipboard contents or null when no URIs can be + * provided. + */ + private String[] provideURIs() { - selectionGet(); + Transferable contents = this.contents; + if (contents == null || contents instanceof GtkSelection) + return null; - this.contents = contents; - this.owner = owner; + try + { + List list = (List) contents.getTransferData + (DataFlavor.javaFileListFlavor); + String[] uris = new String[list.size()]; + int u = 0; + Iterator it = list.iterator(); + while (it.hasNext()) + uris[u++] = ((File) it.next()).toURI().toString(); + return uris; + } + catch (UnsupportedFlavorException ufe) + { + } + catch (IOException ioe) + { + } + catch (ClassCastException cce) + { + } - hasSelection = true; + return null; } - synchronized void selectionClear() + /** + * Called by gtk+ clipboard when an application requests the given + * target mime-type. Returns a byte array containing the requested + * data, or null when the contents cannot be provided in the + * requested target mime-type. Only called after any explicit text, + * image or file/uri requests have been handled earlier and failed. + */ + private byte[] provideContent(String target) { - hasSelection = false; + // Sanity check. The callback could be triggered just after we + // changed the clipboard. + Transferable contents = this.contents; + if (contents == null || contents instanceof GtkSelection) + return null; + + // XXX - We are being called from a gtk+ callback. Which means we + // should return as soon as possible and not call arbitrary code + // that could deadlock or go bonkers. But we don't really know + // what DataTransfer contents object we are dealing with. Same for + // the other provideXXX() methods. + try + { + DataFlavor flavor = new DataFlavor(target); + Object o = contents.getTransferData(flavor); + + if (o instanceof byte[]) + return (byte[]) o; + + if (o instanceof InputStream) + { + InputStream is = (InputStream) o; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] bs = new byte[1024]; + int l = is.read(bs); + while (l != -1) + { + baos.write(bs, 0, l); + l = is.read(bs); + } + return baos.toByteArray(); + } - if (owner != null) + if (o instanceof Serializable) + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(o); + oos.close(); + return baos.toByteArray(); + } + } + catch (ClassNotFoundException cnfe) + { + } + catch (UnsupportedFlavorException ufe) { - owner.lostOwnership(this, contents); - owner = null; - contents = null; } + catch (IOException ioe) + { + } + catch (ClassCastException cce) + { + } + + return null; } - native void initNativeState(); - static native void requestStringConversion(); - static native void selectionGet(); + /** + * Initializes the gtk+ clipboard and caches any native side + * structures needed. Returns whether or not the contents of the + * Clipboard can be cached (gdk_display_supports_selection_notification). + */ + private static native boolean initNativeState(String stringTarget, + String imageTarget, + String filesTarget); } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java index 1578a9c..60e8371 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkComponentPeer.java @@ -70,6 +70,9 @@ import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; import java.awt.image.VolatileImage; import java.awt.peer.ComponentPeer; +import java.awt.peer.ContainerPeer; +import java.util.Timer; +import java.util.TimerTask; public class GtkComponentPeer extends GtkGenericPeer implements ComponentPeer @@ -83,6 +86,8 @@ public class GtkComponentPeer extends GtkGenericPeer boolean isInRepaint; + static final Timer repaintTimer = new Timer (true); + /* this isEnabled differs from Component.isEnabled, in that it knows if a parent is disabled. In that case Component.isEnabled may return true, but our isEnabled will always return false */ @@ -95,6 +100,7 @@ public class GtkComponentPeer extends GtkGenericPeer native void gtkWidgetGetPreferredDimensions (int[] dim); native void gtkWidgetGetLocationOnScreen (int[] point); native void gtkWidgetSetCursor (int type); + native void gtkWidgetSetCursorUnlocked (int type); native void gtkWidgetSetBackground (int red, int green, int blue); native void gtkWidgetSetForeground (int red, int green, int blue); native void gtkWidgetSetSensitive (boolean sensitive); @@ -372,8 +378,26 @@ public class GtkComponentPeer extends GtkGenericPeer if (x == 0 && y == 0 && width == 0 && height == 0) return; - q().postEvent (new PaintEvent (awtComponent, PaintEvent.UPDATE, - new Rectangle (x, y, width, height))); + repaintTimer.schedule(new RepaintTimerTask(x, y, width, height), tm); + } + + private class RepaintTimerTask extends TimerTask + { + private int x, y, width, height; + + RepaintTimerTask(int x, int y, int width, int height) + { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public void run() + { + q().postEvent (new PaintEvent (awtComponent, PaintEvent.UPDATE, + new Rectangle (x, y, width, height))); + } } public void requestFocus () @@ -396,7 +420,11 @@ public class GtkComponentPeer extends GtkGenericPeer public void setBounds (int x, int y, int width, int height) { + int new_x = x; + int new_y = y; + Component parent = awtComponent.getParent (); + Component next_parent; // Heavyweight components that are children of one or more // lightweight containers have to be handled specially. Because @@ -414,30 +442,44 @@ public class GtkComponentPeer extends GtkGenericPeer { lightweightChild = true; + next_parent = parent.getParent (); + i = ((Container) parent).getInsets (); - x += parent.getX () + i.left; - y += parent.getY () + i.top; + if (next_parent instanceof Window) + { + new_x += i.left; + new_y += i.top; + } + else + { + new_x += parent.getX () + i.left; + new_y += parent.getY () + i.top; + } - parent = parent.getParent (); + parent = next_parent; } // We only need to convert from Java to GTK coordinates if we're // placing a heavyweight component in a Window. if (parent instanceof Window && !lightweightChild) { - Insets insets = ((Window) parent).getInsets (); GtkWindowPeer peer = (GtkWindowPeer) parent.getPeer (); + // important: we want the window peer's insets here, not the + // window's, since user sub-classes of Window can override + // getInset and we only want to correct for the frame borders, + // not for any user-defined inset values + Insets insets = peer.getInsets (); + int menuBarHeight = 0; if (peer instanceof GtkFramePeer) menuBarHeight = ((GtkFramePeer) peer).getMenuBarHeight (); - // Convert from Java coordinates to GTK coordinates. - setNativeBounds (x - insets.left, y - insets.top + menuBarHeight, - width, height); + new_x = x - insets.left; + new_y = y - insets.top + menuBarHeight; } - else - setNativeBounds (x, y, width, height); + + setNativeBounds (new_x, new_y, width, height); } void setCursor () @@ -447,7 +489,10 @@ public class GtkComponentPeer extends GtkGenericPeer public void setCursor (Cursor cursor) { - gtkWidgetSetCursor (cursor.getType ()); + if (Thread.currentThread() == GtkToolkit.mainThread) + gtkWidgetSetCursorUnlocked (cursor.getType ()); + else + gtkWidgetSetCursor (cursor.getType ()); } public void setEnabled (boolean b) @@ -480,16 +525,26 @@ public class GtkComponentPeer extends GtkGenericPeer return new Color (rgb[0], rgb[1], rgb[2]); } + public native void setVisibleNative (boolean b); + public native void setVisibleNativeUnlocked (boolean b); + public void setVisible (boolean b) { - if (b) - show (); + if (Thread.currentThread() == GtkToolkit.mainThread) + setVisibleNativeUnlocked (b); else - hide (); + setVisibleNative (b); + } + + public void hide () + { + setVisible (false); } - public native void hide (); - public native void show (); + public void show () + { + setVisible (true); + } protected void postMouseEvent(int id, long when, int mods, int x, int y, int clickCount, boolean popupTrigger) @@ -586,7 +641,8 @@ public class GtkComponentPeer extends GtkGenericPeer public void updateCursorImmediately () { - + if (awtComponent.getCursor() != null) + setCursor(awtComponent.getCursor()); } public boolean handlesWheelScrolling () @@ -648,4 +704,36 @@ public class GtkComponentPeer extends GtkGenericPeer { backBuffer.flush(); } + + public String toString () + { + return "peer of " + awtComponent.toString(); + } + public Rectangle getBounds() + { + // FIXME: implement + return null; + } + public void reparent(ContainerPeer parent) + { + // FIXME: implement + + } + public void setBounds(int x, int y, int width, int height, int z) + { + // FIXME: implement + setBounds (x, y, width, height); + + } + public boolean isReparentSupported() + { + // FIXME: implement + + return false; + } + public void layout() + { + // FIXME: implement + + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java index c2865f7..b035a98 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkContainerPeer.java @@ -52,7 +52,6 @@ public class GtkContainerPeer extends GtkComponentPeer implements ContainerPeer { Container c; - boolean isValidating; public GtkContainerPeer(Container c) { @@ -62,7 +61,6 @@ public class GtkContainerPeer extends GtkComponentPeer public void beginValidate () { - isValidating = true; } public void endValidate () @@ -90,8 +88,6 @@ public class GtkContainerPeer extends GtkComponentPeer if (!(awtComponent instanceof Window)) setParentAndBounds (); } - - isValidating = false; } public Insets getInsets() @@ -153,4 +149,21 @@ public class GtkContainerPeer extends GtkComponentPeer comp.getPeer().setBackground(c); } } + + public boolean isRestackSupported() + { + // FIXME: implement + return false; + } + + public void cancelPendingPaint(int x, int y, int width, int height) + { + // FIXME: implement + } + + public void restack() + { + //FIXME: implement + + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java index bd1f077..333407b 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFileDialogPeer.java @@ -42,6 +42,7 @@ import java.awt.Dialog; import java.awt.FileDialog; import java.awt.Graphics; import java.awt.Window; +import java.awt.event.ComponentEvent; import java.awt.peer.FileDialogPeer; import java.io.File; import java.io.FilenameFilter; @@ -54,7 +55,7 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer private String currentDirectory = null; private FilenameFilter filter; - native void create (GtkContainerPeer parent); + native void create (GtkContainerPeer parent, int mode); native void connectSignals (); native void nativeSetFile (String file); public native String nativeGetDirectory(); @@ -63,7 +64,8 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer public void create() { - create((GtkContainerPeer) awtComponent.getParent().getPeer()); + create((GtkContainerPeer) awtComponent.getParent().getPeer(), + ((FileDialog) awtComponent).getMode()); FileDialog fd = (FileDialog) awtComponent; @@ -87,10 +89,10 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer { int[] dims = new int[2]; gtkWidgetGetPreferredDimensions (dims); - ((GtkFileDialogPeer) this).setBoundsCallback ((Window) awtComponent, - awtComponent.getX (), - awtComponent.getY (), - dims[0], dims[1]); + + if (dims[0] != awtComponent.getWidth() + || dims[1] != awtComponent.getHeight()) + awtComponent.setSize(dims[0], dims[1]); } super.setComponentBounds (); } @@ -155,6 +157,7 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer GtkFileFilterInfo object and send it to this method, which will in turn call the filter's accept() method and give back the return value. */ + // called back by native side: filename_filter_cb boolean filenameFilterCallback (String fullname) { String filename = fullname.substring(fullname.lastIndexOf(FS) + 1); String dirname = fullname.substring(0, fullname.lastIndexOf(FS)); @@ -167,20 +170,25 @@ public class GtkFileDialogPeer extends GtkDialogPeer implements FileDialogPeer // GtkFileDialog will repaint by itself return null; } - + + // called back by native side: handle_response_cb + // only called from the GTK thread void gtkHideFileDialog () { + // hide calls back the peer's setVisible method, so locking is a + // problem. ((Dialog) awtComponent).hide(); } + // called back by native side: handle_response_cb void gtkDisposeFileDialog () { ((Dialog) awtComponent).dispose(); } - /* Callback to set the file and directory values when the user is finished - * with the dialog. - */ + // Callback to set the file and directory values when the user is finished + // with the dialog. + // called back by native side: handle_response_cb void gtkSetFilename (String fileName) { FileDialog fd = (FileDialog) awtWidget; diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java index b242d66..6eb90ff 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkFramePeer.java @@ -44,6 +44,7 @@ import java.awt.Image; import java.awt.MenuBar; import java.awt.Rectangle; import java.awt.Window; +import java.awt.event.ComponentEvent; import java.awt.event.PaintEvent; import java.awt.image.ColorModel; import java.awt.peer.FramePeer; @@ -55,6 +56,7 @@ public class GtkFramePeer extends GtkWindowPeer private int menuBarHeight; private MenuBarPeer menuBar; native int getMenuBarHeight (MenuBarPeer bar); + native void setMenuBarWidthUnlocked (MenuBarPeer bar, int width); native void setMenuBarWidth (MenuBarPeer bar, int width); native void setMenuBarPeer (MenuBarPeer bar); native void removeMenuBarPeer (); @@ -117,6 +119,17 @@ public class GtkFramePeer extends GtkWindowPeer public void setBounds (int x, int y, int width, int height) { + // prevent window_configure_cb -> awtComponent.setSize -> + // peer.setBounds -> nativeSetBounds self-deadlock on GDK lock. + if (Thread.currentThread() == GtkToolkit.mainThread) + { + int menuBarWidth = width - insets.left - insets.right; + if (menuBar != null && menuBarWidth > 0) + setMenuBarWidthUnlocked (menuBar, menuBarWidth); + + return; + } + int menuBarWidth = width - insets.left - insets.right; if (menuBar != null && menuBarWidth > 0) setMenuBarWidth (menuBar, menuBarWidth); @@ -192,31 +205,25 @@ public class GtkFramePeer extends GtkWindowPeer protected void postConfigureEvent (int x, int y, int width, int height) { - int frame_x = x - insets.left; - // Since insets.top includes the MenuBar height, we need to add back - // the MenuBar height to the frame's y position. - // If no MenuBar exists in this frame, the MenuBar height will be 0. - int frame_y = y - insets.top + menuBarHeight; int frame_width = width + insets.left + insets.right; - // Ditto as above. Since insets.top already includes the MenuBar's height, - // we need to subtract the MenuBar's height from the top inset. + // Since insets.top already includes the MenuBar's height, we need + // to subtract the MenuBar's height from the top inset. int frame_height = height + insets.top + insets.bottom - menuBarHeight; - if (frame_x != awtComponent.getX() - || frame_y != awtComponent.getY() - || frame_width != awtComponent.getWidth() + + if (frame_width != awtComponent.getWidth() || frame_height != awtComponent.getHeight()) - { - if (frame_width != awtComponent.getWidth() && menuBar != null - && width > 0) - setMenuBarWidth (menuBar, width); + awtComponent.setSize(frame_width, frame_height); - setBoundsCallback ((Window) awtComponent, - frame_x, - frame_y, - frame_width, - frame_height); + int frame_x = x - insets.left; + // Likewise, since insets.top includes the MenuBar height, we need + // to add back the MenuBar height to the frame's y position. If + // no MenuBar exists in this frame, the MenuBar height will be 0. + int frame_y = y - insets.top + menuBarHeight; - awtComponent.validate(); + if (frame_x != awtComponent.getX() + || frame_y != awtComponent.getY()) + { + // awtComponent.setLocation(frame_x, frame_y); } } @@ -251,6 +258,21 @@ public class GtkFramePeer extends GtkWindowPeer { } + public void setBoundsPrivate(int x, int y, int width, int height) + { + // TODO Auto-generated method stub + + } + public void updateAlwaysOnTop() + { + // TODO Auto-generated method stub + + } + public boolean requestWindowFocus() + { + // TODO Auto-generated method stub + return false; + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java index abb4137..82a3463 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImage.java @@ -51,7 +51,10 @@ import java.io.File; import java.io.IOException; import java.util.Hashtable; import java.util.Vector; -import gnu.classpath.RawData; +import java.io.ByteArrayOutputStream; +import java.io.BufferedInputStream; +import java.net.URL; +import gnu.classpath.Pointer; /** * GtkImage - wraps a GdkPixbuf or GdkPixmap. @@ -87,7 +90,7 @@ public class GtkImage extends Image /** * Pointer to the GdkPixbuf */ - RawData pixmap; + Pointer pixmap; /** * Observer queue. @@ -129,11 +132,16 @@ public class GtkImage extends Image private native void setPixels(int[] pixels); /** - * Loads an image using gdk-pixbuf. + * Loads an image using gdk-pixbuf from a file. */ private native boolean loadPixbuf(String name); /** + * Loads an image using gdk-pixbuf from data. + */ + private native boolean loadImageFromData(byte[] data); + + /** * Allocates a Gtk Pixbuf or pixmap */ private native void createPixmap(); @@ -187,6 +195,21 @@ public class GtkImage extends Image } /** + * Constructs a blank GtkImage. This is called when + * GtkToolkit.createImage (String) is called with an empty string + * argument (""). A blank image is loaded immediately upon + * construction and has width -1 and height -1. + */ + public GtkImage () + { + isLoaded = true; + observers = null; + offScreen = false; + props = new Hashtable(); + errorLoading = false; + } + + /** * Constructs a GtkImage by loading a given file. * * @throws IllegalArgumentException if the image could not be loaded. @@ -211,6 +234,58 @@ public class GtkImage extends Image } /** + * Constructs a GtkImage from a byte array of an image file. + * + * @throws IllegalArgumentException if the image could not be + * loaded. + */ + public GtkImage (byte[] data) + { + if (loadImageFromData (data) != true) + throw new IllegalArgumentException ("Couldn't load image."); + + isLoaded = true; + observers = null; + offScreen = false; + props = new Hashtable(); + errorLoading = false; + } + + /** + * Constructs a GtkImage from a URL. May result in an error image. + */ + public GtkImage (URL url) + { + isLoaded = false; + observers = new Vector(); + errorLoading = false; + if( url == null) + return; + ByteArrayOutputStream baos = new ByteArrayOutputStream (5000); + try + { + BufferedInputStream bis = new BufferedInputStream (url.openStream()); + + byte[] buf = new byte[5000]; + int n = 0; + + while ((n = bis.read(buf)) != -1) + baos.write(buf, 0, n); + bis.close(); + } + catch(IOException e) + { + throw new IllegalArgumentException ("Couldn't load image."); + } + if (loadImageFromData (baos.toByteArray()) != true) + throw new IllegalArgumentException ("Couldn't load image."); + + isLoaded = true; + observers = null; + props = new Hashtable(); + } + + /** * Constructs an empty GtkImage. */ public GtkImage (int width, int height) @@ -241,6 +316,25 @@ public class GtkImage extends Image } /** + * Package private constructor to create a GtkImage from a given + * PixBuf pointer. + */ + GtkImage (Pointer pixbuf) + { + pixmap = pixbuf; + createFromPixbuf(); + isLoaded = true; + observers = null; + offScreen = false; + props = new Hashtable(); + } + + /** + * Native helper function for constructor that takes a pixbuf Pointer. + */ + private native void createFromPixbuf(); + + /** * Callback from the image consumer. */ public void setImage(int width, int height, diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java index 564cc8d..299f01d 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkImageConsumer.java @@ -45,6 +45,7 @@ import java.awt.image.DirectColorModel; import java.awt.image.ImageConsumer; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; +import java.awt.image.MemoryImageSource; import java.util.Hashtable; import java.util.Vector; @@ -70,7 +71,10 @@ public class GtkImageConsumer implements ImageConsumer public synchronized void imageComplete (int status) { - source.removeConsumer(this); + // we need to reuse the pixel cache for memory image sources since + // a memory image's backing array can be updated "live". + if (!(source instanceof MemoryImageSource)) + source.removeConsumer(this); target.setImage(width, height, pixelCache, properties); } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java index fdd5fd1..3d099e9 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkLabelPeer.java @@ -41,6 +41,9 @@ package gnu.java.awt.peer.gtk; import java.awt.Label; import java.awt.peer.LabelPeer; +// A composite widget. GtkLabels have transparent backgrounds. An +// AWT Label is opaque. To compensate, a GtkLabelPeer is a GtkLabel +// packed in a GtkEventBox. public class GtkLabelPeer extends GtkComponentPeer implements LabelPeer { @@ -51,6 +54,10 @@ public class GtkLabelPeer extends GtkComponentPeer public native void setText(String text); native void setNativeBounds (int x, int y, int width, int height); + // Because this is a composite widget, we need to retrieve the + // GtkLabel's preferred dimensions, not the enclosing GtkEventBox's. + native void gtkWidgetGetPreferredDimensions (int[] dim); + void create () { Label label = (Label) awtComponent; diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java index 79eeaf9..a1a1cbd 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuBarPeer.java @@ -77,4 +77,9 @@ public class GtkMenuBarPeer extends GtkMenuComponentPeer } public native void delMenu(int index); + + public void addMenu (Menu m) + { + // FIXME: implement + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java index 8d9d1ca..4c63359 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuComponentPeer.java @@ -38,6 +38,7 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; +import java.awt.Font; import java.awt.peer.MenuComponentPeer; public class GtkMenuComponentPeer extends GtkGenericPeer @@ -60,4 +61,9 @@ public class GtkMenuComponentPeer extends GtkGenericPeer } public native void dispose(); + + public void setFont(Font font) + { + // FIXME: implement + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java index 80332dd..fabcf1f 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkMenuPeer.java @@ -100,4 +100,9 @@ public class GtkMenuPeer extends GtkMenuItemPeer } public native void delItem(int index); + + public void addSeparator() + { + // FIXME: implement + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java index a842b83..e6896c9 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextAreaPeer.java @@ -43,6 +43,7 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Rectangle; import java.awt.TextArea; +import java.awt.im.InputMethodRequests; import java.awt.peer.TextAreaPeer; import java.awt.peer.TextComponentPeer; @@ -209,4 +210,10 @@ public class GtkTextAreaPeer extends GtkComponentPeer { insert (str, pos); } + + public InputMethodRequests getInputMethodRequests() + { + // FIXME: implement + return null; + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java index 73a976b..4afdae8 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkTextFieldPeer.java @@ -45,6 +45,7 @@ import java.awt.FontMetrics; import java.awt.Rectangle; import java.awt.TextField; import java.awt.event.KeyEvent; +import java.awt.im.InputMethodRequests; import java.awt.peer.TextFieldPeer; import java.awt.peer.TextComponentPeer; @@ -193,4 +194,9 @@ public class GtkTextFieldPeer extends GtkComponentPeer super.handleEvent (e); } + public InputMethodRequests getInputMethodRequests() + { + // FIXME: implement + return null; + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java index 6990110..0889d85 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkToolkit.java @@ -88,9 +88,9 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit { Hashtable containers = new Hashtable(); static EventQueue q; - static Clipboard systemClipboard; static boolean useGraphics2dSet; static boolean useGraphics2d; + static Thread mainThread; public static boolean useGraphics2D() { @@ -121,11 +121,19 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit portableNativeSync = 0; // false gtkInit(portableNativeSync); + + mainThread = new Thread ("GTK main thread") + { + public void run () + { + gtkMain (); + } + }; + mainThread.start (); } public GtkToolkit () { - systemClipboard = new GtkClipboard (); } public native void beep(); @@ -244,6 +252,9 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit public Image createImage (String filename) { + if (filename.length() == 0) + return new GtkImage (); + if (useGraphics2D()) return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (filename)); else @@ -255,11 +266,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit if (useGraphics2D()) return bufferedImageOrError(GdkPixbufDecoder.createBufferedImage (url)); else - { - GdkPixbufDecoder d = new GdkPixbufDecoder (url); - GtkImage image = new GtkImage (d); - return image; - } + return new GtkImage (url); } public Image createImage (ImageProducer producer) @@ -279,11 +286,9 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit imagelength)); else { - GdkPixbufDecoder d = new GdkPixbufDecoder (imagedata, - imageoffset, - imagelength); - GtkImage image = new GtkImage (d); - return image; + byte[] datacopy = new byte[imagelength]; + System.arraycopy (imagedata, imageoffset, datacopy, 0, imagelength); + return new GtkImage (datacopy); } } @@ -395,7 +400,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit public Clipboard getSystemClipboard() { - return systemClipboard; + SecurityManager secman = System.getSecurityManager(); + if (secman != null) + secman.checkSystemClipboardAccess(); + + return GtkClipboard.getInstance(); } /** @@ -628,7 +637,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit public GraphicsEnvironment getLocalGraphicsEnvironment() { - return new GdkGraphicsEnvironment(this); + return new GdkGraphicsEnvironment(); } public Font createFont(int format, InputStream stream) @@ -646,8 +655,5 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit GdkPixbufDecoder.registerSpis(reg); } - public native boolean nativeQueueEmpty(); - public native void wakeNativeQueue(); - public native void iterateNativeQueue(EventQueue locked, boolean block); - + public static native void gtkMain(); } // class GtkToolkit diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java index 71e05a8..c84d510 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkWindowPeer.java @@ -41,6 +41,7 @@ package gnu.java.awt.peer.gtk; import java.awt.Component; import java.awt.Frame; import java.awt.Window; +import java.awt.event.ComponentEvent; import java.awt.event.WindowEvent; import java.awt.peer.WindowPeer; @@ -104,6 +105,9 @@ public class GtkWindowPeer extends GtkContainerPeer { } + public native void setVisibleNative (boolean b); + public native void setVisibleNativeUnlocked (boolean b); + native void connectSignals (); public GtkWindowPeer (Window window) @@ -115,14 +119,27 @@ public class GtkWindowPeer extends GtkContainerPeer public native void toFront(); native void nativeSetBounds (int x, int y, int width, int height); + native void nativeSetBoundsUnlocked (int x, int y, int width, int height); public void setBounds (int x, int y, int width, int height) { + // prevent window_configure_cb -> awtComponent.setSize -> + // peer.setBounds -> nativeSetBounds self-deadlock on GDK lock. + if (Thread.currentThread() == GtkToolkit.mainThread) + return; + nativeSetBounds (x, y, width - insets.left - insets.right, height - insets.top - insets.bottom); } + public void setBoundsUnlocked (int x, int y, int width, int height) + { + nativeSetBoundsUnlocked (x, y, + width - insets.left - insets.right, + height - insets.top - insets.bottom); + } + public void setTitle (String title) { gtkWindowSetTitle (title); @@ -140,10 +157,6 @@ public class GtkWindowPeer extends GtkContainerPeer gtkWindowSetResizable (resizable); } - native void setBoundsCallback (Window window, - int x, int y, - int width, int height); - protected void postInsetsChangedEvent (int top, int left, int bottom, int right) { @@ -153,36 +166,36 @@ public class GtkWindowPeer extends GtkContainerPeer insets.right = right; } + // called back by native side: window_configure_cb + // only called from GTK thread protected void postConfigureEvent (int x, int y, int width, int height) { - int frame_x = x - insets.left; - int frame_y = y - insets.top; int frame_width = width + insets.left + insets.right; int frame_height = height + insets.top + insets.bottom; - if (frame_x != awtComponent.getX() - || frame_y != awtComponent.getY() - || frame_width != awtComponent.getWidth() + if (frame_width != awtComponent.getWidth() || frame_height != awtComponent.getHeight()) - { - setBoundsCallback ((Window) awtComponent, - frame_x, frame_y, frame_width, frame_height); + awtComponent.setSize(frame_width, frame_height); - awtComponent.validate(); + int frame_x = x - insets.left; + int frame_y = y - insets.top; + + if (frame_x != awtComponent.getX() + || frame_y != awtComponent.getY()) + { + // awtComponent.setLocation(frame_x, frame_y); } } - native void nativeSetVisible (boolean b); - public void setVisible (boolean b) + public void show () { // Prevent the window manager from automatically placing this // window when it is shown. - if (b) - setBounds (awtComponent.getX(), - awtComponent.getY(), - awtComponent.getWidth(), - awtComponent.getHeight()); - nativeSetVisible (b); + setBounds (awtComponent.getX(), + awtComponent.getY(), + awtComponent.getWidth(), + awtComponent.getHeight()); + setVisible (true); } void postWindowEvent (int id, Window opposite, int newState) @@ -209,4 +222,14 @@ public class GtkWindowPeer extends GtkContainerPeer else q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite)); } + public void updateAlwaysOnTop() + { + // TODO Auto-generated method stub + + } + public boolean requestWindowFocus() + { + // TODO Auto-generated method stub + return false; + } } diff --git a/libjava/classpath/gnu/java/nio/FileLockImpl.java b/libjava/classpath/gnu/java/nio/FileLockImpl.java index 245fa73..673ca25 100644 --- a/libjava/classpath/gnu/java/nio/FileLockImpl.java +++ b/libjava/classpath/gnu/java/nio/FileLockImpl.java @@ -1,5 +1,5 @@ -/* FileLockImpl.java -- - Copyright (C) 2002, 2004 Free Software Foundation, Inc. +/* FileLockImpl.java -- FileLock associated with a FileChannelImpl. + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -44,20 +44,29 @@ import java.io.IOException; import java.nio.channels.FileLock; /** + * A FileLock associated with a FileChannelImpl. + * * @author Michael Koch * @since 1.4 */ -public class FileLockImpl extends FileLock +public final class FileLockImpl extends FileLock { - private FileChannelImpl ch; - + /** + * Whether or not this lock is valid, false when channel is closed or + * release has been explicitly called. + */ + private boolean valid; + public FileLockImpl (FileChannelImpl channel, long position, long size, boolean shared) { super (channel, position, size, shared); - ch = channel; + valid = true; } + /** + * Releases this lock. + */ protected void finalize() { try @@ -70,13 +79,26 @@ public class FileLockImpl extends FileLock } } - public boolean isValid () + /** + * Whether or not this lock is valid, false when channel is closed or + * release has been explicitly called. + */ + public boolean isValid() { - return channel().isOpen(); + if (valid) + valid = channel().isOpen(); + return valid; } - public synchronized void release () throws IOException + /** + * Releases the lock if it is still valid. Marks this lock as invalid. + */ + public void release() throws IOException { - ch.unlock(position(), size()); + if (isValid()) + { + valid = false; + ((FileChannelImpl) channel()).unlock(position(), size()); + } } } diff --git a/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java b/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java index a87a2e8..0ee5d3f 100644 --- a/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java +++ b/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java @@ -73,6 +73,10 @@ public final class FileChannelImpl extends FileChannel public static final int SYNC = 16; public static final int DSYNC = 32; + public static FileChannelImpl in; + public static FileChannelImpl out; + public static FileChannelImpl err; + private static native void init(); static @@ -83,6 +87,10 @@ public final class FileChannelImpl extends FileChannel } init(); + + in = new FileChannelImpl(0, READ); + out = new FileChannelImpl(1, WRITE); + err = new FileChannelImpl(2, WRITE); } /** @@ -97,6 +105,8 @@ public final class FileChannelImpl extends FileChannel private int mode; + final String description; + /* Open a file. MODE is a combination of the above mode flags. */ /* This is a static factory method, so that VM implementors can decide * substitute subclasses of FileChannelImpl. */ @@ -109,7 +119,8 @@ public final class FileChannelImpl extends FileChannel private FileChannelImpl(File file, int mode) throws FileNotFoundException { - final String path = file.getPath(); + String path = file.getPath(); + description = path; fd = open (path, mode); this.mode = mode; @@ -126,21 +137,26 @@ public final class FileChannelImpl extends FileChannel /* ignore it */ } - throw new FileNotFoundException(path + " is a directory"); + throw new FileNotFoundException(description + " is a directory"); } } - /* Used by init() (native code) */ + /** + * Constructor for default channels in, out and err. + * + * Used by init() (native code). + * + * @param fd the file descriptor (0, 1, 2 for stdin, stdout, stderr). + * + * @param mode READ or WRITE + */ FileChannelImpl (int fd, int mode) { this.fd = fd; this.mode = mode; + this.description = "descriptor(" + fd + ")"; } - public static FileChannelImpl in; - public static FileChannelImpl out; - public static FileChannelImpl err; - private native int open (String path, int mode) throws FileNotFoundException; public native int available () throws IOException; @@ -179,7 +195,7 @@ public final class FileChannelImpl extends FileChannel throws IOException { if (position < 0) - throw new IllegalArgumentException (); + throw new IllegalArgumentException ("position: " + position); long oldPosition = implPosition (); position (position); int result = read(dst); @@ -230,7 +246,7 @@ public final class FileChannelImpl extends FileChannel throws IOException { if (position < 0) - throw new IllegalArgumentException (); + throw new IllegalArgumentException ("position: " + position); if (!isOpen ()) throw new ClosedChannelException (); @@ -288,10 +304,11 @@ public final class FileChannelImpl extends FileChannel throw new NonWritableChannelException(); } else - throw new IllegalArgumentException (); + throw new IllegalArgumentException ("mode: " + mode); if (position < 0 || size < 0 || size > Integer.MAX_VALUE) - throw new IllegalArgumentException (); + throw new IllegalArgumentException ("position: " + position + + ", size: " + size); return mapImpl(nmode, position, (int) size); } @@ -336,7 +353,8 @@ public final class FileChannelImpl extends FileChannel { if (position < 0 || count < 0) - throw new IllegalArgumentException (); + throw new IllegalArgumentException ("position: " + position + + ", count: " + count); if (!isOpen ()) throw new ClosedChannelException (); @@ -399,7 +417,8 @@ public final class FileChannelImpl extends FileChannel { if (position < 0 || count < 0) - throw new IllegalArgumentException (); + throw new IllegalArgumentException ("position: " + position + + ", count: " + count); if (!isOpen ()) throw new ClosedChannelException (); @@ -424,24 +443,31 @@ public final class FileChannelImpl extends FileChannel return total; } - public FileLock tryLock (long position, long size, boolean shared) + // Shared sanity checks between lock and tryLock methods. + private void lockCheck(long position, long size, boolean shared) throws IOException { if (position < 0 || size < 0) - throw new IllegalArgumentException (); + throw new IllegalArgumentException ("position: " + position + + ", size: " + size); if (!isOpen ()) - throw new ClosedChannelException (); + throw new ClosedChannelException(); - if (shared && (mode & READ) == 0) - throw new NonReadableChannelException (); - - if (!shared && (mode & WRITE) == 0) - throw new NonWritableChannelException (); + if (shared && ((mode & READ) == 0)) + throw new NonReadableChannelException(); + if (!shared && ((mode & WRITE) == 0)) + throw new NonWritableChannelException(); + } + + public FileLock tryLock (long position, long size, boolean shared) + throws IOException + { + lockCheck(position, size, shared); + boolean completed = false; - try { begin(); @@ -468,15 +494,9 @@ public final class FileChannelImpl extends FileChannel public FileLock lock (long position, long size, boolean shared) throws IOException { - if (position < 0 - || size < 0) - throw new IllegalArgumentException (); - - if (!isOpen ()) - throw new ClosedChannelException (); + lockCheck(position, size, shared); boolean completed = false; - try { boolean lockable = lock(position, size, shared, true); @@ -504,7 +524,7 @@ public final class FileChannelImpl extends FileChannel throws IOException { if (newPosition < 0) - throw new IllegalArgumentException (); + throw new IllegalArgumentException ("newPostition: " + newPosition); if (!isOpen ()) throw new ClosedChannelException (); @@ -519,7 +539,7 @@ public final class FileChannelImpl extends FileChannel throws IOException { if (size < 0) - throw new IllegalArgumentException (); + throw new IllegalArgumentException ("size: " + size); if (!isOpen ()) throw new ClosedChannelException (); @@ -532,4 +552,12 @@ public final class FileChannelImpl extends FileChannel return this; } + + public String toString() + { + return (this.getClass() + + "[fd=" + fd + + ",mode=" + mode + "," + + description + "]"); + } } diff --git a/libjava/classpath/gnu/java/nio/charset/UTF_16Decoder.java b/libjava/classpath/gnu/java/nio/charset/UTF_16Decoder.java index 302c83e..e3927d9 100644 --- a/libjava/classpath/gnu/java/nio/charset/UTF_16Decoder.java +++ b/libjava/classpath/gnu/java/nio/charset/UTF_16Decoder.java @@ -1,5 +1,5 @@ /* UTF_16Decoder.java -- - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -105,8 +105,9 @@ final class UTF_16Decoder extends CharsetDecoder } // FIXME: Change so you only do a single comparison here. - char c = byteOrder == BIG_ENDIAN ? (char) ((b1 << 8) | b2) - : (char) ((b2 << 8) | b1); + char c = (byteOrder == BIG_ENDIAN + ? (char) (((b1 & 0xFF) << 8) | (b2 & 0xFF)) + : (char) (((b2 & 0xFF) << 8) | (b1 & 0xFF))); if (0xD800 <= c && c <= 0xDFFF) { @@ -119,8 +120,9 @@ final class UTF_16Decoder extends CharsetDecoder return CoderResult.UNDERFLOW; byte b3 = in.get (); byte b4 = in.get (); - char d = byteOrder == BIG_ENDIAN ? (char) ((b3 << 8) | b4) - : (char) ((b4 << 8) | b3); + char d = (byteOrder == BIG_ENDIAN + ? (char) (((b3 & 0xFF) << 8) | (b4 & 0xFF)) + : (char) (((b4 & 0xFF) << 8) | (b3 & 0xFF))); // make sure d is a low surrogate if (d < 0xDC00 || d > 0xDFFF) return CoderResult.malformedForLength (2); diff --git a/libjava/classpath/gnu/java/nio/charset/iconv/IconvDecoder.java b/libjava/classpath/gnu/java/nio/charset/iconv/IconvDecoder.java index fa265a9..fa6f497 100644 --- a/libjava/classpath/gnu/java/nio/charset/iconv/IconvDecoder.java +++ b/libjava/classpath/gnu/java/nio/charset/iconv/IconvDecoder.java @@ -38,7 +38,7 @@ exception statement from your version. */ package gnu.java.nio.charset.iconv; -import gnu.classpath.RawData; +import gnu.classpath.Pointer; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -55,7 +55,7 @@ final class IconvDecoder extends CharsetDecoder openIconv(info.iconvName()); } - private RawData data; + private Pointer data; private int inremaining; private int outremaining; diff --git a/libjava/classpath/gnu/java/nio/charset/iconv/IconvEncoder.java b/libjava/classpath/gnu/java/nio/charset/iconv/IconvEncoder.java index bb10c9b..d5cc887 100644 --- a/libjava/classpath/gnu/java/nio/charset/iconv/IconvEncoder.java +++ b/libjava/classpath/gnu/java/nio/charset/iconv/IconvEncoder.java @@ -38,7 +38,7 @@ exception statement from your version. */ package gnu.java.nio.charset.iconv; -import gnu.classpath.RawData; +import gnu.classpath.Pointer; import java.nio.ByteBuffer; import java.nio.CharBuffer; @@ -49,7 +49,7 @@ import java.nio.charset.CoderResult; final class IconvEncoder extends CharsetEncoder { - private RawData data; + private Pointer data; private int inremaining; private int outremaining; diff --git a/libjava/classpath/gnu/java/security/OID.java b/libjava/classpath/gnu/java/security/OID.java index 8cda43e..473b6ba 100644 --- a/libjava/classpath/gnu/java/security/OID.java +++ b/libjava/classpath/gnu/java/security/OID.java @@ -1,5 +1,5 @@ /* OID.java -- numeric representation of an object identifier - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,7 +48,7 @@ import java.util.StringTokenizer; /** * This immutable class represents an object identifier, or OID. * - * <p>OIDs are represented as a series of hierarcical tokens, each of + * <p>OIDs are represented as a series of hierarchical tokens, each of * which is usually represented as a single, unsigned integer. The * hierarchy works so that later tokens are considered within the group * of earlier tokens. Thus, the OID for the Serpent block cipher, diff --git a/libjava/classpath/gnu/java/security/PolicyFile.java b/libjava/classpath/gnu/java/security/PolicyFile.java index dd3a4de..c6a3061 100644 --- a/libjava/classpath/gnu/java/security/PolicyFile.java +++ b/libjava/classpath/gnu/java/security/PolicyFile.java @@ -37,6 +37,10 @@ exception statement from your version. */ package gnu.java.security; +import gnu.classpath.SystemProperties; +import gnu.classpath.debug.Component; +import gnu.classpath.debug.SystemLogger; + import java.io.File; import java.io.IOException; import java.io.InputStreamReader; @@ -66,6 +70,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.StringTokenizer; +import java.util.logging.Logger; /** * An implementation of a {@link java.security.Policy} object whose @@ -143,24 +148,16 @@ public final class PolicyFile extends Policy // Constants and fields. // ------------------------------------------------------------------------- - private static final boolean DEBUG = true; - // Package-private to avoid a trampoline. - static void debug(String msg) - { - System.err.print(">> PolicyFile: "); - System.err.println(msg); - } - - private static void debug(Throwable t) - { - System.err.println(">> PolicyFile"); - t.printStackTrace(System.err); - } + private static final Logger logger = SystemLogger.SYSTEM; - private static final String DEFAULT_POLICY = System.getProperty("java.home") - + System.getProperty("file.separator") + "lib" - + System.getProperty("file.separator") + "security" - + System.getProperty("file.separator") + "java.policy"; + private static final String DEFAULT_POLICY = + SystemProperties.getProperty("java.home") + + SystemProperties.getProperty("file.separator") + "lib" + + SystemProperties.getProperty("file.separator") + "security" + + SystemProperties.getProperty("file.separator") + "java.policy"; + private static final String DEFAULT_USER_POLICY = + SystemProperties.getProperty ("user.home") + + SystemProperties.getProperty ("file.separator") + ".java.policy"; private final Map cs2pc; @@ -185,7 +182,8 @@ public final class PolicyFile extends Policy CodeSource cs = (CodeSource) e.getKey(); if (cs.implies(codeSource)) { - if (DEBUG) debug(cs+" -> "+codeSource); + logger.log (Component.POLICY, "{0} -> {1}", new Object[] + { cs, codeSource }); PermissionCollection pc = (PermissionCollection) e.getValue(); for (Enumeration ee = pc.elements(); ee.hasMoreElements(); ) { @@ -193,50 +191,69 @@ public final class PolicyFile extends Policy } } else - if (DEBUG) debug(cs+" !-> "+codeSource); + logger.log (Component.POLICY, "{0} !-> {1}", new Object[] + { cs, codeSource }); } - if (DEBUG) debug ("returning permissions " + perms + " for " + codeSource); + logger.log (Component.POLICY, "returning permissions {0} for {1}", + new Object[] { perms, codeSource }); return perms; } public void refresh() { cs2pc.clear(); - List policyFiles = new LinkedList(); + final List policyFiles = new LinkedList(); try { - policyFiles.add(new File(DEFAULT_POLICY).toURL()); - if (DEBUG) debug ("defualt policy is " + DEFAULT_POLICY); - policyFiles.addAll((List) AccessController.doPrivileged( + policyFiles.add (new File (DEFAULT_POLICY).toURL()); + policyFiles.add (new File (DEFAULT_USER_POLICY).toURL ()); + + AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws Exception { - LinkedList l = new LinkedList(); + String allow = Security.getProperty ("policy.allowSystemProperty"); + if (allow == null || Boolean.getBoolean (allow)) + { + String s = SystemProperties.getProperty ("java.security.policy"); + logger.log (Component.POLICY, "java.security.policy={0}", s); + if (s != null) + { + boolean only = s.startsWith ("="); + if (only) + s = s.substring (1); + policyFiles.clear (); + policyFiles.add (new URL (s)); + if (only) + return null; + } + } for (int i = 1; ; i++) { - String s = Security.getProperty("policy.file."+i); - if (DEBUG) debug("policy.file."+i+"="+s); + String pname = "policy.url." + i; + String s = Security.getProperty (pname); + logger.log (Component.POLICY, "{0}={1}", new Object [] + { pname, s }); if (s == null) break; - l.add(new URL(s)); + policyFiles.add (new URL (s)); } - String s = System.getProperty("java.security.policy"); - if (DEBUG) debug("java.security.policy="+s); - if (s != null) - l.add(new URL(s)); - return l; + return null; } - })); + }); } catch (PrivilegedActionException pae) { - if (DEBUG) debug(pae); + logger.log (Component.POLICY, "reading policy properties", pae); } catch (MalformedURLException mue) { - if (DEBUG) debug(mue); + logger.log (Component.POLICY, "setting default policies", mue); } + + logger.log (Component.POLICY, "building policy from URLs {0}", + policyFiles); for (Iterator it = policyFiles.iterator(); it.hasNext(); ) { try @@ -246,7 +263,7 @@ public final class PolicyFile extends Policy } catch (IOException ioe) { - if (DEBUG) debug(ioe); + logger.log (Component.POLICY, "reading policy", ioe); } } } @@ -273,7 +290,7 @@ public final class PolicyFile extends Policy */ private void parse(final URL url) throws IOException { - if (DEBUG) debug ("reading policy file from " + url); + logger.log (Component.POLICY, "reading policy file from {0}", url); final StreamTokenizer in = new StreamTokenizer(new InputStreamReader(url.openStream())); in.resetSyntax(); in.slashSlashComments(true); diff --git a/libjava/classpath/gnu/java/security/provider/DSAKeyPairGenerator.java b/libjava/classpath/gnu/java/security/provider/DSAKeyPairGenerator.java index 2c643d5..ddd1800 100644 --- a/libjava/classpath/gnu/java/security/provider/DSAKeyPairGenerator.java +++ b/libjava/classpath/gnu/java/security/provider/DSAKeyPairGenerator.java @@ -1,5 +1,5 @@ /* GnuDSAKeyPairGenerator.java --- Gnu DSA Key Pair Generator - Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 1999, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -45,10 +45,12 @@ import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; import java.security.KeyPair; import java.security.KeyPairGeneratorSpi; +import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.interfaces.DSAParams; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.DSAParameterSpec; +import java.security.spec.InvalidParameterSpecException; import java.util.Random; public class DSAKeyPairGenerator extends KeyPairGeneratorSpi @@ -60,18 +62,15 @@ private BigInteger q = null; // the small prime private BigInteger p = null; // the big prime private BigInteger g = null; -DSAKeyPairGenerator() +public DSAKeyPairGenerator() { keysize = 1024; + getDefaults (); } public void initialize(int keysize, SecureRandom random) { - //if( ((keysize % 64) != 0) || (keysize < 512) || (keysize > 1024) ) - // throw new InvalidAlgorithmParameterException("Invalid key size"); - - this.keysize = keysize; - this.random = random; + initialize (keysize, false, random); } public void initialize(AlgorithmParameterSpec params, @@ -81,65 +80,87 @@ public void initialize(AlgorithmParameterSpec params, if( !( params instanceof DSAParameterSpec ) ) throw new InvalidAlgorithmParameterException("Must be DSAParameterSpec"); + try + { + initialize ((DSAParams) params, random); + } + catch (InvalidParameterException ipe) + { + InvalidAlgorithmParameterException iape = + new InvalidAlgorithmParameterException(); + iape.initCause (ipe); + throw iape; + } +} + +public void initialize (DSAParams params, SecureRandom random) +{ DSAParameterSpec dsaparameterspec = (DSAParameterSpec)params; + if (dsaparameterspec.getP() == null + || dsaparameterspec.getQ() == null + || dsaparameterspec.getG() == null) + { + throw new InvalidParameterException ("none of p, q, or g may be null"); + } p = dsaparameterspec.getP(); q = dsaparameterspec.getQ(); g = dsaparameterspec.getG(); this.random = random; } -public void initialize(DSAParams params, SecureRandom random) - throws InvalidParameterException -{ - if(params.getP() != null) - p = params.getP(); - else - throw new InvalidParameterException(); - - if(params.getQ() != null) - q = params.getQ(); - else - throw new InvalidParameterException(); - - if(params.getG() != null) - g = params.getG(); - else - throw new InvalidParameterException(); - - this.random = random; -} - public void initialize(int modlen, boolean genParams, SecureRandom random) throws InvalidParameterException { if( ((modlen % 64) != 0) || (modlen < 512) || (modlen > 1024) ) throw new InvalidParameterException(); - if( (genParams == false) && (modlen != 512) && (modlen != 768) && (modlen != 1024) ) - throw new InvalidParameterException(); - this.keysize = modlen; - this.random = random; - p = null; - q = null; - g = null; + this.keysize = modlen; + this.random = random; + if (this.random == null) + { + this.random = new SecureRandom (); + } + if (genParams) + { + try + { + AlgorithmParameterGenerator apgDSA = AlgorithmParameterGenerator.getInstance("DSA"); + apgDSA.init (modlen, random); + AlgorithmParameters apDSA = apgDSA.generateParameters(); + DSAParameterSpec dsaparameterspec = (DSAParameterSpec)apDSA.getParameterSpec( DSAParameterSpec.class ); + p = dsaparameterspec.getP(); + q = dsaparameterspec.getQ(); + g = dsaparameterspec.getG(); + } + catch (NoSuchAlgorithmException nsae) + { + InvalidParameterException ipe = + new InvalidParameterException ("can't generate DSA parameters"); + ipe.initCause (nsae); + throw ipe; + } + catch (InvalidParameterSpecException ipse) + { + InvalidParameterException ipe = + new InvalidParameterException ("can't generate DSA parameters"); + ipe.initCause (ipse); + throw ipe; + } + } + else if (!getDefaults ()) + { + throw new InvalidParameterException ("unsupported key size: " + modlen); + } } public KeyPair generateKeyPair() { - if( getDefaults() == false) { - try { - AlgorithmParameterGenerator apgDSA = AlgorithmParameterGenerator.getInstance("DSA"); - AlgorithmParameters apDSA = apgDSA.generateParameters(); - DSAParameterSpec dsaparameterspec = (DSAParameterSpec)apDSA.getParameterSpec( DSAParameterSpec.class ); - p = dsaparameterspec.getP(); - q = dsaparameterspec.getQ(); - g = dsaparameterspec.getG(); - } catch ( Exception e ) { - return null; - } - } + if (random == null) + { + random = new SecureRandom (); + } - BigInteger x = new BigInteger( 159, new Random() ); + BigInteger x = new BigInteger( 159, random ); BigInteger y = g.modPow( x, p ); @@ -160,10 +181,12 @@ private boolean getDefaults() p = new BigInteger("e9e642599d355f37c97ffd3567120b8e25c9cd43e927b3a9670fbec5d890141922d2c3b3ad2480093799869d1e846aab49fab0ad26d2ce6a22219d470bce7d777d4a21fbe9c270b57f607002f3cef8393694cf45ee3688c11a8c56ab127a3daf", 16); q = new BigInteger("9cdbd84c9f1ac2f38d0f80f42ab952e7338bf511", 16); g = new BigInteger("30470ad5a005fb14ce2d9dcd87e38bc7d1b1c5facbaecbe95f190aa7a31d23c4dbbcbe06174544401a5b2c020965d8c2bd2171d3668445771f74ba084d2029d83c1c158547f3a9f1a2715be23d51ae4d3e5a1f6a7064f316933a346d3f529252", 16); - } else if( keysize == 512) { + return true; + } else if( keysize == 1024) { p = new BigInteger("fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 16); q = new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16); g = new BigInteger("f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d0782675159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243bcca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 16); + return true; } return false; } diff --git a/libjava/classpath/gnu/java/security/provider/PKIXCertPathValidatorImpl.java b/libjava/classpath/gnu/java/security/provider/PKIXCertPathValidatorImpl.java index 1268b16..ab89434 100644 --- a/libjava/classpath/gnu/java/security/provider/PKIXCertPathValidatorImpl.java +++ b/libjava/classpath/gnu/java/security/provider/PKIXCertPathValidatorImpl.java @@ -1,5 +1,5 @@ /* PKIXCertPathValidatorImpl.java -- PKIX certificate path validator. - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -331,7 +331,7 @@ public class PKIXCertPathValidatorImpl extends CertPathValidatorSpi continue; try { - if (anchorCert == null) + if (anchorCert != null) anchorCert.checkValidity(now); p[p.length-1].verify(anchorKey); if (anchorCert != null && anchorCert.getBasicConstraints() >= 0 |